Saltearse al contenido

Pago por transferencia bancaria

El flujo más simple de los tres proveedores. No hay iframe, no hay catastro de tarjeta. El cliente transfiere desde su home banking y sube el comprobante; el operador del comercio lo aprueba o rechaza desde el dashboard.

Diagrama del flow

sequenceDiagram
    autonumber
    participant Cliente as Cliente final
    participant TuApp as Tu app
    participant Ingalca as INGALCA Pay
    participant Operador as Operador del comercio

    TuApp->>Ingalca: POST /v1/payments
provider=transferencia Ingalca-->>TuApp: pay_xxx (status=pending) +
cuentas bancarias TuApp-->>Cliente: Mostrar cuentas + monto + ref Cliente->>Cliente: Transferir desde home banking Cliente-->>TuApp: Subir comprobante (foto/PDF) TuApp->>Ingalca: POST /v1/payments/{id}/receipt Ingalca-->>TuApp: status=receipt_uploaded Ingalca->>TuApp: webhook payment.receipt_uploaded Ingalca->>Operador: Email "tenés comprobantes para revisar" Operador->>Ingalca: Aprobar / Rechazar (dashboard) alt Aprobado Ingalca->>TuApp: webhook payment.confirmed TuApp-->>Cliente: Pantalla de éxito else Rechazado Ingalca->>TuApp: webhook payment.rejected (con motivo) TuApp-->>Cliente: Pantalla con motivo end

Paso a paso

1. Crear el pago

Ventana de terminal
curl -X POST https://api.pay.ingalca.com/v1/payments \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"provider": "transferencia",
"amount": 250000,
"reference": "ORDEN-1042",
"customer": {
"customerId": "user_42",
"name": "Juan",
"email": "juan@example.com"
}
}'

La respuesta incluye las cuentas bancarias del comercio que tenés que mostrarle al cliente:

{
"data": {
"id": "pay_abc123",
"status": "pending",
"provider_data": {
"bank_accounts": [
{
"bank_name": "BNF",
"account_type": "corriente",
"account_number": "123-456789-0",
"holder_name": "Tu Comercio S.A.",
"holder_ruc": "80012345-6"
}
],
"instructions": "Transferí ₲ 250.000 a la cuenta indicada y subí el comprobante."
}
}
}

2. Mostrar al cliente y esperar la transferencia

Tu app le muestra al cliente:

  • Las cuentas bancarias.
  • El monto y la referencia (que conviene que el cliente incluya en el detalle de la transferencia).
  • Un botón para subir el comprobante.

3. Subir el comprobante

Cuando el cliente sube la imagen/PDF:

Ventana de terminal
curl -X POST https://api.pay.ingalca.com/v1/payments/pay_abc123/receipt \
-H "Authorization: Bearer sk_test_..." \
-F "file=@comprobante.jpg" \
-F "notes=Transferí desde BNF a las 14:30"

Restricciones:

  • Formatos: image/jpeg, image/png, application/pdf.
  • Tamaño máximo: 10 MB.
  • Las imágenes se normalizan automáticamente (max 1200px de ancho, calidad 80%) y se genera un thumbnail de 300px.

El status pasa a receipt_uploaded. Disparamos payment.receipt_uploaded a tu webhook.

4. Aprobación manual

El operador del comercio entra al dashboard, revisa el comprobante y decide:

  • Aprobar → status pasa a confirmed, disparamos payment.confirmed.
  • Rechazar → status pasa a rejected con motivo, disparamos payment.rejected.

También podés aprobar/rechazar vía API si querés automatizar:

Ventana de terminal
# Aprobar
curl -X POST https://api.pay.ingalca.com/v1/payments/pay_abc123/confirm \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{"notes": "Verificado contra extracto"}'
# Rechazar
curl -X POST https://api.pay.ingalca.com/v1/payments/pay_abc123/reject \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{"reason": "Comprobante ilegible"}'

Una vez aprobado, ¿hay reversa?

No automatizable. Las transferencias bancarias en Paraguay no tienen mecanismo de reversa por API — si aprobaste por error, tenés que hacer una transferencia manual de vuelta al cliente y comunicártelo. Por eso aprobar es deliberadamente irreversible.

Estados posibles

stateDiagram-v2
    [*] --> pending: POST /v1/payments
    pending --> receipt_uploaded: POST /receipt
    pending --> expired: TTL agotado
    pending --> cancelled: cancel API
    receipt_uploaded --> confirmed: aprobado
    receipt_uploaded --> rejected: rechazado
    confirmed --> [*]
    rejected --> [*]
    expired --> [*]
    cancelled --> [*]