OMS系统开放API接口请求文档
1. 接口概述
OMS系统提供了丰富的开放API接口,供外部系统进行数据交互。本文档详细说明API接口的调用方式、参数规范、签名算法及错误处理机制。
2. API调用基础
2.1 请求方式
所有API接口均支持POST方式请求。
2.2 请求URL
http(s)://[域名]/index.php/openapi/rpc/service/2.3 系统级参数
所有API请求必须包含以下系统级参数:
| 参数名 | 类型 | 必选 | 描述 |
|---|---|---|---|
| ver | number | 否 | 接口版本号,默认值:1 |
| charset | string | 否 | 字符编码,支持:utf-8,默认值:utf-8 |
| type | string | 否 | 返回数据格式,支持:json,默认值:json |
| method | string | 是 | 接口方法名,格式:class.method |
| flag | string | 是 | 来源标识,对应系统中配置的接入方标识 |
| timestamp | string | 是 | 时间戳,单位:秒,必须在服务器时间±3600秒范围内 |
| sign | string | 是 | 签名,详见签名算法章节 |
3. 签名算法
3.1 签名生成步骤
- 收集所有请求参数(不包括sign本身)
- 按照参数名的ASCII码顺序进行排序(ksort)
- 递归拼接参数名和参数值(对于嵌套数组,递归处理)
- 对拼接后的字符串进行MD5加密,再转大写
- 将上一步的结果与token(接口密钥)拼接
- 再次进行MD5加密并转大写,得到最终签名
3.2 签名算法代码示例(PHP)
php
// 签名生成函数
function gen_sign($params, $token)
{
// 参数排序
ksort($params, SORT_STRING);
// 拼接字符串
$assemble_str = '';
foreach($params AS $key=>$val){
if(is_null($val)) continue;
if(is_bool($val)) $val = ($val) ? 1 : 0;
$assemble_str .= $key . (is_array($val) ? assemble($val) : $val);
}
// 生成签名
return strtoupper(md5(strtoupper(md5($assemble_str)).$token));
}
// 递归拼接数组参数
function assemble($params)
{
if(!is_array($params)) return null;
ksort($params, SORT_STRING);
$sign = '';
foreach($params AS $key=>$val){
if(is_null($val)) continue;
if(is_bool($val)) $val = ($val) ? 1 : 0;
$sign .= $key . (is_array($val) ? assemble($val) : $val);
}
return $sign;
}3.3 签名防重复机制
- 系统会缓存生成的签名1小时(3600秒)
- 相同签名的重复请求将被拒绝,返回错误码:e000009
4. 接口响应格式
4.1 成功响应
json
{
"response": {
// 具体接口返回数据
}
}4.2 错误响应
json
{
"error_response": {
"code": "错误码",
"msg": "错误信息",
"sub_msg": "详细错误信息(可选)"
}
}5. 系统级错误码
| 错误码 | 描述 | 可能原因 |
|---|---|---|
| e000001 | system params lost or error | 系统级参数缺失或错误 |
| e000002 | sign error | 签名错误,请检查签名算法和参数 |
| e000003 | class or method not exist | 接口类或方法不存在 |
| e000004 | no permissions to access | 没有权限访问该接口 |
| e000005 | init interface fail | 初始化接口失败 |
| e000006 | application params error | 应用级参数错误 |
| e000007 | init template fail | 初始化模板失败 |
| e000008 | refer server time invalid | 时间戳无效,与服务器时间偏差过大 |
| e000009 | repeat request invalid | 重复请求,签名已存在于缓存中 |
6. 接口调用示例
6.1 PHP示例
php
<?php
// 应用标识(需要替换为实际的flag)
$flag = 'your_oms_flag';
// 私钥(需要替换为实际的token)
$token = 'your_interface_key';
// 接口方法(例如,查询订单列表:orders.getList)
$method = 'orders.getList';
// 系统级参数
$systemParams = array(
'flag' => $flag, // 应用标识
'method' => $method, // 接口方法
'ver' => 1,
'charset' => 'utf-8',
'type' => 'json',
'timestamp' => time(),
);
// 应用级参数
$ApiParams = array(
'start_time' => '2025-10-01 00:00:00',
'end_time' => '2025-11-01 00:00:00',
'page_no' => 1,
'page_size' => 50
);
// 组装接口参数
$params = array_merge($systemParams, $ApiParams);
// 签名生成函数
function gen_sign($params, $token)
{
// 参数排序
ksort($params, SORT_STRING);
// 拼接字符串
$assemble_str = '';
foreach($params AS $key=>$val){
if(is_null($val)) continue;
if(is_bool($val)) $val = ($val) ? 1 : 0;
$assemble_str .= $key . (is_array($val) ? assemble($val) : $val);
}
// 生成签名
return strtoupper(md5(strtoupper(md5($assemble_str)).$token));
}
// 递归拼接数组参数
function assemble($params)
{
if(!is_array($params)) return null;
ksort($params, SORT_STRING);
$sign = '';
foreach($params AS $key=>$val){
if(is_null($val)) continue;
if(is_bool($val)) $val = ($val) ? 1 : 0;
$sign .= $key . (is_array($val) ? assemble($val) : $val);
}
return $sign;
}
// 生成签名
$params['sign'] = gen_sign($params, $token);
// curl发送请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http(s)://www.***.com/index.php/openapi/rpc/service/');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
// 处理响应
$result = json_decode($response, true);
// 测试Api接口返回的结果
echo('<pre>Response:<br>');
print_r($response);
echo('<br><br>Result:<br>');
print_r($result);
exit;6.2 Java示例(使用HttpClient)
java
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import java.security.MessageDigest;
import java.util.*;
public class OpenApiClient {
public static void main(String[] args) throws Exception {
// 接口URL
String url = "http://your-domain.com/index.php/openapi/rpc/service/";
// 接口参数
Map<String, String> params = new TreeMap<>(); // TreeMap自动按键排序
params.put("ver", "1");
params.put("charset", "utf-8");
params.put("type", "json");
params.put("method", "orders.getList");
params.put("flag", "test_flag");
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
params.put("start_time", "2024-01-01 00:00:00");
params.put("end_time", "2024-01-31 23:59:59");
params.put("page", "1");
params.put("page_size", "20");
// 生成签名
String token = "your_interface_key";
String assembleStr = assemble(params);
String sign = md5(md5(assembleStr).toUpperCase() + token).toUpperCase();
params.put("sign", sign);
// 发送请求
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<>();
for (Map.Entry<String, String> entry : params.entrySet()) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
httppost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
} finally {
response.close();
}
}
// 拼接参数
private static String assemble(Map<String, String> params) {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
sb.append(entry.getKey()).append(entry.getValue());
}
return sb.toString();
}
// MD5加密
private static String md5(String str) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes("UTF-8"));
byte[] digest = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : digest) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}7. 支持的API模块列表
系统支持以下API模块:
| 模块名 | 描述 | 主要方法 |
|---|---|---|
| aftersales | 售后单 | getList |
| appropriation | 调拨单 | getList, add |
| ar | 应收账款 | 待补充 |
| basicmaterial | 基础物料 | getList, add, edit |
| brand | 品牌 | getList |
| branch | 仓库 | getList |
| warehouse | 仓库管理 | 待补充 |
| delivery | 发货单 | getList |
| finance | 财务 | getList, getJZT, getJDbill, getReportItems |
| inventory | 库存管理 | 待补充 |
| iostock | 出入库明细 | getList |
| invoice | 发票操作 | getList, update, getResultList |
| member | 会员 | add, edit |
| orders | 订单 | getList, getCouponList, getPmtList |
| po | 采购单 | add, getList |
| purchasereturn | 采购退货单 | getList, add, cancel |
| refunds | 退款单 | 待补充 |
| sales | 销售单 | getList, getSalesAmount, getDeliveryList |
| salesmaterial | 销售物料 | getList, add, edit |
| shop | 店铺 | getList, add |
| stock | 库存查询 | getAll, getDetailList, getBarcodeStock, getBnStock |
| stockdump | 转储单 | getList |
| supplier | 供应商 | add, edit |
| transfer | 出入库单 | add, getList, getIsoList |
| warehouse | 仓库转仓单 | getList, add |
| workorder | 加工单 | getList |
8. 注意事项
- 请妥善保管接口密钥(token),避免泄露
- 时间戳必须与服务器时间保持同步,误差不超过3600秒
- 每个请求必须生成唯一的签名,避免重复提交
- 请根据实际业务需求选择合适的API接口和参数
- 对于大数据量查询,请使用分页参数控制返回结果数量
- 如遇签名错误,请仔细检查参数拼写、排序及token是否正确
9. 附录
9.1 数据脱敏说明
部分敏感数据(如客户信息、联系方式等)在API返回时可能会进行脱敏处理。
9.2 调用频率限制
为保证系统稳定性,API调用可能存在频率限制,具体限制规则请联系系统管理员获取。
