public async Task <Result <PaymentResponse> > Charge(string referenceCode, ApiCaller apiCaller, IPaymentCallbackService paymentCallbackService) { return(await GetChargingAccountId() .Bind(GetChargingAccount) .Bind(GetChargingAmount) .Check(ChargeMoney) .Tap(SendNotificationIfRequired) .Bind(StorePayment) .Bind(ProcessPaymentResults) .Map(CreateResult)); Task <Result <int> > GetChargingAccountId() => paymentCallbackService.GetChargingAccountId(referenceCode); async Task <Result <AgencyAccount> > GetChargingAccount(int accountId) => await _context.AgencyAccounts.SingleOrDefaultAsync(a => a.Id == accountId) ?? Result.Failure <AgencyAccount>("Could not find agency account"); async Task <Result <(AgencyAccount, MoneyAmount)> > GetChargingAmount(AgencyAccount account) { var(_, isFailure, amount, error) = await paymentCallbackService.GetChargingAmount(referenceCode); if (isFailure) { return(Result.Failure <(AgencyAccount, MoneyAmount)>(error)); } return(account, amount); } Task <Result> ChargeMoney((AgencyAccount account, MoneyAmount amount) chargeInfo) { var(account, amount) = chargeInfo; return(_accountPaymentProcessingService.ChargeMoney(account.Id, new ChargedMoneyData( currency: amount.Currency, amount: amount.Amount, reason: $"Charge money for service '{referenceCode}'", referenceCode: referenceCode), apiCaller)); } async Task <Result <Payment> > StorePayment((AgencyAccount account, MoneyAmount amount) chargeInfo) { var(account, amount) = chargeInfo; var(paymentExistsForBooking, _, _, _) = await GetPayment(referenceCode); if (paymentExistsForBooking) { return(Result.Failure <Payment>("Payment for current booking already exists")); } var now = _dateTimeProvider.UtcNow(); var info = new AccountPaymentInfo(string.Empty); var payment = new Payment { Amount = amount.Amount, AccountNumber = account.Id.ToString(), Currency = amount.Currency, Created = now, Modified = now, Status = PaymentStatuses.Captured, Data = JsonConvert.SerializeObject(info), AccountId = account.Id, PaymentMethod = PaymentTypes.VirtualAccount, ReferenceCode = referenceCode }; _context.Payments.Add(payment); await _context.SaveChangesAsync(); _context.Detach(payment); return(payment); } Task <Result> ProcessPaymentResults(Payment payment) => paymentCallbackService.ProcessPaymentChanges(payment); Task SendNotificationIfRequired((AgencyAccount account, MoneyAmount amount) chargeInfo) => _balanceManagementNotificationsService.SendNotificationIfRequired(chargeInfo.account, chargeInfo.amount); PaymentResponse CreateResult() => new(string.Empty, CreditCardPaymentStatuses.Success, string.Empty); }
public ActionResult Profile(Account account) { try { var loginedAccount = (Account)SessionPersister.account; var currentAccount = ocmde.Accounts.SingleOrDefault(a => a.Id == account.Id); if (account.Username != null && account.Username.Length > 0 && loginedAccount.Username != account.Username) { if (Exists(account.Username)) { ModelState.AddModelError("username", Resources.Customer.Username_exists); } } if (account.Password != null && account.Password.Length != 0 && !PasswordHelper.IsValidPassword(account.Password)) { ModelState.AddModelError("Password", Resources.Vendor.Password_validate_message); } if (ModelState.IsValid) { if (account.Password != null && account.Password.Length != 0) { currentAccount.Password = BCrypt.Net.BCrypt.HashPassword(account.Password); } currentAccount.Email = account.Email; currentAccount.FullName = account.FullName; currentAccount.Phone = account.Phone; currentAccount.Username = account.Username; if (currentAccount.AccountAddresses.Count <= 0) { AccountAddress acctAddress = account.defaultAddress; acctAddress.Id = Guid.NewGuid(); currentAccount.AccountAddresses.Add(acctAddress); } else { AccountAddress acctAddressOriginal = currentAccount.AccountAddresses.FirstOrDefault(); AccountAddress forUpdate = ocmde.AccountAddresses.Find(acctAddressOriginal.Id); forUpdate.City = account.defaultAddress.City; forUpdate.LineAddress1 = account.defaultAddress.LineAddress1; forUpdate.LineAddress2 = account.defaultAddress.LineAddress2; forUpdate.ZipCode = account.defaultAddress.ZipCode; } if (currentAccount.AccountPaymentInfoes.Count <= 0) { AccountPaymentInfo paymentInfo = new AccountPaymentInfo(); paymentInfo.CreditCardNo = account.accountPaymentInfo.CreditCardNo; paymentInfo.ExpiryDate = account.accountPaymentInfo.ExpiryDate; paymentInfo.FullName = account.accountPaymentInfo.FullName; //paymentInfo.Id = Guid.NewGuid(); currentAccount.AccountPaymentInfoes.Add(paymentInfo); } else { AccountPaymentInfo acctPaymentOriginal = currentAccount.AccountPaymentInfoes.FirstOrDefault(); acctPaymentOriginal.CreditCardNo = account.accountPaymentInfo.CreditCardNo; acctPaymentOriginal.ExpiryDate = account.accountPaymentInfo.ExpiryDate; acctPaymentOriginal.FullName = account.accountPaymentInfo.FullName; } ocmde.SaveChanges(); SessionPersister.account = ocmde.Accounts.Find(account.Id); return(RedirectToAction("Profile", "Login")); } else { return(View("Profile", account)); } } catch (Exception e) { return(View("Error", new HandleErrorInfo(e, "Login", "Profile"))); } }
public Task <Result <PaymentResponse> > Charge(Booking booking, UserInfo user, int agencyId, string clientIp) { return(Result.Success() .BindWithTransaction(_context, () => Charge() .Tap(_ => ChangePaymentStatusToCaptured()))); async Task <Result <PaymentResponse> > Charge() { var(_, isAmountFailure, amount, amountError) = await GetAmount(); if (isAmountFailure) { return(Result.Failure <PaymentResponse>(amountError)); } var(_, isAccountFailure, account, accountError) = await _accountManagementService.Get(agencyId, booking.Currency); if (isAccountFailure) { return(Result.Failure <PaymentResponse>(accountError)); } return(await Result.Success() .BindWithLock(_locker, typeof(Booking), booking.Id.ToString(), () => Result.Success() .Ensure(IsNotPayed, $"The booking '{booking.ReferenceCode}' is already paid") .Ensure(CanCharge, $"Could not charge money for the booking '{booking.ReferenceCode}'") .Bind(ChargeMoney) .Bind(StorePayment) .Map(CreateResult))); Task <Result <decimal> > GetAmount() => GetPendingAmount(booking).Map(p => p.Amount); bool IsNotPayed() => booking.PaymentStatus != BookingPaymentStatuses.Captured; bool CanCharge() => booking.PaymentMethod == PaymentMethods.BankTransfer && ChargeableStatuses.Contains(booking.Status); Task <Result> ChargeMoney() => _accountPaymentProcessingService.ChargeMoney(account.Id, new ChargedMoneyData( currency: account.Currency, amount: amount, reason: $"Charge money after booking '{booking.ReferenceCode}'", referenceCode: booking.ReferenceCode), user); async Task <Result> StorePayment() { var(paymentExistsForBooking, _, _, _) = await GetPayment(booking.Id); if (paymentExistsForBooking) { return(Result.Failure("Payment for current booking already exists")); } var now = _dateTimeProvider.UtcNow(); var info = new AccountPaymentInfo(clientIp); var payment = new Payment { Amount = amount, BookingId = booking.Id, AccountNumber = account.Id.ToString(), Currency = booking.Currency.ToString(), Created = now, Modified = now, Status = PaymentStatuses.Captured, Data = JsonConvert.SerializeObject(info), AccountId = account.Id, PaymentMethod = PaymentMethods.BankTransfer }; _context.Payments.Add(payment); await _context.SaveChangesAsync(); return(Result.Success()); } PaymentResponse CreateResult() => new PaymentResponse(string.Empty, CreditCardPaymentStatuses.Success, string.Empty); } async Task ChangePaymentStatusToCaptured() { if (booking.PaymentStatus == BookingPaymentStatuses.Captured) { return; } booking.PaymentStatus = BookingPaymentStatuses.Captured; _context.Update(booking); await _context.SaveChangesAsync(); } }