18 KiB
18 KiB
SRM 与 STP 数据交换接口方案说明书
| 文档名称 | SRM 与 STP 数据交换接口方案说明书 |
|---|---|
| 文档版本 | V1.0 |
| 编制日期 | 2026-06-26 |
| 编制人 | 叶伟文 |
1. 项目背景与目标
1.1 背景
当前,供应商关系管理系统与智慧招标平台各自独立运行,存在数据孤岛。供应商需在两套系统中分别维护信息、管理账号,在跨平台操作时需重复登录,严重影响用户体验与业务协同效率。
1.2 目标
- 数据互通:实现供应商主数据、采购计划、中标资料在两个系统间的实时或准实时同步。
- 业务协同:打通从供应商准入、招标到合同签订的全流程,实现业务流程无缝衔接。
- 体验优化:构建统一登录认证体系,实现"一次登录,两平台通行"的无感跳转体验。
2. 总体架构设计
2.1 系统交互架构图
<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
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
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的账号密码登录
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的账号密码登录(流程对称)
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 无感跳转流程:
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
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 |
系统内部错误 | 数据库连接超时 |