成都奥印商贸有限公司内部系统
API 对接教程
小程序、货架电商、直播电商调用奥印ERP货盘、库存、上下架和订单接口。奥印ERP API 对接文档
适用对象:微信小程序开发、外部商城开发、淘宝/拼多多/抖音/直播渠道同步服务开发、内部数据对接人员。 后端基础地址:https://aolaierp.com/jshERP-boot 线上正式地址:https://aolaierp.com/jshERP-boot
1. 对接目标
奥印ERP 对外提供三类核心能力:
1. 货盘 API:给小程序、商城、平台服务读取商品、图片、价格、库存、上下架状态。 2. 收银 API:给门店 POS 或其它内部收银设备扫码、结账、生成零售出库单。 3. 渠道订单 API:接收淘宝、拼多多、抖音、直播、小程序等订单,并转成 ERP 零售出库单扣库存。
推荐总流程:
flowchart LR
ERP["奥印ERP 商品/库存"] --> Goods["货盘 API"]
Goods --> Mini["微信小程序"]
Goods --> Shop["淘宝/拼多多/抖音货架"]
Goods --> Live["直播电商"]
Mini --> Order["渠道订单 API"]
Shop --> Order
Live --> Order
Order --> Convert["转 ERP 零售出库单"]
Convert --> Stock["库存扣减/财务记录"]
2. 通用规则
2.1 请求格式
GET:参数放 query string。POST:请求体使用 JSON。- 编码:
UTF-8。 - 时间:建议使用
yyyy-MM-dd HH:mm:ss或 ISO 时间。 - 金额:数字类型,保留 2 位或 6 位小数均可。
2.2 返回格式
所有接口统一返回:
{
"code": 200,
"data": {}
}
常见 code:
| code | 含义 | 处理建议 |
|---|---|---|
| 200 | 成功 | 读取 data |
| 400 | 参数错误 | 检查必填字段、格式、商品条码 |
| 401 | 未登录或 token 缺失 | 重新登录或刷新 token |
| 500 | 服务端异常 | 记录请求参数和返回,联系 ERP 管理员 |
2.3 登录和鉴权
写接口必须带 X-Access-Token。
登录接口:
POST /user/login
Content-Type: application/json
请求:
{
"loginName": "aoyin",
"password": "e10adc3949ba59abbe56e057f20f883e"
}
说明:
password是原始密码的 MD5 小写值。123456的 MD5 是e10adc3949ba59abbe56e057f20f883e。
返回:
{
"code": 200,
"data": {
"msgTip": "user can login",
"token": "token-value",
"user": {
"id": 63,
"loginName": "aoyin",
"username": "奥印管理员",
"tenantId": 63
}
}
}
后续写接口请求头:
X-Access-Token: token-value
2.4 正式开放平台账号
正式给线下收银台、小程序、淘宝、拼多多、抖音、自建站对接时,不使用 ERP 管理员账号,也不把 X-Access-Token 给外部团队。
管理员在 ERP 中进入 开放平台 -> API账号管理,给每个渠道创建独立账号。每个账号会得到:
appKey:账号标识。appSecret:签名密钥,只在创建或重置时显示一次。channel:渠道标识,例如mini、taobao、pdd、douyin、douyin-live、pos-store-001。permissions:权限,例如读取商品、读取库存、锁库存、确认扣库存、取消释放库存。- 默认仓库、默认收款账户、内部制单用户。
- POS 离线开关,默认关闭。
外部系统调用 /open/** 时必须带签名请求头:
X-Aoyin-App-Key: <appKey>
X-Aoyin-Timestamp: <当前Unix秒级时间戳>
X-Aoyin-Nonce: <随机字符串,每次请求不能重复>
X-Aoyin-Signature: <HMAC-SHA256签名Base64>
签名原文:
HTTP_METHOD
REQUEST_URI_WITH_QUERY
TIMESTAMP
NONCE
JSON_BODY
说明:
GET请求的JSON_BODY为空字符串。POST请求的JSON_BODY是实际发送的请求体 JSON 字符串,必须和 HTTP body 完全一致,包括字段顺序和空格。- 签名算法是
HmacSHA256(appSecret, 签名原文),结果用 Base64。 - 时间戳允许误差 10 分钟。
- 同一
appKey + nonce只能使用一次,防止重放。
Node.js 签名示例:
import crypto from 'crypto'
function sign({ method, uri, timestamp, nonce, body, appSecret }) {
const raw = [method, uri, timestamp, nonce, body || ''].join('\n')
return crypto.createHmac('sha256', appSecret).update(raw, 'utf8').digest('base64')
}
2.5 公司ID/companyId
当前系统是公司自用版,但数据库底层仍保留 tenantId 字段作为公司数据隔离字段。对外文档建议统一叫:
companyId:公司 ID,对外使用。tenantId:内部字段,兼容旧系统。
当前验收环境公司 ID:63。
读接口可以传 companyId=63;写接口根据 token 自动识别公司。
3. 货盘 API
货盘 API 是给小程序、商城、平台同步服务读取商品用的。
正式对接建议优先使用签名版开放接口:
GET /open/material/listGET /open/material/detailGET /open/material/stock
旧版公开读取接口 /mini/material/ 保留兼容,但生产集成建议逐步切到 /open/,这样可以按渠道账号控制权限、记录日志、绑定默认仓库。
3.1 商品列表
GET /mini/material/list
是否需要 token:不强制,建议由小程序后端调用。 用途:读取可售商品卡片列表。
请求参数:
| 参数 | 必填 | 说明 |
|---|---|---|
companyId |
否 | 公司 ID,不传默认当前配置 |
categoryId |
否 | 商品分类 ID |
depotId |
否 | 指定仓库库存 |
keyword |
否 | 搜索标题、商品名、条码、规格 |
saleStatus |
否 | ON_SALE、OFF_SALE、ALL,默认 ON_SALE |
onlyInStock |
否 | true 只看有库存 |
page |
否 | 页码,默认 1 |
pageSize |
否 | 每页条数,默认 20,最大 100 |
示例:
GET /mini/material/list?companyId=63&page=1&pageSize=20&onlyInStock=true
返回示例:
{
"code": 200,
"data": {
"page": 1,
"pageSize": 20,
"total": 9,
"companyId": 63,
"list": [
{
"materialId": 568,
"barCode": "1001",
"title": "Aoyin ERP Mini Product-568",
"subTitle": "Title, cover, gallery, price, stock and shelf status acceptance",
"coverUrl": "https://cdn.example.com/aoyin/products/568-cover.jpg",
"imageUrls": [
"https://cdn.example.com/aoyin/products/568-cover.jpg"
],
"price": 19.9,
"saleStatus": "ON_SALE",
"stock": 1,
"inStock": true,
"unit": "个"
}
]
}
}
小程序使用建议:
- 商品卡片用
title、coverUrl、price、stock。 - 加入购物车前再调一次详情或库存接口。
- 不要直接用 ERP 内部商品名做营销标题,优先用
title。
3.2 商品详情
GET /mini/material/detail
用途:商品详情页读取图文、轮播图、规格、库存。
请求参数:
| 参数 | 必填 | 说明 |
|---|---|---|
companyId |
否 | 公司 ID |
materialId |
二选一 | ERP 商品 ID |
barCode |
二选一 | 商品条码 |
depotId |
否 | 指定仓库库存 |
示例:
GET /mini/material/detail?companyId=63&materialId=568&depotId=15
返回重点字段:
{
"code": 200,
"data": {
"materialId": 568,
"title": "Aoyin ERP Mini Product-568",
"coverUrl": "https://cdn.example.com/aoyin/products/568-cover.jpg",
"imageUrls": [
"https://cdn.example.com/aoyin/products/568-cover.jpg",
"https://cdn.example.com/aoyin/products/568-detail-1.jpg"
],
"price": 19.9,
"description": "<p>商品详情 HTML</p>",
"stock": 1,
"variants": [
{
"materialExtendId": 2,
"barCode": "1001",
"sku": "sp1",
"unit": "个",
"price": 15
}
]
}
}
3.3 商品库存
GET /mini/material/stock
用途:下单前二次校验库存。
示例:
GET /mini/material/stock?companyId=63&barCode=1001&depotId=14
返回:
{
"code": 200,
"data": {
"companyId": 63,
"materialId": 568,
"depotId": 14,
"stock": 1,
"inStock": true
}
}
3.4 商品分类
GET /mini/material/categories?companyId=63
返回:
{
"code": 200,
"data": {
"companyId": 63,
"list": [
{
"id": 17,
"name": "目录1",
"parentId": null,
"serialNo": "11"
}
]
}
}
3.5 保存货盘展示资料
POST /mini/material/save
X-Access-Token: <token>
Content-Type: application/json
用途:保存小程序/外部货盘展示资料,不会改 ERP 商品主表。
请求:
{
"materialId": 568,
"title": "奥印热销商品标题",
"subTitle": "适合小程序卡片的短描述",
"coverUrl": "https://cdn.example.com/aoyin/products/568-cover.jpg",
"imageUrls": [
"https://cdn.example.com/aoyin/products/568-cover.jpg",
"https://cdn.example.com/aoyin/products/568-detail-1.jpg",
"https://cdn.example.com/aoyin/products/568-detail-2.jpg"
],
"price": 19.9,
"saleStatus": "ON_SALE",
"sort": 10,
"stockStrategy": "REAL_STOCK",
"autoOffSale": true,
"autoOnSale": false,
"description": "<p>商品图文详情</p>"
}
字段说明:
| 字段 | 必填 | 说明 |
|---|---|---|
materialId |
是 | ERP 商品 ID |
title |
建议 | 对外展示标题 |
subTitle |
否 | 副标题 |
coverUrl |
建议 | 商品封面图 |
imageUrls |
建议 | 轮播图数组 |
price |
建议 | 对外展示价 |
saleStatus |
否 | ON_SALE 或 OFF_SALE |
sort |
否 | 排序,越小越靠前 |
stockStrategy |
否 | 默认 REAL_STOCK |
autoOffSale |
否 | 无库存自动下架 |
autoOnSale |
否 | 有库存自动上架 |
description |
否 | HTML 或富文本字符串 |
3.6 上架
POST /mini/material/onSale
X-Access-Token: <token>
只改状态:
{
"materialId": 568
}
同时保存资料并上架:
{
"materialId": 568,
"title": "奥印上架商品",
"coverUrl": "https://cdn.example.com/aoyin/products/568-cover.jpg",
"imageUrls": [
"https://cdn.example.com/aoyin/products/568-cover.jpg"
],
"price": 19.9
}
3.7 下架
POST /mini/material/offSale
X-Access-Token: <token>
{
"materialId": 568
}
说明:下架不会删除商品,也不会删除图片资料。
3.8 按库存同步上下架
POST /mini/material/syncStock
X-Access-Token: <token>
{
"materialIds": [568, 619],
"depotId": 15,
"offSaleWhenNoStock": true,
"onSaleWhenHasStock": false
}
建议:
- 小程序定时任务可以每 5-15 分钟调用一次。
- 大促或直播时建议更高频率,但要避免每秒重复扫全量商品。
4. POS 收银 API
POS API 适合门店、内部收银设备、扫码台使用。
生产建议:
- 门店在线收银台使用 ERP 内置页面
收银管理 -> 收银台。 - 外部自建 POS 使用开放平台账号调用
/open/order/reserve和/open/order/confirm。 - POS 离线模式默认关闭,避免门店离线销售和小程序/电商/直播同时销售造成超卖。
- 如确实需要离线,必须先给门店分配独立门店库存,再由管理员打开该终端账号的离线开关。
4.1 收银配置
GET /pos/config
X-Access-Token: <token>
返回:
{
"code": 200,
"data": {
"defaultDepot": {
"id": 14,
"name": "仓库1",
"isDefault": true
},
"accounts": [
{
"id": 17,
"name": "账户1",
"serialNo": "zzz111",
"isDefault": true
}
],
"paymentMethods": ["现金", "微信", "支付宝", "银行卡", "组合支付"]
}
}
4.2 扫码查商品
POST /pos/scan
X-Access-Token: <token>
Content-Type: application/json
请求:
{
"barCode": "1003",
"depotId": 14
}
返回:
{
"code": 200,
"data": {
"materialId": 570,
"materialExtendId": 4,
"barCode": "1003",
"name": "商品3",
"title": "商品3",
"sku": "sp3",
"unit": "个",
"price": 15,
"stock": 8,
"depotId": 14
}
}
4.3 结账并生成零售出库单
POST /pos/checkout
X-Access-Token: <token>
Content-Type: application/json
请求:
{
"depotId": 14,
"accountId": 17,
"paymentMethod": "现金",
"receivedAmount": 30,
"remark": "门店收银",
"items": [
{
"barCode": "1003",
"quantity": 2,
"unitPrice": 15
}
]
}
返回:
{
"code": 200,
"data": {
"number": "LSCK00000000703",
"totalAmount": 30,
"receivedAmount": 30,
"changeAmount": 0,
"accountId": 17,
"depotId": 14,
"items": [
{
"barCode": "1003",
"name": "商品3",
"quantity": 2,
"unitPrice": 15,
"allPrice": 30
}
]
}
}
结果:
- ERP 生成
LSCK零售出库单。 - 库存扣减。
- 首页零售统计更新。
离线收银同步规则:
- 默认关闭。
- 关闭时,断网不能扫码、不能结账、不能自动保存离线单。
- 打开时,收银台离线订单先保存在本机浏览器本地队列;恢复联网后调用
/pos/checkout同步。 - 离线单必须带
externalOrderNo,建议格式如POS-20260610181200123-ABC123。 - ERP 会按
tenantId + channel + externalOrderNo做唯一校验,同一张离线单重复上传不会重复扣库存。 - 如果同步时 ERP 最新库存不足,接口返回库存不足,离线单保留在待同步队列,需要人工补货、调拨或改单后再处理。
- 生产环境建议继续保持关闭,除非门店有独立库存池。
4.4 查询 POS 单据
GET /pos/detail?number=LSCK00000000703
X-Access-Token: <token>
返回单头和明细,可用于打印小票或二次确认。
5. 开放平台订单 API
开放平台订单 API 是给小程序、电商、自建站、直播同步服务使用的正式生产接口。核心原则是:先锁库存,再确认扣库存;取消或超时释放库存。
5.1 查询可售库存
GET /open/material/stock?barCode=1001&depotId=14
X-Aoyin-App-Key: <appKey>
X-Aoyin-Timestamp: <timestamp>
X-Aoyin-Nonce: <nonce>
X-Aoyin-Signature: <signature>
返回:
{
"code": 200,
"data": {
"materialId": 568,
"stock": 10,
"lockedStock": 2,
"availableStock": 8,
"inStock": true
}
}
5.2 下单锁库存
POST /open/order/reserve
Content-Type: application/json
X-Aoyin-App-Key: <appKey>
X-Aoyin-Timestamp: <timestamp>
X-Aoyin-Nonce: <nonce>
X-Aoyin-Signature: <signature>
请求:
{
"externalOrderNo": "MINI202606100001",
"depotId": 14,
"accountId": 17,
"expireMinutes": 30,
"items": [
{
"barCode": "1001",
"title": "商品标题",
"quantity": 1,
"unitPrice": 15
}
]
}
规则:
- 同一
channel + externalOrderNo只能锁一次。 - 如果库存不足,返回
400,不锁库存。 expireMinutes不传默认 30 分钟。- 锁库存不会生成 ERP 出库单,只是占用可售库存。
5.3 支付成功后确认扣库存
POST /open/order/confirm
请求:
{
"externalOrderNo": "MINI202606100001",
"paidAmount": 15,
"paymentMethod": "微信支付",
"remark": "微信小程序订单"
}
结果:
- ERP 生成真实零售出库单。
- 库存正式扣减。
- 锁库存状态变为
CONFIRMED。 - 重复确认同一订单不会重复扣库存。
5.4 取消订单释放库存
POST /open/order/cancel
请求:
{
"externalOrderNo": "MINI202606100001"
}
规则:
RESERVED可以取消并释放库存。CONFIRMED已经生成 ERP 出库单,不能直接取消,要走 ERP 退货流程。
5.5 查询订单状态
GET /open/order/detail?externalOrderNo=MINI202606100001
状态:
| 状态 | 含义 |
|---|---|
RESERVED |
已锁库存,等待支付/确认 |
CONFIRMED |
已确认并生成 ERP 出库单 |
CANCELLED |
已取消,库存释放 |
6. 渠道订单 API
渠道订单 API 用于接入小程序、淘宝、拼多多、抖音货架、直播电商等外部订单。
说明:/channel/order/ 是内部 token 版接口,保留给 ERP 后台和内部自动化使用。正式给外部团队对接时,优先使用上面的 /open/order/ 签名版接口。
6.1 渠道值建议
| 渠道 | channel 建议值 |
|---|---|
| 微信小程序 | mini |
| 淘宝 | taobao |
| 拼多多 | pdd |
| 抖音货架 | douyin |
| 抖音直播 | douyin-live |
| 快手直播 | kuaishou-live |
| 手工导入 | manual |
6.2 订单状态
| 状态 | 含义 |
|---|---|
NEW |
已接收,未转 ERP 单据 |
CONVERTED |
已转 ERP 零售出库单 |
CANCELLED |
已取消,未扣库存 |
6.3 接收或更新渠道订单
POST /channel/order/receive
X-Access-Token: <token>
Content-Type: application/json
请求:
{
"channel": "douyin-live",
"externalOrderNo": "DOUYIN202606100001",
"externalStatus": "PAID",
"buyerName": "张三",
"buyerMobile": "13800000000",
"receiverName": "张三",
"receiverMobile": "13800000000",
"receiverAddress": "四川省成都市高新区...",
"depotId": 14,
"accountId": 17,
"paymentMethod": "抖音支付",
"paidAmount": 30,
"items": [
{
"barCode": "1003",
"title": "商品3",
"coverUrl": "https://cdn.example.com/aoyin/channel/1003.jpg",
"quantity": 2,
"unitPrice": 15
}
]
}
必填字段:
| 字段 | 说明 |
|---|---|
channel |
渠道标识 |
externalOrderNo |
外部平台订单号 |
items |
商品数组 |
items[].barCode |
ERP 商品条码 |
items[].quantity |
数量,大于 0 |
幂等规则:
- 同一个
companyId + channel + externalOrderNo只会有一条渠道订单。 - 重复推送会更新原订单,不会重复创建。
- 已经
CONVERTED的订单不会被改回NEW。
返回:
{
"code": 200,
"data": {
"id": 2,
"channel": "douyin-live",
"externalOrderNo": "DOUYIN202606100001",
"status": "NEW",
"paidAmount": 30,
"items": [
{
"barCode": "1003",
"quantity": 2,
"unitPrice": 15
}
]
}
}
6.4 渠道订单转 ERP 单据
POST /channel/order/convert
X-Access-Token: <token>
Content-Type: application/json
按 ID 转单:
{
"id": 2
}
按渠道和外部单号转单:
{
"channel": "douyin-live",
"externalOrderNo": "DOUYIN202606100001"
}
可覆盖仓库、账户、支付方式:
{
"id": 2,
"depotId": 14,
"accountId": 17,
"paymentMethod": "抖音支付"
}
返回:
{
"code": 200,
"data": {
"id": 2,
"status": "CONVERTED",
"erpBillNumber": "LSCK00000000706",
"bill": {
"number": "LSCK00000000706",
"totalAmount": 30,
"depotId": 14
}
}
}
结果:
- ERP 生成零售出库单。
- 库存扣减。
- 渠道订单记录 ERP 单号。
- 再次调用转单接口会直接返回已转单状态,不重复扣库存。
6.5 查询渠道订单列表
GET /channel/order/list?channel=douyin-live&status=NEW&page=1&pageSize=20
X-Access-Token: <token>
参数:
| 参数 | 说明 |
|---|---|
channel |
渠道筛选 |
status |
状态筛选 |
keyword |
外部单号、买家、收货人、ERP 单号 |
page |
页码 |
pageSize |
每页条数 |
6.6 查询渠道订单详情
GET /channel/order/detail?id=2
X-Access-Token: <token>
也可以:
GET /channel/order/detail?channel=douyin-live&externalOrderNo=DOUYIN202606100001
6.7 取消未转单订单
POST /channel/order/cancel
X-Access-Token: <token>
Content-Type: application/json
{
"id": 2,
"externalStatus": "CANCELLED"
}
注意:
- 只能取消未转单订单。
- 已转单订单要走 ERP 退货或冲销流程。
7. 推荐对接方案
7.1 微信小程序
推荐架构:
flowchart LR
MP["微信小程序前端"] --> MPS["小程序后端"]
MPS --> ERP["奥印ERP API"]
ERP --> DB["ERP 数据库"]
小程序前端不要直接保存 ERP token。由小程序后端调用 ERP。
小程序商品页:
1. 首页调用 /mini/material/list。 2. 详情页调用 /mini/material/detail。 3. 下单前调用 /mini/material/stock。 4. 付款成功后,小程序后端调用 /channel/order/receive。 5. 按公司规则自动或人工调用 /channel/order/convert。
7.2 淘宝/拼多多/抖音货架
推荐做一个“渠道同步服务”:
1. 保存平台密钥。 2. 拉取平台商品和订单。 3. 用平台 SKU 映射 ERP barCode。 4. 调 ERP 货盘 API 查询库存。 5. 调 ERP 渠道订单 API 回传订单。
不要把淘宝、拼多多、抖音密钥放在 ERP 前端代码里。
7.3 直播电商
直播间常见特点:
- 短时间订单量大。
- 商品上下架频繁。
- 库存超卖风险高。
建议:
- 直播前锁定参与直播的商品清单。
- 直播中高频调用库存接口或建立库存缓存。
- 支付成功后立即调用
/channel/order/receive。 - 出库可以自动转单,也可以先落单后人工复核。
8. JavaScript 调用示例
import md5 from 'md5'
const baseUrl = 'https://aolaierp.com/jshERP-boot'
async function login() {
const res = await fetch(`${baseUrl}/user/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
body: JSON.stringify({
loginName: 'aoyin',
password: md5('你的密码')
})
}).then(r => r.json())
if (res.code !== 200) throw new Error('ERP 登录失败')
return res.data.token
}
async function receiveOrder(token, order) {
const res = await fetch(`${baseUrl}/channel/order/receive`, {
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'X-Access-Token': token
},
body: JSON.stringify(order)
}).then(r => r.json())
if (res.code !== 200) throw new Error(JSON.stringify(res))
return res.data
}
9. curl 调试示例
登录:
curl -X POST "https://aolaierp.com/jshERP-boot/user/login" \
-H "Content-Type: application/json" \
-d '{"loginName":"aoyin","password":"e10adc3949ba59abbe56e057f20f883e"}'
查商品:
curl "https://aolaierp.com/jshERP-boot/mini/material/list?companyId=63&page=1&pageSize=20"
接收渠道订单:
curl -X POST "https://aolaierp.com/jshERP-boot/channel/order/receive" \
-H "Content-Type: application/json" \
-H "X-Access-Token: <token>" \
-d '{
"channel":"douyin-live",
"externalOrderNo":"DOUYIN202606100001",
"paidAmount":30,
"items":[{"barCode":"1003","quantity":2,"unitPrice":15}]
}'
10. 对接验收清单
外部团队完成对接前,至少跑通:
| 场景 | 必须通过 |
|---|---|
| 登录获取 token | 是 |
| 读取商品列表 | 是 |
| 读取商品详情和图片 | 是 |
| 按条码查库存 | 是 |
| 保存或上架测试商品 | 是,运营后台/同步服务 |
| 下架测试商品 | 是 |
| 推送一张渠道订单 | 是 |
| 重复推送同一订单不重复创建 | 是 |
| 转 ERP 零售出库单 | 是 |
| 再次转同一订单不重复扣库存 | 是 |
| 已转单订单走退货流程 | 人工确认 |
11. 生产安全要求
- 正式环境必须 HTTPS。
- ERP token 只放后端服务,不放小程序前端。
- 平台密钥只放渠道同步服务,不放 ERP 前端。
- 写接口建议加网关 IP 白名单。
- 重要接口要记录请求和响应日志。
- 对接服务要处理重试,所有订单按
channel + externalOrderNo幂等。 - 正式使用前修改默认账号密码。
- 定期备份 MySQL 数据库。