public async Task <Result <PaymentResponse> > Authorize(NewCreditCardPaymentRequest request, string languageCode, string ipAddress, IPaymentCallbackService paymentCallbackService, AgentContext agent) { _logger.LogCreditCardAuthorizationStarted(request.ReferenceCode); var(_, isFailure, servicePrice, error) = await paymentCallbackService.GetChargingAmount(request.ReferenceCode); if (isFailure) { _logger.LogCreditCardAuthorizationFailure(request.ReferenceCode, error); return(Result.Failure <PaymentResponse>(error)); } return(await Validate(request) .Bind(Authorize) .TapIf(IsSaveCardNeeded, SaveCard) .Bind(StorePaymentResults) .Finally(WriteLog));
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); }