BMT Recargas API — Integración (Proyecto Adjuntado)

Esta guía describe el flujo init → widget 3DS → confirm y los archivos reales incluidos en los ejemplos de Next.js y PHP. Todo corresponde al proyecto finalizado que montaste.

Ambientes & URLs

Producción (activo)

  • Base: https://api.bmticket.com
  • Init: POST /api/v1/checkout/init
  • Confirm: POST /api/v1/checkout/confirm
  • Orders: GET /api/v1/orders/:order_id
  • Widget: /bmt-checkout.js

El ambiente de desarrollo (sandbox) se habilita bajo solicitud y registra los Origins de dev.

Cabeceras y seguridad

Enviar SIEMPRE

  • Content-Type: application/json
  • Accept: application/json
  • X-API-Key: <clave>
  • X-App-Key: <clave> (si aplica)
  • Origin y Referer que coincidan exacto con la allowlist

Claves

.env / servidor
BMT_BASE_URL=https://api.bmticket.com
BMT_API_KEY=<TU_API_KEY>
BMT_APP_KEY=<OPCIONAL_OTRA_KEY>
BMT_ORIGIN=https://<tu-dominio-exacto>/

Nunca expongas claves de servidor en el navegador.

Crear orden (init)

Request
{
  "amount": 25,
  "currency": "HNL",
  "description": "Recarga Hondubet",
  "customer": { "name": "Nombre", "email": "correo@ejemplo.com" },
  "billing": { "address": "Barrio", "country": "HN", "state": "CM", "city": "Siguatepeque", "phone": "+504..." }
}
Response
{
  "success": true,
  "order_id": "ORD-...",
  "checkout_url": "https://api.bmticket.com/checkout/ORD-...?mode=sale"
}

Widget & 3DS

Carga /bmt-checkout.js y abre el modal con el checkout_url que te devolvió init.

Abrir modal (client)
if (!window.BMTCheckout) throw new Error("Widget no disponible");
window.BMTCheckout.open({
  checkoutUrl: initResp.checkout_url,
  onResult: async (result: any) => {
    // Llama confirm con order_id + datos opcionales del widget
  },
});

Confirmar resultado

Request mínimo
{
  "order_id": "ORD-...",
  "status": "APPROVED",
  "payment_uuid": "P-...",
  "payment_hash": "...",
  "message": "opcional",
  "pixel_codes": { "code": "01", "uuid": "P-...", "hash": "..." }
}
Response
{ "success": true, "status": "PAID|DECLINED|ERROR", "message": "Texto", "data": { "http": 200|401|412|... } }

Integración Next.js (ejemplo adjunto)

  • Handlers: app/api/bmt/init/route.ts y app/api/bmt/confirm/route.ts con headers correctos.
  • UI: src/components/DepositDialog.tsx (init → widget → confirm).
  • Mensajes: src/lib/pixel/codes.ts y src/lib/pixel/buildMessage.ts.
Lado servidor (init)
// Headers claves:
"X-API-Key": key,
"X-App-Key": appKey,
"Origin": process.env.BMT_ORIGIN!,
"Referer": process.env.BMT_ORIGIN!,
"Accept": "application/json",

Integración PHP (ejemplo adjunto)

  • config.php: endpoints, claves y helpers cURL con headers.
  • crear-orden.php/checkout/init
  • confirmar-orden.php/checkout/confirm
  • codes.js: mapa de errores / sandbox
Test rápido (cURL)
curl -X POST https://api.bmticket.com/api/v1/checkout/init  -H 'Content-Type: application/json' -H 'Accept: application/json'  -H 'X-API-Key: <TU_API_KEY>' -H 'X-App-Key: <TU_APP_KEY>'  -H 'Origin: https://<tu-dominio-exacto>/' -H 'Referer: https://<tu-dominio-exacto>/'  -d '{ "amount":1,"currency":"HNL","description":"Recarga Hondubet","customer":{"name":"Nombre","email":"correo@ejemplo.com"},"billing":{"address":"...","country":"HN","state":"CM","city":"Siguatepeque","phone":"+504..."}}'

Errores & mensajes

HTTP del API

  • 401/403 No autorizado (keys/origin)
  • 402 Pago declinado
  • 412 Intentos excedidos / precondición
  • 422 Input inválido
  • 408 Timeout
  • 5xx Falla del servicio

Códigos del proveedor

Ver src/lib/pixel/codes.ts (Next) y codes.js (PHP).

La UI prioriza: estado del API > código proveedor > sandbox.

Sandbox & QA

Casos por monto (1..14) disponibles. En Next: NEXT_PUBLIC_BMT_ENV=sandbox.

Checklist

  • Claves en servidor (no en cliente).
  • Headers completos: X-API-Key, X-App-Key, Origin, Referer, Accept.
  • Origin/Referer coinciden exacto con allowlist.
  • Mensajería de errores integrada.
  • Sandbox activado bajo solicitud.