Chinese
    • Chinese
    • English
    • 开放文档介绍
    • 代收
      • 代收下单-通用
      • 代收下单-印度
      • 代收下单-菲律宾
      • 代收下单-印尼
      • 代收下单-越南
      • 代收下单-虚拟币
      • 代收下单-中国
      • 代收下单-马来西亚
      • 代收下单-巴基斯坦
      • 代收下单-泰国
    • 代付
      • 代付下单-通用
      • 代付下单-印度
      • 代付下单-菲律宾
      • 代付下单-印尼
      • 代付下单-越南
      • 代付下单-虚拟币
      • 代付下单-马来西亚
      • 代付下单-巴基斯坦
      • 代付下单-泰国
    • 回调通知
      • 回调说明
      • 代收回调
      • 代付回调
    • 查询接口
      • 代收查询
      • 代付查询
      • 钱包查询
    • 其他语言的加密签名例子
      • Go语言加密签名例子
      • Python加密签名例子
      • PHP加密签名例子
      • Nodejs加密签名例子
      • 环境变量和请求体json的例子
      • Java加密签名例子
    • 其它说明
      • 响应状态说明
      • 订单状态说明
      • 支付方式列表
      • 银行代码列表
      • 收银台 iframe 复制功能支持说明
      • 后台登录说明

    开放文档介绍

    文档信息#

    API版本: v1.0
    文档版本: v1.0
    协议: HTTPS

    沙箱/正式环境网关说明#

    环境网关地址说明
    沙箱https://sdg.omnipay.global需要使用沙盒密钥(从管理后台进入沙盒获取)
    生产https://api.omnipay.global

    目录#

    I. 基础规范
    沙盒环境对接
    API认证
    请求签名
    消息体加密
    II. 代收代付流程

    I. 基础规范#

    沙盒环境对接#

    沙盒环境接口参数,返回参数,签名规则,数据加密规则与生产一致。沙盒后台可以手动回调,用于帮助快速接入
    沙箱目前仅支持下单、回调及签名验证,无收银台
    沙箱环境接通后可以在正式环境拉单查看收银台
    沙箱接入流程:
    1、登录商户后台,点击右上角切换到沙箱模式;
    image.png
    2、使用沙箱里面的密钥进行下单;
    image.png
    3、下单后可以在收款或付款订单页面进行手动回调;
    image.png

    API认证#

    本系统默认采用 App ID + App Secret 的 HMAC-SHA256 签名机制
    1.
    App ID 认证:每个请求必须在 Header 中携带 App ID(用于标识商户编码)
    2.
    HMAC-SHA256 签名(默认):使用商户 App Secret 对请求进行签名,保证消息完整性、防止篡改
    3.
    AES-GCM-V1 加密:请求体支持使用 aes-gcm-v1(AES-256-GCM)算法加密,保障数据保密性,特殊场景可申请明文模式

    设计要点#

    传输层必须用 TLS(HTTPS):所有数据通过 HTTPS 传输,避免中间人窃听
    App ID 用作标识(public):App ID 是公开的,用于标识商户编码
    App Secret 只用于服务器端签名:App Secret 绝不放到客户端代码仓库或前端
    签名(HMAC-SHA256):用于保证消息完整性与认证,防止篡改与伪造
    请求体加密(AES-GCM-V1):保护敏感字段/整个请求体,可在双方确认后关闭
    防重放攻击:在签名中包含 timestamp + nonce + 请求路径 + HTTP method + body
    幂等与重试:在签名中包含请求ID或nonce,并在服务端记录短期nonce白名单/黑名单

    请求头(Request Headers)#

    Header名称必填说明示例
    X-App-Id是商户编码M20253504WTEX
    X-Ts是Unix时间戳(毫秒,13位数字),服务器允许 ±300秒1699132800000
    X-Nonce是随机字符串(用于防重放)abcd1234efgh
    X-Sign是HMAC-SHA256签名值(Base64编码)a1b2c3d4e5f6...
    Content-Type是请求体类型:application/json(明文)或 application/octet-stream(加密)application/json
    X-Enc是加密方式:aes-gcm-v1, none明文方式(默认)none

    密钥获取与配置#

    步骤1:获取App ID、App Secret 和 apiDataKey
    登录商户后台 → 系统设置 → 支付基础配置,获取:
    商户编码:是App ID,用于标识商户应用
    商户密钥:是App Secret,用于签名
    平台公钥:是apiDataKey用于 AES 加密
    重要:
    App Secret 和 apiDataKey 仅显示一次,请妥善保管
    应存储在安全的位置(如 KMS/Vault),不要硬编码在代码中
    浏览器/移动端不应持久保存长期密钥,建议后端对接或使用短期 token(OAuth2、JWT)模式

    请求签名#

    签名原理#

    HMAC-SHA256签名使用商户App Secret对请求进行HMAC-SHA256签名,流程如下:
    1.
    构建待签名字符串:按照固定格式拼接 HTTP_METHOD + "\n" + REQUEST_PATH + "\n" + X-Ts + "\n" + X-Nonce + "\n" + Base64(body_bytes)
    2.
    REQUEST_PATH里的请求参数要按key升序排序,Nonce作为iv
    3.
    计算HMAC-SHA256:使用App Secret作为密钥,对待签名字符串进行HMAC-SHA256计算
    4.
    Base64编码:将HMAC结果进行Base64编码
    5.
    添加请求头:X-Ts、X-Nonce、X-Sign

    签名算法规范#

    待签名字符串格式(严格规范顺序):
    signing_string = HTTP_METHOD + "\n" +
                     PATH?QUERY + "\n" +      // 包括QUERY(按字典序排序)
                     X-Ts + "\n" +
                     X-Nonce + "\n" +
                     Base64(body_bytes)          // 空 body 用空字符串
    注意事项:
    使用 appSecret 作为 HMAC 密钥
    使用 HMAC-SHA256 算法(不要使用 MD5、SHA1 或可被 length-extension 攻击的方式)
    签名结果使用 Base64 编码(统一使用 Base64)
    路径上的请求参数必须按字典序排序
    空 body 用空字符串,不要省略
    重要:签名中的 body 始终使用加密前的原始 JSON 字符串,与 X-Enc 的值无关
    当 X-Enc = none 时:使用原始 JSON 字符串
    当 X-Enc = aes-gcm-v1 时:仍然使用加密前的原始 JSON 字符串(不是加密后的 Base64)
    签名的目的是验证消息完整性,应该在明文层面进行

    平台验证签名(服务器端)#

    平台使用商户App Secret验证签名,验证流程如下:
    1.
    检查X-App-Id:验证App ID是否存在且有效,加载对应的App Secret(从安全存储,如KMS/Vault)
    2.
    验证X-Ts:检查时间戳是否在允许时间窗口内(例如±300秒)
    3.
    检查X-Nonce:验证nonce是否已短期使用(防重放),若已使用则拒绝。将nonce保存到缓存(如Redis)并设置短期过期(例如5分钟)
    4.
    解密请求体(如果 X-Enc = aes-gcm-v1):先解密请求体得到明文
    5.
    重新构建待签名字符串:使用解密后的明文 body按照与客户端相同的规则构建签名字符串
    6.
    验证签名:使用App Secret计算HMAC-SHA256,与请求中的签名值进行常量时间比较(constant-time compare)
    重要:
    签名验证使用解密后的明文 body,而不是加密后的 body
    客户端计算签名时也应该使用明文 body,即使请求体是加密的

    消息体加密#

    平台默认按照商户配置加密方式,如果没有配置,就默认不加密,如果请求头传了加密,则会按照请求头方式解密(AES-GCM-V1,默认不开启)

    加密数据格式#

    加密后的请求体格式:
    [IV (12字节)] + [实际密文] + [authTag (16字节)]
    说明:
    IV(初始化向量):12 字节随机数
    密文:AES-GCM 加密后的实际数据
    authTag(认证标签):16 字节(128 位),由 AES-GCM 自动生成,用于验证数据完整性和真实性
    数据传递:
    IV 不需要单独传递,它包含在加密后的数据中(前 12 字节)
    加密后的数据使用原始数据进行发送,不需要base64编码
    Content-Type 设置为 application/octet-stream(二进制数据)
    重要提示:
    默认不加密;若双方确认使用明文,请将 X-Enc 设置为 none 并确保网络环境安全
    加密/解密使用 aes-gcm-v1,关联数据(AAD)为 HMAC-SHA256(appId, Base64.encode(aesKey)) 的十六进制字符串
    签名计算使用明文 body(即使请求体是加密的)
    Content-Type:加密时使用 application/octet-stream,明文时使用 application/json

    幂等性保证#

    API请求幂等性:
    创建交易:通过 order_no(商户订单号)保证幂等性。相同 order_no 的重复请求返回相同结果,不会重复创建交易。
    发起代付:通过 order_no(商户代付订单号)保证幂等性。相同 order_no 的重复请求返回相同结果,不会重复发起代付。

    II. 代收代付流程#

    image.png#

    常见问题#

    Q: 代收代付的用户IP地址我们能否不传递,如果一定要传递的话能否使用服务器地址?#
    A: 可以, 如果有客户IP,最好传递,方便我们在掉单的时候,找出关联用户的订单。
    Q: 支付方式编码在哪里查看?#
    A: 在接口文档 其他说明 >> 支付方式列表
    Q: 代收代付下单和查询信息请求头目前使用的是application/json请求体类型,然后加密方式为none对吗,然后代收代付回调信息头没有请求类型和加密方式的参数,是使用默认的方式吗?#
    A: 下单请求加密方式默认可以是none,回调的请求类型也是application/json,没有加密只有签名
    Q: 我们需要对用户实际支付金额进行金额校验,那校验的字段是实付金额对吗?#
    A: 请始终以due_settlement_amount校验金额,并以该字段金额作为用户的结算或上分金额,并且可能存在多付少付的场景,同样以该字段金额为主
    Q: 回调是否是只要返回了200状态码就不会触发重试,响应体的success/failed字段一定要传递吗,如果一定要传递的话我们该怎么判断是成功还是失败?#
    A: 当你订单已经接受到我们的回调信息,且处理完毕的时候(你们认为我们不需要再次推送此消息了),请一定要返回200状态码,且响应内容为纯文本 SUCCESS, 否则我们认为推送失败,会重新推送。 
    Q: 各个接口返回的订单状态,是只会返回接口字段说明中备注的订单状态吗?例如收回调的状态字段说明里success,是回调状态里只有成功的状态码吗?#
    A: 文档参数中的说明和示例仅供参考,所有状态请查看《订单状态说明》,查询或回调时,对于代收只用关注:成功(SUCCEEDED),对于代付只用关注:成功(SUCCEEDED),失败(FAILED)、冲正 (REVERSAL)
    Q: 我看到你们的状态码说明中有HTTP状态码和业务状态码,HTTP状态码为可以理解为是在接口请求时候返回接口状态码code吗,业务状态码又一般在什么时候会返回?他们两个是不是都是200代表成功,除了200之外的其他参数都代表失败?#
    A: 所有HTTP状态码,只代表这次请求的状态是否成功,具体业务的成功与否,以业务状态码为准。 请参考《响应状态说明》
    Q: 订单金额这些金额类型的信息使用的单位是元还是分?#
    A:金额单位为元,同时建议代收金额保留两位小数,代付金额为整数最佳
    Modified at 2026-07-09 12:37:50
    Next
    代收下单-通用
    Built with