private async Task <IActionResult> RegisterUser(RegisterViewModel model, string returnUrl, bool useAP) { //Create the user object and validate it before calling Fraud Protection var user = new ApplicationUser { UserName = model.User.Email, Email = model.User.Email, FirstName = model.User.FirstName, LastName = model.User.LastName, PhoneNumber = model.User.Phone, Address1 = model.Address.Address1, Address2 = model.Address.Address2, City = model.Address.City, State = model.Address.State, ZipCode = model.Address.ZipCode, CountryRegion = model.Address.CountryRegion }; foreach (var v in _userManager.UserValidators) { var validationResult = await v.ValidateAsync(_userManager, user); if (!validationResult.Succeeded) { AddErrors(validationResult); } } ; foreach (var v in _userManager.PasswordValidators) { var validationResult = await v.ValidateAsync(_userManager, user, model.Password); if (!validationResult.Succeeded) { AddErrors(validationResult); } } ; if (ModelState.ErrorCount > 0) { return(View("Register", model)); } #region Fraud Protection Service var correlationId = _fraudProtectionService.NewCorrelationId; // Ask Fraud Protection to assess this signup/registration before registering the user in our database, etc. if (useAP) { AccountProtection.SignUp signupEvent = CreateSignupAPEvent(model); var signupAssessment = await _fraudProtectionService.PostSignupAP(signupEvent, correlationId); //Track Fraud Protection request/response for display only var fraudProtectionIO = new FraudProtectionIOModel(correlationId, signupEvent, signupAssessment, "Signup"); TempData.Put(FraudProtectionIOModel.TempDataKey, fraudProtectionIO); bool rejectSignup = false; if (signupAssessment is AccountProtection.ResponseSuccess signupResponse) { rejectSignup = signupResponse.ResultDetails.FirstOrDefault()?.Decision != AccountProtection.DecisionName.Approve; } if (rejectSignup) { ModelState.AddModelError("", "Signup rejected by Fraud Protection. You can try again as it has a random likelihood of happening in this sample site."); return(View("Register", model)); } } else { SignUp signupEvent = CreateSignupEvent(model); var signupAssessment = await _fraudProtectionService.PostSignup(signupEvent, correlationId); //Track Fraud Protection request/response for display only var fraudProtectionIO = new FraudProtectionIOModel(correlationId, signupEvent, signupAssessment, "Signup"); //2 out of 3 signups will succeed on average. Adjust if you want more or less signups blocked for tesing purposes. var rejectSignup = new Random().Next(0, 3) != 0; var signupStatusType = rejectSignup ? SignupStatusType.Rejected.ToString() : SignupStatusType.Approved.ToString(); var signupStatus = new SignupStatusEvent { SignUpId = signupEvent.SignUpId, StatusType = signupStatusType, StatusDate = DateTimeOffset.Now, Reason = "User is " + signupStatusType }; if (!rejectSignup) { signupStatus.User = new SignupStatusUser { UserId = model.User.Email }; } var signupStatusResponse = await _fraudProtectionService.PostSignupStatus(signupStatus, correlationId); fraudProtectionIO.Add(signupStatus, signupStatusResponse, "Signup Status"); TempData.Put(FraudProtectionIOModel.TempDataKey, fraudProtectionIO); if (rejectSignup) { ModelState.AddModelError("", "Signup rejected by Fraud Protection. You can try again as it has a random likelihood of happening in this sample site."); return(View("Register", model)); } } #endregion var result = await _userManager.CreateAsync(user, model.Password); if (!result.Succeeded) { AddErrors(result); return(View("Register", model)); } await _signInManager.SignInAsync(user, isPersistent : false); await TransferBasketToEmailAsync(user.Email); return(RedirectToLocal(returnUrl)); }
/// <summary> /// Checks the purchase's risk score. /// If the purchase is rejected, submit a REJECTED purchase status. /// If the purchase is approved, submit the bank AUTH, bank CHARGE, and purchase status (approved if the bank also approves the auth and charge, or rejected otherwise). /// If the purchase is in review, submit unknown bank AUTH and unknown purchase status (so that case management case is still created) /// </summary> private async Task <OrderStatus> ApproveOrRejectPurchase(string merchantRuleDecision, string cardNumber, string purchaseId, string correlationId, FraudProtectionIOModel fraudProtectionIO) { var status = OrderStatus.Received; BankEvent auth = null; BankEvent charge = null; PurchaseStatusEvent purchaseStatus; if (!FakeCreditCardBankResponses.CreditCardResponses.TryGetValue(cardNumber, out FakeCreditCardBankResponses creditCardBankResponse)) { //default response creditCardBankResponse = new FakeCreditCardBankResponses { IgnoreFraudRiskRecommendation = false, IsAuthApproved = true, IsChargeApproved = true }; } var isApproved = merchantRuleDecision.StartsWith("APPROVE", StringComparison.OrdinalIgnoreCase); var inReview = merchantRuleDecision.StartsWith("REVIEW", StringComparison.OrdinalIgnoreCase); if (isApproved || inReview || creditCardBankResponse.IgnoreFraudRiskRecommendation) { if (!creditCardBankResponse.IsAuthApproved) { //Auth - Rejected auth = SetupBankEvent(BankEventType.Auth, DateTimeOffset.Now, purchaseId, BankEventStatus.Declined); //Purchase status - Rejected purchaseStatus = SetupPurchaseStatus(purchaseId, PurchaseStatusType.Rejected); status = OrderStatus.Rejected; } else { //Auth - Approved/Unknown var authStatus = inReview ? BankEventStatus.Unknown : BankEventStatus.Approved; auth = SetupBankEvent(BankEventType.Auth, DateTimeOffset.Now, purchaseId, authStatus); //Charge var chargeStatus = creditCardBankResponse.IsChargeApproved ? BankEventStatus.Approved : BankEventStatus.Declined; if (!inReview) { charge = SetupBankEvent(BankEventType.Charge, DateTimeOffset.Now, purchaseId, chargeStatus); } if (inReview) { //Purchase status - Unknown purchaseStatus = SetupPurchaseStatus(purchaseId, PurchaseStatusType.Unknown); status = OrderStatus.InReview; } else if (creditCardBankResponse.IsChargeApproved) { //Purchase status - Approved purchaseStatus = SetupPurchaseStatus(purchaseId, PurchaseStatusType.Approved); } else { //Purchase status - Rejected purchaseStatus = SetupPurchaseStatus(purchaseId, PurchaseStatusType.Rejected); status = OrderStatus.Rejected; } } } else { purchaseStatus = SetupPurchaseStatus(purchaseId, PurchaseStatusType.Rejected); status = OrderStatus.Rejected; } if (auth != null) { var response = await _fraudProtectionService.PostBankEvent(auth, correlationId); fraudProtectionIO.Add(auth, response, "BankEvent Auth"); } if (charge != null) { var response = await _fraudProtectionService.PostBankEvent(charge, correlationId); fraudProtectionIO.Add(charge, response, "BankEvent Charge"); } if (purchaseStatus != null) { var response = await _fraudProtectionService.PostPurchaseStatus(purchaseStatus, correlationId); fraudProtectionIO.Add(purchaseStatus, response, "PurchaseStatus"); } return(status); }