public async Task <ClientResponse <PaymentResult> > ProcessPaymentAsync(PaymentRequest paymentRequest) { if (paymentRequest == null) { throw new ArgumentNullException(nameof(paymentRequest)); } var validationResult = _paymentValidator.Validate(paymentRequest); if (!validationResult.IsValid) { return(ClientResponse <PaymentResult> .FromError(validationResult.ToString(), new PaymentResult(paymentRequest.PaymentRequestId))); } var payment = paymentRequest.ToPayment(); try { await UpdatePaymentAsync(payment); var bankPaymentResult = await _bankPaymentClient.ProcessPaymentAsync(paymentRequest); payment.PaymentStatus = bankPaymentResult.Status ? PaymentStatus.Succeed : PaymentStatus.Declined; payment.PaymentReferenceId = bankPaymentResult.PaymentReferenceId; await UpdatePaymentAsync(payment); var paymentResult = new PaymentResult(payment.PaymentRequestId, payment.PaymentReferenceId); return(bankPaymentResult.Status ? ClientResponse <PaymentResult> .FromPayload(paymentResult) : ClientResponse <PaymentResult> .FromError("Payment was unsuccessful.The bank returns unsuccessful response.", paymentResult)); } catch (PaymentStoreException e) { _logger.LogError("Error in saving payment", e); // TODO: Can be handled in different strategies. E.g Revert the payment with bank or retry saving. return(ClientResponse <PaymentResult> .FromError("Payment was unsuccessful.", new PaymentResult(payment.PaymentRequestId, payment.PaymentReferenceId))); } catch (Exception e) { _logger.LogError("Error in process payment", e); return(ClientResponse <PaymentResult> .FromError("Payment was unsuccessful.", new PaymentResult(payment.PaymentRequestId))); } }