订单消息推送

仅提供已授权的门店数据服务:已完成门店授权(客户门店与收钱吧门店映射)的门店,其订单消息才会被推送。

1. 概述

消息推送平台是开放平台中,由开放平台主动发起调用开发者应用服务的一个通道,用于向应用推送订单变更等消息。

与主动查询接口(请求方为开发者)相反,消息推送为开放平台 → 开发者方向:开发者按消息类型提供 HTTPS 回调地址接收推送。推送与主动调用接口完全复用同一套签名鉴权规范(见鉴权与签名):签名参数通过标准请求头携带,验签使用 HMAC-SHA256 保证消息完整性与防篡改;业务数据以明文 JSON 作为请求体发送,验签通过后即可直接解析。传输强制 HTTPS,接收方使用自己的 accessSecret 即可完成验签,无需额外配置密钥。

2. 通道要求

三方应用需要按消息类型提供 HTTP 回调通道,有需要推送的消息时,开放平台会按照约定格式,主动调用对应消息类型的回调地址,完成消息推送功能。

接口有以下要求:

  1. 请使用标准 HTTP 协议,非标私有实现可能会有一定的兼容问题,必须使用 HTTPS,并需要保证 SSL 证书有效
  2. POST 请求,UTF-8 编码,HTTP 请求头中:Content-Type: application/json,Body 中存放 JSON 格式报文
  3. 接收方需要进行消息体验签
  4. 推送必须遵循推送与回调机制尤其是其中的响应要求(HTTP 200、Content-Type: application/json、Body 为 {"status": "success"}、3 秒内响应)为强制项,不满足即视为推送失败并触发重试;重试策略、幂等处理与消息兼容机制同见该文件

3. 回调地址配置

每种消息类型(msgType)对应一个独立的回调地址,开发者在接入时按消息类型配置。未配置回调地址的消息类型将不会收到推送。

msgType 名称 URL 地址
ORDER_FINISHED 已完成订单 https://3rd.smartopen.com/smart/orderComplete
ORDER_REFUND 订单退款 https://3rd.smartopen.com/smart/orderRefund

消息类型(msgType)由平台定义,回调地址路径由开发者自行定义;接入时需向收钱吧运营提供各消息类型的回调地址,或按开放平台管理后台指引配置。每个回调地址收到的推送请求均需按第 5 节完成验签。

4. 请求参数说明

推送请求的签名参数通过 HTTP 请求头携带,与主动调用接口完全一致。

4.1 请求头

Header 类型 必填 说明
X-AccessKey String 开放平台分配给开发者的公开凭证
X-Timestamp Long 消息实际发送时间戳,单位毫秒,例如:1684986985000
X-Nonce String 参与签名生成的随机字符串,每次推送不同
X-Signature String HMAC-SHA256 签名值(十六进制小写),验签方式见鉴权与签名

4.2 请求体(信封结构)

Body 为业务消息明文 JSON,采用统一的信封结构,外层固定 msgIdmsgTypedata 三个字段:

字段 类型 必填 说明
msgId String 消息 ID,唯一标识 1 个消息,在重复推送时不变
msgType String 消息类型,决定回调地址与 data 结构,见第 3 节
data Object 业务数据,结构随 msgType 而定,见第 6 节

msgId 与主动接口 requestId 的区别msgId 为消息的唯一标识,由开放平台生成,用于推送去重与幂等处理(同一事件重复推送时不变);主动写操作接口的 requestId 为请求幂等键,由调用方(开发者)生成,用于主动写操作请求的重试去重,见幂等机制。二者概念不同,不可混用。

5. 消息验签

应用在接收到消息后,首先需要验签,验证消息未被篡改或部分丢失。推送请求的验签与主动调用接口的请求签名完全一致,签名参数取自请求头 X-AccessKeyX-TimestampX-NonceX-Signature

第一步:拼接签名字符串

其中 requestBody 为推送请求的 HTTP Body 原文(即信封结构 JSON 字符串,需与发送方逐字节一致):

accessKey | timestamp | nonce | requestBody

第二步:计算本地签名

accessSecret 作为密钥,对签名字符串计算 HMAC-SHA256,输出十六进制小写:

localSignature = HMAC_SHA256(accessKey + "|" + timestamp + "|" + nonce + "|" + <HTTP Body 原文>, accessSecret)

第三步:比对签名

比对 localSignature 与请求头中的 X-Signature,一致则验签通过;否则说明消息被篡改或部分丢失,应丢弃该消息。

推送同样适用鉴权与签名的防重放机制:X-Timestamp 与服务器时间差 ≤ 5 分钟,X-Nonce 5 分钟内不可重复使用。

6. 订单业务消息

6.1 已完成订单(msgType: ORDER_FINISHED)

订单完成后,推送订单完整信息给开发者。推送的 data订单完整信息,其字段结构(订单基础信息、商品、优惠、支付等)与订单查询接口的"3. 响应参数"一致,完整字段定义以该接口为准。

6.2 订单退款(msgType: ORDER_REFUND)

用户或客服发起退款流程后推送。推送的 data 为退款信息,包含退款状态、退款方式、退款商品等字段:

data 结构说明

字段 类型 必填 示例值 说明
clientStoreSn String SH001 客户门店号
sqbStoreSn String 1580000003443730 收钱吧门店号
orderSn String 210000001000001 收钱吧订单号
refundMethod String BY_AMOUNT 退款方式,枚举见订单枚举附录
refundReason String 不好吃 退款原因
goods Array 退款商品列表,按金额退款时无此字段
refundAmount Long 1200 退款金额,单位分
updateTime Long 1700318325713 事件发生时间戳

退款商品列表结构说明

字段 类型 必填 示例值 说明
id String 4e351201-9ae2-4142-9863-1a3500ac7857 商品唯一 ID
name String 苹果 商品名称
quantity String 1 退款数量,最多 3 位小数
amount Long 100 金额,单位分

7. 完整请求示例

以下为各消息类型的完整请求示例,包含全部请求头签名参数与完整业务数据。

7.1 已完成订单(msgType: ORDER_FINISHED)

以下为推送"已完成订单"消息的完整请求示例,data 为订单完整信息:

curl --location --request POST 'https://3rd.smartopen.com/smart/orderComplete' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Connection: keep-alive' \
--header 'X-AccessKey: ak_live_xK9mP2nQ7wR4tY6z' \
--header 'X-Timestamp: 1684986985000' \
--header 'X-Nonce: a1b2c3d4' \
--header 'X-Signature: 3f7a8b2c1e9d4f6a5b8c3e2d1f0a9e8b...' \
--data-raw '{
    "msgId": "202312261413412118468370213",
    "msgType": "ORDER_FINISHED",
    "data": {
        "orderSn": "210000001000001",
        "orderStatus": "FINISHED",
        "clientStoreSn": "SH001",
        "sqbStoreSn": "1580000003443730",
        "orderType": "RETAIL",
        "updateTime": 1786590141819,
        "remark": "",
        "originalAmount": 350,
        "merchantDiscountTotalAmount": 0,
        "expectedIncomeAmount": 350,
        "refundAmount": 0,
        "goods": [
            {
                "spuId": "2258087",
                "url": null,
                "name": "伊利 火炬苦咖啡口味冰淇淋 80g",
                "originalAmountPer": 350,
                "effectiveAmountPer": 350,
                "totalAmount": 350,
                "discountCount": null,
                "count": 1,
                "refundCount": null,
                "spuType": "PRODUCT",
                "skuType": "SINGLE",
                "spec": null,
                "specInfo": {
                    "id": "2258087",
                    "name": null,
                    "price": 350,
                    "attachedInfo": null
                },
                "attributeInfos": null,
                "materials": null,
                "packageGoods": null,
                "saleUnit": "袋",
                "refPayType": "PAY",
                "processStatus": "ACCEPTED",
                "extraInfo": {
                    "localGoodsId": "2258087_1774510934030",
                    "userName": "收银员",
                    "saleWeight": 1,
                    "itemSort": 429,
                    "orderTimeStamp": "1774510935802",
                    "userIcon": "https://shouqianba-marketing.oss-cn-hangzhou.aliyuncs.com/99zhe/meal-merge/defaultPortrait.png",
                    "unitType": "NUMBER",
                    "barcode": "6907992822716",
                    "categorySort": 0,
                    "originGoodsPrice": 350
                },
                "extraMap": {
                    "localGoodsId": "2258087_1774510934030",
                    "userName": "收银员",
                    "saleWeight": 1,
                    "itemSort": 429,
                    "orderTimeStamp": "1774510935802",
                    "userIcon": "https://shouqianba-marketing.oss-cn-hangzhou.aliyuncs.com/99zhe/meal-merge/defaultPortrait.png",
                    "unitType": "NUMBER",
                    "barcode": "6907992822716",
                    "categorySort": 0,
                    "originGoodsPrice": 350
                },
                "goodsDiscountType": null,
                "discountAmount": 0,
                "categoryId": "124820",
                "goodsTag": null
            }
        ],
        "payments": [
            {
                "clientSn": "2300003326705134",
                "transSn": "7895210846728718",
                "tradeNo": "14002026032615421600476419057",
                "refClientSn": null,
                "refundBatchNo": null,
                "totalAmount": 350,
                "receiveAmount": 350,
                "buyerPayAmount": 350,
                "discountAmount": 0,
                "channelAssistDiscount": 0,
                "payDiscountAmount": 0,
                "refundAmount": 0,
                "cashBackAmount": 0,
                "chargeGiftAmount": 0,
                "payWay": "WECHAT",
                "subPayWay": "BARCODE",
                "payType": "PAYMENT",
                "orderPayStatus": "PAID",
                "payerLogin": "opwm3uPOkl7dSw71sx_QRr5FPWTQ",
                "tradeTime": 1774510936000,
                "payTime": 1774510938000,
                "cashierId": "6be8a438-eff2-4f5b-8cdc-5c1f4b32be92",
                "profitSharingAmount": 0
            }
        ],
        "discounts": []
    }
}'

7.2 订单退款(msgType: ORDER_REFUND)

以下为推送"订单退款"消息的完整请求示例,data 为退款信息:

curl --location --request POST 'https://3rd.smartopen.com/smart/orderRefund' \
--header 'Content-Type: application/json' \
--header 'Accept: */*' \
--header 'Connection: keep-alive' \
--header 'X-AccessKey: ak_live_xK9mP2nQ7wR4tY6z' \
--header 'X-Timestamp: 1684986985000' \
--header 'X-Nonce: a1b2c3d4' \
--header 'X-Signature: 3f7a8b2c1e9d4f6a5b8c3e2d1f0a9e8b...' \
--data-raw '{
    "msgId": "202312261413412118468370213",
    "msgType": "ORDER_REFUND",
    "data": {
        "clientStoreSn": "SH001",
        "sqbStoreSn": "1580000003443730",
        "orderSn": "210000001000001",
        "refundStatus": "C_REFUND_APPLY",
        "refundMethod": "BY_GOODS",
        "refundReason": "不好吃",
        "goods": [
            {
                "id": "4e351201-9ae2-4142-9863-1a3500ac7857",
                "name": "苹果",
                "quantity": 1,
                "amount": 100
            },
            {
                "id": "6f2c4b3a-1d5e-4f8a-b7c3-9e2d1a0f5c8b",
                "name": "香蕉",
                "quantity": 2,
                "amount": 200
            }
        ],
        "refundAmount": 1200,
        "updateTime": 1700318325713
    }
}'

results matching ""

    No results matching ""