Pagos con OXXO Pay
Pagos en efectivo con OXXO Pay
Recibe pagos en efectivo con notificación en tiempo real.
Primeros pasos
- Es necesario contar con conocimiento de APIs.
- Es preferible ser desarrollador fullstack (frontend + backend).
- Instalar e incluir una de las librerías disponibles de Conekta.
- Contar con tus API Keys (llave personal) de pruebas.
Paso 1 - Añade tu llave privada y versión del API
Necesitarás tu llave privada de pruebas. Si aún no cuentas con ella, puedes obtenerla en tu panel Conekta.
require "conekta"
Conekta.api_key = "key_eYvWV7gSDkNYXsmr"
Conekta.api_version = "2.0.0"
# N/A
require_once("/path/to/lib/Conekta.php");
\Conekta\Conekta::setApiKey("key_eYvWV7gSDkNYXsmr");
\Conekta\Conekta::setApiVersion("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 una orden
Al crear un order se generará el cargo de tu cliente. Si no deseas crear el cargo inmediato, puedes preparar la orden y después generar el cargo mandando la información del arreglo charges.
Los campos mostrados en el ejemplo son los mínimos requeridos, si deseas saber más sobre el objeto order revisa nuestra REST API.
Si deseas que tu ficha expire puedes añadir el atributo expires_at dentro de payment_method, es un campo tipo unix timestamp que te permite generar una ficha que expire ¡hasta por segundos!
begin
thirty_days_from_now = Time.now.advance(days: 30).to_i
order = Conekta::Order.create({
line_items: [{
name: "Tacos",
unit_price: 1000,
quantity: 12
}],
shipping_lines: [{
amount: 1500,
carrier: "FEDEX"
}], #shipping_lines - physical goods only
currency: "MXN",
customer_info: {
name: "Fulanito Pérez",
email: "[email protected]",
phone: "+5218181818181"
},
shipping_contact: {
address: {
street1: "Calle 123, int 2",
postal_code: "06100",
country: "MX"
}
}, #shipping_contact - required only for physical goods
charges: [{
payment_method: {
type: "oxxo_cash",
expires_at: thirty_days_from_now
}
}]
})
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/orders \
--header 'accept: application/vnd.conekta-v2.0.0+json' \
-u key_eYvWV7gSDkNYXsmr: \
--header 'content-type: application/json' \
--data '{
"line_items": [{
"name": "Tacos",
"unit_price": 1000,
"quantity": 12
}],
"shipping_lines": [{
"amount": 1500,
"carrier": "FEDEX"
}],
"currency": "MXN",
"customer_info": {
"name": "Fulanito Pérez",
"email": "[email protected]",
"phone": "+5218181818181"
},
"shipping_contact":{
"address": {
"street1": "Calle 123, int 2",
"postal_code": "06100",
"country": "MX"
}
},
"charges":[{
"payment_method": {
"type": "oxxo_cash",
"expires_at": 1600871926
}
}]
}'
try{
$thirty_days_from_now = (new DateTime())->add(new DateInterval('P30D'))->getTimestamp();
$order = \Conekta\Order::create(
[
"line_items" => [
[
"name" => "Tacos",
"unit_price" => 1000,
"quantity" => 12
]
],
"shipping_lines" => [
[
"amount" => 1500,
"carrier" => "FEDEX"
]
], //shipping_lines - physical goods only
"currency" => "MXN",
"customer_info" => [
"name" => "Fulanito Pérez",
"email" => "[email protected]",
"phone" => "+5218181818181"
],
"shipping_contact" => [
"address" => [
"street1" => "Calle 123, int 2",
"postal_code" => "06100",
"country" => "MX"
]
], //shipping_contact - required only for physical goods
"charges" => [
[
"payment_method" => [
"type" => "oxxo_cash",
"expires_at" => $thirty_days_from_now
]
]
]
]
);
} catch (\Conekta\ParameterValidationError $error){
echo $error->getMessage();
} catch (\Conekta\Handler $error){
echo $error->getMessage();
}
try:
from datetime import datetime
from datetime import timedelta
thirty_days_from_now = int((datetime.now() + timedelta(days=1)).timestamp())
order = conekta.Order.create({
"line_items": [{
"name": "Tacos",
"unit_price": 1000,
"quantity": 12
}],
"shipping_lines": [{
"amount": 1500,
"carrier": "FEDEX"
}], #shipping_lines - physical goods only
"currency": "MXN",
"customer_info": {
"name": "Fulanito Pérez",
"email": "[email protected]",
"phone": "+5218181818181"
},
"shipping_contact":{
"address": {
"street1": "Calle 123, int 2",
"postal_code": "06100",
"country": "MX"
}
}, #shipping_contact - required only for physical goods
"charges":[{
"payment_method": {
"type": "oxxo_cash",
"expires_at": thirty_days_from_now
}
}]
})
except conekta.ConektaError as e:
print e.message
thirty_days_from_now = (Math.round(Date.now()/1000 + 60 \* 60 \* 24 \* 30)).toString()
order = conekta.Order.create({
"line_items": [{
"name": "Tacos",
"unit_price": 1000,
"quantity": 12
}],
"shipping_lines": [{
"amount": 1500,
"carrier": "FEDEX"
}], //shipping_lines - phyiscal goods only
"currency": "MXN",
"customer_info": {
"name": "Fulanito Pérez",
"email": "[email protected]",
"phone": "+5218181818181"
},
"shipping_contact":{
"address": {
"street1": "Calle 123, int 2",
"postal_code": "06100",
"country": "MX"
}
}, //shipping_contact - required only for physical goods
"charges":[{
"payment_method": {
"type": "oxxo_cash",
"expires_at": thirty_days_from_now
}
}]
}, function(err, res) {
console.log(res.toObject());
});
Long nowUnixTimestamp = System.currentTimeMillis();
Long thirtyDaysFromNowUnixTimestamp = (nowUnixTimestamp + 30L \* 24 \* 60 \* 60 \* 1000) / 1000L;
String thirtyDaysFromNow = thirtyDaysFromNowUnixTimestamp.toString();
try{
Order order = Order.create(
new JSONObject("{"
+ "'line_items': [{"
+ "'name': 'Tacos',"
+ "'unit_price': 1000,"
+ "'quantity': 12"
+ "}],"
+ "'shipping_lines': [{"
+ "'amount': 1500,"
+ "'carrier': 'FEDEX',"
+ "}]," //shipping_lines - physical goods only
+ "'currency': 'MXN',"
+ "'customer_info': {"
+ "'name': 'Fulanito Pérez',"
+ "'email': '[email protected]',"
+ "'phone': '+5218181818181'"
+ "},"
+ "'shipping_contact':{"
+ "'address': {"
+ "'street1': 'Calle 123, int 2',"
+ "'postal_code': '06100',"
+ "'country': 'MX'"
+ "}"
+ "}," //shipping_contact - required only for physical goods
+ "'charges':[{"
+ "'payment_method': {"
+ "'type': 'oxxo_cash',"
+ "'expires_at': " + thirtyDaysFromNow
+ "}"
+ "}]"
+ "}"
)
);
}catch (Conekta::Error e) {
System.out.println(e.details.get(0).message);
}
//Calculate an expiration time
DateTime thirtyDaysFromNowDateTime = DateTime.Now.AddDays(30);
long thirtyDaysFromNowUnixTimestamp = (Int64)(thirtyDaysFromNowDateTime.Subtract(new DateTime(1970, 1, 1)).TotalSeconds);
String thirtyDaysFromNow = thirtyDaysFromNowUnixTimestamp.ToString();
try{
conekta.Order order = new conekta.Order ().create(@"{
""line_items"": [{
""name"": ""Tacos"",
""unit_price"": 1000,
""quantity"": 12
}],
""shipping_lines"": [{
""amount"": 1500,
""carrier"": ""FEDEX""
}]," + //shipping_lines - physical goods only
@"""currency"": ""MXN"",
""customer_info"": {
""name"": ""Fulanito Pérez"",
""email"": ""[email protected]"",
""phone"": ""+5218181818181""
},
""shipping_contact"":{
""address"": {
""street1"": ""Calle 123, int 2"",
""postal_code"": ""06100"",
""country"": ""MX""
}
}," + //shipping_contact - required only for physical goods only
@"""charges"":[{
""payment_method"": {
""type"": ""oxxo_cash"",
""expires_at"": " + thirtyDaysFromNow + @"
}
}]
}");
} 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"));
}
}
Address := &conekta.Address{
Street1: "Street1",
Street2: "Street2",
City: "City",
State: "State",
Country: "Country",
PostalCode: "PostalCode",
}
customerParams := &conekta.CustomerParams{
Name: "Fulanito Perez",
Phone: "5512345678",
Email: "[email protected]",
}
lineItemParams := &conekta.LineItemsParams{
Name: "Naranjas Robadas",
UnitPrice: 10000,
Quantity: 2,
}
shippingParams := &conekta.ShippingLinesParams{
Amount: 200,
TrackingNumber: "123",
Carrier: "Test Carrier",
Method: "method",
}
shippingContactParams := &conekta.ShippingContactParams{
Phone: "55-5555-5555",
Receiver: "Miguel",
BetweenStreets: "BetweenStreets",
Address: Address,
}
chargeParams := &conekta.ChargeParams{
PaymentMethod: &conekta.PaymentMethodParams{
Type: "oxxo_cash",
ExpiresAt: time.Now().AddDate(0, 0, 90).Unix(),
},
}
orderParams := &conekta.OrderParams{}
orderParams.Currency = "MXN"
orderParams.CustomerInfo = customerParams
orderParams.LineItems = append(orderParams.LineItems, lineItemParams)
orderParams.ShippingLines = append(orderParams.ShippingLines, shippingParams)
orderParams.ShippingContact = shippingContactParams
orderParams.Charges = append(orderParams.Charges, chargeParams)
ord, err := order.Create(orderParams)
if err != nil {
code := err.(conekta.Error).Details[0].Code
fmt.Printf(code)
} else {
fmt.Println(ord)
}
Paso 3 - Procesar respuesta
Una vez creada la orden y el cargo, deberás procesar la respuesta y presentar la ficha de pago.
Recuerda que la respuesta de una orden es formato JSON.
puts "ID: #{order.id}"
puts "Payment Method: #{order.charges.first.payment_method.service_name}"
puts "Reference: #{order.charges.first.payment_method.reference}"
puts "$ #{(order.amount/100).to_f} #{order.currency}"
puts "Order"
puts "#{order.line_items.first.quantity}
- #{order.line_items.first.name}
- $ #{(order.line_items.unit_price/100).to_f}"
# Response
# ID: ord_2fsQdMUmsFNP2WjqS
# Payment Method: OxxoPay
# Reference: 123456789012
# $ 135.0 MXN
# Order
# 12 - Tacos - $10.0
# N/A
echo "ID: ". $order->id;
echo "Payment Method:". $order->charges[0]->payment_method->service_name;
echo "Reference: ". $order->charges[0]->payment_method->reference;
echo "$". $order->amount/100 . $order->currency;
echo "Order";
echo $order->line_items[0]->quantity .
"-". $order->line_items[0]->name .
"- $". $order->line_items[0]->unit_price/100;
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Payment Method: OxxoPay
// Reference: 123456789012
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
print("ID: " + order.id)
print("Payment Method: " + order.charges[0].payment_method.service_name)
print("Reference: " + order.charges[0].payment_method.reference)
print("$" + str(order.amount/100) + order.currency)
print("Order")
print(order.line_items[0].quantity + " - "
+ order.line_items[0].name + " - "
+ (order.line_items.unit_price/100))
# Response
# ID: ord_2fsQdMUmsFNP2WjqS
# Payment Method: OxxoPay
# Reference: 123456789012
# $ 135.0 MXN
# Order
# 12 - Tacos - $10.0
console.log("ID: " + order.id);
console.log("Payment Method: " + order.charges[0].payment_method.service_name);
console.log("Reference: " + order.charges[0].payment_method.reference);
console.log("$" + (order.amount/100) + order.currency);
console.log("Order");
console.log(order.line_items[0].quantity + " - "
+ order.line_items[0].name + " - "
+ (order.line_items.unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Payment Method: OxxoPay
// Reference: 123456789012
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
OxxoPayment oxxoPayment = (OxxoPayment) charge.payment_method;
System.out.println("ID: " + order.id);
System.out.println("Payment Method: " + oxxoPayment.service_name);
System.out.println("Reference: " + oxxoPayment.reference);
System.out.println("$" + (order.amount/100) + order.currency);
System.out.println("Order");
System.out.println(order.line_items.get(0).quantity + " - "
+ order.line_items.get(0).name + " - "
+ (order.line_items.get(0).unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Payment Method: OxxoPay
// Reference: 123456789012
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
Console.WriteLine("ID: " + order.id);
Console.WriteLine("Payment Method: " + order.charges[0].payment_method.service_name);
Console.WriteLine("Reference: " + order.charges[0].payment_method.reference);
Console.WriteLine("$" + (order.amount/100) + order.currency);
Console.WriteLine("Order");
Console.WriteLine(order.line_items[0].quantity + " - "
+ order.line_items[0].name + " - "
+ (order.line_items.unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Payment Method: OxxoPay
// Reference: 123456789012
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
fmt.Println("ID: ", o.ID)
fmt.Println("Payment Method: ", o.Charges.Data[0].PaymentMethod.ServiceName)
fmt.Println("Reference: ", o.Charges.Data[0].PaymentMethod.Reference)
fmt.Println("$", o.Amount/100, o.Currency)
fmt.Println("------Order------")
fmt.Println(" - ", o.LineItems.Data[0].Quantity)
fmt.Println(" - ", o.LineItems.Data[0].Name)
fmt.Println(" - ", o.LineItems.Data[0].UnitPrice/100)
//Response
//ID: ord_2nCsbdLXvdAgDVcKr
//Payment Method: OxxoPay
//Reference: 98000004875830
//$ 152 MXN
//------Order------
// - 1
// - Producto 7
// - 152
Paso 4 - Presentar ficha de pago
Utiliza una ficha como esta para darle a tu cliente la referencia de pago junto con los pasos necesarios para completar la compra.
Ficha OXXO PAY
Inclúyela en tu checkout o envíala por correo para ofrecer una mejor experiencia.
Consulta el repo en Github.
Paso 5 - Recibir notificaciones
Para poder confirmar los pagos que se realicen con OXXO PAY 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 o localtunnel. Consultar la referencia sobre webhooks.
Paso 6 - Notifica a tu cliente
Una buena práctica es notificar a tu usuario vía email.
Psoa 7 - Prueba tu webhook
Dentro de tu Admin Conekta puedes probar la funcionalidad de tu webhook
¿Qué necesitarás? La URL de tu webhook y acceso al Admin Conekta.
¡Listo!
Recuerda cambiar tus llaves pública y privada de pruebas por tus llaves de producción después de realizar pruebas.