public async Task <Result> Refund(string referenceCode, ApiCaller apiCaller, DateTime operationDate, IPaymentCallbackService paymentCallbackService, string reason) { return(await GetChargingAccountId() .Bind(GetRefundableAmount) .Bind(RefundMoneyToAccount) .Bind(ProcessPaymentResults)); Task <Result <int> > GetChargingAccountId() => paymentCallbackService.GetChargingAccountId(referenceCode); async Task <Result <(int accountId, MoneyAmount)> > GetRefundableAmount(int accountId) { var(_, isFailure, refundableAmount, error) = await paymentCallbackService.GetRefundableAmount(referenceCode, operationDate); if (isFailure) { return(Result.Failure <(int, MoneyAmount)>(error)); } return(accountId, refundableAmount); } async Task <Result <Payment> > RefundMoneyToAccount((int, MoneyAmount) refundInfo) { var(accountId, refundableAmount) = refundInfo; return(await GetPayment(referenceCode) .Check(Refund) .Map(UpdatePaymentStatus)); Task <Result> Refund(Payment _) => _accountPaymentProcessingService.RefundMoney(accountId, new ChargedMoneyData( refundableAmount.Amount, refundableAmount.Currency, reason: reason, referenceCode: referenceCode), apiCaller); async Task <Payment> UpdatePaymentStatus(Payment payment) { payment.Status = PaymentStatuses.Refunded; payment.RefundedAmount = refundableAmount.Amount; _context.Payments.Update(payment); await _context.SaveChangesAsync(); return(payment); } } Task <Result> ProcessPaymentResults(Payment payment) => paymentCallbackService.ProcessPaymentChanges(payment); }
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); }