接口概览
OPENX 支付网关把不同支付方式的差异收敛为统一接口。业务系统只需要对接一次,通过 channel 参数选择具体支付方式,无需分别对接各家通道的 SDK、签名与回调。
| 接口 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 统一下单 | POST | /api/v1/order/create | 创建支付订单,返回二维码或跳转参数 |
| 订单查询 | POST | /api/v1/order/query | 按商户订单号或平台流水号查询 |
| 申请退款 | POST | /api/v1/refund/create | 全额或部分退款,可多次 |
| 退款查询 | POST | /api/v1/refund/query | 查询退款处理结果 |
| 关闭订单 | POST | /api/v1/order/close | 关闭未支付的订单 |
| 对账单 | GET | /api/v1/bill/daily | 按日拉取交易明细 |
所有接口均为
application/json,字符集 UTF-8。金额单位为分,128000 表示 1280.00 元。环境与域名
生产与沙箱使用同一套接口定义,仅域名与密钥不同。沙箱环境的交易不产生真实资金流转,可放心用于联调。
| 环境 | 接口域名 | 用途 |
|---|---|---|
| 生产 | https://pay.openx.net.cn | 正式收款 |
| 沙箱 | https://pay.openx.net.cn/sandbox | 联调测试(开通后分配) |
沙箱密钥与生产密钥完全隔离。请勿在生产环境使用沙箱
app_id,也请勿将密钥写入前端代码或提交到代码仓库。密钥与鉴权
开通后你会拿到两个值:
app_id:应用标识,可公开出现在请求中。app_secret:签名密钥,只能保存在服务端,用于计算与校验签名。
每个请求都需要携带 app_id、timestamp(10 位秒级时间戳)、nonce(随机字符串,32 位以内)与 sign。网关会校验时间戳偏差(±5 分钟)与 nonce 唯一性,防止重放。
签名规则
签名算法为 HMAC-SHA256,步骤如下:
- 取所有非空请求参数(
sign本身除外),按参数名 ASCII 码升序排序; - 拼接为
key=value形式,用&连接,末尾追加&key=app_secret; - 对拼接串以
app_secret为密钥做 HMAC-SHA256; - 输出大写十六进制字符串,即为
sign。
拼接时使用原始值,不做 URL 编码;布尔与数字按字符串处理;嵌套对象不参与签名(本接口均为扁平参数)。
function ox_sign(array $params, string $secret): string { unset($params['sign']); $params = array_filter($params, fn($v) => $v !== '' && $v !== null); ksort($params, SORT_STRING); $pairs = []; foreach ($params as $k => $v) { $pairs[] = $k . '=' . $v; } $raw = implode('&', $pairs) . '&key=' . $secret; return strtoupper(hash_hmac('sha256', $raw, $secret)); }
统一下单
POST https://pay.openx.net.cn/api/v1/order/create
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app_id | string | 是 | 应用标识 |
out_trade_no | string | 是 | 商户订单号,32 位以内,全局唯一,作为幂等键 |
amount | int | 是 | 金额,单位分,最小 1 |
channel | string | 是 | 支付方式,见下方取值 |
subject | string | 是 | 商品或服务标题,128 字以内 |
notify_url | string | 是 | 异步通知地址,必须为公网可访问的 HTTPS 地址 |
return_url | string | 否 | 同步跳转地址(H5 / 收银台场景) |
client_ip | string | 否 | 用户下单 IP,用于风控 |
attach | string | 否 | 附加数据,回调时原样返回 |
expire_minutes | int | 否 | 订单有效期(分钟),默认 30,最大 120 |
timestamp | int | 是 | 秒级时间戳 |
nonce | string | 是 | 随机串,32 位以内 |
sign | string | 是 | 签名,见「签名规则」 |
channel 取值
| 取值 | 支付方式 | 返回 |
|---|---|---|
wechat_native | 微信扫码 | qr_code 二维码链接 |
wechat_jsapi | 微信 JSAPI(公众号 / 小程序) | pay_params 唤起参数 |
wechat_h5 | 微信 H5 | pay_url 跳转地址 |
alipay_qr | 支付宝当面付 | qr_code 二维码链接 |
alipay_wap | 支付宝手机网站 | pay_url 跳转地址 |
unionpay_qr | 云闪付二维码 | qr_code 二维码链接 |
ecny_qr | 数字人民币 | qr_code 二维码链接 |
cashier | 聚合收银台 | pay_url 收银台页面地址 |
响应示例
{
"code": 0,
"msg": "OK",
"request_id": "req_8f2c19d4a7",
"data": {
"trade_no": "OX20261108A73F91",
"out_trade_no": "ORDER20261108001",
"amount": 128000,
"channel": "wechat_native",
"qr_code": "weixin://wxpay/bizpayurl?pr=***",
"expire_at": 1762588800
}
}
订单查询
POST https://pay.openx.net.cn/api/v1/order/query
传 out_trade_no 或 trade_no 之一即可。trade_status 取值:
| 状态 | 含义 | 建议处理 |
|---|---|---|
NOTPAY | 未支付 | 继续等待或引导用户支付 |
PAYING | 支付中 | 稍后再次查询,勿重复下单 |
SUCCESS | 支付成功 | 发货 / 开通服务 |
CLOSED | 已关闭 | 订单失效,需重新下单 |
REFUND | 已退款 | 按退款结果处理 |
申请退款
POST https://pay.openx.net.cn/api/v1/refund/create
支持全额与部分退款。refund_amount 累计不得超过订单金额,同一订单可发起多次部分退款。退款为异步处理,最终结果以退款查询或回调为准。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
out_trade_no | string | 是 | 原商户订单号 |
out_refund_no | string | 是 | 商户退款单号,同一订单下唯一 |
refund_amount | int | 是 | 退款金额,单位分 |
reason | string | 否 | 退款原因,64 字以内 |
关闭订单
POST https://pay.openx.net.cn/api/v1/order/close
关闭未支付的订单,关闭后用户无法再支付。已支付订单请使用退款接口。
回调通知
支付成功后,网关向 notify_url 以 POST application/json 推送通知。你需要在 5 秒 内返回 HTTP 200 且响应体为 success,否则视为失败。
{
"app_id": "ox_live_8f2c****",
"trade_no": "OX20261108A73F91",
"out_trade_no": "ORDER20261108001",
"trade_status": "SUCCESS",
"amount": 128000,
"channel": "wechat_native",
"pay_time": "2026-11-08 14:32:07",
"attach": "uid=10086",
"timestamp": 1762589527,
"nonce": "k3j5h2g4f1",
"sign": "6B1E9A..."
}
处理回调的要点:
- 先验签,再处理业务。用同一套签名规则校验
sign,验签失败直接返回失败,不要发货。 - 做幂等。同一笔订单可能收到多次通知,请以
out_trade_no为幂等键,已处理过的直接返回success。 - 以查询为准。若通知内容与本地记录不一致,主动调用订单查询接口复核。
- 重试策略。失败后网关按 15s / 30s / 3min / 10min / 30min 重试共 5 次,仍失败则停止,需靠主动查询补偿。
对账单
GET https://pay.openx.net.cn/api/v1/bill/daily?date=2026-11-07
返回该日所有交易明细(含支付、退款、手续费、结算金额),支持分页。也可在商户后台下载 CSV,或配置每日邮件推送。
错误码
| code | 说明 | 处理建议 |
|---|---|---|
0 | 成功 | — |
1001 | 参数缺失或格式错误 | 检查必填字段与类型,金额单位为分 |
1002 | 签名校验失败 | 检查排序、空值过滤、密钥与大小写 |
1003 | 时间戳过期 | 校准服务器时间,偏差需在 ±5 分钟内 |
1004 | nonce 重复 | 每次请求生成新的随机串 |
2001 | 应用不存在或已停用 | 确认 app_id 与环境是否匹配 |
2002 | 通道未开通 | 联系技术支持开通对应 channel |
3001 | 商户订单号重复 | 复用原订单结果,勿重复下单 |
3002 | 订单不存在 | 检查 out_trade_no / trade_no |
3003 | 订单状态不允许该操作 | 如对已支付订单调用关单 |
4001 | 退款金额超限 | 累计退款不得超过订单金额 |
5001 | 上游通道异常 | 建议按指数退避重试,仍失败联系技术支持 |
5002 | 风控拦截 | 查看后台风险提示,必要时提交材料申诉 |
所有响应都带 request_id,遇到 5001 等异常时请把它一并提供给技术支持,可快速定位上游报文。
对接常见问题
按出现频率排序:① 没有过滤空值参数;② 排序用了本地化排序而非 ASCII 升序;③ 拼接时多加了
& 或漏了 &key=;④ 输出未转大写;⑤ 误把 sign 本身也参与签名;⑥ 密钥末尾有空格或换行。
先确认
notify_url 是公网可访问的 HTTPS 地址,且未被防火墙、鉴权中间件拦截;再用订单查询接口确认交易状态。回调失败会自动重试 5 次,但生产环境建议额外加一个定时补偿任务。
不会。
out_trade_no 是幂等键,同一订单号重复提交会返回同一笔订单,不会生成新交易。请确保你的订单号生成规则稳定且唯一。
可以。用
channel=cashier 下单后跳转到收银台地址即可,用户在收银台内自行选择支付方式。这种方式接入成本最低,适合快速上线或非技术团队。