概述
在验证官方 v0.0.7 版本时,我又发现了几个后续问题。这些问题不包括目前已经知道的 Polygon / Plasma 监听器启动问题。
补充说明:目前已经有一个与收银台选项注入相关的 PR(#28),这里还是把剩余的问题一起整理出来,方便后续统一跟踪。
1. supported_asset 没有真正完全接管下单和切网逻辑
相关代码:
src/model/service/order_service.go
src/model/data/supported_asset_data.go
相关路由 / 入口:
- 创建订单主入口:
POST /payments/gmpay/v1/order/create-transaction
- 创建订单兼容入口:
POST /payments/epusdt/v1/order/create-transaction
- 切换网络 / 币种:
POST /pay/switch-network
- 对外展示支持项:
GET /payments/gmpay/v1/supported-assets
- 支持项管理:
POST /payments/gmpay/v1/supported-assets/add、POST /payments/gmpay/v1/supported-assets/:id/update、POST /payments/gmpay/v1/supported-assets/:id/delete
当前表现:
v0.0.7 已经引入了 supported_asset,但是创建订单和切换子订单网络时,并没有始终把“启用状态的 supported_asset”作为唯一依据。
- 实际上,只要该网络下还有钱包,即使对应的
supported_asset 已经被禁用或删除,某些币种/网络组合仍然可能通过上述下单或切网入口被创建出来。
GET /payments/gmpay/v1/supported-assets 更像是“展示层过滤结果”,但目前没有成为 POST /payments/gmpay/v1/order/create-transaction 和 POST /pay/switch-network 的硬约束。
影响:
- 后台配置和真实对外行为可能不一致。
- 管理员以为已经禁用的币种/网络,用户仍然可能继续下单或切换过去。
建议:
- 创建订单前,先校验
(network, token) 是否存在于启用状态的 supported_asset 中。
- 创建切网后的子订单前,也做同样的启用项校验。
- 最好让“展示给用户的 supported-assets”和“后端真实允许创建 / 切换的组合”共用同一套判定逻辑。
2. 收银台页面可能展示实际上并不可用的支付选项
相关代码:
src/model/service/pay_service.go
src/controller/comm/pay_controller.go
src/model/response/pay_response.go
src/static/index.html
src/static/payment.js
相关路由 / 入口:
- 收银台页面:
GET /pay/checkout-counter/:trade_id
- 页面内切换网络 / 币种:
POST /pay/switch-network
当前表现:
- 收银台前端仍然保留了硬编码的兜底支付选项。
- 后端没有把“当前真正可用的支付选项”完整注入到
GET /pay/checkout-counter/:trade_id 对应的页面中。
- 结果就是:页面里看到的可选项,不一定和
POST /pay/switch-network 真正能切过去的选项一致。
影响:
- 收银台可能会展示实际上并未配置的币种/网络。
- 已禁用的资产、或者根本没有可用钱包的网络,也可能出现在页面里。
- 用户可能会在前端看到可选项,但实际切换时失败,造成体验和配置认知上的混乱。
建议:
- 由服务端根据以下信息生成收银台支付选项:
- 启用状态的
supported_asset
- 当前启用的钱包
- 当前订单本身
- 把这个真实选项列表注入页面,由前端只渲染这些选项。
- 如果仍然需要兜底逻辑,建议兜底为“当前订单本身”,而不是使用硬编码目录。
3. 钱包地址校验和 EVM 地址归一化在不同入口不一致
相关代码:
src/telegram/handle.go
src/telegram/utils.go
src/controller/comm/wallet_controller.go
src/model/data/wallet_address_data.go
src/model/service/task_service.go
src/model/data/order_data.go
相关路由 / 入口:
- API 添加钱包:
POST /payments/gmpay/v1/wallet/add
- API 查看钱包:
GET /payments/gmpay/v1/wallet/list
- Telegram 添加钱包:机器人对话入口(非 HTTP 路由)
当前表现:
- Telegram 添加钱包时,会按网络校验地址,并且会把 EVM 地址转成小写后再保存。
- 后台/API 通过
POST /payments/gmpay/v1/wallet/add 添加钱包时,没有应用同样的校验和归一化逻辑。
- EVM 链监听到账时,会先把链上接收地址转成小写,再去匹配锁表记录。
- 锁表查询使用的是精确的
address = ? 匹配。
影响:
- 如果 EVM 钱包是通过后台/API 以混合大小写形式录入的,那么链上实际到账后,虽然语义上是同一个地址,仍然可能因为大小写不一致而匹配不上。
- 同一个 EVM 地址,从不同入口录入后,数据库中的保存格式可能不一致。
建议:
- 把钱包地址的校验和归一化逻辑统一收敛到一套公共逻辑里,所有入口共用。
- 录入时接受合法的 EVM 十六进制地址,不要因为不是 checksum 展示格式就直接拒绝。
- 系统内部统一归一化后再存储和匹配,例如统一转小写。
- Telegram 和后台/API 不应继续维持两套不一致的行为。
4. Epay 回调成功判定比普通回调更宽松
相关代码:
相关路由 / 入口:
Epay 兼容下单入口:GET / POST /payments/epay/v1/order/create-transaction/submit.php
- 商户异步回调目标:下单参数里的
notify_url(外部商户地址,不是固定内部路由)
当前表现:
- 普通回调分支会同时检查 HTTP 状态码和响应体,再决定是否把回调标记为成功。
Epay 回调分支虽然提交了表单并读取了响应体,但没有像普通回调那样严格使用同样的成功判定条件。
- 也就是说,问题不是出在固定站内路由,而是出在 paid 之后 worker 对商户
notify_url 的成功判定逻辑。
影响:
- 商户侧回调即使返回了非预期状态码或响应体,系统也可能仍然把它当成回调成功。
- 这样会导致本应继续重试的回调被提前标记为成功,不再重试。
建议:
Epay 回调分支也使用和普通回调一致的成功判定规则:
- 其余情况都按失败处理,让重试机制继续工作。
可选的小清理项
官方发布版本里还有少量控制器侧的调试输出,这不算阻塞性问题,但如果后续一起修复以上问题,顺手清理掉会更合适。
概述
在验证官方
v0.0.7版本时,我又发现了几个后续问题。这些问题不包括目前已经知道的Polygon/Plasma监听器启动问题。补充说明:目前已经有一个与收银台选项注入相关的 PR(
#28),这里还是把剩余的问题一起整理出来,方便后续统一跟踪。1.
supported_asset没有真正完全接管下单和切网逻辑相关代码:
src/model/service/order_service.gosrc/model/data/supported_asset_data.go相关路由 / 入口:
POST /payments/gmpay/v1/order/create-transactionPOST /payments/epusdt/v1/order/create-transactionPOST /pay/switch-networkGET /payments/gmpay/v1/supported-assetsPOST /payments/gmpay/v1/supported-assets/add、POST /payments/gmpay/v1/supported-assets/:id/update、POST /payments/gmpay/v1/supported-assets/:id/delete当前表现:
v0.0.7已经引入了supported_asset,但是创建订单和切换子订单网络时,并没有始终把“启用状态的supported_asset”作为唯一依据。supported_asset已经被禁用或删除,某些币种/网络组合仍然可能通过上述下单或切网入口被创建出来。GET /payments/gmpay/v1/supported-assets更像是“展示层过滤结果”,但目前没有成为POST /payments/gmpay/v1/order/create-transaction和POST /pay/switch-network的硬约束。影响:
建议:
(network, token)是否存在于启用状态的supported_asset中。2. 收银台页面可能展示实际上并不可用的支付选项
相关代码:
src/model/service/pay_service.gosrc/controller/comm/pay_controller.gosrc/model/response/pay_response.gosrc/static/index.htmlsrc/static/payment.js相关路由 / 入口:
GET /pay/checkout-counter/:trade_idPOST /pay/switch-network当前表现:
GET /pay/checkout-counter/:trade_id对应的页面中。POST /pay/switch-network真正能切过去的选项一致。影响:
建议:
supported_asset3. 钱包地址校验和 EVM 地址归一化在不同入口不一致
相关代码:
src/telegram/handle.gosrc/telegram/utils.gosrc/controller/comm/wallet_controller.gosrc/model/data/wallet_address_data.gosrc/model/service/task_service.gosrc/model/data/order_data.go相关路由 / 入口:
POST /payments/gmpay/v1/wallet/addGET /payments/gmpay/v1/wallet/list当前表现:
POST /payments/gmpay/v1/wallet/add添加钱包时,没有应用同样的校验和归一化逻辑。address = ?匹配。影响:
建议:
4.
Epay回调成功判定比普通回调更宽松相关代码:
src/mq/worker.go相关路由 / 入口:
Epay兼容下单入口:GET / POST /payments/epay/v1/order/create-transaction/submit.phpnotify_url(外部商户地址,不是固定内部路由)当前表现:
Epay回调分支虽然提交了表单并读取了响应体,但没有像普通回调那样严格使用同样的成功判定条件。notify_url的成功判定逻辑。影响:
建议:
Epay回调分支也使用和普通回调一致的成功判定规则:可选的小清理项
官方发布版本里还有少量控制器侧的调试输出,这不算阻塞性问题,但如果后续一起修复以上问题,顺手清理掉会更合适。