Example #1
0
        internal static GpApiRequest BuildRequest(AuthorizationBuilder builder, GpApiConnector gateway)
        {
            var paymentMethod = new JsonDoc()
                                .Set("entry_mode", GetEntryMode(builder)); // [MOTO, ECOM, IN_APP, CHIP, SWIPE, MANUAL, CONTACTLESS_CHIP, CONTACTLESS_SWIPE]

            if (builder.PaymentMethod is ICardData)
            {
                var cardData = builder.PaymentMethod as ICardData;

                var card = new JsonDoc()
                           .Set("number", cardData.Number)
                           .Set("expiry_month", cardData.ExpMonth.HasValue ? cardData.ExpMonth.ToString().PadLeft(2, '0') : null)
                           .Set("expiry_year", cardData.ExpYear.HasValue ? cardData.ExpYear.ToString().PadLeft(4, '0').Substring(2, 2) : null)
                           //.Set("track", "")
                           .Set("tag", builder.TagData)
                           .Set("cvv", cardData.Cvn)
                           .Set("cvv_indicator", EnumConverter.GetMapping(Target.GP_API, cardData.CvnPresenceIndicator)) // [ILLEGIBLE, NOT_PRESENT, PRESENT]
                           .Set("avs_address", builder.BillingAddress?.StreetAddress1)
                           .Set("avs_postal_code", builder.BillingAddress?.PostalCode)
                           .Set("funding", builder.PaymentMethod?.PaymentMethodType == PaymentMethodType.Debit ? "DEBIT" : "CREDIT") // [DEBIT, CREDIT]
                           .Set("authcode", builder.OfflineAuthCode);
                //.Set("brand_reference", "")

                card.Set("chip_condition", EnumConverter.GetMapping(Target.GP_API, builder.EmvChipCondition)); // [PREV_SUCCESS, PREV_FAILED]

                paymentMethod.Set("card", card);

                var tokenizationData = new JsonDoc()
                                       .Set("account_name", gateway.TokenizationAccountName)
                                       .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                       .Set("usage_mode", EnumConverter.GetMapping(Target.GP_API, builder.TokenUsageMode))
                                       .Set("name", "")
                                       .Set("card", card);

                if (builder.TransactionType == TransactionType.Tokenize)
                {
                    return(new GpApiRequest {
                        Verb = HttpMethod.Post,
                        Endpoint = "/payment-methods",
                        RequestBody = tokenizationData.ToString(),
                    });
                }
                else if (builder.TransactionType == TransactionType.Verify)
                {
                    if (builder.RequestMultiUseToken && string.IsNullOrEmpty((builder.PaymentMethod as ITokenizable).Token))
                    {
                        return(new GpApiRequest {
                            Verb = HttpMethod.Post,
                            Endpoint = "/payment-methods",
                            RequestBody = tokenizationData.ToString(),
                        });
                    }
                    else
                    {
                        var verificationData = new JsonDoc()
                                               .Set("account_name", gateway.TransactionProcessingAccountName)
                                               .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.Channel))
                                               .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                               .Set("currency", builder.Currency)
                                               .Set("country", gateway.Country)
                                               .Set("payment_method", paymentMethod);

                        if (builder.PaymentMethod is ITokenizable && !string.IsNullOrEmpty((builder.PaymentMethod as ITokenizable).Token))
                        {
                            verificationData.Remove("payment_method");
                            verificationData.Set("payment_method", new JsonDoc()
                                                 .Set("entry_mode", GetEntryMode(builder))
                                                 .Set("id", (builder.PaymentMethod as ITokenizable).Token)
                                                 );
                        }

                        return(new GpApiRequest {
                            Verb = HttpMethod.Post,
                            Endpoint = "/verifications",
                            RequestBody = verificationData.ToString(),
                        });
                    }
                }
            }
            else if (builder.PaymentMethod is ITrackData)
            {
                var track = builder.PaymentMethod as ITrackData;

                var card = new JsonDoc()
                           .Set("track", track.Value)
                           .Set("tag", builder.TagData)
                           .Set("avs_address", builder.BillingAddress?.StreetAddress1)
                           .Set("avs_postal_code", builder.BillingAddress?.PostalCode)
                           .Set("authcode", builder.OfflineAuthCode);

                if (builder.TransactionType == TransactionType.Verify)
                {
                    paymentMethod.Set("card", card);

                    var verificationData = new JsonDoc()
                                           .Set("account_name", gateway.TransactionProcessingAccountName)
                                           .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.Channel))
                                           .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                           .Set("currency", builder.Currency)
                                           .Set("country", gateway.Country)
                                           .Set("payment_method", paymentMethod);

                    return(new GpApiRequest {
                        Verb = HttpMethod.Post,
                        Endpoint = "/verifications",
                        RequestBody = verificationData.ToString(),
                    });
                }

                if (builder.TransactionType == TransactionType.Sale || builder.TransactionType == TransactionType.Refund)
                {
                    if (string.IsNullOrEmpty(track.Value))
                    {
                        card.Set("number", track.Pan);
                        card.Set("expiry_month", track.Expiry?.Substring(2, 2));
                        card.Set("expiry_year", track.Expiry?.Substring(0, 2));
                    }
                    if (string.IsNullOrEmpty(builder.TagData))
                    {
                        card.Set("chip_condition", EnumConverter.GetMapping(Target.GP_API, builder.EmvChipCondition)); // [PREV_SUCCESS, PREV_FAILED]
                    }
                }

                if (builder.TransactionType == TransactionType.Sale)
                {
                    card.Set("funding", builder.PaymentMethod?.PaymentMethodType == PaymentMethodType.Debit ? "DEBIT" : "CREDIT"); // [DEBIT, CREDIT]
                }

                paymentMethod.Set("card", card);
            }

            // payment method storage mode
            if (builder.RequestMultiUseToken)
            {
                //ToDo: there might be a typo: should be storage_mode
                paymentMethod.Set("storage_model", "ON_SUCCESS");
            }

            // tokenized payment method
            if (builder.PaymentMethod is ITokenizable)
            {
                string token = ((ITokenizable)builder.PaymentMethod).Token;
                if (!string.IsNullOrEmpty(token))
                {
                    paymentMethod.Set("id", token);
                }
            }

            // pin block
            if (builder.PaymentMethod is IPinProtected)
            {
                paymentMethod.Get("card")?.Set("pin_block", ((IPinProtected)builder.PaymentMethod).PinBlock);
            }

            // authentication
            if (builder.PaymentMethod is CreditCardData)
            {
                paymentMethod.Set("name", (builder.PaymentMethod as CreditCardData).CardHolderName);

                var secureEcom = (builder.PaymentMethod as CreditCardData).ThreeDSecure;
                if (secureEcom != null)
                {
                    var three_ds = new JsonDoc()
                                   // Indicates the version of 3DS
                                   .Set("message_version", secureEcom.MessageVersion)
                                   // An indication of the degree of the authentication and liability shift obtained for this transaction.
                                   // It is determined during the 3D Secure process.
                                   .Set("eci", secureEcom.Eci)
                                   // The authentication value created as part of the 3D Secure process.
                                   .Set("value", secureEcom.AuthenticationValue)
                                   // The reference created by the 3DSecure provider to identify the specific authentication attempt.
                                   .Set("server_trans_ref", secureEcom.ServerTransactionId)
                                   // The reference created by the 3DSecure Directory Server to identify the specific authentication attempt.
                                   .Set("ds_trans_ref", secureEcom.DirectoryServerTransactionId);

                    var authentication = new JsonDoc().Set("three_ds", three_ds);

                    paymentMethod.Set("authentication", authentication);
                }
            }

            // encryption
            if (builder.PaymentMethod is IEncryptable)
            {
                var encryptionData = ((IEncryptable)builder.PaymentMethod).EncryptionData;

                if (encryptionData != null)
                {
                    var encryption = new JsonDoc()
                                     .Set("version", encryptionData.Version);

                    if (!string.IsNullOrEmpty(encryptionData.KTB))
                    {
                        encryption.Set("method", "KTB");
                        encryption.Set("info", encryptionData.KTB);
                    }
                    else if (!string.IsNullOrEmpty(encryptionData.KSN))
                    {
                        encryption.Set("method", "KSN");
                        encryption.Set("info", encryptionData.KSN);
                    }

                    if (encryption.Has("info"))
                    {
                        paymentMethod.Set("encryption", encryption);
                    }
                }
            }

            var data = new JsonDoc()
                       .Set("account_name", gateway.TransactionProcessingAccountName)
                       .Set("type", builder.TransactionType == TransactionType.Refund ? "REFUND" : "SALE") // [SALE, REFUND]
                       .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.Channel))           // [CP, CNP]
                       .Set("capture_mode", GetCaptureMode(builder))                                       // [AUTO, LATER, MULTIPLE]
                                                                                                           //.Set("remaining_capture_count", "") //Pending Russell
                       .Set("authorization_mode", builder.AllowPartialAuth ? "PARTIAL" : null)
                       .Set("amount", builder.Amount.ToNumericCurrencyString())
                       .Set("currency", builder.Currency)
                       .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                       .Set("description", builder.Description)
                       //.Set("order_reference", builder.OrderId)
                       .Set("gratuity_amount", builder.Gratuity.ToNumericCurrencyString())
                       .Set("cashback_amount", builder.CashBackAmount.ToNumericCurrencyString())
                       .Set("surcharge_amount", builder.SurchargeAmount.ToNumericCurrencyString())
                       .Set("convenience_amount", builder.ConvenienceAmount.ToNumericCurrencyString())
                       .Set("country", gateway.Country)
                       //.Set("language", EnumConverter.GetMapping(Target.GP_API, Language))
                       .Set("ip_address", builder.CustomerIpAddress)
                       //.Set("site_reference", "") //
                       .Set("payment_method", paymentMethod);

            // set order reference
            if (!string.IsNullOrEmpty(builder.OrderId))
            {
                var order = new JsonDoc()
                            .Set("reference", builder.OrderId);

                data.Set("order", order);
            }

            // stored credential
            if (builder.StoredCredential != null)
            {
                data.Set("initiator", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Initiator));
                var storedCredential = new JsonDoc()
                                       .Set("model", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Type))
                                       .Set("reason", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Reason))
                                       .Set("sequence", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Sequence));
                data.Set("stored_credential", storedCredential);
            }

            return(new GpApiRequest {
                Verb = HttpMethod.Post,
                Endpoint = "/transactions",
                RequestBody = data.ToString(),
            });
        }
Example #2
0
        private JsonDoc BuildPaymentMethod(JsonDoc request, RecurringPaymentMethod payment, TransactionType type)
        {
            if (payment != null)
            {
                request.Set("preferredPayment", payment.PreferredPayment);
                request.Set("paymentMethodIdentifier", payment.Id);
                request.Set("customerKey", payment.CustomerKey);
                request.Set("nameOnAccount", payment.NameOnAccount);
                BuildAddress(request, payment.Address);

                if (type == TransactionType.Create)
                {
                    string  tokenValue  = null;
                    var     hasToken    = HasToken(payment.PaymentMethod, out tokenValue);
                    JsonDoc paymentInfo = null;
                    if (payment.PaymentMethod is ICardData)
                    {
                        var method = payment.PaymentMethod as ICardData;
                        paymentInfo = request.SubElement(hasToken ? "alternateIdentity" : "card")
                                      .Set("type", hasToken ? "SINGLEUSETOKEN" : null)
                                      .Set(hasToken ? "token" : "number", hasToken ? tokenValue : method.Number)
                                      .Set("expMon", method.ExpMonth)
                                      .Set("expYear", method.ExpYear);
                        request.Set("cardVerificationValue", method.Cvn);
                    }
                    else if (payment.PaymentMethod is ITrackData)
                    {
                        var method = payment.PaymentMethod as ITrackData;
                        paymentInfo = request.SubElement("track")
                                      .Set("data", method.Value)
                                      .Set("dataEntryMode", method.EntryMethod.ToString().ToUpper());
                    }
                    else if (payment.PaymentMethod is eCheck)
                    {
                        var check = payment.PaymentMethod as eCheck;
                        request.Set("achType", check.AccountType.ToInitialCase())
                        .Set("accountType", check.CheckType.ToInitialCase())
                        .Set("telephoneIndicator", (check.SecCode == SecCode.CCD || check.SecCode == SecCode.PPD) ? false : true)
                        .Set("routingNumber", check.RoutingNumber)
                        .Set("accountNumber", check.AccountNumber)
                        .Set("accountHolderYob", check.BirthYear.ToString())
                        .Set("driversLicenseState", check.DriversLicenseState)
                        .Set("driversLicenseNumber", check.DriversLicenseNumber)
                        .Set("socialSecurityNumberLast4", check.SsnLast4);
                        request.Remove("country");
                    }

                    if (payment.PaymentMethod is IEncryptable)
                    {
                        var enc = (payment.PaymentMethod as IEncryptable).EncryptionData;
                        if (enc != null)
                        {
                            paymentInfo.Set("trackNumber", enc.TrackNumber);
                            paymentInfo.Set("key", enc.KTB);
                            paymentInfo.Set("encryptionType", "E3");
                        }
                    }
                }
                else   // EDIT FIELDS
                {
                    request.Remove("customerKey");
                    request.Set("paymentStatus", payment.Status);
                    request.Set("cpcTaxType", payment.TaxType);
                    request.Set("expirationDate", payment.ExpirationDate);
                }
            }
            return(request);
        }
        internal static GpApiRequest BuildRequest(AuthorizationBuilder builder, GpApiConnector gateway)
        {
            var merchantUrl   = !string.IsNullOrEmpty(gateway.GpApiConfig.MerchantId) ? $"/merchants/{gateway.GpApiConfig.MerchantId}" : string.Empty;
            var paymentMethod = new JsonDoc()
                                .Set("entry_mode", GetEntryMode(builder, gateway.GpApiConfig.Channel)); // [MOTO, ECOM, IN_APP, CHIP, SWIPE, MANUAL, CONTACTLESS_CHIP, CONTACTLESS_SWIPE]

            paymentMethod.Set("narrative", !string.IsNullOrEmpty(builder.DynamicDescriptor) ? builder.DynamicDescriptor : null);
            if (builder.PaymentMethod is CreditCardData && (builder.TransactionModifier == TransactionModifier.EncryptedMobile || builder.TransactionModifier == TransactionModifier.DecryptedMobile))
            {
                var digitalWallet  = new JsonDoc();
                var creditCardData = (builder.PaymentMethod as CreditCardData);
                //Digital Wallet
                if (builder.TransactionModifier == TransactionModifier.EncryptedMobile)
                {
                    digitalWallet
                    .Set("payment_token", JsonDoc.Parse(creditCardData.Token));
                }
                else if (builder.TransactionModifier == TransactionModifier.DecryptedMobile)
                {
                    var tokenFormat = DigitalWalletTokenFormat.CARD_NUMBER;
                    digitalWallet
                    .Set("token", creditCardData.Token)
                    .Set("token_format", DigitalWalletTokenFormat.CARD_NUMBER)
                    .Set("expiry_month", creditCardData.ExpMonth.HasValue ? creditCardData.ExpMonth.ToString().PadLeft(2, '0') : null)
                    .Set("expiry_year", creditCardData.ExpYear.HasValue ? creditCardData.ExpYear.ToString().PadLeft(4, '0').Substring(2, 2) : null)
                    .Set("cryptogram", creditCardData.Cryptogram)
                    .Set("eci", creditCardData.Eci);
                }
                digitalWallet.Set("provider", (builder.PaymentMethod as CreditCardData).MobileType);
                paymentMethod.Set("digital_wallet", digitalWallet);
            }
            else
            {
                if (builder.PaymentMethod is ICardData)
                {
                    var cardData = builder.PaymentMethod as ICardData;

                    var card = new JsonDoc()
                               .Set("number", cardData.Number)
                               .Set("expiry_month", cardData.ExpMonth.HasValue ? cardData.ExpMonth.ToString().PadLeft(2, '0') : null)
                               .Set("expiry_year", cardData.ExpYear.HasValue ? cardData.ExpYear.ToString().PadLeft(4, '0').Substring(2, 2) : null)
                               //.Set("track", "")
                               .Set("tag", builder.TagData)
                               .Set("cvv", cardData.Cvn)
                               .Set("avs_address", builder.BillingAddress?.StreetAddress1)
                               .Set("avs_postal_code", builder.BillingAddress?.PostalCode)
                               .Set("authcode", builder.OfflineAuthCode)
                               .Set("brand_reference", builder.CardBrandTransactionId);

                    card.Set("chip_condition", EnumConverter.GetMapping(Target.GP_API, builder.EmvChipCondition)); // [PREV_SUCCESS, PREV_FAILED]

                    if (!(builder.TransactionType == TransactionType.Tokenize || builder.TransactionType == TransactionType.Verify))
                    {
                        card.Set("cvv_indicator", cardData.CvnPresenceIndicator != 0 ? EnumConverter.GetMapping(Target.GP_API, cardData.CvnPresenceIndicator) : null); // [ILLEGIBLE, NOT_PRESENT, PRESENT]
                        card.Set("funding", builder.PaymentMethod?.PaymentMethodType == PaymentMethodType.Debit ? "DEBIT" : "CREDIT");                                 // [DEBIT, CREDIT]
                    }

                    var hasToken = builder.PaymentMethod is ITokenizable tokenData && !string.IsNullOrEmpty(tokenData.Token);

                    if (!hasToken)
                    {
                        paymentMethod.Set("card", card);
                    }


                    if (builder.TransactionType == TransactionType.Tokenize)
                    {
                        var tokenizationData = new JsonDoc()
                                               .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TokenizationAccountName)
                                               .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                               .Set("usage_mode", EnumConverter.GetMapping(Target.GP_API, builder.PaymentMethodUsageMode))
                                               .Set("card", card);

                        return(new GpApiRequest {
                            Verb = HttpMethod.Post,
                            Endpoint = $"{merchantUrl}/payment-methods",
                            RequestBody = tokenizationData.ToString(),
                        });
                    }
                    else if (builder.TransactionType == TransactionType.DccRateLookup)
                    {
                        // tokenized payment method
                        if (builder.PaymentMethod is ITokenizable)
                        {
                            string token = ((ITokenizable)builder.PaymentMethod).Token;
                            if (!string.IsNullOrEmpty(token))
                            {
                                paymentMethod.Set("id", token);
                            }
                        }

                        var RequestData = new JsonDoc()
                                          .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TransactionProcessingAccountName)
                                          .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.GpApiConfig.Channel))
                                          .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                          .Set("amount", builder.Amount.ToNumericCurrencyString())
                                          .Set("currency", builder.Currency)
                                          .Set("country", gateway.GpApiConfig.Country)
                                          .Set("payment_method", paymentMethod);

                        return(new GpApiRequest
                        {
                            Verb = HttpMethod.Post,
                            Endpoint = $"{merchantUrl}/currency-conversions",
                            RequestBody = RequestData.ToString(),
                        });
                    }
                    else if (builder.TransactionType == TransactionType.Verify)
                    {
                        if (builder.RequestMultiUseToken && string.IsNullOrEmpty((builder.PaymentMethod as ITokenizable).Token))
                        {
                            var tokenizationData = new JsonDoc()
                                                   .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TokenizationAccountName)
                                                   .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                                   .Set("usage_mode", EnumConverter.GetMapping(Target.GP_API, builder.PaymentMethodUsageMode))
                                                   .Set("fingerprint_mode", builder.CustomerData?.DeviceFingerPrint ?? null)
                                                   .Set("card", card);

                            return(new GpApiRequest {
                                Verb = HttpMethod.Post,
                                Endpoint = $"{merchantUrl}/payment-methods",
                                RequestBody = tokenizationData.ToString(),
                            });
                        }
                        else
                        {
                            var verificationData = new JsonDoc()
                                                   .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TransactionProcessingAccountName)
                                                   .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.GpApiConfig.Channel))
                                                   .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                                   .Set("currency", builder.Currency)
                                                   .Set("country", gateway.GpApiConfig.Country)
                                                   .Set("payment_method", paymentMethod);

                            if (builder.PaymentMethod is ITokenizable && !string.IsNullOrEmpty((builder.PaymentMethod as ITokenizable).Token))
                            {
                                verificationData.Remove("payment_method");
                                verificationData.Set("payment_method", new JsonDoc()
                                                     .Set("entry_mode", GetEntryMode(builder, gateway.GpApiConfig.Channel))
                                                     .Set("id", (builder.PaymentMethod as ITokenizable).Token)
                                                     .Set("fingerprint_mode", builder.CustomerData?.DeviceFingerPrint ?? null)
                                                     );
                            }

                            return(new GpApiRequest {
                                Verb = HttpMethod.Post,
                                Endpoint = $"{merchantUrl}/verifications",
                                RequestBody = verificationData.ToString(),
                            });
                        }
                    }
                }
                else if (builder.PaymentMethod is ITrackData)
                {
                    var track = builder.PaymentMethod as ITrackData;

                    var card = new JsonDoc()
                               .Set("track", track.Value)
                               .Set("tag", builder.TagData)
                               .Set("avs_address", builder.BillingAddress?.StreetAddress1)
                               .Set("avs_postal_code", builder.BillingAddress?.PostalCode)
                               .Set("authcode", builder.OfflineAuthCode);

                    if (builder.TransactionType == TransactionType.Verify)
                    {
                        paymentMethod.Set("card", card);

                        var verificationData = new JsonDoc()
                                               .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TransactionProcessingAccountName)
                                               .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.GpApiConfig.Channel))
                                               .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                                               .Set("currency", builder.Currency)
                                               .Set("country", gateway.GpApiConfig.Country)
                                               .Set("payment_method", paymentMethod)
                                               .Set("fingerprint_mode", builder.CustomerData?.DeviceFingerPrint ?? null);

                        return(new GpApiRequest {
                            Verb = HttpMethod.Post,
                            Endpoint = $"{merchantUrl}/verifications",
                            RequestBody = verificationData.ToString(),
                        });
                    }

                    if (builder.TransactionType == TransactionType.Sale || builder.TransactionType == TransactionType.Refund)
                    {
                        if (string.IsNullOrEmpty(track.Value))
                        {
                            card.Set("number", track.Pan);
                            card.Set("expiry_month", track.Expiry?.Substring(2, 2));
                            card.Set("expiry_year", track.Expiry?.Substring(0, 2));
                        }
                        if (string.IsNullOrEmpty(builder.TagData))
                        {
                            card.Set("chip_condition", EnumConverter.GetMapping(Target.GP_API, builder.EmvChipCondition)); // [PREV_SUCCESS, PREV_FAILED]
                        }
                    }

                    if (builder.TransactionType == TransactionType.Sale)
                    {
                        card.Set("funding", builder.PaymentMethod?.PaymentMethodType == PaymentMethodType.Debit ? "DEBIT" : "CREDIT"); // [DEBIT, CREDIT]
                    }

                    paymentMethod.Set("card", card);
                }

                // tokenized payment method
                if (builder.PaymentMethod is ITokenizable)
                {
                    string token = ((ITokenizable)builder.PaymentMethod).Token;
                    if (!string.IsNullOrEmpty(token))
                    {
                        paymentMethod.Set("id", token);
                    }
                }
            }
            // payment method storage mode
            if (builder.RequestMultiUseToken)
            {
                //ToDo: there might be a typo: should be storage_mode
                paymentMethod.Set("storage_mode", "ON_SUCCESS");
            }

            // pin block
            if (builder.PaymentMethod is IPinProtected)
            {
                paymentMethod.Get("card")?.Set("pin_block", ((IPinProtected)builder.PaymentMethod).PinBlock);
            }

            // authentication
            if (builder.PaymentMethod is CreditCardData)
            {
                paymentMethod.Set("name", (builder.PaymentMethod as CreditCardData).CardHolderName);

                var secureEcom = (builder.PaymentMethod as CreditCardData).ThreeDSecure;
                if (secureEcom != null)
                {
                    var authentication = new JsonDoc().Set("id", secureEcom.ServerTransactionId);

                    paymentMethod.Set("authentication", authentication);
                }

                paymentMethod.Set("fingerprint_mode", builder.CustomerData?.DeviceFingerPrint ?? null);
            }

            if (builder.PaymentMethod is EBT)
            {
                paymentMethod.Set("name", (builder.PaymentMethod as EBT).CardHolderName);
            }

            if (builder.PaymentMethod is eCheck)
            {
                eCheck check = (builder.PaymentMethod as eCheck);
                paymentMethod.Set("name", check.CheckHolderName);

                var bankTransfer = new JsonDoc()
                                   .Set("account_number", check.AccountNumber)
                                   .Set("account_type", (check.AccountType != null) ? EnumConverter.GetMapping(Target.GP_API, check.AccountType) : null)
                                   .Set("check_reference", check.CheckReference)
                                   .Set("sec_code", check.SecCode)
                                   .Set("narrative", check.MerchantNotes);

                var bank = new JsonDoc()
                           .Set("code", check.RoutingNumber)
                           .Set("name", check.BankName);

                var address = new JsonDoc()
                              .Set("line_1", check.BankAddress?.StreetAddress1)
                              .Set("line_2", check.BankAddress?.StreetAddress2)
                              .Set("line_3", check.BankAddress?.StreetAddress3)
                              .Set("city", check.BankAddress?.City)
                              .Set("postal_code", check.BankAddress?.PostalCode)
                              .Set("state", check.BankAddress?.State)
                              .Set("country", check.BankAddress?.CountryCode);

                bank.Set("address", address);

                bankTransfer.Set("bank", bank);

                paymentMethod.Set("bank_transfer", bankTransfer);
            }

            if (builder.PaymentMethod is AlternativePaymentMethod)
            {
                var alternatepaymentMethod = (AlternativePaymentMethod)builder.PaymentMethod;

                paymentMethod.Set("name", alternatepaymentMethod.AccountHolderName);

                var apm = new JsonDoc()
                          .Set("provider", alternatepaymentMethod.AlternativePaymentMethodType?.ToString()?.ToLower())
                          .Set("address_override_mode", alternatepaymentMethod.AddressOverrideMode);
                paymentMethod.Set("apm", apm);
            }

            // encryption
            if (builder.PaymentMethod is IEncryptable)
            {
                var encryptionData = ((IEncryptable)builder.PaymentMethod).EncryptionData;

                if (encryptionData != null)
                {
                    var encryption = new JsonDoc()
                                     .Set("version", encryptionData.Version);

                    if (!string.IsNullOrEmpty(encryptionData.KTB))
                    {
                        encryption.Set("method", "KTB");
                        encryption.Set("info", encryptionData.KTB);
                    }
                    else if (!string.IsNullOrEmpty(encryptionData.KSN))
                    {
                        encryption.Set("method", "KSN");
                        encryption.Set("info", encryptionData.KSN);
                    }

                    if (encryption.Has("info"))
                    {
                        paymentMethod.Set("encryption", encryption);
                    }
                }
            }

            if (builder.TransactionType == TransactionType.Create && builder.PayLinkData is PayLinkData)
            {
                var payLinkData = builder.PayLinkData;
                var requestData = new JsonDoc()
                                  .Set("usage_limit", payLinkData.UsageLimit.ToString())
                                  .Set("usage_mode", EnumConverter.GetMapping(Target.GP_API, payLinkData.UsageMode))
                                  .Set("images", payLinkData.Images)
                                  .Set("description", builder.Description ?? null)
                                  .Set("type", payLinkData.Type?.ToString())
                                  .Set("expiration_date", payLinkData.ExpirationDate ?? null);

                var transaction = new JsonDoc()
                                  .Set("country", gateway.GpApiConfig.Country)
                                  .Set("amount", builder.Amount.ToNumericCurrencyString())
                                  .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.GpApiConfig.Channel))
                                  .Set("currency", builder.Currency)
                                  .Set("allowed_payment_methods", GetAllowedPaymentMethod(payLinkData.AllowedPaymentMethods));

                requestData.Set("transactions", transaction)
                .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                .Set("shipping_amount", payLinkData.ShippingAmount.ToNumericCurrencyString())
                .Set("shippable", payLinkData.IsShippable?.ToString() ?? false.ToString())
                .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TransactionProcessingAccountName)
                .Set("name", payLinkData.Name ?? null);

                var notification = new JsonDoc()
                                   .Set("cancel_url", payLinkData.CancelUrl)
                                   .Set("return_url", payLinkData.ReturnUrl)
                                   .Set("status_url", payLinkData.StatusUpdateUrl);

                requestData.Set("notifications", notification)
                .Set("status", payLinkData.Status.ToString());

                return(new GpApiRequest
                {
                    Verb = HttpMethod.Post,
                    Endpoint = $"{merchantUrl}/links",
                    RequestBody = requestData.ToString(),
                });
            }

            var data = new JsonDoc()
                       .Set("account_name", gateway.GpApiConfig.AccessTokenInfo.TransactionProcessingAccountName)
                       .Set("type", builder.TransactionType == TransactionType.Refund ? "REFUND" : "SALE")   // [SALE, REFUND]
                       .Set("channel", EnumConverter.GetMapping(Target.GP_API, gateway.GpApiConfig.Channel)) // [CP, CNP]
                       .Set("capture_mode", GetCaptureMode(builder))                                         // [AUTO, LATER, MULTIPLE]
                                                                                                             //.Set("remaining_capture_count", "") //Pending Russell
                       .Set("authorization_mode", builder.AllowPartialAuth ? "PARTIAL" : null)
                       .Set("amount", builder.Amount.ToNumericCurrencyString())
                       .Set("currency", builder.Currency)
                       .Set("reference", builder.ClientTransactionId ?? Guid.NewGuid().ToString())
                       .Set("description", builder.Description)
                       //.Set("order_reference", builder.OrderId)
                       .Set("gratuity_amount", builder.Gratuity.ToNumericCurrencyString())
                       .Set("cashback_amount", builder.CashBackAmount.ToNumericCurrencyString())
                       .Set("surcharge_amount", builder.SurchargeAmount.ToNumericCurrencyString())
                       .Set("convenience_amount", builder.ConvenienceAmount.ToNumericCurrencyString())
                       .Set("country", gateway.GpApiConfig.Country)
                       //.Set("language", EnumConverter.GetMapping(Target.GP_API, Language))
                       .Set("ip_address", builder.CustomerIpAddress)
                       //.Set("site_reference", "") //
                       .Set("currency_conversion", !string.IsNullOrEmpty(builder.DccRateData?.DccId) ? new JsonDoc().Set("id", builder.DccRateData.DccId) : null)
                       .Set("payment_method", paymentMethod)
                       .Set("link", !string.IsNullOrEmpty(builder.PaymentLinkId) ? new JsonDoc()
                            .Set("id", builder.PaymentLinkId) : null);

            if (builder.PaymentMethod is eCheck || builder.PaymentMethod is AlternativePaymentMethod)
            {
                data.Set("payer", SetPayerInformation(builder));
            }

            // set order reference
            if (!string.IsNullOrEmpty(builder.OrderId))
            {
                var order = new JsonDoc()
                            .Set("reference", builder.OrderId);

                data.Set("order", order);
            }

            if (builder.PaymentMethod is AlternativePaymentMethod)
            {
                setOrderInformation(builder, ref data);

                var alternatepaymentMethod = (AlternativePaymentMethod)builder.PaymentMethod;

                var notifications = new JsonDoc()
                                    .Set("return_url", alternatepaymentMethod?.ReturnUrl)
                                    .Set("status_url", alternatepaymentMethod?.StatusUpdateUrl)
                                    .Set("cancel_url", alternatepaymentMethod?.CancelUrl);

                data.Set("notifications", notifications);
            }

            // stored credential
            if (builder.StoredCredential != null)
            {
                data.Set("initiator", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Initiator));
                var storedCredential = new JsonDoc()
                                       .Set("model", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Type))
                                       .Set("reason", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Reason))
                                       .Set("sequence", EnumConverter.GetMapping(Target.GP_API, builder.StoredCredential.Sequence));
                data.Set("stored_credential", storedCredential);
            }

            return(new GpApiRequest {
                Verb = HttpMethod.Post,
                Endpoint = $"{merchantUrl}/transactions",
                RequestBody = data.ToString(),
            });
        }