/// <summary> /// Invokes AddCard with each currently registered partner. /// </summary> public async Task Invoke() { try { ResultCode resultCode = ResultCode.None; // Determine the partner through whom the deal will be claimed. ICommercePartner partner = SelectPartner(); if (partner == null) { resultCode = ResultCode.UnregisteredDeal; } else { resultCode = await partner.ClaimDealAsync().ConfigureAwait(false); } // Check the invoker's response. if (resultCode == ResultCode.None) { throw new InvalidOperationException("Call to partner invoker returned ResultCode.None."); } // Return result and updated objects to the caller. ClaimDealConcluder claimDealConcluder = new ClaimDealConcluder(Context); claimDealConcluder.Conclude(resultCode); } catch (Exception ex) { RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Executes the Add card invocation. /// </summary> public async Task Execute() { try { AddCardConcluder addCardConcluder = new AddCardConcluder(Context); if ((Context[Key.NewCardInfo] as NewCardInfo) != null) { if (CardMayBeValid() == true && CardProviderRejected() == false) { ResultCode resultCode = PlaceUserInContext(); if (resultCode == ResultCode.Success) { User user = Context[Key.User] as User; if (user != null) { PopulateContextUserAndCard(); Context.Log.Verbose("Attempting to add the card for the user to all current partners."); AddCardInvoker addCardInvoker = new AddCardInvoker(Context); await addCardInvoker.Invoke(); } else { addCardConcluder.Conclude(ResultCode.UnexpectedUnregisteredUser); } } else { addCardConcluder.Conclude(resultCode); } } else { addCardConcluder.Conclude(ResultCode.InvalidCard); } } else { addCardConcluder.Conclude(ResultCode.ParameterCannotBeNull); } } catch (Exception ex) { ((ResultSummary)Context[Key.ResultSummary]).SetResultCode(ResultCode.UnknownError); RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Executes the Remove card invocation. /// </summary> public async Task Execute() { try { SharedUserLogic sharedUserLogic = new SharedUserLogic(Context, CommerceOperationsFactory.UserOperations(Context)); SharedCardLogic sharedCardLogic = new SharedCardLogic(Context, CommerceOperationsFactory.CardOperations(Context)); RemoveCardConcluder removeCardConcluder = new RemoveCardConcluder(Context); User user = sharedUserLogic.RetrieveUser(); Context[Key.User] = user; if (user != null) { Card card = sharedCardLogic.RetrieveCard(); Context[Key.Card] = card; if (card != null) { if (card.GlobalUserId == user.GlobalId) { Context.Log.Verbose("Attempting to remove the card from all current partners."); RemoveCardInvoker removeCardInvoker = new RemoveCardInvoker(Context); await removeCardInvoker.Invoke(); } else { removeCardConcluder.Conclude(ResultCode.CardDoesNotBelongToUser); } } else { removeCardConcluder.Conclude(ResultCode.UnregisteredCard); } } else { removeCardConcluder.Conclude(ResultCode.UnexpectedUnregisteredUser); } } catch (Exception ex) { ((ResultSummary)Context[Key.ResultSummary]).SetResultCode(ResultCode.UnknownError); RestResponder.BuildAsynchronousResponse(Context, ex); } }
public Task <HttpResponseMessage> Add(NewCardNumber newCardNumber) { Stopwatch callTimer = Stopwatch.StartNew(); Task <HttpResponseMessage> result; // Build a context object to pass down the pipeline. CommerceContext context = CommerceContext.BuildAsynchronousRestContext("Add card and queue claiming already claimed deals", Request, new AddCardResponse(), callTimer); try { if (newCardNumber == null) { throw new ArgumentNullException("newCardNumber", "Parameter newCardNumber cannot be null."); } context.Log.Information("Processing {0} call.", context.ApiCallDescription); // Generate a legacy NewCardInfo object from the specified number. NewCardInfo newCardInfo = ControllerUtilities.GenerateLegacyCardInfo(newCardNumber); ControllerUtilities.LogObfuscatedNewCardInfo(newCardInfo, context); // Add parameters of the call to the context. context[Key.QueueJob] = true; context[Key.NewCardInfo] = newCardInfo; context[Key.GlobalUserId] = CommerceContext.PopulateUserId(context); context[Key.ReferrerId] = newCardNumber.Referrer; context[Key.RewardProgramType] = ControllerUtilities.GetRewardProgramAssociatedWithRequest(this.Request); // Create an executor object to execute the API invocation. AddCardExecutor executor = new AddCardExecutor(context); Task.Factory.StartNew(async() => await executor.Execute()); result = ((TaskCompletionSource <HttpResponseMessage>)context[Key.TaskCompletionSource]).Task; } catch (Exception ex) { result = RestResponder.CreateExceptionTask(context, ex); } return(result); }
/// <summary> /// Concludes execution of the Add card request after previous work has been completed. /// </summary> /// <param name="resultCode"> /// The ResultCode to set within the call response. /// </param> /// <param name="context"> /// The context of the current API call. /// </param> /// <exception cref="ArgumentNullException"> /// Parameter context cannot be null. /// </exception> public void Conclude(ResultCode resultCode) { try { // Set the Response ResultCode as needed. Context.Log.Verbose("ResultCode when Conclude process begins: {0}.", resultCode); // If process succeeded, update internal data storage. if (resultCode == ResultCode.Success) { // Add record of the claimed deal. resultCode = AddClaimedDeal(); } ((ClaimDealResponse)Context[Key.Response]).ResultSummary.SetResultCode(resultCode); RestResponder.BuildAsynchronousResponse(Context); } catch (Exception ex) { RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Invokes RemoveCardAsync with each currently registered partner. /// </summary> public async Task Invoke() { try { Card card = (Card)Context[Key.Card]; RewardPrograms rewardPrograms = RewardPrograms.CardLinkOffers; if (Context.ContainsKey(Key.RewardProgramType) == true) { rewardPrograms = (RewardPrograms)Context[Key.RewardProgramType]; } ResultCode resultCode = ResultCode.Success; // Notify the partners of the card removal only if the card is enrolled to the // specified reward program. If the card is enrolled with other reward programs, // we still want to receive notifications from the partners for this card. if (card.RewardPrograms == rewardPrograms) { List <ICommercePartner> partners = new List <ICommercePartner>(); foreach (PartnerCardInfo partnerCardInfo in card.PartnerCardInfoList) { switch (partnerCardInfo.PartnerId) { //case Partner.FirstData: // partners.Add(new FirstData(Context)); // break; case Partner.Amex: partners.Add(new Amex(Context)); break; case Partner.MasterCard: partners.Add(new MasterCard(Context)); break; case Partner.Visa: partners.Add(new Visa(Context)); break; } } foreach (ICommercePartner partner in partners) { string partnerName = partner.GetType().Name; Context.Log.Verbose("Removing card from partner {0}.", partnerName); ResultCode partnerResult = ResultCode.None; try { partnerResult = await partner.RemoveCardAsync(); } catch (Exception ex) { Context.Log.Error("Remove card call to partner {0} ended with an error.", ex, partnerName); } // Update overall result from result of call to partner. switch (partnerResult) { case ResultCode.Success: // No update to overall result is necessary. break; case ResultCode.UnknownError: resultCode = ResultCode.UnknownError; break; default: throw new InvalidOperationException("Call to partner invoker returned ResultCode.None."); } } } // Return result and updated objects to the caller. RemoveCardConcluder removeCardConcluder = new RemoveCardConcluder(Context); removeCardConcluder.Conclude(resultCode); } catch (Exception ex) { RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Executes the Claim Deal API invocation. /// </summary> public async Task Execute() { try { SharedUserLogic sharedUserLogic = new SharedUserLogic(Context, CommerceOperationsFactory.UserOperations(Context)); SharedCardLogic sharedCardLogic = new SharedCardLogic(Context, CommerceOperationsFactory.CardOperations(Context)); SharedDealLogic sharedDealLogic = new SharedDealLogic(Context, CommerceOperationsFactory.DealOperations(Context)); ClaimDealConcluder claimDealConcluder = new ClaimDealConcluder(Context); ResultCode extractionResult = ExtractClaimDealPayload(); if (extractionResult == ResultCode.Success) { Deal deal = sharedDealLogic.RetrieveDeal(); Context[Key.Deal] = deal; if (deal != null) { Context[Key.DealDiscountSummary] = deal.DiscountSummary; User user = sharedUserLogic.RetrieveUser(); Context[Key.User] = user; if (user != null) { Card card = sharedCardLogic.RetrieveCard(); Context[Key.Card] = card; if (card != null) { // If the deal and card have common ground, claim the deal for the card. if (MustClaim(deal, card) == true) { Context[Key.MerchantName] = deal.MerchantName; Context.Log.Verbose("Trying to claim the deal for the user with the appropriate partner."); ClaimDealInvoker claimDealInvoker = new ClaimDealInvoker(Context); await claimDealInvoker.Invoke(); } else { Context.Log.Verbose("It is not necessary to claim this deal for this card."); ((ResultSummary)Context[Key.ResultSummary]).SetResultCode(ResultCode.Success); RestResponder.BuildAsynchronousResponse(Context); } } else { claimDealConcluder.Conclude(ResultCode.UnregisteredCard); } } else { claimDealConcluder.Conclude(ResultCode.UnexpectedUnregisteredUser); } } else { claimDealConcluder.Conclude(ResultCode.UnactionableDealId); } } else { claimDealConcluder.Conclude(extractionResult); } } catch (Exception ex) { ((ResultSummary)Context[Key.ResultSummary]).SetResultCode(ResultCode.UnknownError); RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Concludes execution of the Add card call after previous work has been completed. /// </summary> /// <param name="resultCode"> /// The ResultCode to set within the call response. /// </param> /// <exception cref="ArgumentNullException"> /// Parameter context cannot be null. /// </exception> public void Conclude(ResultCode resultCode) { try { Context.Log.Verbose("ResultCode when Conclude process begins: {0}.", resultCode); // If process succeeded, update internal data storage. AddCardResponse response = (AddCardResponse)Context[Key.Response]; if (resultCode == ResultCode.Created) { // Add the card. resultCode = AddCard(); if (resultCode == ResultCode.Created || resultCode == ResultCode.Success) { response.NewCardId = General.GuidFromInteger(((Card)Context[Key.Card]).Id); // If a new card was added, kick off confirmation process for unauthenticated users and add needed information to analytics. // TODO: AddCard() above returns ResultCode.Success. So the code below will not execute. Is it ok? if (resultCode == ResultCode.Created) { // Kick off confirmation process for unauthenticated users. bool createUnauthenticatedAccount = false; if (Context[Key.CreateUnauthenticatedAccount] != null) { createUnauthenticatedAccount = (bool)Context[Key.CreateUnauthenticatedAccount]; } if (createUnauthenticatedAccount == true) { IUsersDal usersDal = PartnerFactory.UsersDal(Context.Config); Task.Run(() => usersDal.CompleteUnauthenticatedUserSetUp((Guid)Context[Key.GlobalUserId])); } // Add analytics info. Context.Log.Verbose("Adding new card to analytics."); User user = (User)Context[Key.User]; Analytics.AddAddCardEvent(user.GlobalId, user.AnalyticsEventId, Guid.Empty, Context[Key.ReferrerId] as string); } // Queue deal claiming if set to do so. bool queueDealClaiming = false; if (Context[Key.QueueJob] != null) { queueDealClaiming = (bool)Context[Key.QueueJob]; } // Linking is only for First Data, but by the time execution reaches this part of the code, the card may need to be linked to CLO offers or // Burn offers, or both, but definitely at least one of them. Therefore, a job has to be scheduled to cover the relevant combination of CLO // and Burn offers. That Earn offers are not registered with First Data doesn't change this-- the filtering will have to occur as part of the job. if (queueDealClaiming == true) { QueueClaimingDeals(response); resultCode = ResultCode.JobQueued; } } } response.ResultSummary.SetResultCode(resultCode); RestResponder.BuildAsynchronousResponse(Context); } catch (Exception ex) { RestResponder.BuildAsynchronousResponse(Context, ex); } }
/// <summary> /// Invokes AddCard with each currently registered partner. /// </summary> public async Task Invoke() { try { ResultCode resultCode = ResultCode.Created; NewCardInfo newCardInfo = (NewCardInfo)Context[Key.NewCardInfo]; Card card = (Card)Context[Key.Card]; List <ICommercePartner> partners = new List <ICommercePartner>(); //partners.Add(new FirstData(Context)); CardBrand cardBrand = (CardBrand)Enum.Parse(typeof(CardBrand), newCardInfo.CardBrand); switch (cardBrand) { case CardBrand.AmericanExpress: partners.Add(new Amex(Context)); break; case CardBrand.MasterCard: partners.Add(new MasterCard(Context)); break; case CardBrand.Visa: partners.Add(new Visa(Context)); break; } foreach (ICommercePartner partner in partners) { string partnerName = partner.GetType().Name; Context.Log.Verbose("Adding card to partner {0}.", partnerName); ResultCode partnerResult = ResultCode.None; try { partnerResult = await partner.AddCardAsync(); } catch (Exception ex) { Context.Log.Error("Add card call to partner {0} ended with an error.", ex, partnerName); } // Update overall result from result of call to partner. switch (partnerResult) { case ResultCode.Created: // At this time, FirstData PartnerCardId is used as the PanToken for the card. if (partner is FirstData) { PartnerCardInfo firstDataInfo = card.PartnerCardInfoList.SingleOrDefault(info => info.PartnerId == Partner.FirstData); if (firstDataInfo != null) { card.PanToken = firstDataInfo.PartnerCardId; } } break; case ResultCode.InvalidCard: resultCode = ResultCode.InvalidCard; break; case ResultCode.UnknownError: resultCode = ResultCode.UnknownError; break; case ResultCode.InvalidCardNumber: resultCode = ResultCode.InvalidCardNumber; break; case ResultCode.CorporateOrPrepaidCardError: resultCode = ResultCode.CorporateOrPrepaidCardError; break; case ResultCode.MaximumEnrolledCardsLimitReached: resultCode = ResultCode.MaximumEnrolledCardsLimitReached; break; case ResultCode.CardRegisteredToDifferentUser: resultCode = ResultCode.CardRegisteredToDifferentUser; break; case ResultCode.CardExpired: resultCode = ResultCode.CardExpired; break; default: throw new InvalidOperationException("Call to partner invoker returned ResultCode.None."); } } AddCardConcluder addCardConcluder = new AddCardConcluder(Context); addCardConcluder.Conclude(resultCode); } catch (Exception ex) { RestResponder.BuildAsynchronousResponse(Context, ex); } }