1. Autenticación 3DS
Kushki Docs
Español
  • Español
  • English
  • Inicio
  • Inicio rápido
    • Preguntas frecuentes
    • Paso a producción
    • Política de cambios importantes del API
    • Códigos de error
    • Datos de prueba
    • Últimas novedades
  • Glosario de pagos
    • Glosario de pagos
  • Pagos únicos con tarjeta (Online)
    • Network Tokens
    • Marcas de tarjeta soportadas
    • Funcionalidades por modelo de negocio
    • Pagos en un paso
      • ¿Cómo funcionan los pagos con tarjeta?
      • Acepta pagos únicos con OTP
      • Códigos de error autenticación OTP
      • Códigos de error pagos únicos con tarjeta
      • Cargo directo (sin token)
      • Acepta un pago con tarjeta
    • Pagos en dos pasos
      • ¿Cómo funcionan los pagos únicos con autorización y captura?
      • Recibe pagos con autorización y captura
    • Devoluciones
      • Devoluciones, anulaciones y reembolsos
    • Autenticación 3DS
      • Integración 100% API de 3DS
      • Integración 3DS con librería kushki.js
      • Códigos de error autenticación 3DS
      • Integración 3DS API + librería kushki.js
      • Introducción a 3DS
    • Pagos con Apple Pay
      • Configuración de Apple Pay
      • Pruebas en Sandbox Apple Pay
  • Pagos recurrentes con tarjeta (Online)
    • Autentica tus suscripciones con 3DS
    • Apple Pay en Suscripciones
    • Acepta pagos one click con 3DS
    • Funcionalidades por modelo de negocio
    • Códigos de error en cargos recurrentes
    • Suscripciones externas a Kushki
    • Pagos calendarizados
      • Crea un cargo recurrente
      • Maneja tus cargos calendarizados
      • ¿Cómo funcionan los cargos recurrentes con tarjeta?
    • Pagos OneClick
      • ¿Cómo funcionan los pagos OneClick con autorización y captura?
      • Genera pagos one click
      • Recibe pagos OneClick con autorización y captura
  • Pagos con tarjeta presente
    • Datos de prueba
    • Acepta pagos con tarjeta presente
    • Webhooks para tarjeta presente
    • Raw card-present API
      • Introducción a Raw card-present API
      • Script de ejemplo para cifrar información
      • Intercambio de claves criptográficas
      • Preguntas frecuentes
      • Códigos de error para transacciones con tarjeta presente
      • Acepta pagos
    • Transacciones
      • Anula un pago
      • Transacciones
    • Kushki One
      • Autenticación y Cifrado de Requests
      • Realiza cobros con Kushki One
      • Servicios asíncronos y webhooks
      • Formato de montos en Kushki ONE
      • Catálogo Unificado de Errores — Kushki ONE Connect
      • Primeros Pasos
      • Impresión en terminal SmartPOS
    • Kushki One App de Pagos
      • Descripción general
      • Devoluciones y PreAuth & Capture
      • Pago Dividido en la terminal
      • Configuración del terminal
      • Consulta tus transacciones
      • Procesa un cobro
  • Pagos con transferencias
    • Consulta el estado de una transacción
    • Experiencias de compra y detalles de operación para pagos con transferencia bancaria
    • Recibe transferencias bancarias
  • Pagos en efectivo
    • Puntos de recaudo
    • Códigos de error para transacciones declinadas en efectivo
    • Acepta un pago en efectivo
  • Métodos alternativos de pago (APM)
    • ¿Cómo funcionan los pagos con APM?
    • Acepta pagos con Yape
  • Dispersión de dinero
    • Transferencia bancaria
      • ¿Cómo funciona la dispersión por transferencia bancaria?
      • Códigos de error para dispersiones por transferencia
      • Dispersa a cuentas bancarias
    • Tarjeta
      • ¿Cómo funciona el envío de fondos a tarjetas?
      • Envía dinero a una tarjeta
      • Códigos de error
  • Plugins
    • Shopify
      • Operación del Plugin
      • Shopify
    • Vtex
      • Guía de integración VTEX
  • Links de pago
    • Smartlinks
  • Formularios y botones de pago
    • Kajita
      • Kajitas de pago
      • ¿Cómo funciona?
    • Botón de pago
      • ¿Cómo funciona el botón de pago?
      • Genera un botón de pago
  • Administración de sucursales
    • ¿Cómo realizar el onboarding de subcomercios vía API?
  • Notificaciones
    • Buenas prácticas
    • Consulta tus webhooks
    • Webhooks para pagos únicos
      • Webhook para pagos únicos con tarjeta
      • Webhook para pagos únicos con transferencia bancaria
      • Webhook para pagos únicos con efectivo
    • Webhooks para pagos recurrentes
      • Webhook para pagos recurrentes con tarjeta
    • Webhooks para dispersiones
      • Webhook para dispersión de dinero con Transferencia
      • Webhook para dispersión con tarjeta
    • Webhooks para smartlinks
      • Webhooks con Smartlinks
    • Webhooks para botón de pagos
      • Webhooks con Botón de pago
    • Webhooks para devoluciones
      • Webhook para devoluciones
      • Webhook para contracargos
HomeMexico 🇲🇽Ecuador 🇪🇨Chile 🇨🇱Colombia 🇨🇴Peru 🇵🇪
HomeMexico 🇲🇽Ecuador 🇪🇨Chile 🇨🇱Colombia 🇨🇴Peru 🇵🇪
Status
Soporte / Support
Español
  • Español
  • English
  1. Autenticación 3DS

Integración 3DS API + librería kushki.js

Importante
Esta opción de integración requiere ser PCI Compliance
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.
Opción 2 - NPM#
Instala el paquete desde npm.
Luego impórtalo en tu código utilizando el siguiente código.

Configura el objeto Kushki#

Añade el siguiente código a tu aplicación

Consume el método requestSecureInit()#

Usa el método requestSecureInit() enviando el número de la tarjeta, para obtener el jwt.
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#
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:
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:

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().
Nota: Cuando tu comercio esté listo para aceptar pagos reales, es necesario que reemplaces la clave de prueba con la clave de producción.
Añade el siguiente código a tu aplicación:
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.
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ÓDIGOMENSAJEEJEMPLODESCRIPCIÓN
E004Error 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.
E018Longitud de tarjeta inválida{ code: "E018", message: "Longitud de tarjeta inválida" }Por favor, verifica que la longitud de la tarjeta sea válida.
E019Comercio 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": "PEN",
  "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).

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#

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)
  }
};
PROPIEDADTIPOREQUERIDODESCRIPCIÓN
kushkiInstanceIKushkiSÍObjeto con información del comercio y el ambiente de trabajo.
secureInitRequestSecureInitRequestSÍ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ÓDIGOMENSAJEEJEMPLODESCRIPCIÓN
E005Campos 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.
E006Error 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().
El tarjetahabiente tendrá hasta un máximo de 3 reintentos para completar la autenticación 3DS.

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": "PEN"
  },
  "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
Para habilitar 3DS en modo pruebas en tu comercio se requiere una configuración adicional por parte de Kushki.
Modificado en 2026-10-20 14:57:06
Anterior
Códigos de error autenticación 3DS
Siguiente
Introducción a 3DS
Built with