API – Developers Docs API – Developers Docs
  • Cyberpac
  • Addon Payments
  • Pagos integrados en TPV
  • Inglés
API – Developers Docs API – Developers Docs
API – Developers Docs
  • Cyberpac
  • Addon Payments
  • Pagos integrados en TPV
  • Inglés

Addon Payments

  • Icono de carpeta cerrada Icono de apertura de carpetaIntegraciones
    • Empieza a integrar
      • Bienvenida para las integraciones en CMS
      • Introducción a las integraciones: Hosted, Host2Host y JavaScript
    • Plugins para CMS
      • PrestaShop
        • Instalación y configuración de PrestaShop
        • Errores frecuentes en la instalación y configuración de PrestaShop
        • Gestión de transacciones en PrestaShop
      • WooCommerce
        • Instalación y configuración de WooCommerce
        • Errores frecuentes en la instalación y configuración de WooCommerce
        • Gestión de transacciones en WooCommerce
      • Magento
        • Instalación y configuración de Magento
        • Errores frecuentes en la instalación y configuración de Magento
        • Gestión de transacciones en Magento
      • Salesforce
        • Salesforce Commerce Cloud
    • Tarjetas
      • Integración Hosted
      • Integración Host2Host
      • Integración JavaScript
      • PSD2 y 3DSv2
      • Certificación PCI DSS
    • Complementa tu integración
      • Funcionalidades adicionales
      • Gestión de las notificaciones
      • Complementa la integración JavaScript
      • Personalización de la experiencia de pago
      • Pase a Producción
      • Cifrado, firma y envío de la petición
      • Redirección del cliente
    • Métodos de pago
      • Apple Pay
      • PayByBank
      • Amex
      • PayPal
      • Worldpay
      • Bizum
      • PeX
      • Quix
    • Recursos
      • Glosario
      • Soluciones de pago
      • Códigos de respuesta
      • Códigos de países y estados
      • Códigos de divisa
      • Códigos y validaciones del tipo de documento identificativo
      • Tarjetas para pruebas
    • Herramientas
      • Cifrado y descifrado
      • Postman
      • SDKs
  • Icono de carpeta cerrada Icono de apertura de carpetaPortal BackOffice
    • Guía de uso de Pago por Enlace
    • Consulta de operaciones
    • Creación de usuarios
  • Icono de carpeta cerrada Icono de apertura de carpetaConsultas frecuentes

Cifrado, firma y envío de la petición

Introducción

En esta guía se explicará cómo cifrar, firmar y enviar la petición para las integraciones vía Hosted y Host2Host. 

    • Hosted
    • Host2Host

Además, dispones de una herramienta de cifrado o descifrado para que puedas probar tú mismo el proceso que se va a explicar a continuación:

Herramienta de cifrado

Endpoints y elementos de las peticiones

Disponemos de dos entornos a los que puedes enviar las peticiones:

EntornoHostedHost2Host
Staginghttps://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize
https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/pay

Producciónhttps://checkout.addonpayments.com/EPGCheckout/rest/online/tokenize
https://checkout.addonpayments.com/EPGCheckout/rest/online/pay

Las peticiones se componen de 3 parámetros:

ParámetroDescripción
merchantIdEl identificador único de tu comercio
encryptedCadena de parámetros cifrada en AES-256-CBC cifrada
integrityCheckSHA256 de la cadena de parámetros

En la petición, deberás incorporar las siguientes cabeceras: 

CabeceraValor
apiVersion5
encryptionModeCBC
ivVector de inicialización codificado en Base64

A continuación, dejamos un ejemplo de código cURL para una transacción Hosted en la URL del entorno Staging (pruebas) de Addon Payments. Puedes optar por enviar los parámetros como form (primera pestaña) o en la URL (segunda pestaña).

				
					curl --location --request POST 'https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize' \
--header 'apiVersion: 5' \
--header 'encryptionMode: CBC' \
--header 'iv: 0Pn6pDEm73YvekNKUJcvwg==' \
--form 'merchantId="12345"' \
--form 'encrypted="jULXEtDfSVYIgfV29GBTcibe+ED+IvnfI2ssayrpqoJRzmI+SVst1SV3LRjt7DHlU5+0FoBPZy8KfoajNYn6DwRU0ltMtgd2TsR2ccm+Aeg5NAPbMlVZZnDmWA2WUmh3sXFWDMFGcHnwigMv0dWW+0QOieFJN+NLPMo/HMhLOLNNfS9240qdT++PTx7IdtSM3hfbD31ZDgKSkxwCDQYSrcIS0LyPtRuRkMQjHNMjOzo/FNSe0dqTdRw0dI5QpoqAgFk8MEkByIiZPIK6GYzkRv9NsBrVpRw3271VPG7gDlK4+ZEkjRXJ+JQgV0QxybU4XNE1pPlB3BxzBtsr56gPEVCNrVjNQtfTwNqphT39+7GShtEUrAsKU7r+nxivGxhd/8b2ECkk/7Dk7WPLnCJPnXJrIAWzKd1wiPaTPYrMvCuxRAMYF+sk6ZPENAipntbetAbXHDVs6KKbjyCjDLRwGX7rrIlPi0TTIH9nGfPTq4DL1CDxivnjd1eOGOnHzQRr”' \
--form 'integrityCheck="0bc22b4408a6a2bf135fd2eb3832775f44b02f96d7e10d940b81c5069763685f"'
				
			
				
					curl --location --request POST 'https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize?merchantId=123456&encrypted=f5VA44JsAT….zy+wzcQZVu&integrityCheck=050879….aeef51' \
--header 'apiVersion: 5' \
--header 'encryptionMode: CBC' \
--header 'iv: NdQ2zQstp/OGDBBUnuPoAA==' \
				
			

Cifrado de la petición

Estos son los pasos para el cifrado de la petición:

  1. Formar una cadena concatenando los parámetros de la petición
  2. Cifrar en AES-256-CBC la cadena de parámetros del punto 1 para obtener el encrypted
  3. Hacer un SHA256 de la cadena del punto 1 para obtener el integrityCheck

Aquí tienes un ejemplo de cadena antes de cifrar:

				
					merchantId:"12345"
merchantTransactionId:"47725685"
amount:"10.00"
currency:"EUR"
country:"ES"
customerId:"60426139"
paymentSolution:"creditcards"
productId:"123450001"
operationType:"DEBIT"
statusURL:"https://micomercio.com/recepcion_notificacion.php"
successURL:"https://micomercio.com/url_ok"
errorURL:"https://micomercio.com/url_ko"
cancelURL:"https://micomercio.com/url_cancel"
				
			

Formateado de la petición en codificación URL

La petición debe ir formateada en codificación URL y UTF 8 posterior. Esto nos devuelve una cadena en formato: “param1=valor1&param2=valor2&…&paramN=valorN”. Con los datos de la petición anterior, el resultado sería:

				
					merchantId=12345&merchantTransactionId=47725685&amount=10.00&currency=EUR&country
=ES&customerId=60426139&paymentSolution=creditcards&productId=123450001&operationType
=DEBIT&statusURL=https%3A%2F%2Fmicomercio.com%2Frecepcion_notificacion.php&successURL
=https%3A%2F%2Fmicomercio.com%2Furl_ok&errorURL=https%3A%2F%2Fmicomercio
.com%2Furl_ko&cancelURL=https%3A%2F%2Fmicomercio.com%2Furl_cancel
				
			

Generación de un vector de inicialización aleatorio

Antes de cifrar la petición debes generar un vector de inicialización de 16 bytes (128 bits).

				
					NdQ2zQstp/OGDBBUnuPoAA==
				
			

Cifrado AES-256-CBC de la petición

Para cifrar correctamente la petición es necesario disponer de:

  • Contraseña del comercio para usarla como clave de cifrado, correspondiente al entorno al cual se va a enviar la petición. Para el entorno de Staging la recibes en el correo de bienvenida, para el entorno de Producción la debes recuperar desde el Portal BackOffice de Addon Payments. Consulta cómo en recuperarla en la guía de pase a Producción.
  • Petición formateada.
  • Vector de inicialización.

Teniendo todos los datos anteriores, hay que realizar un cifrado AES-256-CBC/PKCS5 o PKCS7 posterior de la petición formateada.

Usa el vector de inicialización en formato binario y la contraseña del comercio como clave de cifrado.

Con el vector de inicialización anterior en formato binario y esta contraseña de cifrado: 8e3ee351caa1813f8b72f68d89b25347,  el resultado es el siguiente:

				
					f5VA44JsATbuRetFjrwH2BJEWiLVrnS0WZlfnkVfAdVbyeye/mkhCqWX03bVv1glCBIuJmr4Todr8cJngUjR4O7bLazgcbi75ZT+gNosjQZCAXPCoAywe8WBAin5qaYGqst8S7FFekOrUqXItKO5+qELFfEFCrzyX1XAokXMVruAUHKCDusPi8xT7aJgQHnBabW02PSqJD6Qk+cGBoCoCaXmXoWsK51jigjoar++pViThvbs9756xnKqXH1l4pa4NkWKlVfEtM14E7rqzHS2S99e71/36TlfPz8FEXSA7H2sLOq38USxbkV0SEnPpVxFaegNQfsOY0kkjB7x1P3DKZMfkdeKQCBxMeHhHCveITK5TkQFxnlR8nCucZbXcC80YE2h4n7qEH2VyjIddBYmXhebWKXKoCgRLVuSCb2HVWL+DUN2f1mJmFJVYABewhJ+Wf3ToqyoSS52i2QbuOe29EnPHk1x9ijO5U+YEVxHcZCtpV1c5Uj8apwXVPiERkTTOMJ8sO9yPkOWI3Q8zwlRlw==
				
			

Recuerda que si eliges enviar los parámetros en la URL deberás codificar el valor de encrypted en URLencode.

Generación del «integrityCheck» de la petición

El último dato necesario antes de enviar la petición es la generación del «integrityCheck» de la petición formateada en codificación URL. Siguiendo el ejemplo anterior, la firma resultante es esta:

				
					E18C015E2E12131094A9123D582425DB29050DCDECBA8225968D198285A84D2Fd13223031afdeafe5825f518e5c495c9203c03583e4353560f1da50a99bd913e
				
			

Aquí tienes un diagrama que resume todo el proceso:

Ejemplos de código de cifrado, firma y envío de la petición

Estos son ejemplos de código del proceso de cifrado, firma y envío de la petición en PHP, JavaScript, Java, Python y C#. Estos ejemplos se aplican a las integraciones por Hosted/Redirección y por Host2Host.

				
					// Parámetros a cifrar
$http_query = http_build_query($data_array);
$formatted_request = utf8_encode($http_query);

// Genera un vector de inicialización
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC')); // Genera una cadena aleatoria de 16 bytes

$base64_iv = base64_encode($iv);

// Recuerda usar tu contraseña de comercio
$merchantPassword = '';
$encrypted= openssl_encrypt($formatted_request, 'AES-256-CBC', $merchantPassword, 0,
$iv);

// Integrity check usando HMAC-SHA256
$integrityCheck = hash('sha256', $formatted_request);

// Recuerda usar el endpoint adecuado
$url = '';

$data_url = [
    'merchantId' => $merchantId,
    'encrypted' => $encrypted,
    'integrityCheck' => $integrityCheck
];
$headers = [
    'apiVersion: 5',
    'encryptionMode: CBC',
    'iv: ' . $base64_iv
];

$ch = curl_init($url);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data_url));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);

curl_close($ch);
				
			
				
					const querystring = require('querystring');
const merchantTransactionId = ('00000000' + Math.floor(Math.random() * 100000000)).slice(-8);

// Parámetros a cifrar
var mandatoryData = {
    merchantId: '123456',
    merchantTransactionId: merchantTransactionId,
    amount: 30,
    currency: 'EUR',
    country: 'ES',
    paymentSolution: 'creditcards',
    customerId: '903,
}

var optionalData = {
    firstName: 'FirstName',
    lastName: 'LastName',
    customerEmail: 'email@micomercio.com',
    phoneCode: '34',
    telephone: '600000000',
    addressLine1: 'Line 1 customer address',
    addressLine2: 'Line 2 customer address',
    buildingName: 'Building',
    buildingNumber: '42',
    city: 'Barcelona',
    postCode: '08001',
    state: 'Barcelona',
    customerCountry: 'ES',
    customerNationalId: '9999999d9R',
    dob: '01-12-1999',
    chName: 'First name Last name',
    chFirstName: 'First name',
    chLastName: 'Last name',
    chEmail: 'correo@micomercio.com',
    chAddress1: 'Line 1 owner address',
    chAddress2: 'Line 2 owner address',
    chCity: 'Barcelona',
    chPostCode: '08001',
    chState: 'Barcelona',
    chCountry: 'ES',
    statusUrl: 'example.com/notif',
}

var data_array = {
    ...mandatoryData,
    ...optionalData
}

const formated_request = querystring.stringify(data_array);
console.log("Formated Request: ",formated_request);

// Clave de cifrado e IV
var encryptionKey = 'a723a2ce8ec3840c848d5914520c8199';
var iv = CryptoJS.lib.WordArray.random(16);

// Convierte el IV a base64
var base64_iv = iv.toString(CryptoJS.enc.Base64);

// Cifrado AES
var encrypted_request = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(formated_request), CryptoJS.enc.Utf8.parse(encryptionKey), {
    iv: CryptoJS.enc.Hex.parse(iv.toString()),
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});

// Integrity check usando HMAC-SHA256
var signature = CryptoJS.SHA256(formated_request).toString();
				
			
				
					    public static String url = "https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize";
    
    public static RequestModel getRequestModel() {
        RequestModel requestModel = new RequestModel();

        requestModel.setCurrency("EUR");
        requestModel.setAmount(30);
        requestModel.setCountry("ES");
        requestModel.setCustomerId(1);
        requestModel.setMerchantId(116659);
        requestModel.setMerchantTransactionId("23558434");
        requestModel.setPaymentSolution("creditcards");
        requestModel.setFirstName("FirstName");
        requestModel.setLastName("LastName");
        requestModel.setCustomerEmail("email@micomercio.com");
        requestModel.setPhoneCode("34");
        requestModel.setTelephone("600000000");
        requestModel.setAddressLine1("Line 1 customer address");
        requestModel.setAddressLine2("Line 2 customer address");
        requestModel.setBuildingName("Building");
        requestModel.setBuildingNumber("42");
        requestModel.setPostCode("08001");
        requestModel.setState("Barcelona");
        requestModel.setCity("Barcelona");
        requestModel.setCustomerCountry("ES");
        requestModel.setCustomerNationalId("9999999d9R");
        requestModel.setDob("01-12-1999");
        requestModel.setChName("First name Last name");
        requestModel.setChFirstName("First name");
        requestModel.setChLastName("Last name");
        requestModel.setChEmail("correo@micomercio.com");
        requestModel.setChAddress1("Line 1 owner address");
        requestModel.setChAddress2("Line 2 owner address");
        requestModel.setChCity("Barcelona");
        requestModel.setChPostCode("08001");
        requestModel.setChState("Barcelona");
        requestModel.setChCountry("ES");
        requestModel.setTopLogo("https://docs.globalpayments.es/wp-content/uploads/2022/12/globalpayments-logo-340x80-BLANCO.png");
        requestModel.setCheckoutTitle("AddonPayments");
        requestModel.setSuccessURL("https://redirection-test.mycompany.com/");

        return requestModel;
    }
    
    

    public byte[] generateIV() {
        Random random = new Random();
        byte[] iv = new byte[16];
        random.nextBytes(iv);
        return iv;
    }

    public String base64Encode(byte[] byteArray) {
        byte[] encodedBytes = Base64.getEncoder().encode(byteArray);
        return new String(encodedBytes);
    }

    public byte[] cbcEncryption(byte[] data, byte[] key, byte[] iv, Boolean encrypt) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
            if (encrypt) {
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            }

            return cipher.doFinal(data);
        } catch (NoSuchPaddingException | NoSuchAlgorithmException | IllegalBlockSizeException | BadPaddingException |
                 InvalidAlgorithmParameterException | InvalidKeyException exception) {
            exception.printStackTrace();
            return null;
        }
    }

    public byte[] hash256(byte[] data) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            return messageDigest.digest(data);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public void sendRequest() {
        try {
						
            String httpQuery = Utils.getInstance().buildQuery(RequestModel.class, Constants.getRequestModel());
            String finalQueryParameter = URLEncoder.encode(httpQuery, StandardCharsets.UTF_8).replace("%3D", "=").replace("%26", "&");
            byte[] formattedRequest = finalQueryParameter.getBytes(StandardCharsets.UTF_8);

            System.out.println("Formatted Query Parameters: " + finalQueryParameter);

            System.out.println(formattedRequest.length);

            byte[] clearIV = SecurityUtils.getInstance().generateIV();

            System.out.println("Hex Iv: " + HexUtils.getInstance().bytesToHex(clearIV));
            System.out.println("Base64 Iv: " + SecurityUtils.getInstance().base64Encode(clearIV));

            String key = HexUtils.getInstance().bytesToHex(Constants.encryptionKey.getBytes());
            System.out.println("key = " + key);

            byte[] encryptedRequest = SecurityUtils.getInstance().cbcEncryption(
                    formattedRequest, // formatted request
                    Constants.encryptionKey.getBytes(),
                    clearIV,
                    true
            );

            System.out.println("Base64 Encrypted Request: " + SecurityUtils.getInstance().base64Encode(encryptedRequest));

            byte[] signature = SecurityUtils.getInstance().hash256(formattedRequest);

            HttpUrl.Builder urlBuilder = HttpUrl.parse(Constants.url).newBuilder();
            urlBuilder.addQueryParameter("merchantId", String.valueOf(Constants.getRequestModel().getMerchantId()));
            urlBuilder.addQueryParameter("encrypted", SecurityUtils.getInstance().base64Encode(encryptedRequest));
            urlBuilder.addQueryParameter("integrityCheck", HexUtils.getInstance().bytesToHex(signature).toLowerCase());

            System.out.println("Signature = " + HexUtils.getInstance().bytesToHex(signature));

            Request request = new Request.Builder()
                    .url(urlBuilder.build().toString())
                    .addHeader("apiVersion", "3")
                    .addHeader("encryptionMode", "CBC")
                    .addHeader("iv", SecurityUtils.getInstance().base64Encode(clearIV))
                    .post(new FormBody.Builder().build())
                    .build();

            Call call = client.newCall(request);
            try (Response response = call.execute()) {
                System.out.println(response.body().string());
                System.out.println(response.code());
                System.out.println(response.message());
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
				
			
				
					EPG_GATEWAY = "https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize"

def build_payment_request(payment_data):
    payment = {
        'currency': payment_data["currency"],
        'amount': payment_data["amount"],
        'country': 'ES',
        'customerId': 1,
        'merchantId': '123456',
        'merchantTransactionId': 56168312,
        'paymentSolution': 'creditcards',
        'firstName': 'FirstName',
        'lastName': 'LastName',
        'customerEmail': 'email@micomercio.com',
        'phoneCode': '34',
        'telephone': '600000000',
        'addressLine1': 'Line 1 customer address',
        'addressLine2': 'Line 2 customer address',
        'buildingName': 'Building',
        'buildingNumber': '42',
        'city': 'Barcelona',
        'postCode': '08001',
        'state': 'Barcelona',
        'customerCountry': 'ES',
        'customerNationalId': '9999999d9R',
        'dob': '01-12-1999',
        'chName': 'First name Last name',
        'chFirstName': 'First name',
        'chLastName': 'Last name',
        'chEmail': 'correo@micomercio.com',
        'chAddress1': 'Line 1 owner address',
        'chAddress2': 'Line 2 owner address',
        'chCity': 'Barcelona',
        'chPostCode': '08001',
        'chState': 'Barcelona',
        'chCountry': 'ES',
        'topLogo': 'https://docs.globalpayments.es/wp-content/uploads/2022/12/globalpayments-logo-340x80-BLANCO.png',
        'checkoutTitle': 'AddonPayments',
        'successURL': 'https://redirection-test.mycompany.com/',
        'statusUrl': 'https://redirection-integration-2-py.epg-addonpayments-doc.xyz/notification',
    }

    formatted_data = urllib.parse.urlencode(payment)
    formatted_data_bytes = bytes(formatted_data, 'utf-8')
    signature = hashlib.sha256(formatted_data_bytes).hexdigest()

    random_iv_bytes = get_random_bytes(16)
    iv_hex_value = binascii.hexlify(random_iv_bytes)
    iv = binascii.unhexlify(iv_hex_value)
    key = binascii.unhexlify(binascii.hexlify('a723a2ce8ec3840c848d5914520c8199'.encode()).decode())

    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded_data = pad(formatted_data_bytes, AES.block_size)
    encrypted_data = cipher.encrypt(padded_data)
    b64_encrypted_data = base64.b64encode(encrypted_data)

    payment_request = {
        "formatted_request": formatted_data,
        "iv": iv_hex_value,
        "iv_b64": base64.b64encode(binascii.unhexlify(iv_hex_value)).decode(),
        "key": key,
        "signature": signature,
        "encrypted_result": b64_encrypted_data,
    }
    print(json.dumps(payment_request, default=str, indent=2))
    return payment_request
    
def process_payment(payment_data):
    payment_request_data = payment_processor.build_payment_request(payment_data)
    payment_response = send_payment_request(payment_request_data)
    return {"payment_url": payment_response} if payment_response else None


def send_payment_request(payment_request_data):
    url = EPG_GATEWAY
    params = {
        "merchantId": str(payment_const.MERCHANT_ID),
        "encrypted": payment_request_data["encrypted_result"],
        "integrityCheck": payment_request_data["signature"]
    }

    headers = {
        "apiVersion": "5",
        "encryptionMode": "CBC",
        "iv": payment_request_data["iv_b64"]
    }

    response = requests.post(url, params=params, headers=headers)
    print(f"Payment response code: {response.status_code}")
    return response.text if response.status_code == 200 else None
				
			
				
					static async Task Main(string[] args)
{
    Dictionary<string, string> paymentData = new Dictionary<string, string>
    {
        { "currency", "EUR" },
        { "amount", "30" },
    };

    Dictionary<string, string> payment = new Dictionary<string, string>
    {
        { "currency", paymentData["currency"] },
        { "amount", paymentData["amount"] },
        { "country", "ES" },
        { "customerId", "1" },
        { "merchantId", "123456" },
        { "merchantTransactionId", "53346159" },
        { "paymentSolution", "creditcards" },
        { "firstName", "FirstName" },
        { "lastName", "LastName" },
        { "customerEmail", "email@micomercio.com" },
        { "phoneCode", "34" },
        { "telephone", "600000000" },
        { "addressLine1", "Line 1 customer address" },
        { "addressLine2", "Line 2 customer address" },
        { "buildingName", "Building" },
        { "buildingNumber", "42" },
        { "city", "Barcelona" },
        { "postCode", "08001" },
        { "state", "Barcelona" },
        { "customerCountry", "ES" },
        { "customerNationalId", "9999999d9R" },
        { "dob", "01-12-1999" },
        { "chName", "First name Last name" },
        { "chFirstName", "First name" },
        { "chLastName", "Last name" },
        { "chEmail", "correo@micomercio.com" },
        { "chAddress1", "Line 1 owner address" },
        { "chAddress2", "Line 2 owner address" },
        { "chCity", "Barcelona" },
        { "chPostCode", "08001" },
        { "chState", "Barcelona" },
        { "chCountry", "ES" },
        { "topLogo", "https://docs.globalpayments.es/wp-content/uploads/2022/12/globalpayments-logo-340x80-BLANCO.png" },
        { "checkoutTitle", "AddonPayments" },
        { "successURL", "https://redirection-integration-2.epg-addonpayments-doc.xyz/" },
        { "statusUrl", "https://redirection-integration-2-py.epg-addonpayments-doc.xyz/notification" },
    };

    // string formattedData = string.Join("&", payment);
    string formattedData = DictionaryToUrlEncodedParams(payment);

    Console.WriteLine("Formated Data = " + formattedData);
    Console.WriteLine();
    byte[] formattedDataBytes = Encoding.UTF8.GetBytes(formattedData);
    string signature = "";
    using (SHA256 sha256 = SHA256.Create())
    {
        byte[] signatureBytes = sha256.ComputeHash(formattedDataBytes);
        signature = BitConverter.ToString(signatureBytes).Replace("-", "");
        Console.WriteLine("signature = " + signature.ToLower());
    }

    byte[] randomIvBytes = new byte[16];
    using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(randomIvBytes);
    }
    byte[] iv = StringToByteArray("807F63FF1F90BBB336AF64983DF6B750");
    byte[] key = Encoding.UTF8.GetBytes("a723a2ce8ec3840c848d5914520c8199");

    string b64EncryptedData = "";
    using (Aes aesAlg = Aes.Create())
    {
        aesAlg.Key = key;
        aesAlg.IV = iv;
        aesAlg.Mode = CipherMode.CBC;
        aesAlg.Padding = PaddingMode.PKCS7;
        byte[] data = aesAlg.EncryptCbc(
            formattedDataBytes,
            iv,
            PaddingMode.PKCS7
        );
        b64EncryptedData = Convert.ToBase64String(data);
        Console.WriteLine(b64EncryptedData);
    }

    using (HttpClient client = new())
    {
        var builder = new UriBuilder("https://checkout-stg.addonpayments.com/EPGCheckout/rest/online/tokenize");
        var query = HttpUtility.ParseQueryString(builder.Query);
        query["merchantId"] = "116659";
        query["encrypted"] = b64EncryptedData;
        query["integrityCheck"] = signature.ToLower();
        builder.Query = query.ToString();
        client.DefaultRequestHeaders.Add("apiVersion", "3");
        client.DefaultRequestHeaders.Add("encryptionMode", "CBC");
        client.DefaultRequestHeaders.Add("iv", Convert.ToBase64String(iv));

        var resposne = await client.PostAsync(builder.Uri, null);
        var result = await resposne.Content.ReadAsStringAsync();
        Console.WriteLine("Redirect URL = " + result);
    }
}


static string DictionaryToUrlEncodedParams(Dictionary<string, string> dictionary)
{
    var encodedPairs = new List<string>();
    foreach (var kvp in dictionary)
    {
        string encodedKey = HttpUtility.UrlEncode(kvp.Key);
        string encodedValue = HttpUtility.UrlEncode(kvp.Value);
        // encodedValue = encodedValue.Replace("%2f", "%2F");
        encodedPairs.Add($"{encodedKey}={encodedValue}");
    }
    return string.Join("&", encodedPairs);
}

static byte[] StringToByteArray(string hex)
{
    int numberChars = hex.Length;
    byte[] bytes = new byte[numberChars / 2];
    for (int i = 0; i < numberChars; i += 2)
    {
        bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    }
    return bytes;
}
				
			
Comparte este documento

Cifrado, firma y envío de la petición

Copiar el enlace

Icono del portapapeles
Tabla de Contenidos

Productos

  • Cyberpac
  • Addon Payments
  • Pagos integrados en TPV
  • Universal Pay
  • Addon 1 - XML API Integration

Ventas

Cuéntanos cómo es tu negocio para ofrecerte la mejor solución.

Contacta con un experto

Soporte técnico

¿Ya eres cliente y necesitas ayuda? Contacta con nosotros, estamos a tu disposición.

Ayuda

Socios

Trabajamos con los mejores partners de soluciones in-store y eCommerce. ¿Quieres unirte?

Únete a nosotros

© Comercia Global Payments

Política de privacidad
Ejercicio de Derechos
Información a Clientes
Canal de denuncia
Aviso Legal
Política de cookies
Pregúntale a la IA
Escribe tu pregunta. Por ejemplo: ¿Cómo creo un enlace de pago?
La SmartWiki puede omitir datos. Verifica la información o contacta con soporte.

SmartWiki, Impulsada por IA

API - Developers Docs
Gestionar el consentimiento de las cookies
Para ofrecer las mejores experiencias, utilizamos tecnologías como las cookies para almacenar y/o acceder a la información del dispositivo. El consentimiento de estas tecnologías nos permitirá procesar datos como el comportamiento de navegación o las identificaciones únicas en este sitio. No consentir o retirar el consentimiento, puede afectar negativamente a ciertas características y funciones.
Funcional Siempre activo
El almacenamiento o acceso técnico es estrictamente necesario para el propósito legítimo de permitir el uso de un servicio específico explícitamente solicitado por el abonado o usuario, o con el único propósito de llevar a cabo la transmisión de una comunicación a través de una red de comunicaciones electrónicas
Preferencias
El almacenamiento o acceso técnico es necesario para la finalidad legítima de almacenar preferencias no solicitadas por el abonado o usuario
Estadísticas
El almacenamiento o acceso técnico que es utilizado exclusivamente con fines estadísticos. El almacenamiento o acceso técnico es necesario para la finalidad legítima de almacenar preferencias no solicitadas por el abonado o usuario
Marketing
El almacenamiento o acceso técnico es necesario para crear perfiles de usuario para enviar publicidad, o para rastrear al usuario en una web o en varias web con fines de marketing similares.
Administrar opciones Gestionar los servicios Gestionar {vendor_count} proveedores Leer más sobre estos propósitos
Ver preferencias
{title} {title} {title}

Cyberpac

Consulta la documentación de Cyberpac. Aquí tienes las distintas secciones:

Canales

Módulos de integración

Integraciones a medida

Consulta la documentación de las distintas secciones de integraciones:

Comienza a integrar

undraw_add_to_cart_re_wrdo 1 (1) (1)

Plugins para CMS

Complementa la integración

SDKs

Métodos de pago

Herramientas

Addon Payments

Consulta la documentación de Addon Payments. Aquí tienes las distintas secciones:

Integraciones

Consultas frecuentes

Portal Backoffice

Pagos integrados en TPV

Crea una solución que te ayudará a automatizar procesos. Incluso, podrás agregar procesos de pago en terminales físicos.

Pago integrado con TPV Android

Pago integrado con Smartphone TPV

Fichas Técnicas TPVs