public AuthorizeTokenExCimBasedManager(
     AuthorizeTokenExService authorizeNetService,
     IOrderGroupCalculator orderGroupCalculator,
     IShippingCalculator shippingCalculator,
     ILineItemCalculator lineItemCalculator,
     IMarketService marketService)
 {
     _authorizeTokenExService = authorizeNetService;
     _orderGroupCalculator    = orderGroupCalculator;
     _shippingCalculator      = shippingCalculator;
     _lineItemCalculator      = lineItemCalculator;
     _marketService           = marketService;
 }
        /// <summary>
        /// Processes the payment.
        /// </summary>
        /// <param name="orderGroup">The order group.</param>
        /// <param name="payment">The payment.</param>
        public override PaymentProcessingResult ProcessPayment(IOrderGroup orderGroup, IPayment payment)
        {
            if (orderGroup is null)
            {
                throw new ArgumentException("Order group should not be null.");
            }

            if (!(payment is ITokenizedPayment tokenPayment))
            {
                throw new PaymentException(PaymentException.ErrorType.ProviderError, "", "Payment is not tokenization.");
            }

            var message            = string.Empty;
            var transactionRequest = new TransactionRequest(
                GetSetting(UserParameterName),
                GetSetting(TransactionKeyParameterName),
                GetTestModeSetting());
            var authorizeNetService = new AuthorizeTokenExService(transactionRequest, new TokenExGateway());

            //Process purchase order
            if (IsRegularTransaction(orderGroup))
            {
                var address = tokenPayment.BillingAddress;
                if (address == null)
                {
                    throw new PaymentException(PaymentException.ErrorType.ConfigurationError, "", "Billing address was not specified.");
                }

                var transactionData  = CreateTransactionDataForRegularTransaction(orderGroup, tokenPayment);
                var merchantCurrency = authorizeNetService.GetMerchantCurrency();
                var amount           = Utilities.ConvertMoney(new Money(tokenPayment.Amount, orderGroup.Currency), merchantCurrency);

                var manager = new AuthorizeTokenExCimBasedManager(
                    authorizeNetService,
                    ServiceLocator.Current.GetInstance <IOrderGroupCalculator>(),
                    ServiceLocator.Current.GetInstance <IShippingCalculator>(),
                    ServiceLocator.Current.GetInstance <ILineItemCalculator>(),
                    ServiceLocator.Current.GetInstance <IMarketService>());
                var response = manager.Process(orderGroup, transactionRequest, transactionData, amount, tokenPayment);

                if (response.IsTransactionCapturedOrSettled)
                {
                    PostProcessPayment(tokenPayment);
                    return(PaymentProcessingResult.CreateSuccessfulResult(string.Empty));
                }

                var result = (GatewayResponse)response.Response;
                if (result.Error || result.Declined)
                {
                    var exception = new PaymentException(PaymentException.ErrorType.ProviderError, result.ResponseCode, result.Message);
                    exception.ResponseMessages.Add("CSCResponse", result.CAVResponse);
                    exception.ResponseMessages.Add("ReasonCode", result.ResponseReasonCode);
                    exception.ResponseMessages.Add("Subcode", $"{result.SubCode}");
                    exception.ResponseMessages.Add("AVSResult", result.AVSResponse);

                    throw exception;
                }

                tokenPayment.AuthorizationCode = tokenPayment.ValidationCode = response.Response.AuthorizationCode;
                if (transactionData.type == TransactionType.Authorization)
                {
                    tokenPayment.TransactionID = response.Response.TransactionID;
                }

                // When doing capture, refund, etc... transactions, Authorize.Net will return a new Transaction Id. We need to store this to ProviderTransactionID
                // instead of TransactionID, because TransactionID should be the Authorization transaction Id, and ProviderTransactionID will be used when we want to refund.
                tokenPayment.ProviderTransactionID = response.Response.TransactionID;

                message = response.Response.Message;
            }

            PostProcessPayment(tokenPayment);

            //TODO Supports Payment plan
            return(PaymentProcessingResult.CreateSuccessfulResult(message));
        }