Integración paso a paso

Paso 1: Configuración del componente


Primero, activa desde nuestro admin e integra el componente de Click to Pay en tu aplicación. Esto implica configurar un iframe con una URL específica que proporcionamos, que debe incluir parámetros esenciales como la clave API pública y datos del usuario.

Configuración en el ADMIN de DEUNA

  • Accede a admin.deuna.com, y activa Click to Pay

Inicializar un Iframe en tu aplicación con la URL de DEUNA

Utiliza la URL proporcionada por nosotros para el iframe. Asegúrate de incluir los parámetros requeridos para personalizar la experiencia del usuario

URL para integración

https://elements.sandbox.deuna.io/click_to_pay?publicApiKey=${apiKey}&firstName=${encodeURIComponent(firstname)}&lastName=${encodeURIComponent(lastname)}&email=${encodeURIComponent(email)}
https://elements.deuna.com/click_to_pay?publicApiKey=${apiKey}&firstName=${encodeURIComponent(firstname)}&lastName=${encodeURIComponent(lastname)}&email=${encodeURIComponent(email)}

Es esencial entender que como desarrollador, tu responsabilidad es integrar este componente dentro de un iframe en tu sitio web o webView para apps. Esta integración es vital para garantizar una experiencia de usuario segura y fluida.

Atributos permitidos en Query Params

AtributoDescripción
publicApiKeyLa llave pública de tu cuenta con DEUNA.
firstNameEl nombre del usuario que está siendo registrado o autenticado.
lastNameEl apellido del usuario.
emailLa dirección de correo electrónico del usuario.
cssFile (opcional)UUID proporcionado por DEUNA. Esto aplica si quieres configurar un archivo css personalizado.
userToken(optional)El bearer token del usuario de DEUNA. Cuando este es enviado, todas las acciones dentro del widget van a hacer sobre este usuario de DEUNA.

👍

Nota importante: Asegúrate de que los Query Params estén codificados adecuadamente en caso de que contengan caracteres especiales. Esto es fundamental para evitar posibles problemas en las solicitudes.

A continuación, te mostramos un ejemplo de cómo integrar esta URL en tu sitio web usando HTML, CSS y JavaScript:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Click to Pay Integration</title>
    <style>
      /* Estilos básicos para el iframe */
      #click-to-pay-iframe {
          width: 100%;
          height: 500px; /* Ajusta la altura según tus necesidades */
          border: none;
      }
    </style>
  </head>
  <body>
    <iframe
      id="click-to-pay-iframe"
      src="https://elements.sandbox.deuna.io/click_to_pay?publicApiKey=${apiKey}&firstName=${encodeURIComponent(firstname)}&lastName=${encodeURIComponent(lastname)}&email=${encodeURIComponent(email)}"
      allow="payment"
    >
    </iframe>

    <script>
      // Escucha los mensajes de postMessage para recibir el card_id (a.k.a card token)
      window.addEventListener('message', function(event) {
          if (event.origin !== "https://elements.sandbox.deuna.io") {
              return;
          }
          let firstParsedData;
          if (typeof event.data === 'string') {
              firstParsedData = JSON.parse(event.data);
          } else {
              firstParsedData = event.data;
          }

          const parsedData = JSON.parse(firstParsedData);
          console.log('postMessage:', parsedData);

          if (
            parsedData &&
            parsedData.type === "vaultSaveSuccess"
        ) {
          // obtener el card_id (a.k.a card token)
          const cardId = parsedData.data.metadata.createdCard.id;

          // crear pago con el card_id
        }
      });
    </script>
  </body>
</html>

El componente de DEUNA se encargará del proceso de comunicación con Click to Pay, incluyendo el proceso de guardado de tarjeta. Una vez que este proceso sea exitoso, DEUNA enviará un evento mediante postMessage con el card_id válido. Este card_id es un elemento clave que debes enviar al realizar la llamada al endpoint de purchase desde tu backend para completar el pago.

Paso 2: Manejo de eventos con postMessage


Tras procesar una tarjeta con éxito en DEUNA, recibirás un evento postMessage con el card_id. Este card_id es esencial para procesar el pago final en tu backend.

window.addEventListener("message", (event) => {
  if (event.origin !== "URL_DE_CONFIANZA") { // Reemplaza con tu URL de confianza
    return;
  }

  switch (event.data.type) {
    case 'VaultStarted':
      // Click to Pay está listo
      break;

    case 'VaultSaveSuccess':
      // Tarjeta guardada con éxito, obtén el card_id
      const cardId = event.data.metadata.createdCard.id;
      // Usa card_id para procesar el pago
      break;

    case 'VaultSaveError':
    case 'VaultFailed':
      // Manejo de errores
      const errorCode = event.data.metadata.errorCode;
      const errorMessage = event.data.metadata.errorMessage;
      break;

    case 'VaultProcessing':
      // Pago en proceso
      break;

    // Añade más casos según sea necesario
  }
});

Utiliza este ejemplo como guía para configurar tu manejador de eventos y reacciona adecuadamente a cada tipo de mensaje.

Visita la sección Manejo de eventos con postMessage donde encontrarás información detallada sobre estos eventos, incluyendo descripciones completas y recomendaciones sobre cómo manejarlos efectivamente.

Paso 3: Proceso para finalizar el pago


Una vez que el proceso de pago se haya iniciado en tu aplicación mediante el backend, el siguiente paso crucial es integrar el endpoint para finalizar la compra. Este proceso implica configurar una solicitud específica al endpoint de la API para concluir la transacción. Por ejemplo, puedes utilizar una solicitud curl como se muestra a continuación:

Nota: El valor enviado en el atributo card_id es el que DEUNA envía mediante el método postMessage durante el evento VaultSavedSuccess.

const requestBody = {
    payer_info: {
        email: "[email protected]"
    },
    payment_source: {
        method_type: "credit_card",
        card_info: {
            card_id: "8d369b6e-113a-4640-9e63-dc29957fc86aza"
        }
    },
    // ... Resto del 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": "[email protected]"
    },
    "payment_source": {
        "method_type": "credit_card",
        "card_info": {
            "card_id": "8d369b6e-113a-4640-9e63-dc29957fc86aza"
        }
    },
    "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-sandbox.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": "[email protected]",
            "first_name": "efren",
            "identity_document": "162915134",
            "is_default": true,
            "last_name": "garcia",
            "phone": "+525222222222",
            "state_code": "MX",
            "state_name": "miguel hidalgo",
            "zipcode": "11500"
        }
    }
}'
$curl = curl_init();

$requestBody = json_encode(array(
    "payer_info" => array(
        "email" => "[email protected]"
    ),
    "payment_source" => array(
        "method_type" => "credit_card",
        "card_info" => array(
            "card_id" => "8d369b6e-113a-4640-9e63-dc29957fc86aza"
        )
    ),
    // 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;
}
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: "[email protected]"
    },
    payment_source: {
        method_type: "credit_card",
        card_info: {
            card_id: "8d369b6e-113a-4640-9e63-dc29957fc86aza"
        }
    }
    # ... 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
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", "[email protected]"))
            .put("payment_source", new JSONObject()
                .put("method_type", "credit_card")
                .put("card_info", new JSONObject().put("card_id", "8d369b6e-113a-4640-9e63-dc29957fc86aza")))
            // ... 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();
    }
}

👍

Nota Importante: Para revisar en detalle el endpoint te recomendamos ir a realizar pago de orden

Demo de experiencia


Felicidades, ya haz implementado click to pay. Ahora podrás ver una experiencia similar a la siguiente

Personalización de CSS en el componente (Opcional)


El componente te permite realizar personalizaciones en el formulario de tarjetas, para más información de configuración ir a la sección Personalización CSS de componentes