414 lines
18 KiB
Markdown
414 lines
18 KiB
Markdown
# SRM 与 STP 数据交换接口方案说明书
|
||
|
||
| 文档名称 | SRM 与 STP 数据交换接口方案说明书 |
|
||
| :--- | :-------------------- |
|
||
| 文档版本 | V1.0 |
|
||
| 编制日期 | 2026-06-26 |
|
||
| 编制人 | 叶伟文 |
|
||
|
||
|
||
## 1. 项目背景与目标
|
||
|
||
### 1.1 背景
|
||
当前,供应商关系管理系统与智慧招标平台各自独立运行,存在数据孤岛。供应商需在两套系统中分别维护信息、管理账号,在跨平台操作时需重复登录,严重影响用户体验与业务协同效率。
|
||
|
||
### 1.2 目标
|
||
* **数据互通**:实现供应商主数据、采购计划、中标资料在两个系统间的实时或准实时同步。
|
||
* **业务协同**:打通从供应商准入、招标到合同签订的全流程,实现业务流程无缝衔接。
|
||
* **体验优化**:构建统一登录认证体系,实现"一次登录,两平台通行"的无感跳转体验。
|
||
|
||
## 2. 总体架构设计
|
||
|
||
### 2.1 系统交互架构图
|
||
|
||
```svg
|
||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 450" font-family="Microsoft YaHei, sans-serif">
|
||
<defs>
|
||
<marker id="arrowPink" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
|
||
<path d="M0,0 L0,6 L9,3 z" fill="#c2185b"/>
|
||
</marker>
|
||
<marker id="arrowBlue" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
|
||
<path d="M0,0 L0,6 L9,3 z" fill="#1565c0"/>
|
||
</marker>
|
||
<linearGradient id="gradSrm" x1="0" y1="0" x2="1" y2="1">
|
||
<stop offset="0%" stop-color="#1565c0"/>
|
||
<stop offset="100%" stop-color="#1e88e5"/>
|
||
</linearGradient>
|
||
<linearGradient id="gradStp" x1="0" y1="0" x2="1" y2="1">
|
||
<stop offset="0%" stop-color="#c2185b"/>
|
||
<stop offset="100%" stop-color="#e91e63"/>
|
||
</linearGradient>
|
||
<filter id="shadow" x="-5%" y="-5%" width="110%" height="110%">
|
||
<feDropShadow dx="2" dy="3" stdDeviation="3" flood-opacity="0.15"/>
|
||
</filter>
|
||
</defs>
|
||
|
||
<!-- 标题 -->
|
||
<text x="400" y="35" text-anchor="middle" font-size="22" font-weight="bold" fill="#333">SRM 与 STP 系统交互架构</text>
|
||
|
||
<!-- SRM 系统框 -->
|
||
<rect x="60" y="70" width="280" height="320" rx="12" fill="url(#gradSrm)" filter="url(#shadow)"/>
|
||
<text x="200" y="105" text-anchor="middle" font-size="20" font-weight="bold" fill="#fff">供应商管理系统</text>
|
||
|
||
<rect x="80" y="125" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="200" y="151" text-anchor="middle" font-size="14" fill="#fff">供应商库管理</text>
|
||
<rect x="80" y="175" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="200" y="201" text-anchor="middle" font-size="14" fill="#fff">采购计划管理</text>
|
||
<rect x="80" y="225" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="200" y="251" text-anchor="middle" font-size="14" fill="#fff">合同管理</text>
|
||
<rect x="80" y="275" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="200" y="301" text-anchor="middle" font-size="14" fill="#fff">中标资料归档</text>
|
||
<rect x="80" y="325" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="200" y="351" text-anchor="middle" font-size="14" fill="#fff">认证与鉴权中心</text>
|
||
|
||
<!-- STP 系统框 -->
|
||
<rect x="460" y="70" width="280" height="320" rx="12" fill="url(#gradStp)" filter="url(#shadow)"/>
|
||
<text x="600" y="105" text-anchor="middle" font-size="20" font-weight="bold" fill="#fff">智慧招标平台</text>
|
||
|
||
<rect x="480" y="125" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="600" y="151" text-anchor="middle" font-size="14" fill="#fff">供应商准入审核</text>
|
||
<rect x="480" y="175" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="600" y="201" text-anchor="middle" font-size="14" fill="#fff">招标项目管理</text>
|
||
<rect x="480" y="225" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="600" y="251" text-anchor="middle" font-size="14" fill="#fff">AI采购委托书</text>
|
||
<rect x="480" y="275" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="600" y="301" text-anchor="middle" font-size="14" fill="#fff">定标与资料转交</text>
|
||
<rect x="480" y="325" width="240" height="40" rx="6" fill="rgba(255,255,255,0.2)"/>
|
||
<text x="600" y="351" text-anchor="middle" font-size="14" fill="#fff">认证与鉴权中心</text>
|
||
|
||
<!-- 中间接口通道 -->
|
||
<rect x="370" y="195" width="60" height="60" rx="30" fill="#fff" stroke="#666" stroke-width="1.5" filter="url(#shadow)"/>
|
||
<text x="400" y="222" text-anchor="middle" font-size="11" font-weight="bold" fill="#333">API</text>
|
||
<text x="400" y="240" text-anchor="middle" font-size="11" fill="#666">网关</text>
|
||
|
||
<!-- 接口连线:SRM -> STP -->
|
||
<line x1="340" y1="145" x2="460" y2="145" stroke="#c2185b" stroke-width="2" marker-end="url(#arrowPink)"/>
|
||
<text x="400" y="138" text-anchor="middle" font-size="10" fill="#c2185b">供应商库查询</text>
|
||
|
||
<line x2="340" y2="290" x1="460" y1="290" stroke="#c2185b" stroke-width="2" marker-end="url(#arrowPink)"/>
|
||
<text x="400" y="283" text-anchor="middle" font-size="10" fill="#c2185b">中标资料接收</text>
|
||
|
||
<line x1="340" y1="340" x2="460" y2="340" stroke="#c2185b" stroke-width="2" marker-end="url(#arrowPink)"/>
|
||
<line x1="460" y1="340" x2="340" y2="340" stroke="#1565c0" stroke-width="2" marker-end="url(#arrowBlue)"/>
|
||
<text x="400" y="333" text-anchor="middle" font-size="10" fill="#333">登录/票据验证</text>
|
||
|
||
<!-- 接口连线:STP -> SRM -->
|
||
<line x1="460" y1="175" x2="340" y2="175" stroke="#1565c0" stroke-width="2" marker-end="url(#arrowBlue)"/>
|
||
<text x="400" y="168" text-anchor="middle" font-size="10" fill="#1565c0">供应商自动注册</text>
|
||
|
||
<line x1="460" y1="240" x2="340" y2="240" stroke="#1565c0" stroke-width="2" marker-end="url(#arrowBlue)"/>
|
||
<text x="400" y="233" text-anchor="middle" font-size="10" fill="#1565c0">采购计划查询</text>
|
||
|
||
<!-- 技术栈标注 -->
|
||
<rect x="250" y="420" width="300" height="24" rx="12" fill="#f5f5f5"/>
|
||
<text x="400" y="437" text-anchor="middle" font-size="11" fill="#555">协议:HTTPS | 格式:JSON | 认证:私钥签名 + Token</text>
|
||
</svg>
|
||
```
|
||
|
||
## 3. 接口详细设计
|
||
|
||
### 3.1 供应商库信息查询接口
|
||
**提供方:** SRM
|
||
**消费方:** STP
|
||
|
||
**接口清单**
|
||
|
||
| 序号 | 接口名称 | 请求方式 | 接口路径(暂拟) | 说明 |
|
||
| :-- | :------ | :---- | :--------------------------------- | :------------------------------- |
|
||
| 1 | 供应商名称查询 | `GET` | `/api/v1/supplier/query/by-name` | 根据供应商名称返回匹配到的供应商对象列表,没有则返回空列表。 |
|
||
| 2 | 供应商税号查询 | `GET` | `/api/v1/supplier/query/by-tax-id` | 根据供应商税号返回匹配到的供应商对象,没有则返回空对象。 |
|
||
| 3 | 供应商ID查询 | `GET` | `/api/v1/supplier/query/by-id` | 根据SRM系统内部ID返回对应的供应商对象,没有则返回空对象。 |
|
||
| 4 | 供应商标签查询 | `GET` | `/api/v1/supplier/query/by-tags` | 根据给定的标签集合返回匹配到的供应商对象列表,没有则返回空列表。 |
|
||
| 5 | 全量供应商同步 | `GET` | `/api/v1/supplier/sync/full` | 返回所有供应商对象,用于全量数据同步。 |
|
||
| 6 | 增量供应商同步 | `GET` | `/api/v1/supplier/sync/delta` | 返回从指定时间至今发生变更的供应商对象,用于增量同步。 |
|
||
|
||
**通用请求头**
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
| :--- | :--- | :--- | :--- |
|
||
| `Authorization` | `String` | 是 | 认证令牌,格式为 `Bearer <token>` |
|
||
| `Content-Type` | `String` | 是 | `application/json` |
|
||
|
||
**供应商对象结构(举例)**
|
||
|
||
| 字段名 | 类型 | 说明 |
|
||
| :------------- | :-------------- | :---------------------- |
|
||
| `supplierId` | `String` | 系统内ID |
|
||
| `supplierName` | `String` | 供应商名称 |
|
||
| `taxId` | `String` | 税号 |
|
||
| `score` | `Integer` | 综合评分 |
|
||
| `tags` | `Array[String]` | 标签列表 |
|
||
| `status` | `String` | 状态,如"ACTIVE","INACTIVE" |
|
||
| `contactInfo` | `Object` | 联系方式 |
|
||
| `createTime` | `String` | 创建时间 |
|
||
| `updateTime` | `String` | 更新时间 |
|
||
|
||
---
|
||
|
||
### 3.2 供应商自动注册接口
|
||
**提供方:** SRM
|
||
**消费方:** STP
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant STP as STP
|
||
participant SRM as SRM
|
||
|
||
STP->>SRM: POST /api/v1/supplier/register (供应商注册信息)
|
||
SRM-->>SRM: 校验数据完整性与合规性
|
||
alt 注册成功
|
||
SRM-->>SRM: 生成系统内ID
|
||
SRM-->>STP: 200 OK { "code":"0", "supplierId":"SRM_2024001" }
|
||
else 注册失败
|
||
SRM-->>STP: 400 Bad Request { "code":"ERR_001", "message":"税号已存在" }
|
||
end
|
||
```
|
||
|
||
**请求参数(暂定)**
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
| :--------------- | :------- | :-- | :----- |
|
||
| `supplierName` | `String` | 是 | 供应商名称 |
|
||
| `taxId` | `String` | 是 | 税号 |
|
||
| `contactInfo` | `Object` | 是 | 联系方式 |
|
||
| `qualifications` | `Array` | 否 | 资质文件列表 |
|
||
|
||
**返回参数(成功)**
|
||
|
||
| 参数名 | 类型 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| `code` | `String` | 业务状态码,成功为"0" |
|
||
| `supplierId` | `String` | SRM系统内ID |
|
||
|
||
---
|
||
|
||
### 3.3 采购计划查询接口
|
||
**提供方:** SRM
|
||
**消费方:** STP
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant STP as STP (AI模块)
|
||
participant SRM as SRM
|
||
|
||
STP->>SRM: GET /api/v1/purchase-plan/query?account=xxx
|
||
SRM-->>SRM: 查询该采购员关联的采购计划
|
||
alt 存在计划
|
||
SRM-->>STP: 200 OK { "code":"0", "data":[计划对象列表] }
|
||
else 不存在计划
|
||
SRM-->>STP: 200 OK { "code":"0", "data":[] }
|
||
end
|
||
```
|
||
|
||
**请求参数**
|
||
|
||
| 参数名 | 类型 | 必填 | 位置 | 说明 |
|
||
| :--- | :--- | :--- | :--- | :--- |
|
||
| `account` | `String` | 是 | `Query` | 采购人员账号 |
|
||
|
||
**返回数据对象**
|
||
|
||
| 字段名 | 类型 | 说明 |
|
||
| :------------- | :------- | :----- |
|
||
| `planId` | `String` | 计划ID |
|
||
| `planName` | `String` | 计划名称 |
|
||
| `budget` | `Float` | 预算金额 |
|
||
| `requiredDate` | `String` | 需求日期 |
|
||
| `items` | `Array` | 采购物料明细 |
|
||
|
||
---
|
||
|
||
### 3.4 统一登录与无感跳转接口
|
||
本节详细描述如何通过**统一登录**和**无感跳转**实现“一次登录,两平台通行”。
|
||
|
||
#### 3.4.1 统一登录
|
||
统一登录解决供应商在两个平台拥有独立账号、需重复输入密码的问题。任一平台均可作为登录入口,调用对方提供的登录验证接口,验证通过后建立本地会话。
|
||
|
||
**场景1:供应商在SRM端输入STP的账号密码登录**
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 供应商
|
||
participant SRM
|
||
participant STP
|
||
|
||
User->>SRM: 输入STP用户名/密码,点击登录
|
||
SRM->>STP: POST /api/v1/auth/login/for-srm { username, password, returnUrl }
|
||
STP-->>STP: 校验用户合法性
|
||
alt 校验成功
|
||
STP-->>SRM: 200 { code:0, userInfo:{ stpId, srmId, name, taxId, ... } }
|
||
SRM-->>SRM: 建立本地会话,关联SRM ID
|
||
SRM-->>User: 登录成功,返回SRM首页
|
||
else 校验失败
|
||
STP-->>SRM: 401 { code:ERR_AUTH_001, message:"用户名或密码错误" }
|
||
SRM-->>User: 提示错误
|
||
end
|
||
```
|
||
|
||
**场景2:供应商在STP端输入SRM的账号密码登录(流程对称)**
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 供应商
|
||
participant STP
|
||
participant SRM
|
||
|
||
User->>STP: 输入SRM用户名/密码,点击登录
|
||
STP->>SRM: POST /api/v1/auth/login/for-stp { username, password, returnUrl }
|
||
SRM-->>SRM: 校验用户合法性
|
||
alt 校验成功
|
||
SRM-->>STP: 200 { code:0, userInfo:{ srmId, name, taxId, ... } }
|
||
STP-->>STP: 建立本地会话
|
||
STP-->>User: 登录成功,返回STP首页
|
||
else 校验失败
|
||
SRM-->>STP: 401 错误
|
||
STP-->>User: 提示错误
|
||
end
|
||
```
|
||
|
||
**接口定义:STP登录验证接口(供SRM调用)**
|
||
|
||
| 项目 | 内容 |
|
||
| :--- | :--- |
|
||
| **提供方** | STP |
|
||
| **路径** | `/api/v1/auth/login/for-srm` |
|
||
| **方法** | `POST` |
|
||
| **请求体** | `{ "username":"供应商STP账号", "password":"密码" }` |
|
||
| **成功响应** | `{ "code":"0", "userInfo":{ "stpId":"STP内部ID", "srmId":"关联的SRM ID", "name":"公司名", "taxId":"税号" } }` |
|
||
| **失败响应** | `{ "code":"ERR_AUTH_001", "message":"用户名或密码错误" }` |
|
||
|
||
**接口定义:SRM登录验证接口(供STP调用)**
|
||
|
||
| 项目 | 内容 |
|
||
| :--- | :--- |
|
||
| **提供方** | SRM |
|
||
| **路径** | `/api/v1/auth/login/for-stp` |
|
||
| **方法** | `POST` |
|
||
| **请求体** | `{ "username":"供应商SRM账号", "password":"密码" }` |
|
||
| **成功响应** | `{ "code":"0", "userInfo":{ "srmId":"SRM内部ID", "name":"公司名", "taxId":"税号" } }` |
|
||
| **失败响应** | `{ "code":"ERR_AUTH_001", "message":"用户名或密码错误" }` |
|
||
|
||
> **说明:** `returnUrl`参数可选,用于指定验证成功后跳转的目标页面。两个系统在验证通过后,返回的用户信息中必须包含 `srmId`,以便对方建立本地会话并关联供应商身份。
|
||
|
||
#### 3.4.2 无感跳转(已登录状态下的跨系统切换)
|
||
当供应商已在任一方登录,点击指向另一方系统的链接时,通过临时跳转票据实现免密登录。
|
||
|
||
**STP → SRM 无感跳转流程:**
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant User as 供应商
|
||
participant STP
|
||
participant SRM
|
||
|
||
Note over User,SRM: 前提:供应商已登录STP
|
||
User->>STP: 点击“查看SRM合同”链接
|
||
STP->>STP: 生成Ticket (srmId, stpSessionId, timestamp)
|
||
STP->>STP: 使用STP私钥签名
|
||
STP->>User: 302重定向到SRM,URL中携带Ticket
|
||
User->>SRM: 访问SRM,携带Ticket
|
||
SRM->>SRM: 使用STP公钥验签
|
||
SRM->>STP: POST /api/v1/auth/session/validate { stpSessionId, srmId }
|
||
STP-->>SRM: 200 OK { valid: true }
|
||
SRM-->>SRM: 根据srmId建立本地会话
|
||
SRM-->>User: 登录成功,展示SRM页面
|
||
```
|
||
|
||
**SRM → STP 无感跳转流程(对称,略)**
|
||
|
||
**跳转票据(Ticket)结构**
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| `srmId` | `String` | 供应商在SRM中的ID(必填) |
|
||
| `sessionId` | `String` | 来源系统当前登录会话ID |
|
||
| `timestamp` | `Long` | 生成时间戳,有效期建议5分钟 |
|
||
| `nonce` | `String` | 随机数,防重放 |
|
||
| `signature` | `String` | 对上述字段的签名(来源系统私钥) |
|
||
|
||
**会话有效性验证接口**
|
||
|
||
| 项目 | STP会话验证(供SRM调用) | SRM会话验证(供STP调用) |
|
||
| :--- | :--- | :--- |
|
||
| **提供方** | STP | SRM |
|
||
| **路径** | `/api/v1/auth/session/validate` | `/api/v1/auth/session/validate` |
|
||
| **方法** | `POST` | `POST` |
|
||
| **请求体** | `{ "sessionId":"STP会话ID", "srmId":"SRM ID" }` | `{ "sessionId":"SRM会话ID" }` |
|
||
| **成功响应** | `{ "code":"0", "valid": true }` | `{ "code":"0", "valid": true }` |
|
||
| **失败响应** | `{ "code":"0", "valid": false }` | `{ "code":"0", "valid": false }` |
|
||
|
||
---
|
||
|
||
### 3.5 中标资料转交接口
|
||
**提供方:** SRM
|
||
**消费方:** STP
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant STP
|
||
participant SRM
|
||
|
||
Note over STP: 定标完成,整理资料
|
||
STP->>SRM: POST /api/v1/bid-result/transfer (中标资料包)
|
||
SRM-->>SRM: 校验数据完整性
|
||
SRM-->>SRM: 归档中标资料、投标过程数据等
|
||
alt 成功
|
||
SRM-->>STP: 200 OK { "code":"0", "recordId":"ARCH_2024001" }
|
||
else 失败
|
||
SRM-->>STP: 500 / 400 { "code":"ERR_002", "message":"资料不完整" }
|
||
end
|
||
```
|
||
|
||
**请求体结构**
|
||
|
||
| 参数名 | 类型 | 必填 | 说明 |
|
||
| :--- | :--- | :--- | :--- |
|
||
| `projectId` | `String` | 是 | 招标项目ID |
|
||
| `bidResult` | `Object` | 是 | 定标结果 |
|
||
| `bidProcessData` | `Object` | 是 | 投标过程数据 |
|
||
| `supplierBidFiles` | `Array` | 是 | 供应商投标文件URL列表 |
|
||
|
||
---
|
||
|
||
## 4. 接口清单总表
|
||
|
||
| 模块 | 接口名称 | 请求方 | 提供方 | 协议 |
|
||
| :--- | :--- | :--- | :--- | :--- |
|
||
| **供应商信息** | 供应商名称查询 | STP | SRM | REST |
|
||
| | 供应商税号查询 | STP | SRM | REST |
|
||
| | 供应商ID查询 | STP | SRM | REST |
|
||
| | 供应商标签查询 | STP | SRM | REST |
|
||
| | 全量供应商同步 | STP | SRM | REST |
|
||
| | 增量供应商同步 | STP | SRM | REST |
|
||
| **供应商注册** | 供应商自动注册 | STP | SRM | REST |
|
||
| **采购计划** | 采购计划查询 | STP | SRM | REST |
|
||
| **登录认证** | SRM登录验证 | SRM | STP | REST |
|
||
| | STP登录验证 | STP | SRM | REST |
|
||
| | STP会话有效性验证 | SRM | STP | REST |
|
||
| | SRM会话有效性验证 | STP | SRM | REST |
|
||
| | STP→SRM无感跳转 | SRM | STP | REST+签名 |
|
||
| | SRM→STP无感跳转 | STP | SRM | REST+签名 |
|
||
| **中标转交** | 中标资料接收 | STP | SRM | REST |
|
||
|
||
## 5. 安全设计
|
||
|
||
| 维度 | 策略 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| **传输安全** | HTTPS/TLS 1.2+ | 所有接口通信必须使用HTTPS加密传输。 |
|
||
| **身份认证** | Token / 证书 | 系统间API调用采用Token认证;无感跳转采用RSA私钥签名验证。 |
|
||
| **防重放** | 时间戳 + 随机数 | 跳转票据和关键请求携带时间戳和随机数,有效期建议5分钟。 |
|
||
| **数据脱敏** | 日志脱敏 | 税号、联系方式等敏感信息在日志中必须脱敏处理。 |
|
||
| **访问控制** | 最小权限原则 | 接口调用方仅能访问其业务所必需的数据。 |
|
||
|
||
## 6. 错误码规范
|
||
|
||
| 错误码 | 说明 | 示例 |
|
||
| :--- | :--- | :--- |
|
||
| `0` | 成功 | — |
|
||
| `ERR_AUTH_001` | 认证失败 | Token无效或已过期 |
|
||
| `ERR_AUTH_002` | 签名验证失败 | 跳转票据签名不匹配 |
|
||
| `ERR_PARAM_001` | 参数缺失/格式错误 | 必填字段为空 |
|
||
| `ERR_BIZ_001` | 供应商已存在 | 注册时税号重复 |
|
||
| `ERR_BIZ_002` | 供应商不存在 | ID查询无结果 |
|
||
| `ERR_SYS_001` | 系统内部错误 | 数据库连接超时 |
|