对接说明
调用接口前请先了解以下通用约定,具体字段以各接口说明为准。
Long 型字段约定
/openapi/v3/**响应中的 Long 型标识字段统一按string返回,避免php,js等出现精度丢失问题。- 请求参数中的
UID、ID、lastId等字段可直接传数字,无需转成字符串。 - 分页场景建议将上次响应中的
nextLastId原样传入下一次请求。 - 常见字段包括:
id、uid、lastId、nextLastId。
通用数据格式约定
- 请求与响应统一使用
UTF-8编码,请求体固定为application/json。 - 时间字段统一使用
yyyy-MM-dd HH:mm:ss,除请求头时间戳外不使用毫秒。 - 时间范围统一使用
datetimeBegin/datetimeEnd;查询区间为左闭右开,即包含开始时间、不包含结束时间。 - 金额、库存、数量等业务数字按数值类型返回,不额外转字符串。
- 涉及金额的字段统一按元处理,数据类型为
BigDecimal;除非接口字段说明中特殊标明,金额参数和返回值都表示“元”,例如12.50表示 12.5 元。 - 连锁门店建议统一使用总部的
appId/appKey,查哪家子门店数据,请求体就传对应门店的account。
对接步骤
对接准备
- 先向开放平台申请
appId与appKey。 - 审核通过并领取
appKey后,建议先登录控制台;首次登录会赠送10000 Token,可直接用于接口调试。 - 根据业务场景确认本次调用对应的门店
account。 - 先阅读“对接说明”、本节与公共响应格式,再进入商品、会员、销售单据、景区票务或网单接口页面查看业务细节。
请求方式
https://platform.pospal.cn,完整接口地址为“正式环境域名 + 接口路径”,例如 https://platform.pospal.cn/openapi/v3/product/increment-page。
POST,请求体为 application/json,编码使用 UTF-8。
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
X-App-Id |
是 | 开放平台分配的 appId,连锁门店建议传总部 appId。 |
X-Timestamp |
是 | Unix 时间戳,单位秒。服务端要求与当前时间差不超过 5 分钟。 |
X-Request-Id |
是 | 请求唯一编号,建议使用 UUID 或业务系统唯一流水号;同一 appId 下不可重复。 |
X-Sign |
是 | 签名结果,签名算法见下文。 |
Content-Type |
是 | 固定为 application/json;charset=UTF-8。 |
业务门店规则
请求体必须包含 account,表示要操作哪家门店的数据。如果调用方传的是总部 appId,则可通过
account 指定子门店数据;如果传的是子门店 appId,account 应与当前门店一致。
签名规则
普通开放接口统一使用轻量签名,便于门店快速接入。
stringToSign = appId + "|" + requestId + "|" + timestamp + "|" + appKey
sign = md5(stringToSign).toUpperCase()
appId取请求头X-App-Id。requestId取请求头X-Request-Id。timestamp取请求头X-Timestamp。- 签名结果放入请求头
X-Sign。
平台校验规则
- 校验
appId是否存在且可用。 - 校验
timestamp是否在允许时间范围内,默认要求与平台时间相差不超过 5 分钟。 - 校验
requestId是否重复;同一appId下,requestId必须唯一。 - 校验
X-Sign是否正确。
Java 签名示例
String appId = "yourAppId";
String requestId = "550e8400-e29b-41d4-a716-446655440000";
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String appKey = "yourAppKey";
String raw = appId + "|" + requestId + "|" + timestamp + "|" + appKey;
String sign = md5(raw).toUpperCase();
公共响应格式
接口统一使用公司标准返回对象 cn.zdwl.base.dto.ApiResponseDTO。
通用响应外层
| 字段 | 类型 | 说明 |
|---|---|---|
status |
string | 请求处理结果,成功时通常返回 success,失败时返回 error。 |
errorCode |
int | 错误码。成功时通常为 0,失败时返回具体业务错误码。 |
messages |
array<string> | 失败提示信息列表;成功时通常不返回或为空。 |
result |
object | 业务结果对象。不同接口的具体字段结构不同,由各接口文档单独说明。 |
{
"status": "success",
"errorCode": 0,
"result": {
}
}
分页接口响应字段
以下字段仅适用于查询查询类接口,如商品、会员、销售单据的 increment-page 接口。
| 字段 | 类型 | 说明 |
|---|---|---|
list |
array | 当前页数据列表。 |
hasMore |
boolean | 是否还有下一页。服务端会按 limit + 1 查询,多出一条则判定为 true。 |
nextLastId |
string | 下一次翻页应传入的游标,取当前返回列表最后一条记录的 id。 |
{
"status": "success",
"errorCode": 0,
"result": {
"list": [],
"hasMore": true,
"nextLastId": "123"
}
}
失败响应
{
"status": "error",
"errorCode": 4004,
"messages": [
"签名错误"
]
}
计费规则
平台统一按 appId 计费。主动调用接口时,按请求头中的 X-App-Id 归集费用;接收回调通知时,按实际订阅并接收该回调的
appId 归集费用。请求体中的 account 仅用于指定目标门店,不作为计费依据。
计费归属
- OpenAPI 调用:
requestAppId传谁,就记到谁对应账户的 Token 消耗。 - 回调通知:哪个
appId配置并订阅了回调,就记到哪个appId对应账户的 Token 消耗。 - 连锁总部使用总部
appId调用或订阅时,费用归总部账户。 - 子门店如拥有独立
appId,则调用或订阅时费用归子门店自己的账户。 - 子门店如没有独立
appId,则相关费用归实际使用的上级appId账户。
扣费时机
联调与正式计费说明
- 首次登录赠送:首次登录开放平台控制台时,系统会自动赠送
10000 Token到当前appId对应计费账户,便于完成接口联调。 - 接口调试:控制台内的接口调试属于真实 OpenAPI 调用,会进入正式链路,记录调用日志,并按标准规则计费,可优先使用首次登录赠送的 Token。
- 回调测试:控制台内的回调测试属于模拟联调能力,仅向指定回调地址发送测试消息,不进入正式回调任务队列,不计费。
- 正式回调:业务系统触发的正式回调推送会进入正式任务队列,并按订阅方
appId计费。
计费示例
appId,请求体 account = 子门店A,表示查询子门店A的数据,但费用归总部账户。
appId 订阅并接收该回调,平台向总部投递消息,费用归总部账户。
appId 和子门店A自己的 appId 都订阅了该事件,平台会分别生成回调任务并分别计费。
appId 调用接口或订阅回调时,费用归自己的账户。
当账户欠费且超过宽限期后,平台会暂停该 appId 的正式 OpenAPI 调用与正式回调发送;
但控制台登录、充值、日志查看、回调测试等管理与排障能力不受影响,方便客户先排查再完成充值恢复服务。
费用评估
客户可登录控制台自助充值。基础换算为 10000 Token ≈ 1 元;充值越多,赠送比例越大,实际可用 Token 会更多。
以下示例仅用于前期估算,实际消耗以控制台调用日志和 Token 明细为准。
场景一:定时同步数据
以下示例按 5 家连锁门店估算。客户可以根据自己实际对接的数据类型,选择对应模块单独估算;如果同时对接多个模块,再把各模块费用相加。
场景 1.1:定时同步商品 查看商品接口
业务假设:5 家门店,每家门店有 1000 个商品,客户需要返回商品基础数据、商品图片和扩展条码。
接口规则:商品分页查询接口默认分页大小为 100 个商品。
因此单次请求的 Token 组成如下:
商品基础数据:100 Token/次
商品图片 needImages=true:额外 20 Token/次
扩展条码 needExtBarcodes=true:额外 20 Token/次
本示例每次请求消耗:100 + 20 + 20 = 140 Token/次
每家门店 1000 个商品,需要 1000 / 100 = 10 次请求。
单店商品同步消耗:140 Token/次 * 10 次 = 1400 Token,约 0.14 元/天
5 家门店商品同步消耗:1400 Token * 5 家 = 7000 Token,约 0.7 元/天
场景 1.2:定时同步销售单据 查看销售单据接口
业务假设:5 家门店,每家门店每天 200 笔销售单据,客户需要返回销售单据基础数据和商品明细。
接口规则:销售单据分页查询接口默认分页大小为 100 笔销售单据。
因此单次请求的 Token 组成如下:
销售单据基础数据:500 Token/次
商品明细 needTicketItems=true: 额外 20 Token/次
本示例每次请求消耗:500 + 20 = 520 Token/次
每家门店每天 200 笔销售单据,需要 200 / 100 = 2 次请求。
单店销售单据同步消耗:520 Token/次 * 2 次 = 1040 Token,约 0.1 元/天
5 家门店销售单据同步消耗:1040 Token * 5 家 = 5200 Token,约 0.52 元/天
场景 1.3:定时同步会员 查看会员接口
业务假设:整个连锁共有 10000 个会员,客户只需要返回会员基础数据。
接口规则:会员分页查询接口默认分页大小为 100 个会员。
会员基础数据单次请求消耗 100 Token/次,整个连锁 10000 个会员,需要 10000 / 100 = 100 次请求。
连锁会员同步消耗:100 Token/次 * 100 次 = 10000 Token,约 1 元/天
场景二:小程序订单推送到银豹网单 查看新增网单接口
客户有自己的小程序,需要把小程序订单推送到银豹收银系统,通过银豹完成接单、厨打、配送、收银 等完整业务流程。
假设这个小程序每天有 150 笔订单,每天调用 150 次新增网单接口,新增网单接口每次消耗 200 Token。
150 次 * 200 Token/次 = 30000 Token
30000 Token ≈ 3 元/天
场景三:实时监听门店商品库存变动
库存每发生一次变化,就会产生一次库存变动事件。例如商品 A 库存从 80 变到 78,再变到 70,再变到 50,会产生 3 次库存变动。
假设一家门店每天有 2000 次商品库存变动,每次库存变动回调消耗 20 Token。
2000 次 * 20 Token/次 = 40000 Token
40000 Token ≈ 4 元/天
费用评估只用于预估接入成本。实际费用会受请求字段、分页次数、回调事件数量、业务量波动和充值赠送比例影响,建议上线后通过控制台调用日志持续观察。
常见错误码
| 错误码 | 说明 |
|---|---|
4001 |
请求参数错误,例如缺少公共请求头、account 为空、JSON 非法。 |
4002 |
无效的 appId。 |
4003 |
请求已过期,或时间范围不合法。 |
4004 |
签名错误,或排序字段不合法。 |
4005 |
无效的 account。 |
4006 |
没有目标门店的访问权限。 |
4021 |
当前账号已欠费且正式服务已暂停,请先充值或联系运营调整宽限期。 |
5000 |
系统异常。 |
5001 |
请求上下文不存在。 |
回调说明
开放平台支持业务事件回调,客户可在控制台配置回调地址、订阅事件,并通过回调日志查看发送结果。
回调能力与配置方式
appId + 门店 维度配置,即某个应用可针对某个门店单独维护回调规则。
http:// 或 https:// 开头,推荐生产环境使用 https://。
- 配置入口:登录控制台后,在“回调地址配置”中维护。
- 每条回调地址可配置
callbackUrl、callbackSecret、订阅事件。 callbackSecret可为空;为空时按空字符串参与签名。- 每次回调消耗
20 token,按实际订阅并接收该回调的appId计费;控制台回调测试不计费。
当前支持的事件
| eventType | 说明 |
|---|---|
product.change |
商品变更 |
customer.change |
会员变更 |
ticket.change |
销售单据变更 |
productOrder.change |
网单变更 |
回调请求方式与请求头
| 请求头 | 说明 |
|---|---|
X-Event-Id |
回调事件唯一标识 |
X-Event-Type |
事件类型 |
X-Timestamp |
Unix 时间戳,单位秒 |
X-Attempt-No |
当前第几次投递,首次发送为 1 |
X-Sign |
签名值,用于客户验签 |
Content-Type |
固定为 application/json;charset=UTF-8 |
请求方法固定为 POST。测试回调时会额外带上 X-Test-Callback: true。
回调请求体
{
"eventId": "evt_4f1c7d8a9b6e4b8baf6c8c3d1a2e9f10",
"eventType": "product.change",
"account": "store001",
"eventTime": "2026-04-07 10:30:00",
"data": {
"uid": 900000001,
"barcode": "6901234567890",
"name": "可乐",
"sellPrice": 3.5,
"stock": 120,
"enable": 1,
"sysUpdateTime": "2026-04-07 10:30:00"
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
eventId |
string | 平台事件唯一标识,建议作为幂等键使用 |
eventType |
string | 事件类型 |
account |
string | 对应门店账号 |
eventTime |
string | 事件发生时间,格式为 yyyy-MM-dd HH:mm:ss |
data |
object | 业务数据,不同事件对应不同字段结构 |
data 字段说明
不同 eventType 的 data 字段结构不同,客户系统应按事件类型解析。
product.change 商品变更
当商品资料发生新增、修改、上下架、价格、库存等任意变更时,平台会触发 product.change 回调。
回调 data 中仅包含商品基础识别信息及部分常用字段,不代表只有这些字段变更才会回调。客户如需获取商品完整信息,请根据 data.uid 或 data.barcode 调用查询商品接口获取最新商品详情。
| data 字段 | 类型 | 说明 |
|---|---|---|
uid | long | 商品 UID,平台内商品唯一标识。 |
barcode | string | 商品条码。 |
name | string | 商品名称。 |
sellPrice | decimal | 商品销售价。 |
stock | decimal | 当前库存数量。 |
enable | int | 启用状态,1 表示启用,0 表示停用。 |
sysUpdateTime | string | 数据最后更新时间,格式为 yyyy-MM-dd HH:mm:ss。 |
customer.change 会员变更
当会员资料、积分、储值、启用状态等任意变更时,平台会触发 customer.change 回调。
回调 data 中仅包含会员基础识别信息及部分常用字段,不代表只有这些字段变更才会回调。客户如需获取会员完整信息,请根据 data.uid 或 data.number 调用查询会员接口获取最新会员详情。
| data 字段 | 类型 | 说明 |
|---|---|---|
uid | long | 会员 UID,平台内会员唯一标识。 |
number | string | 会员编号。 |
name | string | 会员姓名。 |
tel | string | 会员手机号。 |
point | decimal | 会员当前积分。 |
money | decimal | 会员当前储值余额。 |
enable | int | 启用状态,1 表示启用,0 表示停用。 |
sysUpdateTime | string | 数据最后更新时间,格式为 yyyy-MM-dd HH:mm:ss。 |
ticket.change 销售单据变更
当销售单新增、退款、反结账等任意变更时,平台会触发 ticket.change 回调。
回调 data 中仅包含销售单基础识别信息及部分常用字段,不代表只有这些字段变更才会回调。客户如需获取销售单完整信息,请根据 data.uid、data.sn 或 data.webOrderNo 调用查询销售单据接口获取最新单据详情。
| data 字段 | 类型 | 说明 |
|---|---|---|
uid | long | 销售单 UID,平台内销售单唯一标识。 |
sn | string | 销售单流水号。 |
webOrderNo | string | 网单号,只有线上订单才有值。 |
datetime | string | 销售时间,格式为 yyyy-MM-dd HH:mm:ss。 |
totalAmount | decimal | 销售单金额,必须大于等于 0。 |
customerUid | long | 关联会员 UID,无会员时可能为空。 |
refund | int | 是否退款单,1 表示是,0 表示否。 |
reversed | int | 是否反结账,1 表示是,0 表示否。 |
sysUpdateTime | string | 数据最后更新时间,格式为 yyyy-MM-dd HH:mm:ss。 |
productOrder.change 网单变更
当网单新增、修改、状态变化等任意变更时,平台会触发 productOrder.change 回调。
回调 data 中仅包含网单基础识别信息及部分常用字段,不代表只有这些字段变更才会回调。客户如需获取网单完整信息,请根据 data.orderNo 调用查询网单接口获取最新订单详情。
| data 字段 | 类型 | 说明 |
|---|---|---|
orderNo | string | 网单订单号。 |
time | string | 下单时间,格式为 yyyy-MM-dd HH:mm:ss。 |
state | int | 网单状态。 |
totalAmount | decimal | 订单金额。 |
sysUpdateTime | string | 数据最后更新时间,格式为 yyyy-MM-dd HH:mm:ss。 |
回调签名规则
回调签名规则与开放接口调用签名规则不同,使用回调地址配置中的 callbackSecret 参与计算。
stringToSign = callbackSecret + "|" + eventId + "|" + timestamp
sign = md5(stringToSign).toUpperCase()
timestamp取请求头X-Timestamp。eventId取请求头X-Event-Id。callbackSecret取客户在控制台回调配置中设置的回调密钥。- 建议客户同时校验平台出口 IP 白名单、
timestamp有效期以及eventId是否重复处理。
成功判定
- 客户接口返回
HTTP 200,平台即视为回调成功。 - 非
200、超时、网络异常等,均视为回调失败。 - 当前版本不解析客户返回体内容,响应体仅用于日志记录。
重试机制
首次发送会立即执行;单个任务最大总尝试次数为 8 次,即 1 次首次发送 + 最多 7 次失败重试。
| 重试序号 | 间隔 |
|---|---|
| 第1次重试 | 10 秒 |
| 第2次重试 | 30 秒 |
| 第3次重试 | 60 秒 |
| 第4次重试 | 180 秒 |
| 第5次重试 | 600 秒 |
| 第6次重试 | 1800 秒 |
| 第7次重试 | 3600 秒 |
对接建议
- 建议客户回调接口先完成验签和接收,再快速返回
HTTP 200。 - 具体业务处理建议在客户系统内部异步执行,避免因耗时过长被平台判定为失败。
- 如未收到回调,请优先检查是否已配置回调地址、是否订阅了对应事件、客户接口是否正确返回
HTTP 200。