Saltar al contenido principal
En esta página
Método de integración

Tokeniza credenciales de pago para reutilizarlas de forma segura.

Elige una experiencia Vault alojada por DEUNA o un flujo de API compatible con PCI, recibe un ID de tarjeta reutilizable y procesa pagos futuros de forma segura.

Interfaz
Captura de credenciales alojada por DEUNA o captura del comercio compatible con PCI
Modelo de entrega
Componente SDK o API de Cards autorizada por el cliente
Ideal para
Tarjetas guardadas, checkout en un clic y pagos recurrentes

Comprenda los límites de los datos de autenticación#

El card_id que se devuelven en un flujo de tokenización compatible. Son referencias de pago de DEUNA. Su disponibilidad para un pago posterior depende del consentimiento del cliente, el tipo de token, la cuenta del comerciante, la conexión con el proveedor, el entorno, el país y la operación habilitada para ese flujo.

  • No asuma que todos los datos almacenados pueden moverse entre procesadores o métodos de pago.
  • Verifique el comportamiento de red, actualización de cuenta, portabilidad, uso recurrente y eliminación para la cuenta de destino antes de la producción.
  • Mantenga los datos PAN, CVV, token del proveedor y credenciales privadas fuera de los registros y metadatos de su aplicación.
  • Almacene la información del cliente, el propósito del consentimiento, el momento de la tokenización, el estado del dato de autenticación y el uso futuro permitido en su sistema de registro.
  • Soporte para la revocación, la expiración, el reemplazo y la eliminación de datos de autenticación, sin tratar automáticamente un token eliminado como una suscripción cancelada.

Usa la Catálogo de capacidades del proveedor Para el soporte de conexión publicado, confirme el comportamiento específico de la cuenta con su gestor técnico de DEUNA.

Elige un método de integración#

Payment Vault admite tanto los SDK de DEUNA como la API de Cards autorizada por el cliente. Ambos métodos devuelven un card_id; elige el método según quién controle la experiencia de ingreso de credenciales y su alcance según el Estándar de Seguridad de Datos para la Industria de Tarjeta de Pago (PCI DSS).

Integra con la API de Cards#

Usa la API de Cards cuando tu aplicación controle la experiencia de ingreso de tarjetas y esté preparada para las responsabilidades de PCI DSS correspondientes. Este es un flujo autorizado por el cliente: autentica al cliente y luego llama a POST /v2/users/{user_id}/cards con el token Bearer de ese cliente y el contexto del comercio requerido por el endpoint para almacenar una tarjeta.

:::info Ruta pública compatible Para nuevas integraciones, use únicamente POST /v2/users/{user_id}/cards. La ruta sin versión /users/{user_id}/cards preserva un contrato de tarjeta única heredado, mientras que /users/{user_id}/cards/{card_id}/tokens agrega un token específico del procesador a una tarjeta existente y no es un endpoint de creación de tarjetas. Ninguna de las rutas forma parte del catálogo actual de API externas. Consulte Diferencias de ruta POST de tarjeta. :::

El /v2 usa un cuerpo de solicitud que es un arreglo JSON, incluso cuando almacenas una sola tarjeta:

curl --request POST \
  --url 'https://api.sandbox.deuna.io/v2/users/USER_ID/cards' \
  --header 'Authorization: Bearer USER_ACCESS_TOKEN' \
  --header 'X-Merchant-ID: MERCHANT_ID' \
  --header 'Content-Type: application/json' \
  --data '[
    {
      "card_holder": "Jane Doe",
      "card_number": "CARD_NUMBER",
      "card_cvv": "CARD_CVV",
      "expiry_month": "12",
      "expiry_year": "2029",
      "is_default": true
    }
  ]'

Una solicitud correcta devuelve HTTP 201 Created. Guarda el data[].id como card_id; nunca almacenes el PAN ni el CVV enviados.

Tarjeta creadaJSON
{
  "data": [
    {
      "id": "8b5d0b45-e34f-4fd3-8cb5-79a7041f86ec",
      "company": "visa",
      "last_four": "4242",
      "expiration_date": "12/29"
    }
  ]
}

Después de un tiempo de espera agotado o una respuesta ambigua, consulta Enumerar tarjetas almacenadas antes de volver a enviar la tarjeta. El contrato del Gateway no publica un encabezado de idempotencia para esta operación, por lo que los clientes no deben asumir que un reintento es idempotente. Los metadatos de verificación pueden estar ausentes hasta que DEUNA verifique la credencial; consulta Metadatos de verificación de tarjetas.

Integra con un SDK de DEUNA#

La integración de la Bóveda de Pagos es a través de los SDK de DEUNA.

En entornos web, el widget se puede abrir en un elemento HTML de destino o mostrarse como modal.

Elija su plataforma SDK:

Características

  • El SDK expone varios devoluciones de llamada que permiten al comerciante reaccionar dinámicamente ante eventos importantes dentro del flujo de pago, tales como:
    • Cuando el usuario cierra el widget.
    • Cuando una tarjeta o credencial de pago se tokeniza exitosamente.
    • Cuando falla un intento de tokenización.
  • La Bóveda de Pago se puede renderizar incrustado o como un modal.

Información adicional

Obtenga más información sobre la integración de Payment Vault:

  • Verificar el tipo de evento y la marca de la tarjeta: The Vault reconoce marcas de tarjetas a partir de metadatos de eventos.
  • Descuento aplicado si la tarjeta es Mastercard por parte del comercio: Si la tarjeta es Mastercard se aplica un 20% de descuento sobre el carrito de compra actual. Esta acción la realiza íntegramente su aplicación.
  • Actualización de pedido: Después de aplicar un descuento, su aplicación es responsable de actualizar el pedido utilizando el punto final de Actualización de pedido de DEUNA.
  • Notificación al widget para actualizar el pedido y las cuotas.: Los cambios en el estado de un pedido se comunican mediante las devoluciones de llamada del SDK.
  • Mostrar una etiqueta promocionalAdemás de actualizar la cantidad del pedido y el importe del pago, puede aplicar estilos CSS personalizados al widget activo utilizando setCustomStyles(...). Ver el Guía del SDK web.

Procese un pago con el token devuelto card_id

Para procesar un pago en DEUNA con dado card_id utilizar el Comprar API.

Ejemplo de solicitud de rizo

JavaScript
const requestBody = {
    payer_info: {
        email: "eposada@deuna.com"
    },
    payment_source: {
        method_type: "credit_card",
        card_info: {
            card_id: "8d369b6e-113a-4640-9e63-dc29957fc86a",
            installment: {
            	plan_option_id: "<uuid que se retorna en el postMessage 'onInstallmentSelected'>"
            }
        }
    },
    // ... Remaining of the request body
};

fetch('https://api.sandbox.deuna.io/v2/merchants/orders/purchase', {
    method: 'POST',
    headers: {
        'x-api-key': '<YOUR_PRIVATE_API_KEY>',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(requestBody)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
curl --location 'https://api.sandbox.deuna.io/v2/merchants/orders/purchase' \
--header 'x-api-key: YOUR_PRIVATE_API_KEY' \
--header 'Content-Type: application/json' \
--data-raw '{
    "payer_info": {
        "email": "foo@bar.com"
    },
    "payment_source": {
        "method_type": "credit_card",
        "card_info": {
            "card_id": "8d369b6e-113a-4640-9e63-dc29957fc86a"
        }
    },
    "order": {
        "order_id": "testapi-0003",
        "currency": "MXN",
        "items": [
          {
              "id": "216",
              "name": "10 Cellphones",
              "description": "",
              "options": "string option",
              "total_amount": {
                  "original_amount": 2000,
                  "amount": 2000,
                  "currency": "MXN",
                  "currency_symbol": "$"
              },
              "unit_price": {
                  "amount": 200,
                  "currency": "MXN",
                  "currency_symbol": "$"
              },
              "tax_amount": {
                  "amount": 0,
                  "currency": "MXN",
                  "currency_symbol": "$"
              },
              "quantity": 1,
              "uom": "string",
              "upc": "string",
              "sku": "",
              "isbn": "",
              "brand": "",
              "manufacturer": "",
              "category": "",
              "color": "",
              "size": "",
              "weight": {
                  "amount": 0,
                  "unit": "kg"
              },
              "image_url": "https://images-staging.getduna.com/95463fb5-6279-4ec3-8ff9-fe07aacd2142/db5b698c57654116_domicilio_216_750x750_1662162887.png?d=200x200&format=webp",
              "details_url": "",
              "type": "physcal",
              "taxable": true
          }
        ],
        "sub_total": 2000,
        "total_amount": 2000,
        "store_code": "all",
        "billing_address": {
            "address1": "presa angostura 36PH",
            "address2": "",
            "address_type": "home",
            "city": "CDMX",
            "country_code": "MX",
            "email": "foo@bar.com",
            "first_name": "efren",
            "identity_document": "162915134",
            "is_default": true,
            "last_name": "garcia",
            "phone": "+525222222222",
            "state_code": "MX",
            "state_name": "miguel hidalgo",
            "zipcode": "11500"
        }
    }
}'
PHP
$curl = curl_init();

$requestBody = json_encode(array(
    "payer_info" => array(
        "email" => "foo@bar.com"
    ),
    "payment_source" => array(
        "method_type" => "credit_card",
        "card_info" => array(
            "card_id" => "8d369b6e-113a-4640-9e63-dc29957fc86a"
        )
    ),
    // Aquí puedes continuar añadiendo el resto del cuerpo de la solicitud
    "order" => array(
        "order_id" => "testapi-0003",
        "currency" => "MXN",
        "items" => array(
            // Aquí van los detalles de los items
        ),
        // Continúa con el resto de los detalles del pedido
    )
));

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $requestBody, // Aquí se utiliza la variable
  CURLOPT_HTTPHEADER => array(
    "x-api-key: YOUR_PRIVATE_API_KEY", // Asegúrate de reemplazar con tu API key real
    "Content-Type: application/json"
  ),
));


$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}
Ruby
require 'uri'
require 'net/http'
require 'json'

url = URI("https://api.sandbox.deuna.io/v2/merchants/orders/purchase")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request_body = {
    payer_info: {
        email: "foo@bar.com"
    },
    payment_source: {
        method_type: "credit_card",
        card_info: {
            card_id: "8d369b6e-113a-4640-9e63-dc29957fc86a"
        }
    }
    # ... Agrega aquí el resto del cuerpo de la solicitud
}.to_json

request = Net::HTTP::Post.new(url)
request["x-api-key"] = "YOUR_PRIVATE_API_KEY" # Reemplaza con tu API key
request["Content-Type"] = "application/json"
request.body = request_body

response = http.request(request)
puts response.read_body
Java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import org.json.JSONObject;

public class Main {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newHttpClient();
        
        JSONObject requestBody = new JSONObject()
            .put("payer_info", new JSONObject().put("email", "foo@bar.com"))
            .put("payment_source", new JSONObject()
                .put("method_type", "credit_card")
                .put("card_info", new JSONObject().put("card_id", "8d369b6e-113a-4640-9e63-dc29957fc86a")))
            // ... Agrega aquí el resto del cuerpo de la solicitud

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://api.sandbox.deuna.io/v2/merchants/orders/purchase"))
            .header("x-api-key", "YOUR_PRIVATE_API_KEY") // Reemplaza con tu API key
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(requestBody.toString()))
            .build();

        client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();
    }
}

Demostración

Después de integrar Payment Vault, la experiencia es similar a la siguiente demostración: