Pagos vía SPEI
Transferencias Bancarias vía SPEI
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");
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.
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": "spei",
"expires_at": 1600886061
}
}]
}'
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" => "spei",
"expires_at" => $thirty_days_from_now
]
]
]
]
);
} catch (\Conekta\ParameterValidationError $error){
echo $error->getMessage();
} catch (\Conekta\Handler $error){
echo $error->getMessage();
}
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 for physical goods only
charges: [{
payment_method: {
type: "spei",
expires_at: thirty_days_from_now
}
}]
})
rescue Conekta::Error => error
for error_detail in error.details do
puts error_detail.message
end
end
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": "spei",
"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 - 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": "spei",
"expires_at": thirty_days_from_now
}
}]
}, function(err, res) {
console.log(res.toObject());
});
try {
Long nowUnixTimestamp = System.currentTimeMillis();
Long thirtyDaysFromNowUnixTimestamp = (nowUnixTimestamp + 30L * 24 * 60 * 60 * 1000) / 1000L;
String thirtyDaysFromNow = thirtyDaysFromNowUnixTimestamp.toString();
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': 'spei',"
+ "'expires_at': " + thirtyDaysFromNow
+ "}"
+ "}]"
+ "}"
)
);
} catch (io.conekta.Error e) {
System.out.println(e.message);
} catch (io.conekta.ErrorList 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"": ""spei"",
""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{
//ID: "cus_2nD9kZfqRzMuF8czZ",
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: "spei",
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.
# N/A
echo $order;
echo "ID: ". $order->id;
echo "Bank: ". $order->charges[0]->payment_method->receiving_account_bank;
echo "CLABE: ". $order->charges[0]->payment_method->receiving_account_number;
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
// Bank: STP
// CLABE: 646180111812345678
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
puts "ID: #{order.id}"
puts "Bank: #{order.charges.data[0].payment_method.receiving_account_bank}"
puts "CLABE: #{order.charges.data[0].payment_method.receiving_account_number}"
puts "$ #{(order.amount/100).to_f} #{order.currency}"
puts "Order"
puts "#{order.line_items.data[0].quantity}
- #{order.line_items.data[0].name}
- $ #{(order.line_items.data.unit_price/100).to_f}"
# Response
# ID: ord_2fsQdMUmsFNP2WjqS
# Bank: STP
# CLABE: 646180111812345678
# $ 135.0 MXN
# Order
# 12 - Tacos - $10.0
print("ID: " + order.id)
print("Bank: " + order.charges.data[0].payment_method.receiving_account_bank)
print("CLABE: " + order.charges.data[0].payment_method.receiving_account_number)
print("$" + (order.amount/100) + order.currency)
print("Order")
print(order.line_items.data[0].quantity + " - "
+ order.line_items.data[0].name + " - "
+ (order.line_items.data.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("Bank: " + order.charges.data[0].payment_method.receiving_account_bank);
console.log("CLABE: " + order.charges.data[0].payment_method.receiving_account_number);
console.log("$" + (order.amount/100) + order.currency);
console.log("Order");
console.log(order.line_items.data[0].quantity + " - "
+ order.line_items.data[0].name + " - "
+ (order.line_items.data.unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Bank: STP
// CLABE: 646180111812345678
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
System.out.println("ID: " + order.id);
System.out.println("$" + (order.amount/100) + order.currency);
System.out.println("Order");
System.out.println(order.line_items.data[0].quantity + " - "
+ order.line_items.data[0].name + " - "
+ (order.line_items.data.unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// $ 135.0 MXN
// Order
// 12 - Tacos - $10.0
Console.WriteLine("ID: " + order.id);
Console.WriteLine("Bank: " + order.charges.data[0].payment_method.receiving_account_bank);
Console.WriteLine("CLABE: " + order.charges.data[0].payment_method.receiving_account_number);
Console.WriteLine("$" + (order.amount/100) + order.currency);
Console.WriteLine("Order");
Console.WriteLine(order.line_items.data[0].quantity + " - "
+ order.line_items.data[0].name + " - "
+ (order.line_items.data.unit_price/100));
// Response
// ID: ord_2fsQdMUmsFNP2WjqS
// Bank: STP
// CLABE: 646180111812345678
// $ 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 SPEI
Puedes incluirla en tu checkout o envíala por correo para ofrecer una mejor experiencia.
Consulta el repo en GitHub.
Paso 5 - Recibir notificación
Para poder confirmar los pagos que se realicen con SPEI 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.
Paso 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.