⚠️ 金额原样发送,不替你舍入 —— 填 0.005 就发 0.005。
平台接受三位小数且转账响应不舍入,而 member/balance 做 Round(2),
同一笔钱两个接口给两个答案(《41》P20)。这条用业务流就能复现,不必走 raw。
要复现 P20 请走 接口台的 transfer/in。
转账流水(OC 侧本地账本)
| orderId | 方向 | 金额 | 状态 | HTTP | 平台 code | 平台 msg | 转账前余额 | 转账后余额 | 验签 | 耗时(端到端) | 备注 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
{{ r.orderId }} |
{{ r.direction }} | {{ r.amount.raw || r.amount.text }} ⚠️ 超精度 | {{ st(r.status).label }} | {{ tri(r.httpStatus) }} | {{ tri(r.platformCode) }} | {{ r.platformMsg }} | {{ r.balanceBeforeRaw || '—' }} |
{{ r.balanceAfterRaw || '—' }}
⚠️ 对不上
|
{{ sign(r.respSignOK).text }} | {{ r.costMs }}ms | {{ r.note }} |
还没有流水。
⚠️ UNKNOWN 不是 FAILED 的一种:请求发出但没拿到可判定的答复(超时 / HTTP 500 空 body / 非 JSON), 平台那边可能已经做了。把未知当成没发生,是单独一类的错误。
{{ gamesNote }}
启动结果 · {{ launch.game }}
{{ launch.resp.launchUrl || '(空)' }}
⚠️ 这里的单位是秒,转账那边的 timestamp 是毫秒。默认范围是最近 1 小时。
⚠️ 跨自然月返 5004,不是 5018。后端会按自然月自动切分,每段单独一次调用。
{{ orders.note }}
段 {{ i+1 }} · {{ s.label }} [{{ s.startTime }}, {{ s.endTime }}]
{{ badge(s.call).detail }}
{{ s.data || s.call.rawResp || '(空 body)' }}
⚠️ 注单的 data 是原始 JSON,不解析成表格:字段名经过平台的 camelCase 重写, 本地没有真实样本可核对,解错了还不如不解。等拿到真样本再做表格。
这三类当前没有业务接口,走接口台的 raw 入口(《11》8.1 有说明,不是漏了)。
⚠️ 游标拉单的终止条件是 code=7 + msg「最小值超过最大值」——
那不是错误,是已经拉完了。
⚠️ 区间是 id ∈ [minId, minId+pageSize-1],是个 ID 窗口不是「下 N 条」。
ID 在所有商户间共享,一个 1000 宽的窗口可能只返 3 条,
所以游标按 pageSize 步进,不按返回条数步进。
⚠️ 跨自然月不报错但会静默漏单(P17)。
这是「全部接口都要覆盖」的结构性保证,不靠自觉。 业务流里用不到的接口(historySearch 取 ID 上下界、exchange) 在这里同样有一张卡。当前共 {{ benchCount }} 张。
签名口径(11 个接口共用)
四件凭据在请求头里,不再是 body 字段:
X-Merchant X-Timestamp(毫秒)
X-Nonce X-Sign。
签名是 HMAC-SHA256,secret 作 key,输出 64 位小写 hex。
POST\n
{路径,含前缀、不含 query}\n
{商户号}\n
{毫秒时间戳}\n
{32 位随机串}\n
{请求体原文}\n
{HTTP 状态码}\n
{毫秒时间戳}\n
{32 位随机串}\n
{响应体原文}\n
⚠️ 第 6 行是实际发出去的那些字节,不是重新序列化的结果。
差一个空格签名就对不上,而平台只会返 5000 ——
分不出是字节不一致、路径被链路改写,还是 secret 错。
对不上时把下面的「待签串」和平台日志里的 path +
bodySha256 并排看。
{{ ep.name }} {{ ep.path }}
{{ f.name }}
{{ f.kind }} |
{{ f.note }} |
{{ preview(ep).bodyText }}
未发送的字段:{{ o.field }}({{ o.reason }})
⚠️ 这些字段的文本解析不成数字,已按字符串发出(负例照样送得出去):
{{ c }}
凭据覆盖(构造负例)已启用
X-Merchant |
留空 = 用会话里的商户号。 ⚠️ 只覆盖请求头,签名仍用真 secret —— 那才是"商户号写错"的真实形态 | |
X-Timestamp |
留空 = 发送时现取。窗口是 ±300 秒,双向 | |
X-Nonce |
留空 = 每次新生成。 ⚠️ 要触发 5042 必须填一个真正被平台记下过的值, 凭空造一个没用过的随机串不会红 | |
| 签名用的 body | 留空 = 与发送内容一致。 填了则用它算签名、仍发上面那个 body —— 这是"改 body 不重签必须被拒"的唯一做法: 先改小 money 点「锁定」,再改大 money 后发送 |
⚠️ 当前处于签名/内容错配状态,平台应当返 5000。 这条若返成功,说明 body 没有进签名 —— 那是要立刻报的缺陷。
{{ badge(bench[ep.name].result).detail }}
{{ bench[ep.name].result.msg || '(空)' }}{{ bench[ep.name].result.requestId || '(无)' }}
平台在所有响应上都回这个。
拒绝原因只进平台日志、不进响应体 —— 拿它去找他们{{ bench[ep.name].result.reqMerchant }}
{{ bench[ep.name].result.reqTimestampMs }}
{{ bench[ep.name].result.reqNonce }}{{ bench[ep.name].result.reqSign }}
HMAC 结果,不是密钥{{ bench[ep.name].result.reqSignPayload }}
{{ bench[ep.name].result.rawResp || '(空 body)' }}