收款 Webhook
每当收款状态变更,A55 会向您的 webhook_url 发送 POST 请求。Webhook 载荷仅包含关键字段——请使用收款 UUID 从 API 获取完整详情。
载荷字段
| 字段 | 类型 | 说明 |
|---|---|---|
charge_uuid | UUID | 收款唯一标识符 |
status | string | 收款新状态(见下表) |
transaction_reference | string | 客户端发送的 ID / 收单机构交易参考号 |
subscription_uuid | UUID 或 null | 订阅标识符——仅在收款属于订阅时存在 |
payment_link_uuid | UUID 或 null | 支付链接标识符——仅在收款通过支付链接创建时存在 |
载荷示例
{
"charge_uuid": "fe5e2c1e-b3fb-4cc4-bb28-004da37d5804",
"status": "confirmed",
"transaction_reference": "txn-abc-123",
"subscription_uuid": null,
"payment_link_uuid": null
}
所有可能的状态
| 状态 | 说明 |
|---|---|
confirmed | 交易已批准 |
pending | 等待 3DS 挑战 |
issued | 收款已创建,等待处理(如 Apple Pay SDK) |
canceled | 创建后被取消或 3DS 挑战未完成 |
paid | 收款已结算 |
error | 交易失败或被拒绝 |
refunded | 退款已完成 |
refund_error | 退款时发生错误 |
chargeback_refunded | 拒付已退款 |
chargeback_requested | 拒付已申请 |
chargeback_reversed | 拒付已撤销 |
pre_chargeback_resolution | 拒付预处理中 |
获取完整收款详情
Webhook 载荷刻意保持精简。收到后,请使用 Bearer Token 调用 API 获取完整的收款对象:
curl https://api.a55.tech/api/v1/bank/wallet/charge/{charge_uuid}/ \
-H "Authorization: Bearer $ACCESS_TOKEN"
响应为完整的收款对象,包含所有字段,如 local_currency、currency、installments、action_url、applepay_payload 等。
Webhook 是触发器,API 是真实来源
使用 Webhook 感知状态变更,再调用 GET /api/v1/bank/wallet/charge/{uuid}/ 获取完整详情。切勿仅依赖跳转 URL——它可能被伪造。
处理器示例
- Python (Flask)
- JavaScript (Express)
from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
processed = set()
ACCESS_TOKEN = "您的_bearer_token"
@app.route("/webhook", methods=["POST"])
def charge_webhook():
data = request.get_json()
charge_uuid = data.get("charge_uuid")
status = data.get("status")
# 去重
if charge_uuid in processed:
return jsonify(status="duplicate"), 200
processed.add(charge_uuid)
# 从 API 获取完整收款详情
charge = requests.get(
f"https://api.a55.tech/api/v1/bank/wallet/charge/{charge_uuid}/",
headers={"Authorization": f"Bearer {ACCESS_TOKEN}"},
).json()
# 按状态路由
if status == "confirmed":
fulfill_order(charge)
elif status == "error":
notify_customer(charge)
elif status == "refunded":
credit_customer(charge)
elif status in ("chargeback_requested", "chargeback_refunded"):
flag_for_review(charge)
return jsonify(status="accepted"), 200
const express = require("express");
const fetch = require("node-fetch");
const app = express();
app.use(express.json());
const processed = new Set();
const ACCESS_TOKEN = "您的_bearer_token";
app.post("/webhook", async (req, res) => {
const { charge_uuid, status } = req.body;
// 立即响应
res.sendStatus(200);
// 去重
if (processed.has(charge_uuid)) return;
processed.add(charge_uuid);
// 从 API 获取完整收款详情
const response = await fetch(
`https://api.a55.tech/api/v1/bank/wallet/charge/${charge_uuid}/`,
{ headers: { Authorization: `Bearer ${ACCESS_TOKEN}` } }
);
const charge = await response.json();
// 按状态路由
const actions = {
confirmed: fulfillOrder,
error: notifyCustomer,
refunded: creditCustomer,
chargeback_requested: flagForReview,
chargeback_refunded: flagForReview,
};
if (actions[status]) actions[status](charge);
});
最佳实践
| 实践 | 原因 |
|---|---|
立即返回 200 | 避免超时和重复投递 |
| 在后台处理 | 保持响应时间低于 30 秒 |
以 charge_uuid 去重 | 安全处理重试的 Webhook |
| 通过 API 获取完整详情 | Webhook 载荷设计上是精简的 |
| 记录原始载荷 | 无需重新投递即可调试 |