Suscripciones

El Token es un elemento seguro para permitir la interacción de sistemas sin la necesidad de exponer datos sensibles. El token como llave o código seguro es una práctica normalizada en la actualidad y muy común. El token es una referencia (un identificador) que regresa a los datos sensibles a través de un sistema de tokenización.

La tokenización, cuando se aplica a la seguridad de los datos, es el proceso de sustitución de un elemento de datos sensible por un equivalente no sensible denominado token, que no tiene un significado o valor extrínseco o explotable. Saber más.

📘

Indispensable:

  • Es necesario contar con conocimiento de API REST
  • Es preferible ser desarrollador fullstack (frontend + backend).
  • Contar con tus API Keys (llave personal) de pruebas.

Elementos clave para el proceso de tokenización

  1. Deberás crear un Token por cada tarjeta almacenada

  2. El Token es de único uso

  3. Puedes cambiar en las llamadas el uso de token por el source, para habilitar las tarjetas tokenizadas para generar cargos a tus clientes cada vez que ellos lo necesiten, y para subscripciones.

  4. Puedes utilizar las tarjetas de prueba, en tu cuenta Conekta, en ambiente pruebas para agilizar el desarrollo.

301

1. Crear un token

  1. Una vez que se valide el tipo de llamada, tendrás una respuesta como esta:
curl --location --request POST 'https://api.conekta.io/tokens' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
-u key_xxxxxxxxxxxxxx: \
--data-raw '{
    "checkout": {
    "returns_control_on": "Token"
    }
}'
{
    "id": "tok_2qSuGxyiuqmXiVpP5", //IMPORTANTE Parámetro clave 1
    "livemode": false,
    "used": false,
    "checkout": {
        "id": "8132d8a3-5919-4b88-a5e9-7be905f69134", //IMPORTANTE Parámetro clave 2
        "name": "tok-2qSuGxyiuqmXiVpP5",
        "livemode": false,
        "emails_sent": 0,
        "paid_payments_count": 0,
        "sms_sent": 0,
        "status": "Issued",
        "type": "Integration",
        "recurrent": false,
        "starts_at": 1631595600,
        "expires_at": 1631854799,
        "allowed_payment_methods": [
            "card"
        ],
        "exclude_card_networks": [],
        "needs_shipping_contact": false,
        "monthly_installments_options": [], // Por default no vienen los MSI
        "monthly_installments_enabled": false, // Por default no vienen los MSI
        "force_3ds_flow": false,
        "metadata": {},
        "can_not_expire": false,
        "object": "checkout",
        "on_demand_enabled": false // Menciona si los cargos bajo demanda estan activados.
    },
    "object": "token"
}

IMPORTANTE: Considerar el Id que es el Token que debes de guardar, es el identificador de los datos de la tarjeta y lo usarás en la creación del Customer

🚧

Token ID

"id": " tok_2qSuGxyiuqmXiVpP5 "

IMPORTANTE: Dentro del objeto de Checkout, toma en cuenta el Id , este lo tendrás que colocar dentro del Checkout Iframe, que inicializará el iframe para captura de datos de tarjeta.

🚧

Checkout ID

"checkout": {
"id": " 8132d8a3-5919-4b88-a5e9-7be905f69134 ",
...

2. Inicializar el iframe

Un iframe es un documento HTML que está incrustado dentro de otro en un sitio Web.

  1. El iframe se compone de una parte de HTML y una parte de JavaScript
<html>

<head>
  <meta charset="utf-8">
  <title>Checkout</title>
  <script type="text/javascript" src="https://pay.conekta.com/v1.0/js/conekta-checkout.min.js"></script>
</head>

<body>
  <div id="conektaIframeContainer" style="height: 1350px;"></div>
  <script type="text/javascript">
    window.ConektaCheckoutComponents.Card({
      targetIFrame: "#conektaIframeContainer",
//Este componente "allowTokenization" permite personalizar el tokenizador, por lo que su valor siempre será TRUE
      allowTokenization: true, 
      checkoutRequestId: "8132d8a3-5919-4b88-a5e9-7be905f69134", // // Checkout request ID, es el mismo ID generado en el paso 1
      publicKey: "Key_LlavePUBLICA123456789", // Llaves: https://developers.conekta.com/docs/como-obtener-tus-api-keys
      options: {
        styles: {
// inputType modifica el diseño del Web Checkout Tokenizer
//        inputType: 'basic' // 'basic' | 'rounded' | 'line'
          inputType: 'rounded',
// buttonType modifica el diseño de los campos de llenado de información del  Web Checkout Tokenizer
//        buttonType: 'basic' // 'basic' | 'rounded' | 'sharp'
          buttonType: 'rounded',
//Elemento que personaliza el borde de color de los elementos            
          states: {
            empty: {
              borderColor: '#FFAA00' // Código de color hexadecimal para campos vacíos
            },
            invalid: {
              borderColor: '#FF00E0' // Código de color hexadecimal para campos inválidos
            },
            valid: {
              borderColor: '#0079c1' // Código de color hexadecimal para campos llenos y válidos
            }
          }
        },
        languaje: 'es', // 'es' Español | 'en' Ingles
//Elemento que personaliza el botón que finzaliza el guardado y tokenización de la tarjeta
        button: {
          colorText: '#ffffff', // Código de color hexadecimal para el color de las palabrás en el botón de: Alta de Tarjeta | Add Card
          //text: 'Agregar Tarjeta***', //Nombre de la acción en el botón ***Se puede personalizar
          backgroundColor: '#301007' // Código de color hexadecimal para el color del botón de: Alta de Tarjeta | Add Card
        },
//Elemento que personaliza el diseño del iframe
        iframe: {
          colorText: '#65A39B',  // Código de color hexadecimal para el color de la letra de todos los campos a llenar
          backgroundColor: '#FFFFFF' // Código de color hexadecimal para el fondo del iframe, generalmente es blanco.
        }
      },
      onCreateTokenSucceeded: function(token) {
        console.log(token)
      },
      onCreateTokenError: function(error) {
        console.log(error)
      }
    })
  </script>
</body>

</html>
  1. Así se muestra el iframe, a modo de ejemplo:

NOTA: Nosotros utilizamos la herramienta CodePen para mostrar el iframe Esta herramienta es un aliado poderoso de desarrollo, ya que te permite probar en tiempo real los comportamientos del iframe. NO DEBE CONSIDERARSE PARTE DEL DESARROLLO, puedes usar cualquier herramienta siempre y cuando, las herramientas tengan la capacidad de separar HTML, CSS y JS y que estos componentes separados funcionen como un solo componente. Recuerda incrustar el iframe en tu página/tienda en línea.

650

Así se muestra el iframe

❗️

IMPORTANTE:

Este iframe debe estar disponible para que los clientes puedan llenar sus datos de la tarjeta, y de esta forma generar el token correspondiente. En los pasos 3 y 4 podrás comprender el flujo de implementación paso a paso en los endpoints de la API Conekta.

  1. El cliente, al dar Clic en Guardar la tarjeta, va a generar un evento que se tiene que captar para confirmación de creación de Token Satisfactorio:
651

Vista del Iframe lleno

  1. Ahora debemos estar atentos a las notificaciones de los logs que se ejecutan en la consola, para recabar los eventos:
1440

Vista del Iframe lleno visto desde la consola antes de dar clic en Alta de Tarjeta | Add Card

  1. Al dar Clic en Guardar la tarjeta, se genera un evento que se tiene que captar para confirmación de creación de Token Satisfactorio:
  • En el código del Iframe se consideran el manejo de 2 eventos, tomar en cuenta su funcionamiento.
  • Solo se puede guardar una tarjeta por Token. Si necesitas guardar más tarjetas, debes de crear otro token en el Paso 1.

Respuesta exitosa (Una única vez)

  1. Primer escenario, el caso de éxito o camino feliz.
1440

En la consola, podemos ver los eventos que se generan al tener un registro exitoso con los datos de la tarjeta. El objeto es recuperado del evento onCreateTokenSucceeded

Respuesta fallida, cuando el checkout ID ya se ha utilizado una vez

7b. Segundo escenario, este es el caso de uso de error y se muestra cuando algún elemento es incorrecto en la llamada del checkout, pero principalmente cuando el Checkout ID ya se ha utilizado con anterioridad.

1440

Este error se genera cuando el evento ya ha sido consumido una vez y por lo tanto, ya no es útil para tokenizar nuevamente, el evento es En la consola, podemos ver los eventos que se generan al tener un registro exitoso con los datos de la tarjeta. El objeto es recuperado del evento onCreateTokenError

3. Creación de cliente

  • Puedes revisar para este efecto la referencia API.
  • También puedes revisar la receta.
  • El Token previamente creado, lo unirás con la creación de un Customer:
  1. Una vez que se valide el tipo de llamada, tendrás una respuesta como esta:
curl --location --request POST 'https://api.conekta.io/customers' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
-u key_xxxxxxxxxxxxxx: \
--data-raw '{
	"name": "El Fulanito - The guy",
	"email": "[email protected]",
	"phone": "55-5555-5555"
  //Si se decide crear un cliente con un token asociado: https://developers.conekta.com/page/web-checkout-tokenizer
  //"payment_sources": [{
  //"type": "card",
  //"token_id": "tok_2q6cyio5sDqCyvYh7" //Este token se crea en el paso 1 de la implementación del Web Checkout tokenizer y asegurate de haber unido los datos de la tarjeta con el token, mediante el iframe del paso 2.
  //}]
}'
{
    "livemode": false,
    "name": "El Fulanito - The guy",
    "email": "[email protected]",
    "phone": "55-5555-5555",
    "id": "cus_1a2b3c4d5e6f7g8h",//Este ID es indispensable para las llamadas futuras
    "object": "customer",
    "created_at": 1631659751,
    "corporate": false,
    "custom_reference": "",
    "default_payment_source_id": "src_2qSsQUCVaMrfxAfov",
  //Payment Sources es un objeto que solamente se crea cuando se agrega en el request un token desde el Web Checkout Tokenizer
    "payment_sources": {
        "object": "list",
        "has_more": false,
        "total": 1,
        "data": [
            {
                "id": "src_2qSsQUCVaMrfxAfov", //ID clave
                "object": "payment_source",
                "type": "card",
                "created_at": 1631659751,
                "last4": "4242",
                "bin": "424242",
                "card_type": "credit",
                "exp_month": "01",
                "exp_year": "23",
                "brand": "visa",
                "name": "Jaciel Israel Oliva Contreras",
                "parent_id": "cus_1a2b3c4d5e6f7g8h",
                "default": true,
                "visible_on_checkout": false
            }
        ]
    }
}
  1. Considera el Id que representa al Customer, será usado en el siguiente paso para realizar los cargos en las órdenes.

🚧

Customer ID

"id": " cus_1a2b3c4d5e6f7g8h ",

❗️

IMPORTANTE:

Al momento de generar/crear las ordenes, es importante definir que puedes utilizar un token, esto inmediatamente es un cargo único, puedes utilizar un recurso para habilitar cargos por solicitud y utilizar simplemente el parámetro con objeto de utilizar la tarjeta que se ha colocado como principal predeterminada.

Token único: Puedes utilizar por e.g. el token del Paso 2

"charges":[{
    "payment_method": {
       "type": "card", //  CARD. cuando no es el predeterminado, DEFAULT para el determinado.
       "token_id":"tok_test_visa_4242"
      }
  }],

Cargo por solicitud con {payment_sources}:

"charges":[{
    "payment_method": {
        "type": "card", //  CARD. cuando no es el predeterminado, DEFAULT para el determinado.
        "payment_source_id": "src_2qUCNd5AyQqfPMBuV"
      }
  }],

Pagar utilizando el método predeterminado:

"charges":[{
    "payment_method": {
        "type": "default", // Ningún otro dato es requerido aquí.
      }
  }],
  1. Ahora debemos hacer una llamada para actualizar el método de pago PREDETERMINADO
  • Podemos seguir la receta que contiene información descriptiva.
  • O podemos probarlo directamente en la referencia API.

4. Crear un plan

  1. Un plan de servicio es una técnica para describir simultáneamente el proceso de servicio, los puntos de contacto del cliente y las evidencias de servicio desde el lado del del cliente.

Como resultado, recibirás una respuesta JSON

curl --location --request POST 'https://api.conekta.io/plans' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
-u key_xxxxxxxxxxxxxx: \
--data-raw '{
       "id": "Plan_API_TEST",     		 //Id del Plan que usarás para unirlo con la creación de Checkout
       "name": "Plan de elementos API", // Nombre de tu plan
       "amount": 77700,  			    // monto del plan, dependerá de la frecuencia y recurrencia
       "currency": "MXN",   		    //sólo soporta MXN
       "interval": "month",  		    //weekly/biweekly/montly/yearly
       "frequency": 1,			        //frecuencia del cargo
       "trial_period_days": 30,         //Colocar número de días o de lo contrario 0
       "expiry_count": 6 			    // número de repeticiones de la frecuencia
}
'
{
    "id": "Plan_API_TEST", // Parámetro clave para generar las subscripciones,
    "livemode": false,
    "created_at": 1632085172,
    "name": "Plan de elementos API",
    "amount": 77700,
    "currency": "MXN",
    "interval": "month",
    "frequency": 1,
    "expiry_count": 6,
    "trial_period_days": 30,
    "object": "plan"
}
1440

Vista del panel Conekta, cuando se ha creado un plan

5. Crear una subscripción a un plan

  1. La suscripción es la acción que realiza un usuario cuando quiere recibir una serie de servicios, noticias, o productos a un precio determinado, o de forma gratuita.

En este caso existe un importe a cambio de recibir información, cursos, o documentos. El suscriptor se suscribe para recibir contenido premium, o privado, ya que no está disponible para todo el público.

  • Puedes apoyarte en la referencia API
  • NOTA: Para efectos de la presente guía, usaremos el source con objeto de suscribir un cliente utilizando su método de pago predeterminado.

Como resultado, tendrás la confirmación de subscripción de tu cliente:

curl --location --request POST 'https://api.conekta.io/customers/cus_2qUBQEkFJ7Kw4GVTJ/subscription' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
-u key_xxxxxxxxxxxxxx: \
--data-raw '{
   "card": "src_2qUCNd5AyQqfPMBuV",
   "customer_id": "cus_2qUBQEkFJ7Kw4GVTJ",
   "plan": "Plan_API_TEST"
}'
{
    "id": "sub_2qUZfg656aS38RQg8",
    "status": "in_trial",
    "object": "subscription",
    "created_at": 1632107495,
    "subscription_start": 1632107495,
    "trial_end": 1634699495,
    "plan_id": "Plan_API_TEST",
    "customer_id": "cus_2qUBQEkFJ7Kw4GVTJ", // Nosotros utilizamos otro customer_ID, ya que este proceso puede utilizar clientes ya creados con anterioridad.
    "card_id": "src_2qUCNd5AyQqfPMBuV"
}
1440

Vista de la subscripción creada asociada a un plan, para el customer ID mostrado anteriormente.

6. Crear una subscripción a un plan y crear el cliente al mismo tiempo

  • Puedes revisar para este efecto la referencia API.
  • También puedes revisar la receta.
  • El Token previamente creado, lo unirás con la creación de un Customer:
  1. Una vez que se valide el tipo de llamada, tendrás una respuesta como esta:
curl --location --request POST 'https://api.conekta.io/customers' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Basic S2V5X0xsYXZlUFJJVkFEQTEyMzQ1Njc4OQ==' \
--data-raw '{
	"name": "Cliente nuevo otro Fulanito - Another guy",
	"email": "[email protected]",
	"phone": "55-5555-5555",
    "plan_id": "Plan_API_TEST",
  //Si se decide crear un cliente con un token asociado: https://developers.conekta.com/page/web-checkout-tokenizer
  "payment_sources": [{
  "type": "card",
  "token_id": "tok_2qV8X8288FEeiYw7u" //Este token se crea en el paso 1 de la implementación del Web Checkout tokenizer y asegurate de haber unido los datos de la tarjeta con el token, mediante el iframe del paso 2.
  }]
}'
{
    "livemode": false,
    "name": "Cliente nuevo otro Fulanito - Another guy",
    "email": "[email protected]",
    "phone": "55-5555-5555",
    "subscription": {
        "id": "sub_2qV8Yd8oZmg22UEBu",
        "status": "in_trial",
        "object": "subscription",
        "created_at": 1632257310,
        "subscription_start": 1632257310,
        "trial_end": 1634849310,
        "plan_id": "Plan_API_TEST",
        "customer_id": "cus_2qV8Yd8oZmg22UEBs",
        "card_id": "src_2qV8Yd8oZmg22UEBt"
    },
    "id": "cus_2qV8Yd8oZmg22UEBs",
    "object": "customer",
    "created_at": 1632257310,
    "corporate": false,
    "custom_reference": "",
    "default_payment_source_id": "src_2qV8Yd8oZmg22UEBt",
    "payment_sources": {
        "object": "list",
        "has_more": false,
        "total": 1,
        "data": [
            {
                "id": "src_2qV8Yd8oZmg22UEBt",
                "object": "payment_source",
                "type": "card",
                "created_at": 1632257310,
                "last4": "4242",
                "bin": "424242",
                "card_type": "credit",
                "exp_month": "01",
                "exp_year": "23",
                "brand": "visa",
                "name": "Jaciel Israel Oliva Contreras",
                "parent_id": "cus_2qV8Yd8oZmg22UEBs",
                "default": true,
                "visible_on_checkout": false
            }
        ]
    }
}

👍

Características de las suscripciones

  1. Pueden crearse
  2. Pueden ser actualizadas: En caso de actualizar el plan de una suscripción del Plan A al Plan B, se comenzará a realizar el cobro del Plan B en el momento que se termine el ciclo de cobro del Plan A.
  3. Pueden pausarse: Es posible pausar una suscripción siempre y cuando esta se encuentre activa, para continuar haciendo los cargos es necesario reanudar la suscripción
  4. Pueden reanudarse (quitar la pausa.): Una suscripción se puede reanudar cuando a sido pausada con anterioridad.
  5. Se pueden cancelar : En caso de querer terminar la suscripción antes de cumplir con el número de cobros indicados por el plan, se puede cancelar la suscripción.

Cada cliente solo puede mantener una suscripción activa

1440

Vista de los planes asociados al cliente, del paso 6 y 8

7. Notificar a tu cliente

El código es tuyo y tu decides que elementos o acciones realizar cada vez que un evento sea disparado por medio de los webhooks.

8. Crear un webhook

  1. Para entender el concepto de webhook intententemos con un supuesto; Actualmente tienes una tienda online o negocio en línea y deseas proponer un descuento especial a cualquier usuario que abra tu email durante las primeras 12 horas. La primera opción es la manual, es decir, para hacerlo con las estadísticas de los emails vistos en tu estadística, tratar de filtrar aquellos clientes que regularmente los abren y enviar el código de descuento a quienes hayan abierto tu mensaje. No suena muy rápido, ¿verdad?

La segunda opción es automatizarlo con webhooks, que enviarán el descuento a cualquiera que abra tu email. ¿Este escenario parece una forma más eficaz de controlar el negocio, cierto?

En otras palabras, los webhooks son eventos que desencadenan acciones. Su nombre se debe a que funcionan como gancho de los programas en Internet y casi siempre se utilizan para la comunicación entre sistemas. Son la manera más sencilla de obtener un aviso cuando algo ocurre en otro sistema.

El webhook será una dirección en el internet que estará a la espera de recibir alguna notificación y con ello, podrás programar acciones a tomar con estos eventos/avisos recibidos.

📘

Recuerda que:

En tu cuenta de panel Conekta, solamente puedes tener máximo 10 webhooks

Te recomendamos seguir la receta para crear webhooks

curl --location --request POST 'https://api.conekta.io/webhooks' \
--header 'Accept: application/vnd.conekta-v2.0.0+json' \
--header 'Content-Type: application/json' \
-u key_xxxxxxxxxxxxxx: \
--data-raw '{         
            "url": "https://webhook.site/bdd7a24f-64ef-410a-b299-9dee8y8a01c0",
            "status": "listening",
            "subscribed_events": [
                "charge.created",
                "charge.paid",
                "charge.under_fraud_review",
                "charge.fraudulent",
                "charge.refunded",
                "charge.preauthorized",
                "charge.declined",
                "charge.canceled",
                "charge.reversed",
                "charge.pending_confirmation",
                "charge.expired",
                "customer.created",
                "customer.updated",
                "customer.deleted",
                "webhook.created",
                "webhook.updated",
                "webhook.deleted",
                "charge.chargeback.created",
                "charge.chargeback.updated",
                "charge.chargeback.under_review",
                "charge.chargeback.lost",
                "charge.chargeback.won",
                "payout.created",
                "payout.retrying",
                "payout.paid_out",
                "payout.failed",
                "plan.created",
                "plan.updated",
                "plan.deleted",
                "subscription.created",
                "subscription.paused",
                "subscription.resumed",
                "subscription.canceled",
                "subscription.expired",
                "subscription.updated",
                "subscription.paid",
                "subscription.payment_failed",
                "payee.created",
                "payee.updated",
                "payee.deleted",
                "payee.payout_method.created",
                "payee.payout_method.updated",
                "payee.payout_method.deleted",
                "charge.score_updated",
                "receipt.created",
                "order.canceled",
                "order.charged_back",
                "order.created",
                "order.expired",
                "order.fraudulent",
                "order.under_fraud_review",
                "order.paid",
                "order.partially_refunded",
                "order.pending_payment",
                "order.pre_authorized",
                "order.refunded",
                "order.updated",
                "order.voided",
                "order.declined",
                "webhook_ping"
            ]
}'
{
    "url": "https://webhook.site/bdd7a24f-64ef-410a-b299-9dee8y8a01c0",
    "status": "being_pinged",
    "subscribed_events": [
        "charge.created",
        "charge.paid",
        "charge.under_fraud_review",
        "charge.fraudulent",
        "charge.refunded",
        "charge.preauthorized",
        "charge.declined",
        "charge.canceled",
        "charge.reversed",
        "charge.pending_confirmation",
        "charge.expired",
        "customer.created",
        "customer.updated",
        "customer.deleted",
        "webhook.created",
        "webhook.updated",
        "webhook.deleted",
        "charge.chargeback.created",
        "charge.chargeback.updated",
        "charge.chargeback.under_review",
        "charge.chargeback.lost",
        "charge.chargeback.won",
        "payout.created",
        "payout.retrying",
        "payout.paid_out",
        "payout.failed",
        "plan.created",
        "plan.updated",
        "plan.deleted",
        "subscription.created",
        "subscription.paused",
        "subscription.resumed",
        "subscription.canceled",
        "subscription.expired",
        "subscription.updated",
        "subscription.paid",
        "subscription.payment_failed",
        "payee.created",
        "payee.updated",
        "payee.deleted",
        "payee.payout_method.created",
        "payee.payout_method.updated",
        "payee.payout_method.deleted",
        "charge.score_updated",
        "receipt.created",
        "order.canceled",
        "order.charged_back",
        "order.created",
        "order.expired",
        "order.fraudulent",
        "order.under_fraud_review",
        "order.paid",
        "order.partially_refunded",
        "order.pending_payment",
        "order.pre_authorized",
        "order.refunded",
        "order.updated",
        "order.voided",
        "order.declined",
        "webhook_ping",
        "charge.created",
        "charge.paid",
        "charge.under_fraud_review",
        "charge.fraudulent",
        "charge.refunded",
        "charge.preauthorized",
        "charge.declined",
        "charge.canceled",
        "charge.reversed",
        "charge.pending_confirmation",
        "charge.expired",
        "customer.created",
        "customer.updated",
        "customer.deleted",
        "webhook.created",
        "webhook.updated",
        "webhook.deleted",
        "charge.chargeback.created",
        "charge.chargeback.updated",
        "charge.chargeback.under_review",
        "charge.chargeback.lost",
        "charge.chargeback.won",
        "payout.created",
        "payout.retrying",
        "payout.paid_out",
        "payout.failed",
        "plan.created",
        "plan.updated",
        "plan.deleted",
        "subscription.created",
        "subscription.paused",
        "subscription.resumed",
        "subscription.canceled",
        "subscription.expired",
        "subscription.updated",
        "subscription.paid",
        "subscription.payment_failed",
        "payee.created",
        "payee.updated",
        "payee.deleted",
        "payee.payout_method.created",
        "payee.payout_method.updated",
        "payee.payout_method.deleted",
        "charge.score_updated",
        "receipt.created",
        "order.canceled",
        "order.charged_back",
        "order.created",
        "order.expired",
        "order.fraudulent",
        "order.under_fraud_review",
        "order.paid",
        "order.partially_refunded",
        "order.pending_payment",
        "order.pre_authorized",
        "order.refunded",
        "order.updated",
        "order.voided",
        "order.declined",
        "webhook_ping"
    ],
    "synchronous": false,
    "id": "614bc30ffb7dfd7b40f20393",
    "object": "webhook",
    "production_enabled": false,
    "development_enabled": true
}

9. Recibir el evento del webhook

Para poder confirmar los pagos que se realicen en el intervalo que indicaste deberás añadir un Webhook en tu Admin Conekta para recibir las notificaciones POST (HTTP JSON) correctamente.

Utiliza URLs públicos: Si no tienes un IP público o un domino a tu disposición, puedes utilizar servicios como ultrahook, localtunnel, ngrok o pipedream.

Consultar la referencia sobre Webhooks.

A continuación, te mostramos un ejemplo de como viene la estructura del webhook:

{
  "data": {
    "object": {
      "id": "sub_2qVWjd2TP7HZVmxNp",
      "status": "in_trial",
      "object": "subscription",
      "charge_id": null,
      "created_at": 1632358420,
      "subscription_start": 1632358420,
      "canceled_at": null,
      "paused_at": null,
      "billing_cycle_start": null,
      "billing_cycle_end": null,
      "trial_start": null,
      "trial_end": 1634950420,
      "plan_id": "Plan_API_TEST",
      "last_billing_cycle_order_id": null,
      "customer_id": "cus_2qVPCWJ7ksLK1Ldaq",
      "customer_custom_reference": null,
      "card_id": "src_2qVPETFURNfBwEX6v"
    },
    "previous_attributes": {}
  },
  "livemode": false,
  "webhook_status": "pending",
  "webhook_logs": [
    {
      "id": "webhl_2qVWjd2TP7HZVmxP1",
      "url": "https://webhook.site/bdd7xa24f-64ef-410a-b299-9dee8y8a01c0",
      "failed_attempts": 0,
      "last_http_response_status": -1,
      "response_data": null,
      "object": "webhook_log",
      "last_attempted_at": 0
    }
  ],
  "id": "614bd014fb7dfd3edaf1194e",
  "object": "event",
  "type": "subscription.created",
  "created_at": 1632358420
}

Apéndice 1: Máquina de Estados

Suscripciones tienen una máquina de estados para controlar e informar cambios durante su ciclo de vida. Ciertos cambios de estado suceden en automático cuando pasa o se declina un pago, y otros son cambios manuales efectuados desde Panel o el API. Las suscripciones pueden tener los siguientes estados:

in_trial
La suscripción es nueva y no se va a cobrar al cliente todavía hasta el siguiente ciclo de cobranza.

active
La suscripción se ha cobrado correctamente y se ha programado el siguiente ciclo de cobro.

past_due
No se ha podido cobrar el ciclo actual de suscripción correctamente.

paused
La suscripción fue pausada. Sólo se puede llegar a este estado por intervención manual desde el API o Panel.

canceled
La suscripción ha sido cancelada por intervención manual, porque fallaron los 3 reintentos de pago, o porque se terminaron todos los ciclos correctamente (en caso de tener un cupo limitado).

698

Apéndice 2: Reintentos de Cobro

En caso de que falle un intento de cobro, una suscripción va a reintentar el cobro hasta 3 veces, cada 50 horas. En caso de que fallen todos los reintentos de cobro la suscripción se va a cancelar.

601