Webhooks PAY-IN
Webhook é opcional. Zero-code YooCheckout não precisa dele. Merchants API (Modelos B/C) usam-no para notificação push.
MERCHANT_DATABASE_SCHEMA_CHANGE_REQUIRED=no
WEBHOOK_EVENT_TABLE_REQUIRED=noA YooBank não exige uma tabela específica no merchant. Logs não são idempotência financeira.
Entrega
- At-least-once
- Sem garantia de ordem global
- Sem exactly-once
O merchant deve processar de forma idempotente.
| Identidade | Papel |
|---|---|
intent_uuid | Idempotência financeira recomendada |
event_uuid | Identidade do evento (auditoria / dedupe opcional) |
delivery_uuid | Identidade da tentativa de entrega; estável nos retries da mesma entrega |
event_uuid e delivery_uuid não são intercambiáveis.
Eventos
pay_in.createdpay_in.awaiting_paymentpay_in.paid
Headers
X-YooBank-Event-Id
X-YooBank-Delivery-Id
X-YooBank-Event-Type
X-YooBank-Timestamp
X-YooBank-SignatureX-YooBank-Event-Id = event_uuid no JSON.
Assinatura (contrato congelado)
Algoritmo: HMAC-SHA256 (hex).
Entrada exacta:
timestamp + "\n" + event_uuid + "\n" + delivery_uuid + "\n" + event_type + "\n" + raw_bodyO timestamp é obrigatório, sintaxe ATOM, e entra tal qual no HMAC.
WEBHOOK_TIMESTAMP_FRESHNESS_WINDOW_ENFORCED=noA YooBank não aplica janela ±5 minutos. Uma verificação extra de replay no receiver é hardening do merchant, não requisito canónico YooBank.
Verifique o body cru (php://input) antes de json_decode. Não re-serializar JSON para calcular HMAC. Compare com hash_equals.
Payload (campos reais)
{
"event_uuid": "01234567-89ab-7def-8000-123456789abc",
"intent_uuid": "01234567-89ab-7def-8000-123456789abd",
"merchant_uuid": "01234567-89ab-7def-8000-123456789abe",
"status": "paid",
"asset": "usdt",
"rail": "bep20",
"expected_amount": "10.5",
"reference": "order-12345",
"created_at": "2026-09-07T12:00:00+00:00",
"expires_at": "2026-09-07T14:00:00+00:00",
"updated_at": "2026-09-07T12:05:00+00:00"
}UUIDs acima são sintéticos. Não confie só neste JSON para mutação irreversível.
Reconciliação recomendada (pay_in.paid)
- Autenticar HMAC no body cru.
- Extrair
intent_uuid. GETo PAY-IN na API YooBank.- Verificar merchant,
status=paid, asset, montante ereference. - Executar a operação local idempotente por
intent_uuid. - Responder 2xx se processou agora ou se já tinha processado com segurança.
pay_in.created e pay_in.awaiting_payment: autenticar, registar, 2xx, sem efeito financeiro irreversível.
Evento autenticado mas desconhecido: 2xx sem efeito, para não gerar retry infinito.
Respostas e retries (produção)
| Resposta do merchant | Efeito |
|---|---|
| 2xx | Entregue |
| 429 | Retry |
| qualquer 5xx | Retry |
| falha de rede | Retry |
| outros 4xx | Permanente |
- Máximo de tentativas: 10
- Backoff (segundos, após a primeira tentativa imediata): 60, 120, 240, 480, 960, 1920, depois 3600 (teto)
delivery_uuidestável no retry da mesma entregaevent_uuidestável
Princípio zero-schema
Receiver mínimo:
HMAC → GET de reconciliação → operação de negócio idempotente por intent_uuid.
Opcional: persistir event_uuid para auditoria. Não é obrigatório.