# legendshop-open-api
**Repository Path**: legendmall/legendshop-open-api
## Basic Information
- **Project Name**: legendshop-open-api
- **Description**: 供应链适配组件 | 五域协议规范(商品/库存/订单/结算/物流)+ 可插拔适配器 SPI + 幂等/重试/对账工程解法 | 提炼自 87 个生产接口,可脱离商城独立使用 | 配套 legend-cloud
- **Primary Language**: Unknown
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: https://open.legendshop.cn
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-18
- **Last Updated**: 2026-10-22
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 供应链, API, OpenAPI, 电商, Java
## README
# Legendshop Supply Chain Adapter · 供应链适配组件
> **一个不依赖商城业务、可独立使用的供应链接入框架。**
> 解决的是所有 B2B 系统都会遇到的问题:**每接一家上游供应商,就要重写一遍对接代码。**
>
> 完整代码见 [`adapter/`](adapter/)(Maven 多模块,`mvn spring-boot:run` 可直接跑通 Demo),
> 协议细则见 [`docs/五域协议规范.md`](docs/五域协议规范.md)。
[](https://gitee.com/legendmall/legendshop-open-api)
[](#-五域协议规范)
[](./LICENSE)
[](./sdk/java)
[](./sdk/node)
[五域协议规范](#-五域协议规范) ·
[适配器 SPI](#-适配器-spi可插拔接入) ·
[快速开始](#-30-分钟跑通) ·
[主仓 legend-cloud](https://gitee.com/legendmall/legend-cloud)
---
## 它解决什么问题
做 B2B / 采购 / 福利商城,绕不开对接上游供应商。而现实是:
| 现实 | 后果 |
|---|---|
| 每家供应商的字段名、订单模型、库存口径都不一样 | 每接一家重写一遍,2–4 周起 |
| 幂等、重试、对账、限流每家都要重新想一遍 | 同一个坑踩 N 次,线上偶发超卖 |
| 换一家供应商,历史对接代码全废 | 技术债越积越厚,越换越不敢换 |
**本仓做的事:把这些共性抽成一层协议 + 适配器框架。**
对接一家新供应商时,你只需要实现一个适配器接口,其余(字段映射、幂等、重试、分页、对账)由框架承担。
```
你的业务系统
│ (只依赖本框架的抽象接口)
▼
┌─────────────────────────────┐
│ Supply Chain Adapter │
│ ├─ 五域协议规范(统一模型) │
│ ├─ 适配器 SPI(可插拔) │
│ └─ 幂等 / 重试 / 对账 / 限流 │
└─────────────────────────────┘
│ (各自实现)
├──► 供应商 A 适配器
├──► 供应商 B 适配器
└──► 你的自建 ERP 适配器
```
> **可以不配合任何商城使用。** 它是一层协议框架,任何需要接上游供货的系统都能用。
---
## 🧩 五域协议规范
供应链对接真正难的从来不是「调通接口」,而是**五个域的口径统一**:
| 域 | 统一了什么 | 典型坑 |
|---|---|---|
| **商品** | 类目树、SKU 编码、规格维度、多单位换算 | 一箱 = 12 件 vs 一箱 = 10 件,库存直接错 |
| **库存** | 实时库存 / 可售库存 / 锁定库存三分口径 | 把「有货」当「可售」,超卖 |
| **订单** | 下单幂等键、拆单规则、状态机映射 | 供应商状态机和我们不一致,订单卡死 |
| **结算** | 对账周期、差异容忍、退款回冲 | 月末对账差异查三天 |
| **物流** | 运单号回传、轨迹节点标准化、时效承诺 | 每家轨迹节点命名都不一样 |
每一域都给出:**统一数据模型 + 字段映射约定 + 错误码规范 + 幂等要求**。
> 📖 详细规范见 [docs/](docs/) 目录;已踩过的 10 个真实坑见 [docs/供应链对接避坑指南.md](./docs/供应链对接避坑指南.md),开工前建议先看这份。
---
## 🔌 适配器 SPI(可插拔接入)
框架定义抽象接口,供应商实现各自适配器。能力按域声明,支持部分实现——**只接库存、不接订单也合法**。
```java
public interface SupplierAdapter {
/** 供应商标识 */
String supplierCode();
/** 能力声明:本适配器支持哪些域 */
Set capabilities(); // GOODS / STOCK / ORDER / SETTLE / LOGISTICS
/** 商品域(不支持则返回 null) */
default GoodsCapability goods() { return null; }
/** 库存域 */
default StockCapability stock() { return null; }
// ORDER / SETTLE / LOGISTICS 同上
}
```
加上 `@SupplierAdapterProvider("supplier-a")` 注解并声明为 Spring Bean,框架自动注册。
---
## 📊 实战验证:87 个真实接口
本规范不是纸上设计——**它提炼自一套已在生产运行的供应链开放平台,87 个接口对外稳定服务**。
不必相信 README 里的任何一句话,直接对着生产网关敲三条命令:
```bash
# ① 网关活着,且要求令牌
curl -i https://openapi.legendshop.cn/
# HTTP/1.1 401
# {"code":2000,"message":"无效的访问令牌","path":"/"}
# ② 换令牌接口只认 POST
curl -i https://openapi.legendshop.cn/portal/login/getToken
# HTTP/1.1 405
# {"code":4005,"message":"请求方式不支持!"}
# ③ 凭证校验是服务端真实鉴权(用假凭证试)
curl -X POST https://openapi.legendshop.cn/portal/login/getToken \
-d "client_id=DEMO&client_secret=DEMO&scope=shop"
# HTTP/1.1 401
# {"code":2003,"message":"Bad client credentials"}
```
三条响应返回三种不同错误码(`2000` / `4005` / `2003`),是一个真实网关在按自己的逻辑应答,而不是静态占位页。
| 环境 | 网关域名 |
|------|---------|
| 生产 | `https://openapi.legendshop.cn` |
| 测试 | `http://openapi.legendmall.cn` |
> 完整接口清单见 [API清单.md](./API清单.md) 与 [openapi.yaml](./openapi.yaml),覆盖 V1–V5 全部版本。
---
## 📁 文档导航
| 文档 | 看什么 |
|---|---|
| [docs/五域协议规范.md](./docs/五域协议规范.md) | **先看这个**:商品/库存/订单/结算/物流五域的统一模型、幂等、错误码 |
| [docs/供应链对接避坑指南.md](./docs/供应链对接避坑指南.md) | 已踩过的 10 个真实坑,开工前必读 |
| [docs/authentication.md](./docs/authentication.md) | 鉴权、scope、错误码、限流 |
| [API清单.md](./API清单.md) | 87 个接口全清单(V1–V5) |
| [openapi.yaml](./openapi.yaml) | OpenAPI 3 规范,可直接导入 Postman / Apifox |
| [examples/quickstart.md](./examples/quickstart.md) | 30 分钟跑通「查库存 → 下单 → 查物流」 |
---
## 🎯 能力矩阵(按业务域)
| 业务域 | 接口数 | 代表接口 | 覆盖内容 |
|--------|-------|---------|---------|
| 🔑 鉴权 | 2 | `POST /portal/login/getToken`、`/oauth2/accessToken` | client_id + client_secret + scope 换取 access_token(两套体系并存) |
| 👤 用户 | 8 | `/open/v5/user/register`、`/open/v4/user/page` | 注册、查询、注销、详情、登录转发 |
| 🏪 店铺/商户 | 7 | `/open/v4/shop/createMerchant`、`createShop` | 创建商户与店铺、微信开放平台绑定、登录授权码 |
| 📦 商品 | 16 | `/open/v4/product/queryProdListPage`、`saveProd` | 商品列表分页、详情、类目、运费规则、保存商品 |
| 📊 库存与价格 | 5 | `/open/v2/product/queryProdStock`、`queryProdPrice` | 实时库存、价格、最小起订量、可售性校验 |
| 🧾 订单 | 15 | `/open/v2/order/submitOrder`、`/open/v4/order/page` | 提交订单、分页查询、详情、取消、确认收货、运费试算、虚拟订单 |
| 🚚 物流 | 2 | `/open/v4/order/orderTrack`、`getPromiseInfo` | 物流轨迹、预计送达时间 |
| ↩️ 售后 | 7 | `/open/v2/afterSale/apply`、`applySubmit` | 售后申请、取消、状态查询、货运信息 |
| 📍 地址 | 6 | `/open/v2/area/getProvince`、`checkArea` | 四级地址、地址有效性校验、智能解析 |
| 💰 账户/预存款 | 6 | `/open/v1/captitalAccount/*` | 余额查询、下单扣减、退款 |
| 🎯 积分 | 15 | `/open/v5/integral/*`、`/integral/*` | 查询、发放、扣减、同步、流水、批量查询 |
| 🎟️ 优惠券 | 2 | `/open/v4/coupon/batchImport` | 批量发放、列表查询 |
| 🔔 消息 | 2 | `/open/v2/message/get` | 消息推送与已读删除 |
完整清单见 [API清单.md](./API清单.md),机器可读规范见 [openapi.yaml](./openapi.yaml)。
---
## 🚀 快速开始(3 步)
### 1. 换 Token
```bash
curl -X POST "https://openapi.legendshop.cn/portal/login/getToken" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=shop"
```
`scope` 三选一:`tenant`(V1 租户集成)、`shop`(V2/V4 商城商品)、`supplier`(V3 供应商)。
```json
{ "access_token": "6y34634734734gse233", "expires_in": "7200", "scope": "shop" }
```
> **务必缓存 token**,不要每次调用都换取;遇到 401 再刷新即可。
### 2. 调业务接口(注意:多数为表单提交)
```bash
curl -X POST "https://openapi.legendshop.cn/open/v4/product/queryProdListPage" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "shopId=1&curPage=1&pageSize=10"
```
统一响应结构:
```json
{ "status": "1", "success": "true", "message": "消息", "data": { ... } }
```
> ⚠️ 这里最容易踩:**业务是否成功看 `status` / `success` 字段,不是看 HTTP 状态码**。
> 网关层的错误才走 HTTP 状态码(401 / 403 / 429)。完整错误码见 [docs/authentication.md](./docs/authentication.md)。
### 3. 用 SDK
| 语言 | 位置 |
|------|------|
| Java 11+ | [sdk/java/SupplyChainClient.java](./sdk/java/SupplyChainClient.java) |
| Node 18+ | [sdk/node/supplyChainClient.js](./sdk/node/supplyChainClient.js) |
```java
SupplyChainClient c = new SupplyChainClient(
SupplyChainClient.PROD, "CLIENT_ID", "CLIENT_SECRET", "shop");
c.queryProdListPage(1L, 1, 10); // 商品列表
c.queryProdStock(province, city, area, town, skuInfosJson);
c.submitOrder(params); // 提交订单
```
```js
const c = createClient({ clientId, clientSecret, scope: 'shop' });
await c.queryProdListPage({ shopId: 1, curPage: 1, pageSize: 10 });
```
---
## 📁 目录
```
legendshop-open-api/
├── README.md # 本文档
├── API清单.md # 87 个接口速查表(按业务域分组)
├── openapi.yaml # OpenAPI 3.0 机器可读规范
├── docs/authentication.md # 鉴权、scope、错误码、限流
├── docs/供应链对接避坑指南.md # 已踩过的 10 个坑,开工先看
├── sdk/java/… # Java SDK(零依赖)
├── sdk/node/… # Node SDK(零依赖)
├── examples/quickstart.md # 30 分钟跑通「查库存 → 下单 → 查物流」
└── CONTRIBUTING.md # 文档同步与共建
```
---
## ✅ 适合 / ❌ 不适合
| ✅ 适合 | ❌ 不适合 |
|--------|---------|
| 做**员工福利商城**,要接福利供应商的实时库存与额度 | 只想做一个纯 C 端零售站,不需要上游供货体系 |
| 央企 / 国企内购平台,商品、订单、积分、结算要全链路打通 | 要的是支付通道或社交分销玩法,本仓不涉及 |
| MRO 工业品采购,要查实时库存与最小起订量 | |
| 已有供应商体系,想把它变成能下单的商城前台 | |
---
## 🔗 与 Legendshop 开源体系的关系
| 仓 | 定位 |
|---|------|
| [legend-cloud](https://gitee.com/legendmall/legend-cloud) | **① 商城系统开源**:B2B2C / S2B2C 微服务主仓 |
| **legendshop-open-api(本仓)** | **② 带供应链 API 的商城系统**:87 个真实对外接口 + SDK |
| [legendshop-ai-mall](https://gitee.com/legendmall/legendshop-ai-mall) | **③ 带 AI 的开源商城**:推荐算法、AI 客服、供需匹配 |
配套前端:[legend-cloud-admin-ui](https://gitee.com/legendmall/legend-cloud-admin-ui)(平台运营端)·
[legend-cloud-shop-ui](https://gitee.com/legendmall/legend-cloud-shop-ui)(商城 / H5 端)·
[legend-cloud-user-ui](https://gitee.com/legendmall/legend-cloud-user-ui)(用户 / 会员端)
> **一句话定位:Legendshop = 开源商城系统 + 供应链开放 API + AI 电商能力,三位一体。**
---
## ⭐ Star 一下
如果这份规范帮你省下了「对着官方文档一页页抄参数」的时间,右上角给个 Star。
发现文档与实际接口不一致,欢迎 [提 Issue](https://gitee.com/legendmall/legendshop-open-api/issues) —— 24 小时内响应,确认后同步回本仓。
**开发方**:朗尊软件(广州朗尊软件科技有限公司)· 成立 2014 年 · 国家高新技术企业
· [官网](https://www.legendshop.cn)
---
## 📄 许可
AGPL-3.0,与 legend-cloud 主仓保持一致。