电商3.0-运营平台开放接口
    • 接入说明与返回码
    • 订单
      • 查询订单
        POST
      • 取消预约
        POST
    • 售后
      • 申请退单
        POST
      • 查询退单
        POST
    • 景区
      • 查询景区列表
        POST
      • 查询景区营业时间
        POST
    • 数据模型
      • OpenRequest

    接入说明与返回码

    本文说明运营平台开放接口的接入方式:凭证、请求结构、加密、签名、验签流程、响应处理和返回码。所有接口都遵循同一套规则,接口文档里只描述各自的业务字段。

    1. 接入凭证#

    平台管理员在开放平台后台为调用方创建「应用实例」并授权接口后,提供三项凭证:
    凭证长度用途
    key32 位应用实例标识,随每次请求明文传递
    secret64 位签名密钥,只参与签名计算,不随请求传递
    aesKey32 位业务参数加密密钥,同样不随请求传递
    应用实例绑定一名运营平台操作员,接口内的所有操作都记在该操作员名下(例如退单申请人)。这组接口可以查询和处理平台内的任意订单,只允许绑定了运营平台操作员的实例调用。
    环境网关地址
    测试环境https://scthub-open.dev.dmqwl.com
    生产环境上线时提供

    2. 请求结构#

    所有接口均为 POST,请求头 Content-Type: application/json,请求体固定为 4 个字段:
    字段类型必填说明
    keystring是应用实例的 key
    timestampnumber是发起请求时的毫秒时间戳,如 1794370000000
    bodystring是业务参数 JSON 字符串加密后的 Base64 密文,见第 3 节
    signstring是签名,见第 4 节
    {
      "key": "调用方的key",
      "timestamp": 1794370000000,
      "body": "43EYRVvX8lxqL6rR/XZ+iBSNgsos0HHX8JUVQJsDDhk=",
      "sign": "6D1F10D8A10FB9580628DA5C4C00E1CD"
    }
    各接口文档中的「请求业务字段」指加密前的业务参数。没有业务字段的接口,对空对象 {} 加密。
    请求体中不要出现 corpCode 字段,它会让网关改走另一套(服务商)验签规则。

    3. 加密规则#

    对业务参数 JSON 字符串做 AES 加密,得到 body:
    项取值
    算法 / 模式 / 填充AES/CBC/PKCS5Padding(等同 PKCS7)
    密钥aesKey 字符串的 UTF-8 字节,共 32 字节,即 AES-256。直接取字节,不做 Hex 或 Base64 解码
    IV密钥的前 16 个字节,即 aesKey 的前 16 个字符
    明文业务参数 JSON 字符串,UTF-8 编码
    输出标准 Base64(含 + / =,不换行,非 URL-safe)
    业务参数 JSON 的字段顺序、是否带空格都不影响验签:服务端只对密文做签名校验,解密后再解析 JSON。

    4. 签名规则#

    sign = MD5( body + timestamp + secret )
    1.
    body:第 3 节得到的 Base64 密文字符串。签名针对密文而不是明文,所以必须先加密、后签名。
    2.
    timestamp:与请求体中 timestamp 完全一致的十进制数字串。
    3.
    secret:签名密钥原文。
    4.
    三段按上述顺序直接拼接,中间没有分隔符,不做排序、不加字段名。
    5.
    拼接结果按 UTF-8 取字节后计算 MD5,输出 32 位十六进制字符串。大小写均可,建议用大写。

    5. 服务端校验流程#

    网关收到请求后依次做以下校验,任意一步不通过即返回对应错误,后面的步骤不再执行:
    顺序校验内容不通过时返回
    1Content-Type 是否为 application/json405 无效的请求内容
    2key 是否存在1037 无效的key
    3key 是否启用1031 用户状态有误,请联系管理员
    4用该 key 的 secret 按第 4 节重算签名,与 sign 比较(忽略大小写)1037 数据验证失败
    5请求地址是否为已登记的接口405 无效的请求信息
    6该应用实例是否已被授权此接口405 用户权限不足
    7实例开启了 IP 白名单时,来源 IP 是否在白名单内1044 请求的ip不在白名单当中
    8用 aesKey 解密 body1020 无效的AES数据格式
    全部通过后,网关把解密出的业务参数连同操作员身份转给业务服务。
    需要了解的两点:
    timestamp 只参与签名,服务端不校验时效,也没有防重放机制。 同一个已签名的请求可以被重复提交。请妥善保管 secret,只通过 HTTPS 调用,并建议向平台申请开启 IP 白名单。退单类接口自身不会重复退款,详见对应接口文档。
    来源 IP 取 X-Forwarded-For 的第一个地址。

    6. 响应处理#

    HTTP 状态码恒为 200。响应体有两种形态,先判断再处理:
    形态判断方法处理方式
    密文响应体不以 { 开头请求已通过网关校验。用 aesKey 按第 3 节的算法解密,得到统一响应 JSON
    明文 JSON响应体以 { 开头请求被网关拒绝(第 5 节任一步未通过)或系统异常。不要解密,直接读取 code 和 message
    解密后的统一响应:
    字段类型说明
    codenumber0 表示成功,其他值表示失败
    msgstring失败原因;成功时为 null
    dataobject / array业务数据,结构见各接口的「响应业务字段」;失败时为 null
    okboolean是否成功,等价于 code == 0
    {"code": 0, "msg": null, "data": {}, "ok": true}
    {"code": 405, "msg": "订单不存在", "data": null, "ok": false}
    网关直接返回的明文错误,提示信息的字段名是 message(不是 msg):
    {"code": 1037, "data": null, "message": "数据验证失败"}
    数据约定:
    金额单位为分,以字符串形式返回(如 "payAmount": "20000");数量为数字。
    时间格式 yyyy-MM-dd HH:mm:ss,日期格式 yyyy-MM-dd。
    没有值的字段返回 null。
    超时建议:退单、取消预约会同步调用多个内部服务,读超时请设为 30 秒以上。超时不代表失败,请先用查询接口确认结果,再决定是否重试。

    7. 完整示例#

    以下演示数据可用于自测加密和签名实现,算出的 body 和 sign 应与表中完全一致。
    项值
    aesKey0123456789abcdef0123456789abcdef
    secretdemo_secret_do_not_use_0000000000000000000000000000000000000000
    timestamp1794370000000
    业务参数(明文){"orderNo":"SO202611110001"}
    第一步,加密。 密钥为 aesKey 的 32 个字节,IV 为 0123456789abcdef 这 16 个字节:
    body = 43EYRVvX8lxqL6rR/XZ+iBSNgsos0HHX8JUVQJsDDhk=
    第二步,拼接待签名串(密文 + 时间戳 + secret):
    43EYRVvX8lxqL6rR/XZ+iBSNgsos0HHX8JUVQJsDDhk=1794370000000demo_secret_do_not_use_0000000000000000000000000000000000000000
    第三步,计算 MD5:
    sign = 6D1F10D8A10FB9580628DA5C4C00E1CD
    第四步,发送请求:
    第五步,处理响应。 响应体不以 { 开头时用同一个 aesKey 解密,得到统一响应 JSON。
    用 OpenSSL 可以独立验证加密结果(-K 是 aesKey 的十六进制,-iv 是其前 16 字节的十六进制):

    8. 代码示例#

    以下三份示例都包含加密、解密、签名和完整调用,直接运行会先输出第 7 节的演示结果。

    Java(JDK 11+,无第三方依赖)#

    Python(pip install pycryptodome requests)#

    Node.js(18+,无第三方依赖)#

    9. 返回码#

    9.1 网关返回码(明文,字段名 message)#

    codemessage原因与处理
    1037无效的keykey 不存在。检查 key 是否填错、是否用错环境
    1037数据验证失败签名不匹配,或缺少 sign。按第 10 节排查
    1031用户状态有误,请联系管理员key 已被禁用,联系平台管理员
    1044请求的ip不在白名单当中来源 IP 未加入该实例的白名单
    1020无效的AES数据格式body 不是用该实例 aesKey 加密的合法密文
    405无效的请求内容Content-Type 不是 application/json
    405无效的请求信息请求地址不是已登记的接口,检查路径拼写
    405用户权限不足该实例未被授权此接口,联系平台管理员授权
    400Bad Request业务服务异常,可稍后重试;持续出现请联系平台
    500common.system.busy请求体不是合法 JSON,或网关内部异常

    9.2 业务返回码(密文,解密后字段名 msg)#

    code说明
    0成功
    405业务校验不通过,msg 为具体原因,各接口文档列出了常见提示

    10. 签名失败排查#

    返回 1037 数据验证失败 时,按顺序检查:
    1.
    是否对密文签名。待签名串的第一段是加密后的 Base64 字符串,不是明文 JSON。
    2.
    请求体里的 body 与参与签名的 body 是否是同一个字符串。常见问题是加密了两次得到两个不同的密文,或 HTTP 库对 + / = 做了转义。
    3.
    请求体里的 timestamp 与参与签名的时间戳是否一致,是否被序列化成了科学计数法或带小数。
    4.
    secret 是否与 key 属于同一个应用实例、同一个环境,前后是否混入了空格或换行。
    5.
    拼接顺序是否为 body + timestamp + secret,中间是否多了分隔符。
    6.
    MD5 的输入是否按 UTF-8 取字节,输出是否为 32 位十六进制(不是 16 位,也不是 Base64)。
    7.
    用第 7 节的演示数据跑一遍自己的实现,body 和 sign 都一致才说明算法正确。
    返回 1020 无效的AES数据格式 时,检查密钥是否直接取 aesKey 的 UTF-8 字节(不要做 Hex 解码)、IV 是否为密钥前 16 字节、模式是否为 CBC、输出是否为标准 Base64。
    修改于 2026-11-11 13:20:32
    下一页
    查询订单
    Built with