monkeytheme.com 上的 Cryptomus USDT 充值未到账。

订单卡在 PENDING、跳到 CANCELLED、或者用户在 Cryptomus 支付页付款成功后余额没到——这一页给出按顺序的真实诊断流程。所有结论都来自 monkeytheme.com 2026-08-08 的生产 webhook 日志和 payment_orders 表结构。

/api/v1/payment/
webhook/cryptomus
唯一真实端点
400 missing sign探测,不是真实付款
30 分钟默认订单超时
4 条路径7 天日志中观察到

按顺序要做的事

如果一笔 Cryptomus USDT 充值看起来卡住,按下面四步走完再开工单。每一步都有可以直接验证的结论。

1. 订单有没有真的进 payment_orders

登录后打开 /dashboard/orders,找到订单 id。如果这一行根本不存在,说明创建订单的请求根本没到后端——通常是因为用户还没登录就点了充值,或者同一个 key 在多浏览器里被复用。

如果行存在,看 status、paid_at 和 expires_at:

status通常含义下一步
PENDING用户打开了 pay_url 但还没完成链上转账,或者 webhook 还没到。等 30 分钟内复查。Cryptomus 会重试 webhook。
COMPLETEDwebhook 验证通过,余额已到账,订单关闭。不用动。如果余额没动,把订单 id 发工单。
CANCELLED用户没付款就关了支付页,或者订单超时。重新创建一笔。老单不可恢复。
EXPIRED超过 ORDER_TIMEOUT_MINUTES(默认 30)还没有 webhook。重新创建。如果反复出现,说明上游 webhook 在丢失。
FAILEDwebhook 到了,但上游报失败。把订单 id、paid_at 和 Cryptomus invoice id 发工单。

2. Cryptomus 有没有 POST 到官方 webhook

monkeytheme.com 的前端 bundle(providerConfig-*.js)里写死的 notifyUrl 只有一条:

cryptomus:"/api/v1/payment/webhook/cryptomus"

其他都是错的。2026-08-08 截取的生产日志里,七天内一共出现过四条 webhook 路径,其中三条是噪声:

观察到的路径状态码来源
/api/v1/payment/webhook/cryptomus真实 webhook 200,探测 400官方前端
/api/v1/payment/cryptomus/webhook404探测(路径顺序换位)
/api/v1/payment/webhooks/cryptomus404探测(多了一个 s)
/api/cryptomus/webhook404探测(没有 /v1)

官方路径上的 400 全部是 cryptomus webhook missing sign,并且 bodyLen: 2,说明 body 就是 {}。这不是真实充值,是扫描器或客户端配错了。真实的 Cryptomus webhook body 一定带 JSON sign 字段和订单 payload。

3. 用户到底有没有完成链上转账

Cryptomus 托管页需要达到指定确认数后才会显示付款成功。在那之前 Cryptomus 不会 POST webhook。如果用户付款前关掉了标签页,订单会一直 PENDING,直到 expires_at 超时。

可以让用户从托管页 URL 里复制 Cryptomus invoice id(形如 pay_url?...&orderid=...,或者跳转后页面上显示的订单 id),到 Cryptomus 商户后台的 Payments 里直接核对。

4. returnUrl 轮询有没有跑完

链上支付成功后,托管页会跳到 /payment/result。前端用 GET /api/v1/payment/orders/my 轮询几秒钟,等 COMPLETED 状态出现。如果用户等不及关掉了那个标签页,余额其实已经被 webhook 加上了,只是 UI 一直显示 PENDING,下次刷新就好了。

处理:刷新订单页就行。不要因为弹窗关得早就说 webhook 坏了。

真实的端到端流程

USDT 充值从 /purchase 到余额到账,在 monkeytheme.com 上实际走的是这五步:

1. 创建订单POST /api/v1/payment/orders
status=PENDING, expires_at = now + ORDER_TIMEOUT_MINUTES
2. 托管 pay_url用户在 Cryptomus 页面付款
链上转账等待确认数
3. WebhookPOST /api/v1/payment/webhook/cryptomus
验证 sign、幂等、金额、币种
4. 加余额sub2api 更新钱包 + status=COMPLETED
写入 paid_at,发放兑换码
5. 回跳轮询GET /api/v1/payment/orders/my
UI 翻为已支付,弹窗自动关闭

第 3 步是服务端配置错误会让已付款订单悄悄丢失的唯一位置。第 4 步和第 3 步在同一个 webhook handler 里跑,第 3 步返 200,第 4 步就跑完了。如果你看到第 3 步是 400,第 4 步根本没启动,用户当然没收到余额。

生产日志实际长什么样

下面是一行真实的 monkeytheme.com webhook 日志,来源是 journalctl -u sub2api --since "7 days ago",2026-08-08 截取。

INFO  middleware/logger.go:82  http request completed
  service=sub2api  env=production  component=http
  request_id=f55564df-948e-4847-8a17-d72285534880
  path=/api/v1/payment/webhook/cryptomus
  method=POST
  status_code=400
  latency_ms=7
  client_ip=65.49.151.58
  protocol=HTTP/1.1

同一笔交易、紧挨着的上一行:

ERROR slog logger/slog_handler.go:53  [Payment Webhook] verify failed
  provider=cryptomus
  error="cryptomus webhook missing sign"
  method=POST
  bodyLen=2

两点结论:

注意:client_ip 65.49.151.58 和 2a02:4780:10:6b04::1 不是真实用户。同一分钟内它们还命中了 /api/cryptomus/webhook、/api/auth/google、/api/v1/settings/public 等无关端点。如果你看到的日志也是这种形态,那是探测,不是用户。

需要升级处理的时候

上面四步都跑过之后再开工单。一次回复就能定位的四个证据:

  1. 订单 id(/dashboard/orders 里的数字)。
  2. Cryptomus invoice id(托管页 URL 或商户后台)。
  3. 这一行订单的 status 和 paid_at。
  4. 5 分钟日志切片:journalctl -u sub2api --since "5 minutes ago" --no-pager | grep -E "orderid=YOUR_ORDER_ID|payment/webhook/cryptomus|verify failed"

不要发钱包地址截图,不要发账号密码,不要贴 API key。订单 id + invoice id 就够查到这一行。

FAQ

monkeytheme.com 上 Cryptomus 官方 webhook 路径是哪条?

/api/v1/payment/webhook/cryptomus。其他路径如 /api/v1/payment/cryptomus/webhook、/api/v1/payment/webhooks/cryptomus(多一个 s)和 /api/cryptomus/webhook 都没有注册路由,全部返回 404,即使生产日志里能看到请求落到这些路径上。

为什么官方 webhook 一直返回 400 并提示 'cryptomus webhook missing sign'?

说明 Cryptomus POST 的请求体没有带 sign 字段,或者 body 是空的。2026-08-02 的生产日志里,失败的请求全部是 bodyLen=2(字面意义就是 {})。真实的 Cryptomus webhook 请求体总会带一个 JSON sign 字段,所以空 body 不是真实充值,而是探测、客户端配置错或代理把 body 剥掉了。

订单卡在 PENDING 几个小时,是不是 webhook 坏了?

不一定是。webhook 路径只是流程的一半。Cryptomus 第一次失败会重试 webhook,商户后台也可以手动重发。另一半是 returnUrl:用户付完款会被跳回 /payment/result,前端会轮询订单状态。如果用户还没等回跳就关掉标签页,订单可能一直 PENDING 直到超时(默认 30 分钟,由 ORDER_TIMEOUT_MINUTES 控制)。

这一页没覆盖的事

这一页只覆盖付款后:webhook 有没有到、订单有没有进 COMPLETED、余额有没有到账。它不教选钱包、选网络、估 gas。这些选择有各自的判断和风险,上游改得比文档快,直接链到 Cryptomus 文档比抄数字靠谱。