Shared API 文档
接口说明版本:2026-09-21。本文同时覆盖传统 Shared API(/shared/...)与新版下游对接协议(/api/v1/upstream/...)。
基础规则
- 基础地址:本站域名,例如
https://example.com - 接口返回 JSON:
{
"code": 200,
"msg": "success",
"data": {}
}
鉴权规则
除特别说明外,下面所有接口都需要 Shared API 鉴权。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 已授权对接账号的用户 ID |
sign | 是 | 请求签名 |
签名算法:
- 从请求参数中移除
sign。 - 按参数名升序排序。
- 移除值为空字符串
''的参数。 - 使用
http_build_query生成 query string。 - 末尾追加
&key={用户 app_key}。 - 计算
md5(urldecode(query_string + "&key=" + app_key))。
PHP 示例:
function makeSign(array $data, string $appKey): string
{
unset($data['sign']);
ksort($data);
foreach ($data as $key => $value) {
if ($value === '') {
unset($data[$key]);
}
}
return md5(urldecode(http_build_query($data) . '&key=' . $appKey));
}
注意:如果请求体里传了 app_key 字段,它也会参与签名,因为签名逻辑会对除 sign 以外的所有非空字段签名。
接口列表
连接测试
POST /shared/authentication/connect
用于测试 Shared API 凭据是否有效。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
| 返回字段 | 说明 |
|---|---|
shopName | 网站店铺名称 |
balance | 当前用户余额 |
全部商品
POST /shared/commodity/items
获取已启用分类及其已启用 API 对接的商品。返回分类数组,每个分类包含 children 商品列表。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
factory_price会按当前鉴权用户重新计算。- 如果商品存在分类/规格价格,
config.category_factory会包含每个分类/规格重新计算后的成本价。 - 返回结果会移除
leave_message和delivery_message。
按商品代码查询商品
POST /shared/commodity/item
根据本地商品 API 代码查询商品。推荐传 code 获取平铺商品对象;兼容传 sharedCode 获取分类数组结构。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
code | 二选一 | 本地商品 code,返回平铺单商品对象 |
sharedCode | 二选一 | 本地商品 code,返回与 /shared/commodity/items 类似的分类数组结构 |
如果两个字段都不传,会返回 对接CODE不能为空。
库存可购买检测
POST /shared/commodity/inventoryState
检测指定商品数量是否可以购买。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
shared_code | 是 | 本地商品 code |
card_id | 否 | 预选卡密 ID,不预选传 0 |
num | 是 | 购买数量 |
race | 否 | 商品分类/规格名称 |
{
"code": 200,
"msg": "success",
"data": []
}
常见错误:商品不存在、商品已停售、预选卡密不可用、库存不足。
库存详情
POST /shared/commodity/inventory
获取单个商品的库存、发货方式、预选状态、价格和配置。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
sharedCode | 是 | 本地商品 code 或 shared_code |
race | 否 | 商品分类/规格名称 |
| 返回字段 | 说明 |
|---|---|
count | 可用库存数量 |
delivery_way | 发货方式,0 自动发货,其他值为手动/插件发货 |
draft_status | 是否开启预选卡密 |
price | 商品未登录价格 |
user_price | 商品会员价格 |
config | 商品配置,包含重新计算后的规格成本价 |
factory_price | 无规格商品时,当前鉴权用户的计算成本价 |
is_category | 是否为规格/分类价格商品 |
创建订单
POST /shared/commodity/trade
创建订单,并强制使用余额支付。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
shared_code | 是 | 本地商品 code |
contact | 是 | 买家联系方式 |
num | 是 | 购买数量 |
card_id | 否 | 预选卡密 ID,不预选传 0 |
device | 否 | 设备标识 |
password | 否 | 查询密码 |
coupon | 否 | 优惠券代码 |
from | 否 | 推广用户 ID |
race | 否 | 商品分类/规格名称 |
request_no | 建议 | 客户端请求号,用于幂等 |
| 额外 widget 字段 | 视商品而定 | 如果商品配置了控件,需要提交对应字段 |
| 返回字段 | 说明 |
|---|---|
url | 支付地址;因为强制余额支付,通常为 null |
amount | 订单金额 |
tradeNo | 本地订单号 |
secret | 已完成且可展示时返回最终发货内容;异步处理期间返回客户提示,不返回首次未验证卡密。 |
leave_message | 商品发货说明(如果有)。 |
query 或 query2 轮询。建议间隔不少于 10 秒,并在收到 visibility=visible 且 shared_secret 非空后再展示卡密。预选卡密列表
POST /shared/commodity/draftCard
获取商品可预选的卡密列表。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
code | 二选一 | 本地商品 code |
sharedCode | 二选一 | 本地商品 code,兼容旧调用 |
page | 否 | 页码,默认 1 |
limit | 否 | 每页数量,默认 10 |
race | 否 | 商品分类/规格名称 |
sku | 否 | 多规格映射参数;存在嵌套商品时透传 |
返回 data 为分页卡密数据,包含 id、draft;本地商品还会附加 draft_premium。
库存数量
POST /shared/commodity/stock
获取单个商品当前可用库存数量。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
code | 是 | 本地商品 code |
race | 否 | 商品分类/规格名称 |
sku | 否 | 多规格映射参数;存在嵌套商品时透传 |
{
"code": 200,
"msg": "success",
"data": {
"stock": "10"
}
}
预选卡密详情
POST /shared/commodity/draft
根据预选卡密 ID 获取单张预选卡密内容。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
code | 是 | 本地商品 code |
card_id | 是 | 预选卡密 ID |
| 返回字段 | 说明 |
|---|---|
id | 卡密 ID |
draft | 预选展示内容 |
draft_premium | 预选卡密加价 |
按订单号查询订单
POST /shared/commodity/query
根据本地订单号查询订单。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
tradeNo | 是 | 本地订单号 |
| 返回字段 | 说明 |
|---|---|
secret | 仅在可展示时返回最终发货内容;处理期间为空。 |
shared_secret | 给已签名下游同步使用的最终发货内容;处理期间为空。 |
widget | 下单提交的控件值;没有则为 null |
status | 本地订单状态 |
delivery_status | 1 表示订单已进入发货完成状态;仍需结合 visibility 判断是否可展示。 |
tg_detect_status | TG 检测状态:0 未进入、1/2 处理中、3 完成、4 失败。 |
fulfillment_status | pending、fulfilled 或 failed。 |
visibility | processing 处理中、visible 可展示、failed 失败、after_sales_hidden 售后过程单。 |
customer_message | 当前状态给客户的安全提示。处理中通常为“订单正在处理中,预计 1-3 分钟完成,请稍后刷新订单获取最终卡密。” |
after_sales_customer_hidden | 1 表示售后过程单对客户隐藏,应继续查询原订单。 |
按请求号查询订单
POST /shared/commodity/query2
根据客户端请求号查询订单。
| 字段 | 必填 | 说明 |
|---|---|---|
app_id | 是 | 用户 ID |
sign | 是 | 签名 |
requestNo | 是 | 客户端请求号 |
返回 data 与 /shared/commodity/query 相同。
新版下游对接协议(dujiao-next)
新版协议使用 JSON 请求体和请求头签名,适合需要分类、商品、实时库存、下单和订单状态查询的下游系统。协议版本可通过 ping 返回的 protocol_version 确认。
GET /api/v1/upstream/ping
GET /api/v1/upstream/categories
GET /api/v1/upstream/products
GET /api/v1/upstream/products/{product_id}
POST /api/v1/upstream/orders
GET /api/v1/upstream/orders/{order_id}
POST /api/v1/upstream/orders/{order_id}/cancel
新版鉴权
| 请求头 | 必填 | 说明 |
|---|---|---|
Dujiao-Next-Api-Key | 是 | 平台分配的用户 ID(数字字符串),不是密钥明文。 |
Dujiao-Next-Timestamp | 是 | Unix 时间戳;服务端允许的时间偏差不超过 300 秒。 |
Dujiao-Next-Signature | 是 | HMAC-SHA256 签名。 |
签名原文为四行:大写 HTTP 方法、原始请求路径(含查询字符串)、时间戳、请求体 md5,行间使用换行符;使用分配的密钥计算 hash_hmac('sha256', sign_string, app_key)。GET 请求体为空字符串,POST 请求体必须使用实际发送的原始 JSON 字节。
$body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$timestamp = time();
$path = '/api/v1/upstream/orders';
$signString = "POST\n" . $path . "\n" . $timestamp . "\n" . md5($body);
$signature = hash_hmac('sha256', $signString, $appKey);
$headers = [
'Content-Type: application/json',
'Dujiao-Next-Api-Key: ' . $userId,
'Dujiao-Next-Timestamp: ' . $timestamp,
'Dujiao-Next-Signature: ' . $signature,
];
新版返回格式
成功响应使用 {"ok":true,...};失败响应使用 HTTP 状态码和 error_code、error_message,例如:
{
"ok": false,
"error_code": "invalid_signature",
"error_message": "signature verification failed"
}
商品与库存
categories 返回启用分类;products 返回启用商品,支持 page、page_size、category_id。商品详情包含 id、category_id、title、description、price_amount、currency、skus、stock_count、stock_status 和 manual_form_schema。
商品列表可能返回 lightweight=true,此时库存为未知占位值;进入商品详情后应再次读取实时 stock_count,下单前仍需处理库存不足错误。金额统一为人民币 CNY,价格字段为字符串格式(如 "12.34")。
新版创建订单
POST /api/v1/upstream/orders
{
"sku_id": 12300001,
"quantity": 1,
"downstream_order_no": "your-unique-order-no",
"manual_form_data": {
"contact": "buyer-contact"
}
}
| 字段 | 必填 | 说明 |
|---|---|---|
sku_id | 是 | 商品 SKU ID。 |
quantity | 是 | 购买数量,必须大于 0。 |
downstream_order_no | 建议 | 下游唯一订单号;相同请求号会幂等返回原订单。 |
manual_form_data | 按商品 | 商品控件数据;字段由 manual_form_schema 描述。 |
订单响应包含 order_no、request_no、payment_status、fulfillment_status、visibility、customer_message、secret、card_secret、cards 和 fulfillment。处理期间 secret、card_secret、cards 和发货载荷为空;不要把空值当作失败,应按提示轮询订单详情。
新版订单查询与取消
GET /api/v1/upstream/orders/{order_id} 返回与创建订单相同的订单结构。建议下单后间隔不少于 10 秒查询,直到 visibility=visible、fulfillment_status=fulfilled 且 secret 非空。
POST /api/v1/upstream/orders/{order_id}/cancel 当前只返回取消判定;已支付或已发货订单不会自动取消,响应中的 cancelled 为 false,并附带 cancel_reason。
错误说明
业务错误会抛出 JSONException,框架通常会返回 JSON 错误响应。
- 缺少
app_id - 缺少
sign - 用户 ID 不存在
- 签名错误
- 商品不存在或已停售
- 库存不足
- 余额支付失败
- 订单不存在
- 新版协议错误码:
missing_auth_headers、timestamp_expired、invalid_signature、invalid_product_id、product_not_found、invalid_order_payload、order_not_found