最佳实践
处理回调
每当交易状态发生变化时,PayZu 会实时向您的 callbackUrl 发送回调。核心规则:在 5 秒内返回 2xx 响应。响应不够快的请求会进入重试队列(最多 72 次尝试,采用指数退避策略)。
推荐模式:入队并返回 2xx
将重处理任务放在处理器之外执行。处理器只负责接收、入队并响应。
import express from 'express';
const app = express();
app.post('/webhooks/payzu', express.json(), async (req, res) => {
await queue.enqueue('payzu-callback', req.body);
res.status(204).end();
});from flask import Flask, request
app = Flask(__name__)
@app.post('/webhooks/payzu')
def payzu_webhook():
queue.enqueue('payzu_callback', request.get_json())
return '', 204http.HandleFunc("/webhooks/payzu", func(w http.ResponseWriter, r *http.Request) {
var payload map[string]any
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
queue.Enqueue("payzu-callback", payload)
w.WriteHeader(http.StatusNoContent)
})<?php
$payload = json_decode(file_get_contents('php://input'), true);
$queue->enqueue('payzu-callback', $payload);
http_response_code(204);本地测试
通过 ngrok 或 Cloudflare Tunnel 暴露本地服务,然后手动触发 payload:
curl -X POST https://seu-tunel.ngrok.io/webhooks/payzu \
-H "Content-Type: application/json" \
-d '{
"id": "PAYZU20251123104518DF75D20A8F",
"type": "DEPOSIT",
"status": "COMPLETED",
"amount": 99.90,
"clientReference": "order-1234",
"virtualAccount": "loja-rj-01",
"paidAt": "2025-11-23T10:46:26.986Z"
}'await fetch('https://seu-tunel.ngrok.io/webhooks/payzu', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: 'PAYZU20251123104518DF75D20A8F',
type: 'DEPOSIT',
status: 'COMPLETED',
amount: 99.90,
clientReference: 'order-1234',
virtualAccount: 'loja-rj-01',
paidAt: '2025-11-23T10:46:26.986Z',
}),
});import requests
requests.post(
'https://seu-tunel.ngrok.io/webhooks/payzu',
headers={'Content-Type': 'application/json'},
json={
'id': 'PAYZU20251123104518DF75D20A8F',
'type': 'DEPOSIT',
'status': 'COMPLETED',
'amount': 99.90,
'clientReference': 'order-1234',
'virtualAccount': 'loja-rj-01',
'paidAt': '2025-11-23T10:46:26.986Z',
},
)重新发送真实回调
如需重新处理在您侧失败的回调(在修复处理器之后),请使用重发端点:
查看历史记录
PayZu 保留所有送达尝试记录,便于排查故障:
GET /user/callbacks,分页列表GET /user/callbacks/{id},包含状态码、响应体、响应时间的详细信息
常见陷阱
| 陷阱 | 症状 |
|---|---|
| 在处理器中同步处理 | 超时、重试、重复入账 |
| 因内部校验错误返回 4xx | PayZu 不会重试,回调丢失 |
仅按 id 去重 | 退款(REFUNDED)被忽略 |
| 端点缺少 IP 保护 | 端点可能收到伪造的 payload |
日志打印 payload 未脱敏 payerDocument | LGPD 合规风险 |
Multi-tenant com virtualAccount
Uma só conta PayZu pode atender N tenants (lojas, filiais, marketplaces) usando virtualAccount. Volta em todo callback, permite filtrar listagens e dispensa criar contas filhas.
Paginação
Endpoints de listagem (transações, callbacks, infrações) usam paginação clássica por page + limit com flag hasNextPage. Para janelas grandes prefira o relatório assíncrono em CSV.