unis_crm/docs/OMS接口整理.md

16 KiB
Raw Blame History

OMS 接口整理

整理日期2026-06-10

本文档基于当前后端代码整理,覆盖两类接口:

  • CRM 主动推送/同步项目到 OMS。
  • OMS 或内部系统回写更新 CRM 项目/商机。

相关代码位置:

  • backend/src/main/java/com/unis/crm/controller/OpportunityController.java
  • backend/src/main/java/com/unis/crm/controller/OpportunityIntegrationController.java
  • backend/src/main/java/com/unis/crm/service/OmsClient.java
  • backend/src/main/java/com/unis/crm/service/impl/OpportunityServiceImpl.java
  • backend/src/main/resources/mapper/opportunity/OpportunityMapper.xml

一、CRM 推送项目到 OMS

1. 前端/CRM 触发推送接口

该接口由 CRM 前端调用后端,后端再调用 OMS。

项目 内容
请求方式 POST
CRM 路径 /api/opportunities/{opportunityId}/push-oms
鉴权头 X-User-Id: <当前用户ID>
Content-Type application/json
返回 ApiResponse<Long>,成功时 data 为 CRM 商机 ID

请求体可为空;如需要指定 OMS 售前人员,可传:

{
  "preSalesId": 123,
  "preSalesName": "张三"
}

字段说明:

字段 类型 必填 说明
preSalesId number OMS 售前用户 ID。优先按该字段匹配 OMS 售前人员。
preSalesName string OMS 售前姓名。未传 preSalesId 时按姓名匹配。

成功示例:

{
  "code": "0",
  "msg": "success",
  "data": 10001
}

2. 推送前校验规则

后端会在推送前校验:

校验项 失败提示
商机 ID 不能为空且必须大于 0 商机不存在
当前用户有权操作该商机 无权操作该商机
已签单/归档商机不可推送 已签单商机不允许推送
商机名称不能为空 商机名称不能为空
最终客户不能为空 最终客户不能为空
运作方不能为空 运作方不能为空
预计金额必须大于 0 预计金额不能为空
预计下单时间不能为空 预计下单时间不能为空
项目把握度不能为空且需为字典有效值,兼容 A/B/C 项目把握度不能为空项目把握度无效: xxx
项目阶段不能为空且需为字典有效值 项目阶段不能为空项目阶段无效: xxx
建设类型不能为空 建设类型不能为空
运作方包含渠道时必须关联渠道名称 推送 OMS 前请先关联渠道名称
必须能在 OMS 售前列表中解析售前人员 推送 OMS 前请选择售前人员 / 所选售前人员在OMS中不存在

3. CRM 调用 OMS 售前列表

用于获取 OMS 售前人员列表,也是推送前校验售前人员的依据。

项目 内容
CRM 路径 GET /api/opportunities/oms/pre-sales
CRM 鉴权头 X-User-Id: <当前用户ID>
后端调用 OMS GET {OMS_BASE_URL}{OMS_USER_INFO_PATH}
默认 OMS 路径 /api/v1/user/info
OMS 请求头 {OMS_API_KEY_HEADER}: {OMS_API_KEY},默认头名为 apiKey
OMS 查询参数 userCode=roleName=售前

CRM 返回示例:

{
  "code": "0",
  "msg": "success",
  "data": [
    {
      "userId": 123,
      "loginName": "zhangsan",
      "userName": "张三"
    }
  ]
}

4. CRM 确保当前用户存在于 OMS

推送项目时CRM 会把当前登录用户作为 OMS 创建人来源:

  1. 先调用 GET {OMS_BASE_URL}{OMS_USER_INFO_PATH} 查询用户:
userCode=<CRM当前用户username>
roleName=
  1. 如果 OMS 中不存在该用户,则调用 POST {OMS_BASE_URL}{OMS_USER_ADD_PATH} 新增用户。

默认新增用户路径:/api/v1/user/add

新增用户请求体:

{
  "userName": "CRM用户显示名",
  "loginName": "CRM用户名"
}

5. CRM 调用 OMS 新增/更新项目

后端统一调用 OMS 的项目新增路径;当请求体中带 projectCode 时,该调用被当前代码视为更新已有 OMS 项目。

项目 内容
后端调用 OMS POST {OMS_BASE_URL}{OMS_PROJECT_ADD_PATH}
默认 OMS 路径 /api/v1/project/add
OMS 请求头 {OMS_API_KEY_HEADER}: {OMS_API_KEY}
Content-Type application/json
连接超时 OMS_CONNECT_TIMEOUT_SECONDS,默认 5 秒
读取超时 OMS_READ_TIMEOUT_SECONDS,默认 15 秒

请求体字段映射:

OMS 字段 来源 说明
projectCode crm_opportunity.opportunity_code 有值时传入,用于更新已有 OMS 项目;无值时不传。
projectName opportunity_name 项目/商机名称。
operateInstitution operator_name 运作方。
h3cPerson crm_sales_expansion.candidate_name 新华三负责人姓名。
h3cPhone crm_sales_expansion.mobile 新华三负责人手机号。
estimatedAmount amount 预计金额,转为字符串并去掉多余 0。
estimatedOrderTime expected_close_date 预计下单时间,格式 YYYY-MM-DD
projectGraspDegree confidence_pct 项目把握度,统一映射为 ABC
projectStage stage CRM 项目阶段码值。
competitorList competitor_name 竞品名称按 ,、;;换行 拆分为数组。
hzSupportUser pre_sales_id 售前 ID转字符串。
createBy 当前 CRM 用户在 OMS 的 userId 创建人。
constructionType opportunity_type 建设类型。
partner 渠道拓展信息 渠道伙伴对象。

partner 对象字段:

OMS 字段 来源 说明
partnerCode 固定 null 当前代码不传渠道编码。
partnerName crm_channel_expansion.channel_name 渠道名称。
province 渠道省份,优先匹配 cnarea.name 省份。
city 渠道城市,优先匹配 cnarea.name 城市。
address crm_channel_expansion.office_address 办公地址。
contactPerson 首要渠道联系人或渠道主联系人 联系人。
contactPhone 首要渠道联系人手机号或渠道主联系人手机号 联系电话。
level crm_channel_expansion.certification_level 认证级别。

请求示例:

{
  "projectCode": "V001234",
  "projectName": "某云桌面项目",
  "operateInstitution": "新华三+渠道",
  "h3cPerson": "李四",
  "h3cPhone": "13800000000",
  "estimatedAmount": "2800000",
  "estimatedOrderTime": "2026-06-30",
  "projectGraspDegree": "A",
  "projectStage": "business_negotiation",
  "competitorList": ["竞品A", "竞品B"],
  "hzSupportUser": "123",
  "createBy": "456",
  "constructionType": "新建",
  "partner": {
    "partnerCode": null,
    "partnerName": "某渠道公司",
    "province": "浙江省",
    "city": "杭州市",
    "address": "杭州市某地址",
    "contactPerson": "王五",
    "contactPhone": "13900000000",
    "level": "金牌"
  }
}

6. OMS 返回约定

后端期望 OMS 返回 JSON。HTTP 非 2xx、非 JSON、业务 code 非成功都会被视为失败。

成功 code 兼容:

0, 200, success, SUCCESS

code 为空也按成功处理。

项目编号提取规则:

  1. 如果 data 是字符串/数字,直接作为项目编号。
  2. 如果 data 是对象或数组,优先查找以下字段:
    • project_code
    • projectCode
    • projectNo
    • omsProjectCode
    • code
    • projectId
    • id
  3. 如果仍未找到,会递归查找字段名包含 codeno 或以 id 结尾的标量字段。

若 OMS 返回成功但无法提取项目编号,后端抛出:

OMS返回成功但未返回项目编号

成功返回示例:

{
  "code": "0",
  "msg": "success",
  "data": {
    "projectCode": "V001234"
  }
}

7. 推送成功后 CRM 本地更新

手动推送成功后CRM 会更新 crm_opportunity

字段
pushed_to_oms true
oms_push_time now()
opportunity_code OMS 返回的项目编号,或已有非 OPP- 编号
updated_at now()

项目编号处理规则:

  • 如果 CRM 已有 opportunity_code 且不是 OPP- 开头,保留已有编号。
  • 否则使用 OMS 返回的项目编号。

二、CRM 新增/编辑商机时自动同步 OMS

除手动推送外,当前服务层还在新增/编辑商机时调用 OMS。

1. 新增商机

项目 内容
CRM 接口 POST /api/opportunities
同步方式 新增本地商机后,严格调用 OMS 项目新增接口
是否传 projectCode 不传
成功后 将 OMS 返回项目编号写入 crm_opportunity.opportunity_code
失败影响 抛出异常,新增流程失败
是否标记 pushed_to_oms

2. 编辑商机

项目 内容
CRM 接口 PUT /api/opportunities/{opportunityId}
同步方式 本地更新成功后,尽力调用 OMS 项目接口
是否传 projectCode opportunity_code 时传入
成功后 如返回编号与本地需更新编号不同,则更新 opportunity_code
失败影响 仅记录 warn 日志,不阻断编辑流程
是否标记 pushed_to_oms

三、OMS 或内部系统更新 CRM 项目/商机

该接口用于外部系统按 opportunityCode 回写 CRM 商机信息。

1. 接口信息

项目 内容
请求方式 PUT
CRM 路径 /api/opportunities/integration/update
Content-Type application/json
鉴权头 X-Internal-Secret: <内部接口密钥>
返回 ApiResponse<Long>,成功时 data 为 CRM 商机 ID

该路径已加入安全白名单,但仍由接口自身校验内部密钥。

2. 请求参数

必填字段:

字段 类型 说明
opportunityCode string 商机编号/OMS 项目编号,用于定位 CRM 商机。最大 50 字符。

其他字段均为可选;未传字段不修改。为兼容历史数据,当前接口不再要求除 opportunityCode 外必须存在更新字段。

可更新字段:

字段 类型 说明
opportunityName string 商机名称,最大 200 字符。
projectLocation string 项目地,最大 100 字符。
operatorName string 运作方,最大 100 字符。
amount number 预计金额;历史数据回写不再限制必须大于 0。
actualSignedAmount number 实际签约金额;兼容字段名 actual_signed_amount
expectedCloseDate string 预计结单日期,格式 YYYY-MM-DD
confidencePct string 项目把握度,支持 ABC,兼容 406080
stage string 项目阶段,支持 CRM 字典值,也兼容部分中文阶段名。
opportunityType string 建设类型,最大 50 字符。
productType string 产品类型,最大 100 字符;空字符串会存为 null
source string 商机来源,最大 50 字符;空字符串会存为 null
salesExpansionId number 销售拓展 ID历史数据回写不再限制必须大于 0。
channelExpansionId number 渠道拓展 ID历史数据回写不再限制必须大于 0。
preSalesId number 售前 ID历史数据回写不再限制必须大于 0。
preSalesName string 售前姓名,最大 100 字符;空字符串会存为 null
competitorName string 竞品名称,最大 200 字符;空字符串会存为 null
archived boolean 是否归档。
archivedAt string 归档时间ISO 8601 格式。传该字段且未传 archived 时会自动视为归档。
pushedToOms boolean 是否已推送 OMS。传 true 且未传 omsPushTime 时自动填当前时间。
omsPushTime string 推送 OMS 时间ISO 8601 格式。
isPoc boolean 是否 POC 测试项目;兼容字段名 is_poc
status string 商机状态,支持 activeclosedwonlost,但 won/lost 需配合对应阶段。
description string 备注;空字符串会存为 null

3. 阶段与状态规则

阶段兼容值:

传入值 归一化结果
初步沟通 / initial_contact initial_contact
方案交流 / solution_discussion solution_discussion
招投标 / bidding bidding
商务谈判 / business_negotiation business_negotiation
已成交 / won won
已放弃 / lost lost

状态联动规则:

条件 结果
stage = won 且未传 status 自动设置 status = won
stage = wonstatus != won 报错:项目阶段为已成交时状态必须为won
stage = lost 且未传 status 自动设置 status = lost
stage = loststatus != lost 报错:项目阶段为已放弃时状态必须为lost
传入非终态 stage 且未传 status 自动设置 status = active
仅传 status = won/lost,未传对应 stage 报错:更新状态为won或lost时请同步传入对应的项目阶段

4. 请求示例

{
  "opportunityCode": "V001234",
  "stage": "won",
  "status": "won",
  "confidencePct": "A",
  "amount": 2800000,
  "expectedCloseDate": "2026-06-30",
  "pushedToOms": true,
  "description": "OMS回写成交结果"
}

成功返回:

{
  "code": "0",
  "msg": "success",
  "data": 10001
}

失败返回:

{
  "code": "-1",
  "msg": "商机不存在",
  "data": null
}

curl 示例:

curl -X PUT 'http://localhost:8080/api/opportunities/integration/update' \
  -H 'Content-Type: application/json' \
  -H 'X-Internal-Secret: <内部接口密钥>' \
  -d '{
    "opportunityCode": "V001234",
    "stage": "won",
    "status": "won",
    "confidencePct": "A",
    "amount": 2800000,
    "expectedCloseDate": "2026-06-30",
    "pushedToOms": true,
    "description": "OMS回写成交结果"
  }'

5. 常见错误

错误信息 原因
内部接口鉴权失败 未传内部密钥、密钥错误,或服务端未配置有效密钥。
opportunityCode 不能为空 未传商机编号。
商机不存在 CRM 中找不到对应 opportunity_code
项目把握度无效: xxx 把握度无法匹配 CRM 字典或兼容值。
项目阶段无效: xxx 阶段无法匹配 CRM 字典或兼容值。

四、配置项

OMS 配置前缀:unisbase.app.oms

配置项 环境变量 默认值/说明
enabled OMS_ENABLED 默认 true。关闭后调用 OMS 会报 OMS推送未启用
base-url OMS_BASE_URL OMS 基础地址。
api-key OMS_API_KEY OMS 接口密钥。
api-key-header OMS_API_KEY_HEADER 默认 apiKey
user-info-path OMS_USER_INFO_PATH 默认 /api/v1/user/info
user-add-path OMS_USER_ADD_PATH 默认 /api/v1/user/add
project-add-path OMS_PROJECT_ADD_PATH 默认 /api/v1/project/add
pre-sales-role-name OMS_PRE_SALES_ROLE_NAME 默认 售前
connect-timeout-seconds OMS_CONNECT_TIMEOUT_SECONDS 默认 5 秒。
read-timeout-seconds OMS_READ_TIMEOUT_SECONDS 默认 15 秒。

内部回写鉴权配置前缀:unisbase.internal-auth

配置项 说明
enabled 默认 true。关闭后不校验内部密钥。
secret 内部接口密钥。
header-name 默认 X-Internal-Secret

五、接口方向速查

方向 场景 接口
CRM 前端 -> CRM 后端 获取 OMS 售前列表 GET /api/opportunities/oms/pre-sales
CRM 前端 -> CRM 后端 手动推送商机到 OMS POST /api/opportunities/{opportunityId}/push-oms
CRM 后端 -> OMS 查询 OMS 用户/售前 GET {OMS_BASE_URL}/api/v1/user/info
CRM 后端 -> OMS 创建 OMS 用户 POST {OMS_BASE_URL}/api/v1/user/add
CRM 后端 -> OMS 新增或更新 OMS 项目 POST {OMS_BASE_URL}/api/v1/project/add
OMS/内部系统 -> CRM 后端 按项目编号回写更新 CRM 商机 PUT /api/opportunities/integration/update