Pagos con Tarjeta

Acepta pagos únicos con Tarjetas y permite a tus clientes guardar sus tarjetas para futuros pagos

En esta documentación explicamos cómo aceptar pagos con Tarjetas de crédito y débito a través del Checkout Component. Selecciona el flujo que aplica a tu caso de uso:

  • Cargo Único: el cliente realiza un pago sin necesidad de crear una cuenta. Ideal para compras puntuales.
  • Tarjetas Guardadas: los clientes recurrentes pueden reutilizar tarjetas previamente guardadas, acelerando el checkout. Requiere Early Access.
👍

Acepta Apple Pay y Google Pay con esta misma integración

Tu integración de tarjetas puede aceptar Apple Pay y Google Pay: pagos en un toque, autenticados por el dispositivo y con una tasa de aprobación 15 a 20 puntos porcentuales más alta que la tarjeta digitada. Si las tienes habilitadas en tu Conekta Panel, se muestran automáticamente en tu checkout — sin cambios en tu integración.

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/v8
<dependency>
  <groupId>io.conekta</groupId>
  <artifactId>ct-conekta-java</artifactId>
  <version>6.0.0</version>
  <scope>compile</scope>
</dependency>

Flujo para pagos puntuales sin necesidad de asociar una cuenta de cliente. El campo customer_info puede incluir los datos del comprador directamente o un customer_id si ya tienes al cliente registrado en Conekta.

Crear un Customer (opcional)

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 esta información, como tarjetas guardadas, puedes seguir las instrucciones a continuación.

Con la siguiente llamada crearás un customer y obtendrás un customer_id el cual podrás guardar para realizar cobros en el futuro a la misma persona.

curl --location --request POST 'https://api.conekta.io/customers' \
    --header 'Accept: application/vnd.conekta-v2.3.0+json' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer key_xxxx' \
  --data-raw '{
    "name": "Felipe Gomez",
    "email": "[email protected]",
    "phone": "+5215522997233"
  }'
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();
            config.AccessToken = "key_xxxx";

            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";

            try
            {
                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 os
import time
from conekta.rest import ApiException
from pprint import pprint

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

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:
        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 'conekta'
Conekta.configure do |config|
  config.access_token = 'key_xxxx'
end

api_instance = Conekta::CustomersApi.new
customer = Conekta::Customer.new({email: '[email protected]', name: 'miguel', phone: '+5215555555555'})
opts = { accept_language: 'es' }

begin
  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 config = new Configuration({ accessToken: "key_xxxx" });
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/v8"
)

func main() {
    const acceptLanguage = "es"
    cfg := conekta.NewConfiguration()
    client := conekta.NewAPIClient(cfg)
    ctx := context.WithValue(context.TODO(), conekta.ContextAccessToken, "key_xxxx")
    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();
        HttpBearerAuth bearerAuth = (HttpBearerAuth) defaultClient.getAuthentication("bearerAuth");
        bearerAuth.setBearerToken("key_xxxx");

        CustomersApi apiInstance = new CustomersApi(defaultClient);
        Customer customer = new Customer();
        customer.setName("Customer Name");
        customer.setEmail("[email protected]");
        customer.setPhone("55454545454");
        try {
            CustomerResponse result = apiInstance.createCustomer(customer, "es", null);
            System.out.println(result);
        } catch (ApiException e) {
            System.err.println("Exception when calling CustomersApi#createCustomer");
            e.printStackTrace();
        }
    }
}
🚧

Importante:

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

Crear una Orden (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.

ℹ️

En esta versión, los métodos de pago disponibles en el Checkout se configuran directamente desde el Conekta Panel, no desde el API. Asegúrate de tener habilitado el método de pago Tarjeta en tu Panel antes de realizar pruebas.

Tipo de 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.3.0+json' \
 --header 'authorization: Bearer {PRIVATE KEY}' \
 --header 'content-type: application/json' \
 --data '
{
"checkout": {
"type": "Integration",
"name": "Example"
},
"customer_info": {
"name": "DevTest",
"email": "[email protected]",
"phone": "5522997233"
},
"pre_authorize": false,
"currency": "MXN",
"line_items": [
{
  "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.


Integración en el Cliente

ℹ️

Esta sección aplica únicamente al Checkout Embebido (Integration). Si usas Checkout Redireccionado (HostedPayment), redirige al usuario a la URL checkout.url que recibes en la respuesta de la orden y omite estos pasos.

Inicializar el 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>
  </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
      };
      const config = {
        locale: 'es',
        publicKey: '{{yourKey}}',
        targetIFrame: '#example',
        checkoutRequestId: '{{checkoutRequestId}}',
      };

      const callbacks = {
        onGetInfoSuccess: function (loadingTime) {
          console.log('loading time en milisegundos', loadingTime.initLoadTime);
        },
        onFinalizePayment: function (order) {
          console.log('success: ', JSON.stringify(order));
        },
        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>

Con el Checkout Component inicializado en tu página, tu cliente solo deberá ingresar los datos de su tarjeta y confirmar el pago.

Una vez procesado el pago, se disparará el evento onFinalizePayment con la información de la orden y el cargo. Los pagos con tarjeta son síncronos — el status llegará como paid directamente.

{
    "id": "ord_2tQAKpPrfkdyzZvfM",
    "reference": "646180111812345678",
    "charge": {
        "id": "63f3ea0d88dc6c0019a3fe39",
        "currency": "MXN",
        "payment_method": {
            "type": "card"
        },
        "status": "paid",
        "customer_id": "",
        "order_id": "ord_2tQAKpPrfkdyzZvfM"
    },
    "metaData": {}
}

En este momento podrás tomar decisiones relacionadas con el estado de la compra, como redirigir a una página de pago exitoso o mostrar el resumen de la compra.

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.

const config = {
  locale: 'es',
  publicKey: 'key_xxxx',
  targetIFrame: '#example',
  checkoutRequestId: '235c92c6-a174-45f7-9daa-6a1718c2d521',
  useExternalSubmit: true,
};

const submitPayment = () => {
  submitConektaPayment();
};

let submitConektaPayment = () => {
  console.log('submit function is not available');
};

const callbacks = {
  onGetInfoSuccess: function (loadingTime) {
    console.log('loading time en milisegundos', loadingTime.initLoadTime);
  },
  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.

⚠️

Este paso es crucial para mantener el estado de tus órdenes siempre actualizado. No depender únicamente del resultado del frontend te permite detectar pagos confirmados, declinados o pendientes en tiempo real — y tomar acción inmediata. Tener tus sistemas sincronizados con el estado real de cada cobro es también una de las medidas más efectivas para prevenir contracargos.

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 postventa como:

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

Siguiente paso: acepta wallets

Con tu integración de tarjetas lista, las wallets se habilitan desde tu Conekta Panel — sin cambios en tu request:



Did this page help you?