Pagos con Checkout Component

💎 Propuesta de Valor

Diseñamos el Checkout Component basándonos en el comportamiento de millones de usuarios para garantizar que nada se interponga entre tu cliente y la venta final.

Time-to-Market Record

Reduce el tiempo de desarrollo. Una sola integración te da acceso a todos nuestros métodos de pago actuales y futuros.

Conversión Optimizada

Validación de datos en tiempo real, detección automática de marca de tarjeta y autocompletado inteligente para minimizar el abandono.

Seguridad de Clase Mundial

Cumplimiento PCI-DSS Nivel 1 heredado. Los datos sensibles nunca tocan tus servidores, reduciendo tu responsabilidad legal al mínimo.



En esta documentación explicamos cómo aceptar pagos únicos con Tarjeta (crédito y débito), Transferencia electrónica, Efectivo, Pago en plazos y Pago Directo a través del Checkout Component . Podrás utilizar todo el poder de nuestra API de Pagos con un front end pre-diseñado, que se adapta a las necesidades de tu negocio en línea.


Pasos para integrar el Checkout Component

  1. Configurar tu servidor — Instala el SDK y configura tu backend.
  2. Crear un Customer (opcional) — Necesario solo si quieres habilitar tarjetas guardadas o referencias recurrentes.
  3. Crear una orden — Define los métodos de pago habilitados y el tipo de checkout (Integration o HostedPayment).
  4. Crear tu página de pago (solo Checkout Embebido) — Inicializa el Component en el cliente con el checkoutRequestId obtenido en el paso anterior.

1. Configurar tu Servidor

Instalar el SDK de Conekta

Instala el SDK de Conekta para el lenguaje de programación de tu preferencia.

dotnet add package Conekta.net
pip install conekta
gem install conekta
npm install conekta
go get -u github.com/conekta/conekta-go
<dependency>
  <groupId>io.conekta</groupId>
  <artifactId>ct-conekta-java</artifactId>
  <version>6.1.0</version>
  <scope>compile</scope>
</dependency>

2. Crear un customer (opcional)

💳

Early Access — Tarjetas Guardadas en Checkout 🎉

La funcionalidad de Tarjetas Guardadas permite que clientes recurrentes reutilicen de forma segura tarjetas previamente guardadas durante el checkout, mejorando la velocidad de pago y la conversión. Para esto, es necesario que crees un objeto customer y usarlo al crear una orden para mostrar el Conekta Checkout

Actualmente está disponible a través de nuestro programa de Early Access. Para solicitar acceso, completa el formulario a continuación. Nuestro equipo revisará tu integración y te contactará si tu configuración de checkout es compatible.

Cuando tienes cargos únicos, no es necesario generar un customer en Conekta, pues no vas a asociar ningún método de pago recurrente a éste. Sin embargo si quisieras almacenar en Conekta la informacion de tu cliente y metodos de pagos recurrentes como tarjetas guardadas y referencias para transferencias, sigue las siguientes instrucciones para crear un customer.

curl --location --request POST 'https://api.conekta.io/customers' \
	--header 'Accept: application/vnd.conekta-v2.2.0+json' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer key_XXXXXXX' \
  --data-raw '{
  	"name": "Felipe Gomez",
    "email": "[email protected]",
    "phone": "3143159054"
  }'
using System.Collections.Generic;
using System.Diagnostics;
using Conekta.net.Api;
using Conekta.net.Client;
using Conekta.net.Model;

namespace Example
{
    public class CreateCustomerExample
    {
        public static void Main()
        {
            Configuration config = new Configuration();
            // Configure Bearer token for authorization: bearerAuth
            config.AccessToken = "API_KEY";

            var apiInstance = new CustomersApi(config);
            var customer = new(
                name: "test dot",
                phone: "+573143159063",
                email: "[email protected]",
                corporate: true,
                planId: "plan_2tXx672QLQ68CkmMn",
                defaultShippingContactId: "",
                defaultPaymentSourceId: "",
                customReference: "dotnet_12345678"
            );
            var acceptLanguage = "es";  // string | Use for knowing which language to use (optional)  (default to es)
            
            try
            {
                // Create customer
                CustomerResponse result = apiInstance.CreateCustomer(customer, acceptLanguage);
                Debug.WriteLine(result);
            }
            catch (ApiException  e)
            {
                Debug.Print("Exception when calling CustomersApi.CreateCustomer: " + e.Message);
                Debug.Print("Status Code: " + e.ErrorCode);
                Debug.Print(e.StackTrace);
            }
        }
    }
}
import conekta
import time
from conekta.rest import ApiException
from pprint import pprint

configuration = conekta.Configuration(
    access_token = os.environ["API_KEY"]
)

with conekta.ApiClient(configuration) as api_client:
    api_instance = conekta.CustomersApi(api_client)
    customer = conekta.Customer(
        email='[email protected]',
        name='Customer Name',
        phone='5534343434'
    )
    accept_language = 'es'

    try:
        # Create Customer
        api_response = api_instance.create_customer(customer, accept_language=accept_language)
        print("The response of CustomersApi->create_customer:\n")
        pprint(api_response)
    except ApiException as e:
        print("Exception when calling CustomersApi->create_customer: %s\n" % e)
require 'time'
require 'conekta'
# setup authorization
Conekta.configure do |config|
  # Configure Bearer authorization: bearerAuth
  config.access_token = 'API_KEY'
end

api_instance = Conekta::CustomersApi.new
customer = Conekta::Customer.new({email: '[email protected]', name: 'miguel', phone: '+5215555555555'}) # Customer | requested field for customer
opts = {
  accept_language: 'es' # String | Use for knowing which language to use
}

begin
  # Create customer
  result = api_instance.create_customer(customer, opts)
  p result
rescue Conekta::ApiError => e
  puts "Error when calling CustomersApi->create_customer: #{e}"
end
import { CustomersApi, Configuration, Customer, CustomerResponse } from "conekta";

const apikey = "API_KEY";
const config = new Configuration({ accessToken: apikey });
const client = new CustomersApi(config);

const customer: Customer = {
  name: "John Constantine",
  email: "[email protected]",
  phone: "+5215555555555"
}

client.createCustomer(customer).then(response => {
  const customerResponse = response.data as CustomerResponse;
  console.log(customerResponse.id);
}).catch(error => {
  console.error("here", error);
});
package main

import (
	"context"
	"fmt"
	"io"
	"net/http"

	"github.com/conekta/conekta-go"
)

func main() {
	const acceptLanguage = "es"
	cfg := conekta.NewConfiguration()
	client := conekta.NewAPIClient(cfg)
	ctx := context.WithValue(context.TODO(), conekta.ContextAccessToken, "$API_KEY")
	req := conekta.Customer{
		Name:            "test dot",
		Phone:           "+573143159063",
		Email:           "[email protected]",
		Corporate:       conekta.PtrBool(true),
		PlanId:          conekta.PtrString("plan_2tXx672QLQ68CkmMn"),
		CustomReference: conekta.PtrString("go_12345678"),
	}
	customer, response, err := client.CustomersApi.CreateCustomer(ctx).Customer(req).AcceptLanguage(acceptLanguage).Execute()
	if err != nil {
		panic(err)
	}
	if response.StatusCode != http.StatusCreated {
		responseBody, err := io.ReadAll(response.Body)
		if err != nil {
			panic(err)
		}
		panic(fmt.Sprintf("response body: %s", responseBody))
	}
	fmt.Printf("customer: %v", customer)
}
import com.conekta.*;
import com.conekta.auth.*;
import com.conekta.model.*;
import com.conekta.CustomersApi;

public class CustomersApiExample {

    public static void main(String[] args) {
        ApiClient defaultClient = Configuration.getDefaultApiClient();

        // Configure HTTP bearer authorization: bearerAuth
        HttpBearerAuth bearerAuth = (HttpBearerAuth) defaultClient.getAuthentication("bearerAuth");
        bearerAuth.setBearerToken("API_KEY");

        CustomersApi apiInstance = new CustomersApi(defaultClient);
        Customer customer = new Customer(); // Customer | requested field for customer
        customer.setName("Customer Name");
        customer.setEmail("[email protected]");
        customer.setPhone("55454545454");
        String acceptLanguage = "es"; // String | Use for knowing which language to use
        try {
            CustomerResponse result = apiInstance.createCustomer(customer, acceptLanguage,null);
            System.out.println(result);
        } catch (ApiException e) {
            System.err.println("Exception when calling CustomersApi#createCustomer");
            System.err.println("Status code: " + e.getCode());
            System.err.println("Reason: " + e.getResponseBody());
            System.err.println("Response headers: " + e.getResponseHeaders());
            e.printStackTrace();
        }
    }
}

En la respuesta obtendrás un customer_id el cual podrás guardar para mostrar las tarjetas guardadas de tu customer o su referencia de transferencias bancarias.

🚧

Importante:

Si ya tienes un customer_id asociado al usuario al que quieres cobrar, no es necesario que realices este paso de nuevo.


3. Crear orden con la configuración de tus métodos de pago (obligatorio)

📘

¿Qué es una Orden?

Una orden representa la intención de compra/pago de tu cliente. Incluye todos los detalles relacionados a los métodos de pago, información de envío, lista de productos a comprar/pagar, cargos, descuentos, impuestos, o cualquier información que se requiera por el negocio para documentar la transacción.

La orden requiere de cierta información que se obtiene ya sea de algún servicio interno del negocio, o directamente del FrontEnd al solicitarla al usuario/cliente final. Los datos principales traducidos a atributos del request son:

CampoDescripción
customer¿Quién está pagando?
line_items¿Qué está pagando?
unit_price multiplicado por Quantity¿Cuánto está pagando?
payment_method¿Cuál es el método de pago?
metadata¿Información extra requerida por el negocio?

Para habilitar los métodos de pago dentro del request:

Utiliza el atributo allowed_payment_methods en el objeto checkout de la orden al momento de crearla. Puedes utilizar los siguientes valores: card, apple, bank_transfer, cash, bnpl, apple

Tipo de Checkout

En este proceso se define el tipo de implementación que usarás: Componente embebido o redireccionado. El tipo de componente que desees, debe ser definido en el campo type del objeto checkout.

ComponenteNombreConsideraciones adicionales
EmbebidoIntegrationNA
RedireccionadoHostedPayment
  • success url - failure url - redireccionar al checkout.url - redirection_time

Request

   curl --request POST \
    --url https://api.conekta.io/orders \
    --header 'Accept-Language: es' \
    --header 'accept: application/vnd.conekta-v2.2.0+json' \
    --header 'authorization: Bearer {PRIVATE KEY}' \
    --header 'content-type: application/json' \
    --data '
   {
   "checkout": {
   "allowed_payment_methods": ["card", "bank_transfer", "cash", "bnpl", "pay_by_bank"],
   "type": "Integration",
   "name": "Example"
   },
   "customer_info": {
   "name": "DevTest",
   "email": "[email protected]",
   "phone": "5522997233"
   },
   "pre_authorize": false,
   "currency": "MXN",
   "line_items": [
   {
     "brand": "Cohiba",
     "description": "Imported From Mex.",
     "name": "Box of Cohiba S1s",
     "quantity": 1,
     "unit_price": 500000
   }
   ]
   }
   '

Una vez creada la orden deberás obtener de la respuesta el Checkout ID asociado para inicializar el Checkout Component embebido en tu página de Checkout.

4. Crear una página de pago en el cliente (Checkout Embebido)

ℹ️

¿Usas Checkout Redireccionado (HostedPayment)? Este paso no aplica. Una vez creada la orden, redirige al usuario a la URL checkout.url que recibes en la respuesta.

Inicializar tu embedded Checkout Component

Carga nuestro paquete de JavaScript para mantenerte en cumplimiento con PCI asegurando que los detalles de pago sean enviados directamente a Conekta sin pasar por tu servidor.

El Checkout Component expone los siguientes eventos a través del objeto callbacks. Úsalos para reaccionar al estado del flujo de pago desde tu frontend:

EventoCuándo se disparaDatos recibidosAcción recomendada
onGetInfoSuccessEl Checkout Component terminó de cargarloadingTime.initLoadTime — tiempo de carga en msOcultar un loader, registrar métricas de rendimiento
onFinalizePaymentEl pago fue procesado correctamenteObjeto con id, charge y reference de la ordenRedirigir a página de éxito, actualizar tus sistemas
onErrorPaymentOcurrió un error durante el pagoDetalle del errorMostrar mensaje al usuario, registrar el error
onUpdateSubmitTriggerEl Checkout Component está listo para recibir un submit externoFunción de submitGuardar la función para invocarla desde tu propio botón "Pagar" (requiere useExternalSubmit: true)

Inicializa el Checkout Component con tu Llave Pública para completar el pago desde el Cliente:

<html>
  <head>
    <meta charset="utf-8" />
    <title>Checkout</title>
    <script
      crossorigin
      src="https://pay.conekta.com/v1.0/js/conekta-checkout.min.js"
    ></script>
    <!-- En este archivo esta la config del componente -->
  </head>
  <body>
    <div id="example" style="height: 714px"></div>
    <script type="text/javascript">
      const options = {
        backgroundMode: 'lightMode', //lightMode o darkMode
        colorPrimary: '#081133', //botones y bordes
        colorText: '#585987', // títulos
        colorLabel: '#585987', // input labels
        inputType: 'minimalMode', // minimalMode o flatMode,
  			excludeCardNetworks: ['Amex'], // Lista de marcas de tarjeta a ocultar (Amex, Visa, Mastercard) - opcional

      };
      const config = {
        locale: 'es',
        publicKey: '{{yourKey}}',
        targetIFrame: '#example',
        checkoutRequestId: '{{checkoutRequestId}}',
      };

      const callbacks = {
        // Evento que notifica cuando finalizó la carga del component/tokenizer
        onGetInfoSuccess: function (loadingTime) {
          console.log('loading time en milisegundos', loadingTime.initLoadTime);
        },
        // Evento que notifica cuando finalizó el pago correctamente
        onFinalizePayment: function (order) {
          console.log('success: ', JSON.stringify(order));
        },
        // Evento que notifica que ocurrió un error durante el pago
        onErrorPayment: function (error) {
          console.log('error en pago: ', error);
        },
      };
      window.ConektaCheckoutComponents.Integration({
        config,
        callbacks,
        options
      });
    </script>
  </body>
</html>

Nota: Con la configuración anterior tu componente de pago tendrá un alto fijo, si el contenido del componente de pago es más alto que el definido aparecerá un scroll automaticamente.

Si quieres que tu componente de pago no tenga un alto fijo sino que se adapte al alto del contenido puedes hacerlo evitando establecer el alto al contenedor y agregando el atributo autoresize: true a las options.

<html>
  ...
  <body>
    <div id="example"></div>  <!-- contenedor sin height -->
    <script type="text/javascript">
      const options = {
        ...,
        autoResize: true // activamos el autoResize
      };
       </script>
  </body>
</html>

El componente renderizado se debe ver de la siguiente manera

Ocultar el botón de pago y usar un trigger externo (opcional)

Si necesitas controlar desde tu propia interfaz cuándo se envía el pago (por ejemplo, usar un botón propio fuera del iframe del
componente o disparar el cobro desde un flujo de checkout personalizado), puedes ocultar el botón de pago integrado del Checkout Component y
encargarte tú mismo de invocar la acción de submit.

Para activar este comportamiento agrega el atributo useExternalSubmit: true dentro del objeto config y captura la función de
submit a través del callback onUpdateSubmitTrigger. Este callback recibe la función que debes ejecutar para disparar el pago manualmente desde tu propio botón.

const config = {
  locale: 'es',
  publicKey: 'key_xxxx',
  targetIFrame: '#example',                                                                 
  checkoutRequestId: '235c92c6-a174-45f7-9daa-6a1718c2d521',
  useExternalSubmit: true,                                                                                                           
};                                                        
                                                                                                                                     
// Función que invocarás desde tu propio botón "Pagar"    
const submitPayment = () => {
  submitConektaPayment();
};                                                                                                                                   
 
// Placeholder hasta que el componente notifique la función real                                                                     
let submitConektaPayment = () => {                        
  console.log('submit function is not available');
};

const callbacks = {
  // Evento que notifica cuando finalizó la carga del tokenizer                                                                      
  onGetInfoSuccess: function (loadingTime) {
    console.log('loading time en milisegundos', loadingTime.initLoadTime);                                                           
  },                                                                                                                                 
  // Evento que actualizará el trigger de submit externo
  onUpdateSubmitTrigger: function (submitFunction) {                                                                                 
    console.log('onUpdateSubmitTrigger');                                                                                            
    submitConektaPayment = submitFunction;
  },                                                                                                                                 
  onFinalizePayment: function (order) {                   
    console.log('success: ', order);
  },                                                                                                                                 
  onErrorPayment: function (error) {
    console.log('error en pago: ', error);                                                                                           
  },                                                      
};

window.ConektaCheckoutComponents.Integration({
  config,                  
  callbacks,
});                                                                                                                                  
📘

Notas:

  • Con useExternalSubmit: true, el botón de pago dentro del componente se oculta automáticamente.
  • onUpdateSubmitTrigger se ejecuta cuando el componente está listo para recibir la orden de submit; guarda la función recibida y úsala desde el botón de tu interfaz (por ejemplo, en el onClick de tu propio botón "Pagar").
  • Los eventos onFinalizePayment y onErrorPayment siguen funcionando igual que en la integración estándar.

Capturar eventos del pago

Automatiza tus procesos a través de los eventos que se generan en el flujo de pago. Para recibir estos eventos y ejecutar acciones sigue la guía de webhooks

Te recomendamos capturar los siguientes eventos:

EventoDescripción
order.paidEnviado cuando el cliente completa un pago de forma exitosa
order.pending_paymentEnviado cuando una orden es creada pero está pendiente de pago
order.declinedEnviado cuando el pago de una orden es declinado.

Al capturar estos eventos podrás tomar acciones post venta como:

  • Ejecutar un flujo de logística.
  • Actualizar tus bases de datos de órdenes.
  • Actualizar tus sistemas contables.