Pagos Recurrentes en Efectivo
Pagos Recurrentes en efectivo
Hemos creado este tutorial para que puedas recibir pagos recurrentes en efectivo a través de Conekta. Así, tus clientes podrán pagar las veces que quieran tus productos o servicios. En el caso de Oxxo, cada cliente tendrá una referencia única para realizar los pagos.
Primeros pasos
-Te recomendamos tener conocimiento de APIs.
Paso 1 - Agrega tu llave privada y versión del API
Copia tus llaves privadas de pruebas. Si aún no las tienes, puedes obtenerlas en el siguiente enlace: panel Conekta](https://admin.conekta.com/settings/keys).
# N/A
require_once("/path/to/lib/Conekta.php");
\Conekta\Conekta::setApiKey("key_eYvWV7gSDkNYXsmr");
\Conekta\Conekta::setApiVersion("2.0.0");
require "conekta"
Conekta.api_key = "key_eYvWV7gSDkNYXsmr"
Conekta.api_version = "2.0.0"
import conekta
conekta.api_key = "key_eYvWV7gSDkNYXsmr"
conekta.api_version = "2.0.0"
var conekta = require('conekta');
conekta.api_key = 'key_eYvWV7gSDkNYXsmr';
conekta.api_version = '2.0.0';
import com.conekta;
Conekta.setApiKey("key_eYvWV7gSDkNYXsmr");
com.conekta.Conekta.apiVersion = "2.0.0";
using conekta;
conekta.Api.apiKey = "key_eYvWV7gSDkNYXsmr";
conekta.Api.version = "2.0.0";
import (
conekta "github.com/conekta/conekta-go"
)
conekta.APIKey = "key_pMcnDF4zFyWKyLG15LuqwA"
Paso 2 - Crea tu orden de pago recurrente
CUSTOM_REFERENCE_RETURNED se refiere a su referencia personalizada y barcode_url es la imagen del código de barras generada.
begin
customer = Conekta::Customer.create({
name: "Fulanito",
email: "[email protected]",
phone: "52134659439",
payment_method: {
type: "cash_recurrent"
}
})
rescue Conekta::Error => error
for error_detail in error.details do
puts error_detail.message
end
end
curl --request POST \
--url https://api.conekta.io/customers \
--header 'accept: application/vnd.conekta-v2.0.0+json' \
-u key_eYvWV7gSDkNYXsmr: \
--header 'content-type: application/json' \
--data '{
"name": "Fulanito",
"email": "[email protected]",
"phone": "+5218181818181",
"payment_sources": [{
"type": "oxxo_recurrent"
}]
}'
#Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn" }]
}}try{
$customer = \Conekta\Customer::create(
array(
'name' => "fulanito",
'email' => "[email protected]",
'phone' => "+5218181818181",
'payment_sources' => array(
array(
'type' => "oxxo_recurrent"
)
)
)
);
var_dump(json_encode($customer));
} catch (\Conekta\ProcessingError $error){
echo $error->getMessage();
} catch (\Conekta\ParameterValidationError $error){
echo $error->getMessage();
} catch (\Conekta\Handler $error){
echo $error->getMessage();
}
#Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn" }]
}}
try{
$customer = \Conekta\Customer::create(
array(
'name' => "fulanito",
'email' => "[email protected]",
'phone' => "+5218181818181",
'payment_sources' => array(
array(
'type' => "oxxo_recurrent"
)
)
)
);
var_dump(json_encode($customer));
} catch (\Conekta\ProcessingError $error){
echo $error->getMessage();
} catch (\Conekta\ParameterValidationError $error){
echo $error->getMessage();
} catch (\Conekta\Handler $error){
echo $error->getMessage();
}
#Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
try:
customer = conekta.Customer.create({
"name": "Fulanito",
"email": "[email protected]",
"phone": "+5218181818181",
"payment_method": {
"type": "oxxo_recurrent"
}
})
except conekta.ConektaError as e:
print e.message
#Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
customer = conekta.Customer.create({
"name": "Fulanito",
"email": "[email protected]",
"phone": "+5218181818181",
"payment_method": {
"type": "oxxo_recurrent"
}
}, function(err, res) {
console.log(res.toObject());
});
//Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
try{
Customer customer = Customer.create(
new JSONObject("{"
+ "'name': 'Fulanito',"
+ "'email': '[email protected]',"
+ "'phone': '+5218181818181',"
+ "'payment_method': {"
+ "'type': 'oxxo_recurrent',"
+ "}"
+ "}"
)
);
}catch (Conekta::Error e) {
System.out.println(e.details.get(0).message);
}
//Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
try{
conekta.Customer customer = new conekta.Customer ().create(@"{
""name"": ""Fulanito"",
""email"": ""[email protected]"",
""phone"": ""+5218181818181"",
""payment_method"": {
""type"": ""oxxo_recurrent"",
}
}");
} catch (ConektaException e) {
foreach (JObject obj in e.details) {
System.Console.WriteLine("\n [ERROR]:\n");
System.Console.WriteLine("message:\t" + obj.GetValue("message"));
System.Console.WriteLine("debug:\t" + obj.GetValue("debug_message"));
System.Console.WriteLine("code:\t" + obj.GetValue("code"));
}
}
//Respuesta json de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
payment := &conekta.PaymentSourceCreateParams{
PaymentType: "oxxo_recurrent",
}
cus := &conekta.CustomerParams{}
cus.Name = "fulanito"
cus.Email = "[email protected]"
cus.Phone = "+5215555555555"
cus.PaymentSources = append(cus.PaymentSources, payment)
res, err := customer.Create(cus)
//Respuesta de API
{
"livemode":false,
"name":"Oxxo recc",
"email":"[email protected]",
"phone":"52134659439",
"id":"cus_2jP5P8huCTWqcTtrn",
"object":"customer",
"created_at":1538686075,
"corporate":false,
"custom_id":"",
"payment_sources":{
"object":"list",
"has_more":false,
"total":1,
"data":[{
"id":"off_ref_2jP5P8huCTWqcTtro",
"object":"payment_source",
"type":"oxxo_recurrent",
"provider":"Oxxo",
"reference":"CUSTOM_REFERENCE_RETURNED",
"barcode":"CUSTOM_REFERENCE_RETURNED",
"barcode_url":"https://sandbox_reference.png",
"expires_at":0,
"created_at":1538686075,
"parent_id":"cus_2jP5P8huCTWqcTtrn"}]
}}
Paso 3 - Presenta la ficha de pago
Utiliza la ficha de pago que muestre las cadenas que corresponden al pago en efectivo configurado para tu negocio. Esta ficha permitirá mostrarle a tus clientes la referencia de pago en efectivo junto con los pasos necesarios para completarlo en el punto de venta de su preferencia.
Referencia de pago "Oxxo"
Referencia de pago "Otras cadenas"
Ficha de pago en efectivo con Conekta
Tienes que incluirla en tu Checkout o enviarla por correo para ofrecer una mejor experiencia.
Puedes obtenerla en Ejemplo de pago en efectivo con Conekta
En este link puedes descargar los logos de nuestra red de efectivo.
Paso 4 - Crea un Webhook
Recuerda que Conekta debe estar en constante comunicación con tu sitio a través de Webhooks para:
1) Validar que la referencia del usuario sea correcta y pueda hacer pagos
2) Aprobar la cantidad que el usuario quiere pagar
3) Notificar un pago
Un “Webhook” es un sistema de notificaciones, donde tu sitio debe definir una dirección o URL, para que nuestra API mande peticiones HTTP y pueda notificarte de los eventos que se van a realizar en tu sitio. Por ello, deberás crear un “Webhook” desde tu perfil de administrador con los siguientes pasos:
Abre el menú principal de tu cuenta, ubicado en la esquina superior derecha, y selecciona la sección “Webhooks”.
Paso 4.1 - Crear un Webhook Sincrónico para Aprobar Pagos
En el caso de pagos recurrentes, vas a recibir eventos especiales para poder aprobar o declinar los pagos de forma dinámica. Estas peticiones te van a llegar en tiempo real y tienes un máximo de dos segundos para contestarlas o se va declinar el pago. En el Perfil de Administrador abre el menú principal de tu cuenta, ubicado en la esquina superior derecha, y selecciona Webhooks
Selecciona la opción “Crear Webhook” al presionarlo se abrirá una ventana con un formulario en donde deberás colocar la dirección o URL del “Webhook” donde deseas recibir las notificaciones de los pagos recurrentes en efectivo con Conekta, selecciona la casilla de "Usar para Oxxo Pay Recurrente" y da clic en “Crear”.
Ya estás listo para recibir pagos recurrentes desde tu sitio.
Paso 4.2 - Crea un Webhook asincrónico para recibir notificaciones de pagos
Adicional al primer Webhook, tendrías que armar endpoint para escuchar notificaciones asincrónicas de pago. A diferencia de las notificaciones anteriores, Conekta va reintentar las notificaciones en caso de que fallen y vas a recibir mayor carga de otras notificaciones por eso que es importante ocupar otro endpoint.
Cuando creas este Webhook, no tendrías que indicar que es para pagos recurrentes.
Paso 5 - Responder a Webhooks
A diferencia de métodos de pago en línea, como tarjetas, los usuarios tienen que realizar acciones offline para hacer pagos en efectivo así que flujo es asincrónico y el procesamiento y seguridad de notificaciones es fundamental para tu flujo.
Paso 5.1 - Responder a Consultas
El primero notificación a responder, es una notificación sincrónica de consulta y con el tipo de inbound_payment.lookup
.
{
"data":{
"object": {
"payment_method": {
"service_name": "OxxoPay",
"barcode_url": "https://barcode/url.png",
"object": "cash_payment",
"type": "oxxo",
"expires_at": 1541289600,
"reference": "8400003726321"
},
"charge_id": "5bb675388a268e0ef4a56a42",
"livemode": true,
"created_at": 0,
"object": "inbound_payment",
"amount": 0,
"currency": "MXN",
"customer_id": "cus_2jP5P8huCTWqcTtrn"
},
"previous_attributes": {}
},
"livemode": true,
"webhook_status": "not_applicable",
"webhook_logs": [],
"id": "5b438f82583eb80d50b4652c",
"object": "event",
"type": "inbound_payment.lookup",
"created_at": 1531154306
}
Para aprobar el pago tendrías que contestar en JSON, indica que payable es true, y el rango de cantidades en centavos.
{
"payable": true,
"min_amount": 5000,
"max_amount": 1000000
}
En caso que quieras declinar un pago, puedes indicar payable: false y un código de rechazo. Puedes consultar la lista completa de códigos de rechazo al final del tutorial.
{
"payable": false,
"failure_code": "15"
}
Paso 5.2 - Responder a confirmaciones de Pago
La primer notificación a responder, es una notificación sincrónica de consulta y con el tipo de inbound_payment.payment_attempt
.
{
"data": {
"object": {
"payment_method": {
"service_name":"OxxoPay",
"barcode_url": "https://s3.amazonaws.com/cash_payment_barcodes/84000045432316.png",
"object": "cash_payment",
"type": "oxxo",
"expires_at": 1541289600,
"reference": "84000045432316"
},
"charge_id": "5bb6755d8a268e0ed9a56acb", "livemode": true,
"created_at": 1538684253,
"object": "inbound_payment",
"amount": 110700,
"currency": "MXN",
"customer_id": "cus_2jHUgfTB4pYmjmHpB"
},
"previous_attributes": {}
},
"livemode": true,
"webhook_status": "not_applicable",
"webhook_logs": [],
"id": "5b439072583eb80d50b46534",
"object": "event",
"type": "inbound_payment.payment_attempt",
"created_at": 1531154546
}
Para aprobar el pago tendrías que contestar en JSON, indicando que payable es true
{
"payable": true
}
En caso que quieras declinar un pago, puedes indicar payable: false y un código de rechazo. Puedes consultar la lista completa de códigos de rechazo al fin del tutorial.
{
"payable": false,
"failure_code": "15"
}
Paso 6 - Recibir confirmaciones de pago
La última notificación a recibir es una notificación asincrónica de pago con el tipo de charge.paid
. Para seguridad es crítico verificar la firma de notificaciones. El siguiente ejemplo pertenece a una notificación de pago:
{
"data": {
"object": {
"id": "5c0968098a268e02ab8aa3f7",
"livemode": true,
"created_at": 1544120329,
"currency": "MXN",
"description": null,
"reference_id": null,
"failure_code": null,
"failure_message": null,
"monthly_installments": null,
"device_fingerprint": null,
"refunds": [],
"payment_method": {
"barcode": "XXXXXXXXX",
"reference": "XXXXXXXXX",
"barcode_url": "https://s3.amazonaws.com/cash_payment_barcodes/XXXXXXXXX.png",
"object": "cash_payment",
"type": "oxxo",
"expires_at": 1546732800,
"store_name": "OXXO"
},
"details": {
"name": "Juan Perez",
"phone": null,
"email": "[email protected]",
"line_items": [],
"coupons": [],
"object": "details"
},
"object": "charge",
"status": "paid",
"amount": 350000,
"paid_at": 1544120362,
"fee": 10150,
"customer_id": "cus_2j35ehQaF1jZEcWH7",
"subscription_id": "",
"amount_refunded": null
},
"previous_attributes": {}
},
"livemode": true,
"webhook_status": "not_applicable",
"webhook_logs": [],
"id": "5b439072583eb80d50b46534",
"object": "event",
"type": "charge.paid",
"created_at": 1531154546
}
Paso 7 - Flujos de prueba
Tienes disponibles endpoints para que para que puedas probar el flujo de pagos end-to-end antes de hacer pruebas. Recuerda que todo se puede probar pegando el endpoints de https://api.conekta.io/payment_test
Paso 7.1 - Pruebas de Consultas
El siguiente payload va lanzar la notificación a tu endpoint de consulta.
{
"event_type": "inbound_payment.lookup",
"reference": "99000000001273"
}
Por ejemplo
curl --request POST \
--url https://api.conekta.io/payment_test \
--header 'accept: application/vnd.conekta-v2.0.0+json' \
-u YOUR_PRIVATE_SANDBOX_API_KEY: \
--header 'content-type: application/json' \
--data '{ "event_type": "inbound_payment.lookup", "reference": "99000000001273" }'
Paso 7.2 - Pruebas de confirmaciones de pago
El siguiente payload te enviará una notificación de confirmación de pago a tu Webhook.
{
"event_type": "inbound_payment.payment_attempt",
"reference": "99000000001273",
"amount": "10000"
}
Por ejemplo
curl --request POST \
--url https://api.conekta.io/payment_test \
--header 'accept: application/vnd.conekta-v2.0.0+json' \
-u YOUR_PRIVATE_SANDBOX_API_KEY: \
--header 'content-type: application/json' \
--data '{ "event_type": "inbound_payment.payment_attempt", "reference": "99000000001273", "amount": "10000" }'
Paso 7.3 - Pruebas de reversos de pago
El siguiente payload va lanzar una notificación de reverso de pago a tu Webhook.
{
"event_type": "inbound_payment.reverse",
"reference": "99000000001273"
}
Por ejemplo
curl --request POST \
--url https://api.conekta.io/payment_test \
--header 'accept: application/vnd.conekta-v2.0.0+json' \
-u YOUR_PRIVATE_SANDBOX_API_KEY: \
--header 'content-type: application/json' \
--data '{ "event_type": "inbound_payment.reverse", "reference": "99000000001273" }'
Addendum - Códigos de rechazo
Te compartimos los siguientes códigos de rechazo para que puedes comunicar fallas a tus clientes en cajero
failure_code | Descripción |
---|---|
01 | Referencia no encontrada |
02 | Cantidad inválida |
03 | Referencia expirada |
10 | Referencia sin deuda |
13 | Referencia inactiva |
14 | Referencia cancelada |
15 | Usuario bloqueado |
16 | Cantidad no permitida |
18 | Comercio fuera de horario |
19 | No autorizado |
35 | Monto fuera del rango permitido |
36 | Referencia ya pagada |