Files
medical-mall/pages/mall/delivery/webhook-server/PARTNER_ONBOARDING.md
2026-03-12 18:05:32 +08:00

85 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**概述**
- **目标**: 让快递合作方(例如韵达)能安全、可靠地向系统的 `/webhook/express/status` 发送回调,用于运单状态同步与推送触发。
- **范围**: 包含鉴权/验签约定、幂等策略、测试样例、部署与运维建议。
**接入概览**
- **Endpoint**: `https://<your-domain>/webhook/express/status`
- **协议**: HTTPSTLS 必需)
- **数据格式**: `application/json`body 为第三方原始回调 JSON。
**鉴权与验签**
- **方式**: 每个合作方分配一份 HMAC secretUTF-8 文本),服务端按 `client_id` 查秘钥(建议把 `client_id` 放在请求头 `X-Client-Id`)。
- **签名头**: `X-Timestamp`UTC 秒)与 `X-Signature`hex 小写)。
- **签名算法**: HMAC-SHA256(secret, rawBodyText + timestamp) → hex。
- **时窗**: 接收端按 ±300 秒(可配置)判定时间窗,超时拒绝(防重放)。
- **严格模式**: `WEBHOOK_REJECT_INVALID_SIGNATURE=true` 时签名不合将直接 401上线初期可先设 false观测后切为 true
**幂等与去重**
- **推荐字段**: 合作方可在 body 中提供 `dedupe_key`(优先使用);若无,服务端基于稳定字段计算哈希(建议用 `tracking_no|carrier|event_time|event_code` 组合)。
- **数据库约束**: `platform_express_tracking_events` 应有唯一约束 `(waybill_id, dedupe_key)`,重复回调不再写入事件表。
- **返回语义**: 对重复回调可返回 200 并在 body 标注 `duplicate: true`,以便合作方不再重试。
**请求/响应与重试策略**
- **接收端快速 ACK**: 推荐返回 HTTP 202 Accepted或 200表示“已入队/接收”,不代表处理完成。
- **错误返回**: 4xx 表示请求问题(签名/格式5xx 表示服务端异常(合作方可按重试策略重试)。
- **建议重试规则**(对方遵守): 35 次,指数退避(例如 1m, 2m, 4m, ...),总重试时长不超过 1 小时。
**示例签名与发送bash**
```bash
TS=$(date -u +%s)
BODY='{"tracking_no":"YT123","event_code":"DELIVERED","event_time":"2026-03-12T10:00:00Z"}'
SECRET='YOUR_PARTNER_SECRET'
SIG=$(printf '%s%s' "$BODY" "$TS" | openssl dgst -sha256 -hmac "$SECRET" -binary | xxd -p -c 256)
curl -v -X POST https://your-domain/webhook/express/status \
-H 'Content-Type: application/json' \
-H "X-Timestamp: $TS" \
-H "X-Signature: $SIG" \
-H "X-Client-Id: partner-yd" \
-d "$BODY"
```
**示例PowerShellWindows**
```powershell
$ts = [int][double]::Parse((Get-Date).ToUniversalTime().Subtract([datetime]'1970-01-01').TotalSeconds)
$body = '{"tracking_no":"YT123","event_code":"DELIVERED","event_time":"2026-03-12T10:00:00Z"}'
$secret = 'YOUR_PARTNER_SECRET'
$hmac = New-Object System.Security.Cryptography.HMACSHA256([Text.Encoding]::UTF8.GetBytes($secret))
$hash = $hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($body + $ts))
$sig = ($hash | ForEach-Object { $_.ToString("x2") }) -join ''
Invoke-RestMethod -Uri 'https://your-domain/webhook/express/status' -Method Post -Body $body -ContentType 'application/json' -Headers @{ 'X-Timestamp'=$ts; 'X-Signature'=$sig; 'X-Client-Id'='partner-yd' }
```
**测试与沙箱**
- **临时隧道**: 联调期可使用 `ngrok``cloudflared` 将本地服务映射到公网供合作方发送测试回调。
- **测试密钥**: 为每个合作方发放 `test_secret``prod_secret`,并在系统中分离管理。
- **回放工具**: 提供一个简单 `test-send.js`(仓库已有)并在 README 中示例化如何运行。
**部署与网关建议**
- **域名与 TLS**: 使用 `webhook.<your-domain>`,证书推荐用 Let's Encrypt 自动续期。
- **反向代理 / 网关**: 推荐放在 Nginx / Kong / Cloud Load Balancer 前做:
- TLS 终端、IP 白名单、速率限制rate-limiting、日志落盘与审计。
- 如使用 Kong可在网关做 `key-auth` 或 IP 白名单做第一道防护。
- **WAF/防护**: 对外公开时开启基础 WAF过滤常见攻击与 DDOS 保护。
**监控与告警**
- **关键 Metric**: 接收量、验签失败率、重复率duplicate percent、处理延时、no-targets 率。
- **告警阈值**: 验签失败率 >1% 或 no-targets 突增 触发 PagerDuty/邮件告警。
**上线流程(最小安全步骤)**
1. 在测试环境配置 partner test_secret 与 `X-Client-Id`,提供示例脚本。
2. 使用 `ngrok` 联调,通过 23 次真实回调验证 `dedupe_key`、waybill 匹配和入队。
3. 把 partner 的 prod_secret 写入生产密钥存储(避免明文在 repo
4. 在生产网关启用 IP 白名单或 key-auth并在低流量窗口把 `WEBHOOK_REJECT_INVALID_SIGNATURE` 改为 `true`
**常见问题与排查**
- **验签失败**: 检查是否对方用了 stringify 后的 body 或时间戳单位不一致(秒 vs 毫秒);建议双方按示例脚本校验。
- **重复回调仍写入**: 检查 `dedupe_key` 的字段组合与 DB 唯一约束 `(waybill_id,dedupe_key)` 是否生效。
- **no-targets**: 确保 `push_devices` 已按 `merchant_id``user_id` 正确写入(见 `GET /api/v1/push/devices` 验证)。
**联系人与上游联调清单**
- **提供方需给出**: 回调样例(真实 JSON、回调频率预估、回调 IP 段、是否支持 `dedupe_key` 字段、联系人邮箱/电话。
- **我方需要提供**: `test_secret`、测试域名、示例脚本、接入说明(本文件)。
---
作者:自动生成;可根据合作方反馈补充示例与节流策略。