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)));
            }
        }