Skip to content

v0.0.8 仍存在的问题整理 #32

@jiamovo

Description

@jiamovo

概述

在验证官方 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/addPOST /payments/gmpay/v1/supported-assets/:id/updatePOST /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-transactionPOST /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 回调成功判定比普通回调更宽松

相关代码:

  • src/mq/worker.go

相关路由 / 入口:

  • Epay 兼容下单入口:GET / POST /payments/epay/v1/order/create-transaction/submit.php
  • 商户异步回调目标:下单参数里的 notify_url(外部商户地址,不是固定内部路由)

当前表现:

  • 普通回调分支会同时检查 HTTP 状态码和响应体,再决定是否把回调标记为成功。
  • Epay 回调分支虽然提交了表单并读取了响应体,但没有像普通回调那样严格使用同样的成功判定条件。
  • 也就是说,问题不是出在固定站内路由,而是出在 paid 之后 worker 对商户 notify_url 的成功判定逻辑。

影响:

  • 商户侧回调即使返回了非预期状态码或响应体,系统也可能仍然把它当成回调成功。
  • 这样会导致本应继续重试的回调被提前标记为成功,不再重试。

建议:

  • Epay 回调分支也使用和普通回调一致的成功判定规则:
    • 校验预期 HTTP 状态码
    • 校验预期成功响应体
  • 其余情况都按失败处理,让重试机制继续工作。

可选的小清理项

官方发布版本里还有少量控制器侧的调试输出,这不算阻塞性问题,但如果后续一起修复以上问题,顺手清理掉会更合适。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions