Files
medical-mall/pages/mall/delivery/webhook-server
not-like-juvenile 4acbb8ced5 补充方案
2026-03-12 10:36:51 +08:00
..
2026-03-12 10:36:51 +08:00
2026-03-09 10:39:29 +08:00
2026-03-10 16:39:50 +08:00
2026-03-09 10:39:29 +08:00

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_URLSupabase REST 地址(示例 http://192.168.1.62:18000
  • SUPA_KEYSupabase 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_REJECT_INVALID_SIGNATURE(可选):若为 true,且配置了 WEBHOOK_SECRET,则验签失败会直接返回 HTTP 401默认不拒绝只记录
  • 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/.envserver/config.json(由 server/load-config.js 负责)。

示例配置文件:仓库内提供 server/webhook.config.json.example,你可以复制一份到本目录作为 webhook.config.json 使用。

启动PowerShell

node pages/mall/delivery/webhook-server/webhook-receiver.js

推荐使用同目录配置文件启动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

$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

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/.envserver/config.json(以及 CONFIG_FILE/CONFIG_PATH 指定的文件),并把其中的键注入到 process.env
  • 因为接收器已在启动时 require 了该加载器,所以你只要把 SUPA_URLSUPA_KEY 写进上述文件之一即可。

如果你不想与 server/config.json 共用 PORT(避免端口冲突),建议为 webhook 单独准备一个配置文件,然后用 CONFIG_FILE 指定:

# 复制示例文件并填写真实 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 中写入:

SUPA_URL=http://192.168.1.62:18000
SUPA_KEY=your_service_role_key
WEBHOOK_SECRET=your-secret
PORT=7201

测试curl 模拟第三方推送):

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"

重要:签名计算必须使用原始请求体文本raw body。接收器也会使用 raw body 进行验签;不要用 JSON 对象 stringify 后的字符串替代。

健康检查:

  • 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,进程结束就不会再监听。

# 后台启动并把日志写到文件(推荐)
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 结束进程):

# 先用 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

# 示例:列最近 5 条原始回文
curl -s -H "apikey: $SUPA_KEY" -H "Accept: application/json" \
  "$SUPA_URL/rest/v1/platform_express_event_raw?select=*&order=received_at.desc&limit=5" | jq .

# 查看最近轨迹事件
curl -s -H "apikey: $SUPA_KEY" -H "Accept: application/json" \
  "$SUPA_URL/rest/v1/platform_express_tracking_events?select=*&order=created_at.desc&limit=5" | jq .

# 如果你的环境已确认 Bearer 可用(不会触发 PGRST301也可以额外加上
# -H "Authorization: Bearer $SUPA_KEY"

与仓库中 Mock 实现的关系:

  • pages/mall/delivery/test/mock-service.uts 已包含写库逻辑(pushWebhookDatabindShipmentrunScenario)。新接收器复用了同样的入库思路,但以 HTTP/REST 的形式对外暴露。

注意事项:

  • 本接收器通过 Supabase REST API 直接写表,使用 SUPA_KEY 时请确保权限与密钥安全(不要将 service_role key 公开到前端)。
  • 如果你的 Supabase 接口部署在内网,请确保接收器能访问 SUPA_URL(网络/防火墙)。
  • 若需要更严格的验签/重放检测/幂等,请告知,我可以把这些能力加入接收器(例如记录并比对 dedupe_key 或检查 X-Timestamp 时间窗口)。

下一步建议:

  • 若你要把第三方直接接到该接收器,请把 WEBHOOK_SECRET 与对方约定并启用验签。
  • 若需要我加重放防护或返回 4xx/5xx 更精确的逻辑,也可继续实现。

文件位置:

作者:自动生成(可手动调整)