Files
junhong_cmp_fiber/docs/integrations/gateway/README.md
break 7891189712
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m52s
feat(代理自充): AUG26-017 代理自充收款方式与线下预存款审批字段
- 受控配置新增代理在线自充允许范围(仅微信/仅支付宝/同时支持),读侧与创建侧取允许范围与可用商户池交集,两侧失败关闭
- 新增允许范围查询与修改端点,读限代理与平台账号、写限超级管理员,复用受控配置写服务留痕
- tb_agent_recharge_record 新增交易流水号、线下收款方式三列快照与其他凭证列(成对迁移 000213)
- 线下申请校验启用的收款方式字典项与必填交易流水号,交易流水号独立于在线渠道交易号、不参与去重
- 扩展 offline_recharge_approval 场景可映射字段白名单与字典引用保护
- 新增付款凭证识别能力与交易流水号预填接口,识别不落库、日志不记录载荷
2026-09-11 15:21:23 +08:00

5.2 KiB
Raw Permalink Blame History

Gateway 接入契约

元数据

  • OwnerIoT Gateway 适配维护人
  • 实现:internal/gateway/
  • 核验日期2026-09-11
  • 证据:internal/gateway/client.gocrypto.gocard_status.goflow_card.godevice.gopayment_voucher.go

当前实际使用范围

Gateway 是运营商流量卡、实名、停复机、限速和设备信息的统一封装入口。具体路径、请求字段和响应字段以同目录详细协议与 internal/gateway/*.go 的实际调用交集为准;文档中出现但代码未调用的接口不视为系统能力。

付款凭证识别(POST /ai/ocr/extract-payment,入参 image_base64)由 internal/gateway/payment_voucher.go 封装,当前唯一调用方是代理线下预存款申请的「交易流水号表单预填」。该能力只消费响应中的 order_number(作为交易流水号预填值);amountremarkpayment_methodpayeepayment_time 不进入本系统响应、不预填、不落库,识别结果不是资金事实。核验证据:internal/gateway/payment_voucher.go 的类型定义只对外暴露支付单号,internal/application/agentrecharge/payment_voucher_ocr.go 只返回该字段,接口响应 DTO 仅含 external_transaction_no

付款凭证识别刻意不走 doRequest / doRequestWithResponse:前者在 Info 级别打印加密前完整请求体、后者在 Info 级别打印完整原始响应,会把凭证图片内容与识别原始结果写进日志。该能力改用 Client.doRequestWithoutPayloadLog,仅记录路径、耗时与结果字节数摘要;既有能力的请求与日志语义保持不变(internal/gateway/client.goexecuteWithRetrylogPayload 分支)。

付款凭证识别的已知限制

  • 长号码可能不完整:对位数较多的转账单号,该接口可能只返回前若干位,实测存在识别值与凭证图片所示号码不一致的情况(位数少于凭证所示)。连续多次识别同一凭证所得长度与内容稳定,属上游侧确定性截断,而非本系统侧裁剪;预填值必须由提交人对照凭证人工核对,系统以人工确认值为准。
  • 单号缺失即失败:响应未给出单号时,本系统按识别失败返回明确失败(CodeGatewayInvalidResp,中文提示),不返回空值。
  • 字段类型会漂移:响应 dataamount 为 JSON 数值而非字符串。本系统只解码 order_number,不声明其余字段,故不受类型漂移影响;新增消费字段前必须重新核对上游类型。
  • 解析失败不回显原文:响应解码失败时只返回固定中文提示,不携带底层解析错误,避免第三方库的错误消息把识别原始结果带进日志与错误上下文。
  • 单次识别只接受单个附件键图片由后端读取对象存储后编码Gateway 凭证不下发前端;识别结果不落库、不构成资金事实。

本条限制的核验方式(可复现、不依赖样本取值):对同一图片凭证连续三次调用该识别接口,比较三次返回值的位数与内容是否一致——一致说明是上游确定性行为而非随机抖动;再将该位数与凭证图片所示号码的位数(用等长掩码计数,只比位数)对照,得出是否缺位。判定责任方时看本系统的解码路径 internal/gateway/payment_voucher.go:它只对返回值做 strings.TrimSpace,无截断、无按长度裁剪、无正则截取,因此位数差异只能来自上游。识别结果不落库,复核该接口的返回值需重新发起识别调用,不能从业务表反查。

配置、认证与报文

配置键为 gateway.base_urlgateway.app_idgateway.app_secretgateway.timeout。业务参数先包装为 {"params": ...},使用 AppSecret 做 AES-128-ECB 加密;外层请求含 appIddatasigntimestamp,签名使用 MD5。HTTP 方法统一为 POST内容类型为 application/json;charset=utf-8。HTTP 200 且 Gateway code=200 才算成功,data 再按具体能力解码。

超时、重试与幂等

客户端默认超时 60 秒;生效配置可覆盖。默认最多重试 2 次,即最多 3 次尝试,退避为 100ms、200ms更多重试时封顶 300ms。仅客户端超时、连接和 DNS 等网络级错误重试;用户 Context 取消、HTTP 非 200、响应解析失败和 Gateway 业务码失败不重试。每次尝试重新生成时间戳与签名。

查询天然只读;停复机、限速等写操作的幂等和状态条件由调用它的业务 Service 承担Gateway 客户端本身不提供幂等键。

安全、错误与验证

AppSecret、加密前业务数据、完整身份标识不得写入本文或普通日志当前客户端存在请求结构日志运行环境必须依赖日志脱敏策略。Gateway 错误映射为项目 CodeGatewayErrorCodeGatewayTimeoutCodeGatewayInvalidResp

可复现静态证据:internal/gateway/client.gointernal/gateway/crypto.go 及同目录能力文件。真实写操作可能改变卡或设备状态,本次只允许静态核对和隔离账号只读验证,不调用生产写接口。

协议、路径、认证、成功码、超时或重试分类变化时更新本文。