Apple Pay con payload desencriptado
Si cuentas con certificación PCI DSS y controlas la llave privada de tu Apple Pay Payment Processing Certificate, desencripta el token de Apple Pay de tu lado y envía a Conekta el payload ya desencriptado.
En la integración estándar de Apple Pay por Direct API, tu backend envía a Conekta el objeto pk_payment como lo devuelve Apple, con el token de pago encriptado, y Conekta lo desencripta con su certificado. Esta guía cubre el flujo alterno: tú desencriptas el token con tu propio certificado y nos mandas el contenido ya desencriptado.
Requiere habilitación y certificación PCI DSSEste flujo está disponible solo para comercios con PCI DSS vigente y se habilita por cuenta. Contacta a tu ejecutivo de Conekta para activarlo.
1. Cuándo usar este flujo
Úsalo si necesitas que el token de Apple Pay no quede atado a un solo procesador.
| Flujo estándar | Payload desencriptado | |
|---|---|---|
| Quién desencripta | Conekta | Tu backend |
| Quién tiene la llave que descifra | Conekta (su Payment Processing Certificate) | Tuyo (Payment Processing Certificate) |
| Quién firma la sesión de Apple | Conekta | Tu servidor |
| PCI DSS | No requerido | Requerido |
| Qué envías | pk_payment.paymentData (encriptado) | pk_payment.decryptedPaymentData.data (Base64) |
source | external si Conekta descifra con el certificado de su PSP; omitido si descifra con el tuyo | merchant_decrypted |
2. Requisitos previos
- Certificación PCI DSS vigente y el flujo habilitado en tu cuenta por Conekta.
- Tu propio Apple Pay Payment Processing Certificate, con su llave privada bajo tu control.
- Tu propio Apple Pay Merchant Identity Certificate y tu
merchantIdentifier, con tu dominio verificado bajo ese merchant id.
El merchant validation sí cambiaEl markup del botón es el mismo, pero la sesión de Apple Pay debe crearla tu servidor, contra Apple, con tu propio Merchant Identity Certificate. No uses el endpoint de sesión de Conekta ni envíes
"source": "external": esa sesión se firma con la identidad del PSP de Conekta, y entonces Apple cifra el token al Payment Processing Certificate del PSP — cuya llave privada no tienes, así que no podrías descifrarlo. Sigue la Opción B, certificado propio de la guía de integración.
Los dos certificados de Apple Pay hacen cosas distintasEl Payment Processing Certificate es al que Apple cifra el token: su llave privada es la que descifra. El Merchant Identity Certificate autentica tu servidor ante Apple al crear la sesión de pago (mTLS) y no participa en el descifrado. Para este flujo necesitas los dos.
3. Construye el payload desencriptado
Después de que Apple te devuelve el pk_payment, desencripta paymentData con tu certificado y toma el JSON. Posteriormente se debe serializar y codificar en Base64 estándar, con un máximo de 8,192 bytes.
// payload = JSON obtenido al desencriptar pk_payment.paymentData
const data = Buffer.from(JSON.stringify(payload)).toString('base64');
Manda el JSON completo, no lo recortesConekta solo rechaza la petición si falta alguno de los campos de la primera tabla, pero lee otros que vienen en el mismo JSON. Quitarlos no da error de validación: degrada o tumba el cargo más adelante.
El JSON desencriptado conserva el formato de Apple. Estos campos son obligatorios y, si falta cualquiera, la petición se rechaza:
| Campo | Descripción | Tipo |
|---|---|---|
| applicationPrimaryAccountNumber | DPAN. | string |
| applicationExpirationDate | Expiración en formato YYMMDD. | string |
| paymentDataType | Campo de Apple que indica el formato del dato de pago, no un flujo de autenticación. Conekta exige que venga presente pero no interpreta su valor: mándalo tal cual. | string |
| paymentData | Objeto que contiene los datos criptográficos. | object |
| paymentData.onlinePaymentCryptogram | Criptograma de la transacción. | string |
Estos no se validan, pero sí se usan:
| Campo | Descripción | Si no viene |
|---|---|---|
| paymentData.eciIndicator | ECI que viaja al adquirente junto con el criptograma. | Conekta solo tiene valor por defecto para Mastercard y American Express. En cualquier otra marca — Visa y Carnet incluidas — el cargo falla. |
| deviceManufacturerIdentifier | Identificador del dispositivo que generó el token. | Llega vacío al adquirente. No tumba el cargo. |
4. Crea el cargo
Envía el payload dentro de pk_payment.decryptedPaymentData e incluye "source": "merchant_decrypted" en payment_method. Todos los parámetros de la tabla son obligatorios.
| Parámetro | Descripción | Tipo |
|---|---|---|
| source | Debe ser merchant_decrypted para activar este flujo. | string |
| pk_payment.decryptedPaymentData.data | JSON desencriptado, serializado y codificado en Base64. | string |
| pk_payment.transactionIdentifier | Identificador de la transacción que devolvió Apple. | string |
| pk_payment.paymentMethod.displayName | Nombre que Apple muestra para la tarjeta (Visa 0121) | string |
| pk_payment.paymentMethod.network | Red de la tarjeta (Visa) | string |
| pk_payment.paymentMethod.type | Tipo de tarjeta (credit) | string |
curl --location 'https://api.conekta.io/orders' \
--header 'Accept: application/vnd.conekta-v2.3.0+json' \
--header 'Content-type: application/json' \
--header 'Authorization: Bearer key_YOUR_PRIVATE_API_KEY' \
--data '{
"currency": "MXN",
"customer_info": { "customer_id": "cus_xxxxxxxxxxxx" },
"line_items": [{ "name": "Vasija de Cerámica", "unit_price": 20000, "quantity": 1 }],
"charges": [{
"payment_method": {
"type": "apple",
"source": "merchant_decrypted",
"pk_payment": {
"decryptedPaymentData": { "data": "eyJhcHBsaWNhdGlvblByaW1hcnlBY2NvdW50TnVtYmVyIjoi..." },
"paymentMethod": { "displayName": "Visa 0121", "network": "Visa", "type": "credit" },
"transactionIdentifier": "610c88f19c8d43e289fd1f15bee320d5440c3bd450fcb8431d3a8d4be73f2f01"
}
}
}]
}'La respuesta es idéntica a la de cualquier cargo de Apple Pay: payment_status es paid y el cargo indica "product_type": "apple_pay".
{
"livemode": false,
"amount": 20000,
"currency": "MXN",
"payment_status": "paid",
"object": "order",
"id": "ord_2yYE5xyYQaJ8YRAG9",
"charges": {
"object": "list",
"has_more": false,
"total": 1,
"data": [
{
"id": "68a5e90679fcdd001abab388",
"livemode": false,
"created_at": 1755703558,
"currency": "MXN",
"payment_method": {
"auth_code": "976866",
"object": "card_payment",
"type": "credit",
"last4": "0121",
"brand": "visa",
"country": "MX",
"fraud_indicators": [],
"three_ds_flow_required": false,
"product_type": "apple_pay"
},
"object": "charge",
"description": "Payment from order",
"status": "paid",
"amount": 20000,
"paid_at": 1755703558,
"fee": 2785,
"customer_id": "cus_2yYDbYkcDCB5queoa",
"order_id": "ord_2yYE5xyYQaJ8YRAG9"
}
]
}
}El cargo guarda payment_method.source como merchant_decrypted para que puedas distinguirlo en tus reportes.
5. Errores
Si el payload es inválido, la respuesta nombra el campo que falla pero nunca su valor.
| Error | Causa |
|---|---|
source.merchant_decrypted_disabled | Tu cuenta no tiene habilitado el flujo desencriptado. |
pk_payment.decrypted_payment_data.conflicts_with_payment_data | Enviaste paymentData y decryptedPaymentData en la misma petición. |
pk_payment.decrypted_payment_data.not_allowed_for_source | Enviaste decryptedPaymentData con un source distinto de merchant_decrypted. |
Campo faltante o data inválido | El Base64 no decodifica, no es JSON, excede 8,192 bytes o falta un campo obligatorio. |
Updated 1 day ago

