Integración 3DS API + librería kushki.js
Si tienes una integración por API (backend) y requieres autenticar pagos mediante 3D Secure, es necesario implementar cualquiera de las bibliotecas frontend Kushki.js o Kushki.js Hosted Fields para inicializar el servicio de 3D Secure y posteriormente desplegar el modal de autenticación, en caso de que sea requerido.
Transacciones soportadas con esta opción
Soporta ✅ | No soporta ⛔️ |
---|---|
Autenticación 3DS para cargos únicos con tarjeta | |
Autenticación 3DS para preautorizaciones |
Paso 1. Obtén un Json Web Token (JWT)
Es necesario implementar el método requestSecureInit()
desde Kushki.js o Kushki.js Hosted Fields para obtener un Json Web Token (JWT), el cual será necesario al momento de generar un token.
Kushki.js
Usa Kushki.js si necesitas un mayor control sobre el “look & feel” o apariencia de tu formulario de pago.
Importa Kushki.js
Puedes importar la biblioteca de Kushki.js a través de CDN o como un paquete NPM.
Opción 1 - CDN
Usa el siguiente tag script
al final del <body>
en tu página de pagos.
<script src="https://cdn.kushkipagos.com/kushki.min.js"></script>
Opción 2 - NPM
Instala el paquete desde npm.
npm install --save @kushki/js
Luego impórtalo en tu código utilizando el siguiente código.
import { Kushki } from “@kushki/js”;
Configura el objeto Kushki
Añade el siguiente código a tu aplicación
const kushki = new Kushki({merchantId: 'public-merchant-id', // Your public merchant idinTestEnvironment: true,});
Recoge la información del usuario y envíala a tu back-end
Primero, añade el formulario a tu página de pagos con los campos requeridos. Puedes diseñarlo de la forma que mejor te parezca.
Por ejemplo:
<form id="payment-form"><input placeholder="Card Number" type="text" name="number"><input placeholder="Full Name" type="text" name="name"><input placeholder="MM" type="text" name="expiry_month"><input placeholder="YY" type="text" name="expiry_uear"><input placeholder="CVC" type="text" name="cvc"><button id="submit">Pay $49.99</button></form>
Consume el método requestSecureInit()
Usa el método requestSecureInit()
enviando el número de la tarjeta, para obtener el jwt
.
var callback = function(response) {if(!response.code){console.log(response);} else {console.error('Error: ',response.error, 'Code: ', response.code, 'Message: ',response.message);}}kushki.requestSecureInit({card: {number: "4000000000000002"}}, callback);
Si la solicitud ha sido exitosa, se regresará un objeto json con el jwt
:
{"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTQ2NTY4ODYsImlhdCI6MTY1NDY0OTY4NiwiaXNzIjoiNWVhMzJmZDJmZjQ2NDU2OTY3YjUyNDliIiwianRpIjoiMDFhZTQyYWUtYzMyZS00YWRjLWFmOWQtZWVhMmFlNjRkMDkxIiwiT3JnVW5pdElkIjoiNWVhMzJmZDJhZDA3ZDIxYTM2OTc4OGFlIiwiUmVmZXJlbmNlSWQiOiI3ZjY1NzM5NS0yMDIwLTQ1ZjEtOTY4Mi05MzJiNTU5YWYzMWIifQ.JUkk70Kg4KlUYW7eIvsW8LoDhxJeG8P00VrJH9oQipc"}
En caso contrario, te arrojará la siguiente respuesta de error:
{"mensaje" : "mensaje de error" ,"código" : "código de error" ,"error" : "mensaje de error"}
Kushki.js Hosted Fields
Con Hosted Fields, incluido en Kushki.js, podrás recolectar de forma segura la información de pago del cliente a través de campos almacenados en infraestructura de Kushki. Devuelve un token el cual permite continuar con el flujo de pago desde el back-end.
Importa Kushki.js Hosted Fields en tu aplicación
Opción 1 - CDN
Importa la biblioteca de Kushki.js Hosted Fields en tu aplicación a través de una etiqueta <script>
dentro de la etiqueta <body>
. Una vez importada, podrás acceder a los recursos descritos más adelante para crear un flujo de pago con Kushki.
Es necesario importar la biblioteca kushki.min.js
(la cuál trae el código necesario para almacenar las credenciales de tu comercio) y la biblioteca antifraud.min.js
(la cuál trae las herramientas necesarias para poder realizar autenticaciones de seguridad).
Opción 1 - CDN
<script src="https://cdn.kushkipagos.com/js/latest/kushki.min.js"></script><script src="https://cdn.kushkipagos.com/js/latest/antifraud.min.js"></script>
Opción 2 - NPM
Instala la biblioteca Kushki.js Hosted Fields como un paquete npm dentro de tu aplicación con el siguiente código:
npm install --save @kushki/js-sdk
Opción 3 - YARN
Instala la biblioteca Kushki.js Hosted Fields como un paquete yarn dentro de tu aplicación con el siguiente código:
yarn install @kushki/js-sdk
Crea una instancia de KushkiOptions
Para hacer uso de la biblioteca Kushki.js Hosted Fields, es necesario primero crear una instancia de tipo KushkiOptions
la cuál te permite declarar la clave pública del comercio así como poder seleccionar el ambiente (prueba o producción) mediante el método init()
.
Añade el siguiente código a tu aplicación:
import { IKushki, init, KushkiError } from "@kushki/js-sdk";const kushkiOptions : KushkiOptions = {publicCredentialId: '<public-credential-id>', // This corresponds to the public credential of the merchantinTest: true};const buildKushkiInstance = async () => {try {const kushkiInstance : Ikushki = await init(kushkiOptions);} catch (e: KushkiError) {console.error(e.message);}}
Revisa la referencia para más información sobre la instancia KushkiOptions.
Inicializa el servicio de autenticación por 3D Secure
Consume el método requestSecureInit()
enviando el número de tarjeta para obtener un JWT.
import { init, IKushki } from "@kushki/js-sdk";import { requestSecureInit, SecureInitRequest, SecureInitResponse } from "@kushki/js-sdk/Antifraud";const onRequestSecureInit = async () => {try {const kushkiInstance: IKushki = await init({inTest: true,publicCredentialId: merchantId});const secureInitRequest: SecureInitRequest = {card: {number: cardNumber}};const secureInitResponse: SecureInitResponse = await requestSecureInit(kushkiInstance,secureInitRequest);console.log(secureInitResponse);} catch (error: any) {console.log(error)}};
Si la solicitud ha sido exitosa, se regresará un objeto json con el jwt
:
{"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTQ2NTY4ODYsImlhdCI6MTY1NDY0OTY4NiwiaXNzIjoiNWVhMzJmZDJmZjQ2NDU2OTY3YjUyNDliIiwianRpIjoiMDFhZTQyYWUtYzMyZS00YWRjLWFmOWQtZWVhMmFlNjRkMDkxIiwiT3JnVW5pdElkIjoiNWVhMzJmZDJhZDA3ZDIxYTM2OTc4OGFlIiwiUmVmZXJlbmNlSWQiOiI3ZjY1NzM5NS0yMDIwLTQ1ZjEtOTY4Mi05MzJiNTU5YWYzMWIifQ.JUkk70Kg4KlUYW7eIvsW8LoDhxJeG8P00VrJH9oQipc"}
En caso contrario, te arrojará uno de los siguientes errores:
CÓDIGO | MENSAJE | EJEMPLO | DESCRIPCIÓN |
---|---|---|---|
E004 | Error en solicitud de JWT | { code: “E004”, message: “Error en solicitud de JWT” } | Si el comercio tiene una regla de 3D Secure activa y hubo un problema durante la inicialización del servicio, se regresará un error con código E004. |
E018 | Longitud de tarjeta inválida | { code: “E018”, message: “Longitud de tarjeta inválida” } | Por favor, verifica que la longitud de la tarjeta sea válida. |
E019 | Comercio no tiene activo 3DS | { code: “E019”, message: “Comercio no tiene activo 3DS” } | El comercio no tiene activo el servicio de 3DS. Para activarlo, revisa la guía herramientas de detección de fraude. |
Paso 2. Solicita un token de tarjeta
Solicita un token de tarjeta enviando el JWT obtenido en el paso anterior.
{"card": {"name": "John Doe","number": "4000000000000002","expiryMonth": "01","expiryYear": "28","cvv": "123"},"totalAmount": 59,"currency": "USD","jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NTQ2NTg0ODgsImlhdCI6MTY1NDY1MTI4OCwiaXNzIjoiNWVhMzJmZDJmZjQ2NDU2OTY3YjUyNDliIiwianRpIjoiZjc4NzQzNTctMmY2Zi00OTExLTg3MDctZDBmN2RlYTZlNTk4IiwiT3JnVW5pdElkIjoiNWVhMzJmZDJhZDA3ZDIxYTM2OTc4OGFlIiwiUmVmZXJlbmNlSWQiOiIyZDdhOTA2OS04MjhjLTQxNDItYWYwNC1hMjZjNWI4YzQ3MjMifQ.5nmFrf3sOAxKNIcJTzc5i2GNY5ALABpu42YsrHIibio"}
Si el comercio tiene reglas 3D Secure activas y se inicializó 3D Secure correctamente como se describió en el paso 1, además del token, se devolverán otras propiedades que serán requeridas en el siguiente paso.
Si una transacción requiere autenticación 3D Secure por parte del tarjetahabiente, se devolverá la propiedad authRequired
dentro del objeto security
como true
(security.authRequired
).
Parámetro | Tipo | Descripción |
---|---|---|
authRequired | Booleana | Este campo te indica si se requiere o no challenge de 3DS. |
acsURL | URL | Hace referencia a la URL de la página del reto que el usuario debe pasar (Access Control System). |
specificationVersion | String | Se refiere a la versión de 3DS aplicable. |
authenticationTransactionId | String | ID de la transacción verificada desde las marcas. |
paReq | String | Significa Payer Authentication Request. Es un campo codificado en base64 que contiene información de tu comercio y del tarjetahabiente y que se envía al emisor para la autenticación Nota: en caso de estar haciendo pruebas en ambiente UAT, se debe enviar sandbox . |
Ejemplos
Objeto de respuesta con autenticación 3D Secure requerida
{"token": "g9m2XG100000uut73n085881SMOP3bP1","secureService": "3dsecure","secureId": "61efd064-b9df-4c0c-81fb-5b39a5d0cf9f","security": {"acsURL": "https://merchantacsstag.cardinalcommerce.com/MerchantACSWeb/pareq.jsp?vaa=b&gold=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA","authenticationTransactionId": "uvvZn0ND0ukTOJIfhfi0","authRequired": true,"paReq": "eNpVUstuwjAQvPsrItRTD7HjhAjQYokWqQVUSksqKm5RYkiU5oFjE/j72iFAK/mws7Nr78wagkRwPl3zSAnO4I3XdbjnVhqPe+p43BZkOSUqC97ns12yS0mPwWryyQ8MjlzUaVkwxyY2BXyFSF8hoiQsJIMwOjzNlszzh9TxAXcQQc7FbMr6nksdAviCEBRhztlivXh8ScpaWitRxiqSpRXwWqYF4JZHEJWqkOLMfOIBvgIESvywRMpqhHHTNHam6iRLq3Bf1nZU5oANjwDfh1spE9Va8ymNWfy9pZvca4Lso4k38isg1XybJ3kYTMaATQWCOJScUUIp8cnAIu5IH1cP0eYRhLkZhj30hzbRsjqIoDIPTS6oPzTU34wWpITgRXRmA09zN4SAn6qy4LpG23uLtYb75M+vxuRIGjd9z3UpNS63uG1PtTXUJ07bn7Y+YdODux3ibt06+vcNfgHbNq5L","specificationVersion": "2.2.0"}}
Objeto de respuesta con autenticación 3D Secure no requerida
{"token": "URkTD3100000aSfrJk085881gtsxGts6","secureService": "3dsecure","secureId": "9903cc36-6e9c-42b0-bb76-34c9c4dbaff5","security": {"acsURL": "","authenticationTransactionId": "","authRequired": false,"paReq": "","specificationVersion": "2.2.0"}}
Objeto de respuesta sin 3D Secure
{"token": "3c1518cf6f844e248880aad6187cf8d7"}
Obtén más información sobre solicitar un token de tajeta.
Paso 3. Autentica una transacción a través de 3D Secure
En caso de que la propiedad security.authRequired
obtenida en el paso anterior venga con el valor de true
, será necesario realizar una autenticación por medio de 3D Secure. Para realizar una autenticación 3D Secure, es requerido llamar el método requestValidate3DS
en Kushki.js o Kushki.js Hosted Fields, enviando el objeto de la respuesta del paso anterior.
Kushki.js
var callback = function(response) {if(!response.code){console.log(response);} else {console.error('Error: ',response.error, 'Code: ', response.code, 'Message: ',response.message);}}kushki.requestValidate3DS({secureId: "5e44449e-869b-4fed-bbca-e1bfa5af53c3",security: {acsURL: "https://authentication.cardinalcommerce.com/ThreeDSecure/V1_0_2/PayerAuthentication?issuerId\u00d2aa20412b0063aca652facd9g\u0034transactionId\u003dQhcf3XOjdZmjve336Vee2gb5rof1",authenticationTransactionId: "1d8cf7jg5Bfn8Nj73mn7",paReq: "eNpVUtluwjAQfPdXoH5A7DghtGixxFUViRt6iDfXGGJCDpykQL++doDSvu3sjtYzs4ZlqKXsLaQotWQwknnOt7Km1q2HyeIx6EW7w2dn09NjFXnxxn1gMG3P5YHBl9S5ShPmOsShgG8QmRVahDwpGHBx6AzGzKdXoH5A7DghtGixxpVUtluwjAQfPdXoH5A7DghtGixs4ZlqKXsLaQot0u4KqLQKRlUugzC4gP+AYQlHrPwqLImhgfj0cnKvMwUhnfprkj0hiwnSPAxn1gMG3P5YHBl9S5ShPmOsShOqLqJ7x73Gx2vVbgC0DwZoXklFCKXFpo0bcpu83qWht0u4KqLQKRlUugzC4gP+AYQlHrpfUGenfxtGEOl1jIRN0c3hECesjSRhmNC+62Nh7vy7otNVxQmtdkm3Ew/Jrv1Kp0X4elF8Pb6p/n2KH/k0skaqcyeVHfdaulqgoP20X4elF8Pb6p/n2KH/k0sv8\u003d",specificationVersion: "2.2.0",authRequired: true}, callback);
Si el valor de la variable authRequired
es igual a true
el modal para validación de 3DS será presentado y tu cliente entonces recibirá el valor a ingresar por correo electrónico o mensaje de texto.
Si el valor de la variable authRequired
es igual a false
no se presentará el modal para validación 3DS.
La respuesta que recibirás en la función callback será:
{"code":"3DS000","message":"ok"}
En caso de error, la respuesta de la función callback será algo como:
{"message":"error-message","code":"error-code","error": "error-message"}
La respuesta de la autenticación la obtendrás en el cargo. Si la autenticación se declina, recibirás un código K322 y alguno de los subcódigos especificados en la guía de Códigos de error.
Kushki.js Hosted Fields
El método requestValidate3DS()
recibe como parámetro el objeto obtenido en la respuesta del paso anterior.
import { init, IKushki } from "@kushki/js-sdk";import { CardTokenResponse, requestValidate3DS, TokenResponse } from "@kushki/js-sdk/Antifraud";const on3DSValidation = async () => {try {const kushkiInstance = await init({inTest: true,publicCredentialId: merchantId});const cardTokenResponse: CardTokenResponse = {secureId: "secure_id",secureService: "secure_service",security: {acsURL: "https://kushki.com",authenticationTransactionId: "transaction_id",authRequired: true,paReq: "jwt",specificationVersion: "2.0.1"},token: "token"};const response: TokenResponse = await requestValidate3DS(kushkiInstance, cardTokenResponse);console.log(response);} catch (error: any) {console.log(error)}};
PROPIEDAD | TIPO | REQUERIDO | DESCRIPCIÓN |
---|---|---|---|
kushkiInstance | IKushki | SÍ | Objeto con información del comercio y el ambiente de trabajo. |
secureInitRequest | SecureInitRequest | SÍ | Objeto obtenido al inicializar el servicio de 3D Secure con el método requestSecureInit() . |
Si la autenticación 3D Secure ha sido exitosa, se devolverá el mismo token del paso 2 con las validaciones correspondientes para seguir con el flujo de pago.
{"token": "3c1518cf6f844e248880aad6187cf8d7"}
En caso de error durante la autenticación, se devolverá alguno de los siguientes mensajes:
CÓDIGO | MENSAJE | EJEMPLO | DESCRIPCIÓN |
---|---|---|---|
E005 | Campos 3DS inválidos (Invalid 3DS fields) | { code: “E005”, message: “Campos 3DS inválidos” } | Si el comercio tiene habilitada una regla 3DS y hubo un error en la autenticación 3DS, se regresará el código de error E005. Intente nuevamente asegurándose de ingresar los datos correctamente para la validación de 3DS. |
E006 | Error en solicitud de validación de token (Token validation request error) | { code: “E006”, message: “Error en solicitud de validación de token” } | Si el comercio tiene habilitada una regla 3DS y hubo un error en la autenticación 3DS, se regresará el código de error E005. Intente nuevamente asegurándose de ingresar los datos correctamente para la validación de 3DS. |
Consulta más sobre el método requestValidate3DS().
Paso 4. Realiza un cargo único o un cargo recurrente
Continua con el flujo de pago generando un cargo único o un cargo recurrente con el token validado en el paso anterior.
{"token": "f5c64f7ac8ea42d5a58dcdc74de973dc","amount": {"subtotalIva": 0,"subtotalIva0": 16.98,"ice": 0,"iva": 0,"currency": "USD"},"metadata": {"Referencia": "987654"},"contactDetails": {"documentType": "CC","documentNumber": "1234567890","email": "user@example.com","firstName": "John","lastName": "Doe","phoneNumber": "+593912345678"},"orderDetails": {"siteDomain": "example.com","shippingDetails": {"name": "John Doe","phone": "+593912345678","address1": "Eloy Alfaro 139 y Catalina Aldaz","address2": "centro 123","city": "Quito","region": "Pichincha","country": "Ecuador"},"billingDetails": {"name": "John Doe","phone": "+593912345678","address1": "Eloy Alfaro 139 y Catalina Aldaz","address2": "centro 123","city": "Quito","region": "Pichincha","country": "Ecuador"}},"productDetails": {"product": [{"id": "198952AB","title": "eBook Digital Services","price": 10000,"sku": "10101042","quantity": 1},{"id": "198953AB","title": "eBook Virtual Selling","price": 6980,"sku": "004834GQ","quantity": 1}]},"fullResponse": "v2"}
Prueba tu integración
Existen tarjetas de prueba que puedes utilizar en modo prueba para asegurarte que tu integración está lista. Úsalas con cualquier CVV, 1234
como código OTP y fecha de expiración futura.
- Transacción aprobada con generación de modal 3DS:
4456528080389860
4456529267234200
4456529165328302
4456524869770255
4456523340069956
- Transacción aprobada sin generación de modal 3DS:
4456540000000063
4456543371713314
4456541982068615
4456541249811088