常见问题
用 Ctrl-F 搜索你正在调试的症状。每则回答刻意保持精简,并链接到包含完整说明的章节。
入门
我从哪里取得 api_key?
你的客户经理会在 onboarding 期间发放。你会收到两把独立的密钥 — 一把给 sandbox(通常以 pre_ 为前缀),一把给生产环境。没有自助式发放入口。请见 Security 了解存储与轮换规则。
sandbox 与生产环境有什么差别?
Sandbox(https://pre-api.open-pay.co)跑的是与生产环境(https://api.open-pay.co)相同的代码,但对应到隔离的数据库、隔离的渠道与模拟资金。凭证、余额与订单不会在两者之间互通。请见 Sandbox 取得完整对比。
我的 api_key 正确,为什么请求还是回 401?
401 的成因可能是签名错误或 X-Timestamp 超出时窗,而不是密钥本身。检查 JSON 信封中的 code 字段:INVALID_SIGNATURE 与 INVALID_TIMESTAMP 都是 401。请见 Errors 取得验证码目录。
我可以不用公开的 callback URL 测试整合吗?
不行。Gateway 会通过 HTTPS 把回调送到它能连到的 URL。本地开发可以用 ngrok 通道、request-bin,或你自己基础设施中仅 sandbox 用的主机。请见 Callbacks 了解你必须接受的请求形状。
我怎么知道我的账号有哪些渠道可用?
渠道路由由运营方管理,不通过商户 API 揭露。请向你的客户经理询问你的商户在 sandbox 与生产环境分别串了哪些币种与渠道。请见 Sandbox 了解为什么 sandbox 的渠道覆盖通常比生产环境少。
认证与签名
我的签名一直失败,要检查什么?
依序检查:用 ASCII(不是 locale)排序 keys、跳过 null 值但包含空字符串、拼接 api_key 时不加 & 分隔符、输出小写 hex。Authentication 中的四份参考实现经 CI 逐字节验证 — 用示例对照你的输出与它们的差异。
我的时间戳在 5 分钟内,为什么还是收到 INVALID_TIMESTAMP?
你的本机时钟正在漂移。5 分钟时窗是针对 gateway 的 NTP 同步时钟判定,不是你的时钟。执行 ntpdate(或你平台对应的指令)后重试。不要靠「相信服务器回传的时间戳」来「修正」漂移。请见 Security。
GET 请求也要签名吗?
要。签名是针对查询参数(若没有任何参数则仅针对 timestamp=...)加上你的 api_key 计算。GET 示例见 Quickstart 第 4 步。
我可以改用 HMAC-SHA256 取代 MD5 吗?
目前不行。签名契约是 MD5(sorted_params + api_key)。未来若迁移到 HMAC-SHA256 会在 changelog 公告并提供并行接受期。不要预先实现。请见 Security 了解理由。
我要如何轮换 api_key?
联系你的客户经理。运营方会发放第二把有效密钥,你完成切换后,旧密钥会在短暂重叠期(约 5 分钟)后退役。没有商户入口的自助轮换。请见 Security。
充值与提款
Direct API 与 Cashier session 有什么差别?
Direct API(POST /deposit)会立刻建立 DepositOrder,并回传银行信息或 payment_url 让你渲染。Cashier session(POST /deposit/cashier)会建立 CashierSession 并回传 cashier_url;不带 amount 时,DepositOrder 会在付款人于托管页面提交时建立;带 amount 时会立即建立 DepositOrder 并跳过面额选择。请见 Deposits。
status MATCHED 何时会转成 COMPLETED?
MATCHED 代表 gateway 已识别付款;COMPLETED 代表账本已把资金落账到你的余额。转换通常在毫秒级,但不保证即时。签名回调是在 COMPLETED 触发,不是 MATCHED。请见 Deposits。
为什么我的提款卡在 PENDING?
提款上的 PENDING 代表必须由运营人员手动核准才能继续前进。这由审核引擎驱动 — 订单金额、单日笔数、白名单匹配都会影响。请见 Withdrawals 了解审核规则。
我可以通过商户 API 取消提款吗?
不行。没有商户取消端点。CANCELLED 只能通过运营方在内部 TransferTask 取消才能达到。若你误送,请联系平台运营。请见 Withdrawals。
若付款人在我的充值单到期前未完成会发生什么事?
订单会转成 EXPIRED 并停止接受付款。在到期后抵达的资金不会自动匹配,可能需要人工对账。默认到期不会触发回调 — 通过 GET /query/deposit/{order_no} 对账。请见 Deposits。
回调
为什么我会收到同一个回调两次?
Gateway 会对任何未收到 2xx ack 的回调重试,最多 5 次、每次间隔 30 秒。合法重试期间的网络 race 与恶意重放在外观上无法区分。请以 (order_no, status) 去重并以 200 ack。请见 Callbacks。
我的 callback_url 曾回 500 一次,gateway 会重试吗?
会。5xx、超时与网络错误都会触发重试。排程固定为 30s、30s、30s、30s — 总共五次尝试、横跨约 2 分钟 — 之后转 FAILED。请见 Callbacks 了解重试语义。
回调最久会重试多久?
5 次尝试之后(距首次送出约 2 分钟)NotificationLog 会标记为 FAILED,不再尝试。若你的端点整个时窗都挂掉,5 次都会失败,你必须通过 /query/* 端点对账。请见 Callbacks。
回调可能不按顺序抵达吗?
可能。在故障恢复期间,deposit.matched 可能在 deposit.completed 之后才抵达。你的 (order_no, status) 幂等表会避免状态重复套用,但你的业务逻辑必须能接受终态,无论中间态以什么顺序先到。请见 Callbacks。
ack 响应需要回传 body 吗?
不需要。任何 2xx 都视为成功 ack;body 会被忽略。包含 success 一词的 body 也接受。请快速响应 — 每次尝试的超时是 10 秒。请见 Callbacks。
错误与重试
我收到 5xx,应该重试吗?
要重试,使用指数退避,并用相同的 merchant_order_no。建立类调用上的 5xx 不代表订单没建立 — 服务器可能在失败前已 commit。重试后用 merchant_order_no 查询确认真实状态。请见 Errors。
OPTIMISTIC_LOCK_ERROR 是什么意思?
并发更新在同一笔商户余额或订单列上与你的请求竞争到。这是暂态的。用短 jitter 最多重试 3 次,再查询订单确认首次尝试是否已落地,再决定是否重送。请见 Errors 与 Withdrawals 了解重试模式。
为什么重复的 merchant_order_no 会回 409?
重复的 merchant_order_no 现在会以 HTTP 409 返回,并在标准 {success, code, message, data} 错误信封中带上 CONFLICT code。不要盲目重试;请先用 merchant_order_no 查询既有订单,再决定下一步。请见 Deposits 与 Errors。
我可以依赖 message 文字做错误处理吗?
不可以。message 字段不属于 API 契约 — 措辞可能毫无预警地变动。请永远以信封中的 code 字段做分支。请见 Errors。
Sandbox 与运营
我的来源 IP 被拒绝连接,该怎么排查?
来源 IP 的管控只在边缘的 Cloudflare Access 完成;应用层不再做任何来源 IP 检查。若你的 IP 不在 Cloudflare Access 允许名单内,请求会在边缘被挡下——表现为 TLS 握手失败或一个 HTML 质询 / 拦截页,而不是 JSON 形式的 403。请你的客户经理把 IP 加进 Cloudflare Access。注意:JSON 形式的 403 AUTHORIZATION_ERROR 与来源 IP 无关,它代表商户被停用或缺少 can_deposit / can_withdraw 权限。请见 Sandbox。
我要怎么在 sandbox 重现特定渠道失败?
Sandbox 渠道可由运营团队调整,回传特定状态(PENDING、COMPLETED、FAILED)以供测试。请你的客户经理把你的 sandbox 商户接上设置为你所需失败模式的 mock_channel。请见 Sandbox。
有 rate limit 吗?
Cloudflare 边缘 rate limit 套用在 API 主机名上。429 状态在错误目录中已保留,但目前并未在所有端点上强制执行。Sandbox 通常比生产环境宽松 — 不要从 sandbox 的吞吐量去外推。请见 Errors 与 Sandbox。
Sandbox 凭证与生产环境的不同吗?
完全不同。生产环境会拒绝 sandbox 的 api_key,反之亦然。将两者放在不同的 secret manager 路径,且不要设 fall-through 默认值。请见 Security。
合规与安全
我可以把 api_key 存在环境变量吗?
在 runtime 时从 secret manager(AWS Secrets Manager、GCP Secret Manager、Vault)注入到你的 process 环境。不要把它 commit 到版本控制中即使加密过、不要把它烤进 container image,也绝不能放到 client-side 代码。请见 Security。
Payment Gateway 会记录哪些数据?
平台会记录 request metadata、信封码与 order_no。敏感字段(api_key、X-Signature、bank_card_number、account_no)会被遮蔽。你这边也必须套用相同的遮蔽纪律 — 请见 Security 中的 do-log / do-not-log 清单。
我要如何回报安全漏洞?
直接联系你的客户经理。不要把漏洞细节记在公开的 ticketing 系统或商户入口中。他们会把回报转到平台安全团队。
还需要协助吗?
若你的症状不在本页,请联系你的客户经理。附上响应信封中的 code 字段、你的 merchant_order_no、gateway 的 order_no(若有),以及你送出的 X-Timestamp。这四个值能让平台团队在几秒内从 log 中找到你的请求。