Files
medical-mall/pages/mall/delivery/webhook-server/README.md
not-like-juvenile e67016a6f4 消息推送
2026-03-10 16:39:50 +08:00

152 lines
7.5 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 接收器 — 说明
路径:`pages/mall/delivery/webhook-server/webhook-receiver.js`
目的:接收承运方或 Mock Server 的 HTTP 回调POST /webhook/express/status将原始回文写入 `platform_express_event_raw`,并按项目现有映射更新 `platform_express_waybills` 与写入 `platform_express_tracking_events`
环境变量(必须/可选):
- `SUPA_URL`Supabase REST 地址(示例 `http://192.168.1.62:18000`
- `SUPA_KEY`Supabase service_role 或 anon key用于 REST 写入)
- `SUPA_USE_BEARER`(可选):是否附加 `Authorization: Bearer <SUPA_KEY>`,默认 `false`
- 在一些自托管 Supabase/Kongkey-auth环境中**只需要** `apikey`;如果误加 Bearer 且 key 不是 JWT可能出现 `PGRST301`"None of the keys was able to decode the JWT")。
- `WEBHOOK_SECRET`(可选):与第三方共享的 HMAC-SHA256 secret用于校验 `X-Signature`(签名为 hex
- `WEBHOOK_PORT`(可选):接收器监听端口,默认 `7201`(推荐用这个,便于与 push-server 共享同一份 `server/config.json`
- `PORT`(可选):接收器监听端口(兼容旧用法;若共享 `server/config.json` 且其中 `PORT=7301`,会导致端口冲突)
配置方式(推荐用配置文件,避免与其他服务端口冲突):
- **同目录配置文件(推荐)**:在 `webhook-receiver.js` 同目录放置 `webhook.config.json`,启动时会自动读取。
- **显式指定配置文件**:设置 `CONFIG_FILE` / `CONFIG_PATH` 指向你的 `.env``.json`
- **回退加载**:若未指定 `CONFIG_FILE` 且同目录无 `webhook.config.json`,会尝试读取 `server/.env``server/config.json`(由 `server/load-config.js` 负责)。
示例配置文件:仓库内提供 [server/webhook.config.json.example](server/webhook.config.json.example),你可以复制一份到本目录作为 `webhook.config.json` 使用。
启动PowerShell
```powershell
node pages/mall/delivery/webhook-server/webhook-receiver.js
```
推荐使用同目录配置文件启动PowerShell
```powershell
# 复制示例并填写真实 SUPA_KEY
Copy-Item .\server\webhook.config.json.example .\pages\mall\delivery\webhook-server\webhook.config.json
node pages/mall/delivery/webhook-server/webhook-receiver.js
```
如果你使用显式 CONFIG_FILE
```powershell
$env:CONFIG_FILE=(Resolve-Path .\pages\mall\delivery\webhook-server\webhook.config.json)
node pages/mall/delivery/webhook-server/webhook-receiver.js
```
启动Linux / macOS / WSL
```bash
export SUPA_URL='http://192.168.1.62:18000'
export SUPA_KEY='your_service_role_key'
export WEBHOOK_SECRET='your-secret' # optional
node pages/mall/delivery/webhook-server/webhook-receiver.js
```
也可以用配置文件(更适合长期运行):
- `server/load-config.js` 会自动尝试加载:`server/.env``server/config.json`(以及 `CONFIG_FILE/CONFIG_PATH` 指定的文件),并把其中的键注入到 `process.env`
- 因为接收器已在启动时 `require` 了该加载器,所以你只要把 `SUPA_URL``SUPA_KEY` 写进上述文件之一即可。
如果你不想与 `server/config.json` 共用 `PORT`(避免端口冲突),建议为 webhook 单独准备一个配置文件,然后用 `CONFIG_FILE` 指定:
```powershell
# 复制示例文件并填写真实 SUPA_KEY
Copy-Item .\server\webhook.config.json.example .\server\webhook.config.json
# 指定配置文件启动(不会影响 push-server 的配置):
$env:CONFIG_FILE=(Resolve-Path .\server\webhook.config.json)
node pages/mall/delivery/webhook-server/webhook-receiver.js
```
示例:在 `server/.env` 中写入:
```env
SUPA_URL=http://192.168.1.62:18000
SUPA_KEY=your_service_role_key
WEBHOOK_SECRET=your-secret
PORT=7201
```
测试curl 模拟第三方推送):
```bash
BODY='{"mailNo":"TEST_123","infoContent":"SENT","remark":"派送中","acceptTime":"2026-02-25 12:00:00","carrier":"YTO"}'
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# 如果启用了 WEBHOOK_SECRET计算签名
SIG=$(printf "%s%s" "$BODY" "$TS" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | awk '{print $2}')
curl -i -X POST http://localhost:7201/webhook/express/status \
-H "Content-Type: application/json" \
-H "X-Timestamp: $TS" \
-H "X-Client-Id: mock_carrier" \
-H "X-Signature: $SIG" \
-d "$BODY"
```
健康检查:
- `GET http://localhost:7201/health`(端口以 `PORT` 为准)
常见问题排查:
- 返回 `{ ok:false, message:'waybill not found' }`:说明 webhook 已收到请求,但在 `platform_express_waybills` 中找不到 `tracking_no`(或 `order_no`)匹配的记录。
- 返回 `502 supabase unauthorized (check SUPA_KEY/SUPA_URL)`:说明当前 `SUPA_KEY` / `SUPA_URL` 无法通过 Supabase REST 鉴权(常见于 key 填错、已失效、URL 不对)。请换成 Supabase 控制台中的真实 `service_role` key并重启接收器。
Windows 下保持“持续监听”(后台运行):
> 只要 Node 进程还在webhook 就会持续监听;如果你关闭终端/窗口或按 `Ctrl+C`,进程结束就不会再监听。
```powershell
# 后台启动并把日志写到文件(推荐)
Start-Process node -ArgumentList 'pages/mall/delivery/webhook-server/webhook-receiver.js' \
-WorkingDirectory (Get-Location) \
-RedirectStandardOutput '.\webhook-receiver.log' \
-RedirectStandardError '.\webhook-receiver.err.log' \
-PassThru
# 查看是否在监听(把 7201 换成你的 PORT
netstat -ano | findstr :7201
# 查看健康检查
Invoke-RestMethod -Uri 'http://localhost:7201/health' -Method GET | ConvertTo-Json
```
停止服务(按 PID 结束进程):
```powershell
# 先用 netstat 找到 LISTENING 的 PID然后结束它
Stop-Process -Id <PID>
```
依赖说明:
- 建议使用 Node.js 18+(例如你当前的 Node.js 22已内置 `fetch`,无需安装 `node-fetch`
- 若使用更老的 Node 且没有 `fetch`,需要安装 `node-fetch`(并保持 CommonJS 兼容)。
预期:接口返回 200 JSON {ok:true}(若未找到对应运单会返回 {ok:false, message:'waybill not found'})。
验证写入(查看 Supabase
```bash
# 示例:列最近 5 条原始回文
curl -s -H "apikey: $SUPA_KEY" -H "Authorization: Bearer $SUPA_KEY" \
"$SUPA_URL/rest/v1/platform_express_event_raw?select=*&order=received_at.desc&limit=5" | jq .
# 查看最近轨迹事件
curl -s -H "apikey: $SUPA_KEY" -H "Authorization: Bearer $SUPA_KEY" \
"$SUPA_URL/rest/v1/platform_express_tracking_events?select=*&order=created_at.desc&limit=5" | jq .
```
与仓库中 Mock 实现的关系:
- `pages/mall/delivery/test/mock-service.uts` 已包含写库逻辑(`pushWebhookData``bindShipment``runScenario`)。新接收器复用了同样的入库思路,但以 HTTP/REST 的形式对外暴露。
注意事项:
- 本接收器通过 Supabase REST API 直接写表,使用 `SUPA_KEY` 时请确保权限与密钥安全(不要将 service_role key 公开到前端)。
- 如果你的 Supabase 接口部署在内网,请确保接收器能访问 `SUPA_URL`(网络/防火墙)。
- 若需要更严格的验签/重放检测/幂等,请告知,我可以把这些能力加入接收器(例如记录并比对 dedupe_key 或检查 X-Timestamp 时间窗口)。
下一步建议:
- 若你要把第三方直接接到该接收器,请把 `WEBHOOK_SECRET` 与对方约定并启用验签。
- 若需要我加重放防护或返回 4xx/5xx 更精确的逻辑,也可继续实现。
文件位置:
- [Webhook 接收器](pages/mall/delivery/server/webhook-receiver.js)
作者:自动生成(可手动调整)