Pago SPEI
Dispersar en México, desde el alta del beneficiario hasta el recibo.
Para pagar por SPEI registras una CLABE, la apruebas en el panel y creas el pago. Los pasos siguientes usan el simulador público.
Requisitos
| Requisito | Valor |
|---|---|
rail | mxn_spei |
| País | México |
| Moneda del pago | MXN |
| Datos de la cuenta | CLABE |
| Disponible si | mxn_spei aparece en rails de GET /v1/limits. Si no, 403 rail_not_enabled |
| Cuenta de prueba | Se simula, con CLABE 999 y titular con FICTICIO |
1. Registra el beneficiario
Con POST /v1/beneficiaries. La CLABE lleva exactamente 18 dígitos, sin espacios.
Variables de estas muestras: simulador público, sin cuenta
Define esto en tu terminal. Con estos valores las muestras corren tal cual contra el simulador público:
export FITAL_API="https://widget.fital.xyz/explorar/v1"
export FITAL_KEY="sk_test_sandbox_publica"
export FITAL_SIGNING_SECRET="secreto_de_firma_de_prueba_publico"En la cuenta de prueba o en producción cambia la base, la llave y el secreto, y sustituye los id de ejemplo por los tuyos. Ver Ambientes.
CUERPO='{"rail":"mxn_spei","holder_name":"PROVEEDOR FICTICIO SA DE CV","clabe":"999180000000000011"}'
CLAVE="beneficiario-proveedor-77"
TS=$(date +%s)
HASH=$(printf '%s' "$CUERPO" | openssl dgst -sha256 -r | cut -d' ' -f1)
FIRMA=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" POST /v1/beneficiaries "$HASH" "$CLAVE" \
| openssl dgst -sha256 -hmac "$FITAL_SIGNING_SECRET" -r | cut -d' ' -f1)
curl -sS -X POST "$FITAL_API/beneficiaries" \
-H "Authorization: Bearer $FITAL_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CLAVE" \
-H "X-Fital-Timestamp: $TS" \
-H "X-Fital-Signature: v1=$FIRMA" \
-d "$CUERPO"Nace pendiente. Apruébalo en el panel: por API no se puede.
2. Cotiza, si te importa el débito
POST /v1/quotes con beneficiary_id, amount y currency. Envía el quote_id al crear el pago y el débito no superará lo cotizado.
3. Crea el pago
Con POST /v1/payments:
CUERPO='{"beneficiary_id":"ben_3kTMd9wQp2LxZ7vR1nYcA4bE","amount":"1500.00","currency":"MXN","external_ref":"factura-1042"}'
CLAVE="pago-factura-1042"
TS=$(date +%s)
HASH=$(printf '%s' "$CUERPO" | openssl dgst -sha256 -r | cut -d' ' -f1)
FIRMA=$(printf '%s\n%s\n%s\n%s\n%s' "$TS" POST /v1/payments "$HASH" "$CLAVE" \
| openssl dgst -sha256 -hmac "$FITAL_SIGNING_SECRET" -r | cut -d' ' -f1)
curl -sS -X POST "$FITAL_API/payments" \
-H "Authorization: Bearer $FITAL_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $CLAVE" \
-H "X-Fital-Timestamp: $TS" \
-H "X-Fital-Signature: v1=$FIRMA" \
-d "$CUERPO"4. Sigue el estado
curl -sS "$FITAL_API/payments/pay_6nRtY1wKs3QzD8cL5mVhF2gB" \
-H "Authorization: Bearer $FITAL_KEY" \
-H "X-Fital-Scenario: payment_completed"El detalle trae freshness. Con delayed, status es lo último que se sabe. Ver Frescura del detalle.
5. Cancela si aún se puede
POST /v1/payments/{id}/cancel sólo funciona mientras el pago espera fondos. 409 not_cancellable es la respuesta normal cuando ya avanzó.
Tras cancelar, el detalle puede responder canceled con freshness.status en delayed hasta que una lectura lo confirme, y GET /v1/payments puede tardar una vuelta de sincronización en reflejarlo.
Errores comunes
422 beneficiary_not_approved: apruébalo y repite con la misma clave.422 insufficient_funds: fondea y repite con una clave nueva. La misma clave repite el rechazo.403 rail_not_enabled: el riel no está habilitado para tu cuenta.