应用集成平台-系统之间的桥梁-思路分享

一、集成平台是什么?(小白秒懂版)

1.1 简介

想象一下:医院里有挂号处诊室药房三个地方。

  • 传统方式:你要先去挂号处拿号 → 自己找诊室 → 自己找药房(容易迷路)

  • 集成平台方式:你只告诉前台(集成平台)需求 → 前台带你去每个地方(安全又省心)

  • "应用集成平台充当认证中心和授权中心,协助系统间安全传递业务参数。"
  • 应用集成平台只做"桥梁",不替代各系统自己的功能!

一句话总结集成平台 = 系统间的"前台服务员",帮你安全地从A系统走到B系统!

1.2 安全机制

  • Token认证 :所有接口调用都需要有效的Token

  • SM4加密 :数据传输使用SM4加密保护

  • 防重复请求 :使用Redisson分布式锁防止重复请求

  • 黑名单验证 :系统/IP级别的黑名单验证

  • 参数验证 :严格的参数格式和有效性验证

1.3 技术实现关键点

  • Redis缓存 :Token(5小时)、Ticket(300秒)、会话ID等缓存

  • Kafka消息 :使用主题 IAP_TOPIC_${servCode} 进行消息广播

  • 分布式锁 :Redisson锁防止重复请求

  • 事务管理 :@Transactional注解确保数据一致性

  • 异常处理 :统一的异常处理机制


二、集成平台能做什么?(三大场景)

场景 适用情况 例子 需要哪些接口
1. 页面重定向 需要浏览器跳转到另一个系统页面 从挂号系统跳转到互联网医院问诊页 申请Token + 申请授权码(A系统地址重定向) + 认证授权(B系统校验授权码)
2. HTTP API调用 需要后台获取数据(用户无感) 互联网医院调用挂号系统的科室列表 申请Token + 服务调用
3. 消息广播 需要通知多个系统同一件事 挂号系统发布"新号源",通知所有相关系统 申请Token + 发布消息 + 确认消息

记住这个判断法

  • 页面跳转 ? → 用场景1

  • 需要后台取数据 ? → 用场景2

  • 群发通知 ? → 用场景3 绝不混用!

2.1 核心组件

  • IapRuntimeController.java :核心运行时控制器,处理所有接口请求

  • 服务层 :实现业务逻辑(订阅验证、token管理等)

  • 数据访问层 :使用MyBatis-Plus操作数据库

  • 缓存层 :Redis用于token、ticket等缓存

  • 消息队列 :Kafka用于消息广播

2.2 主要接口

接口地址 功能描述 请求方法
/interface/v1/token 申请访问令牌 POST
/interface/v1/preauth 页面重定向预授权(申请授权码) POST
/interface/v1/authentication 页面重定向认证(认证授权) POST
/runtime/v1/** 服务调用 POST
/interface/v1/publish/message 消息广播发布 POST

三、前期准备:必须知道的基础知识

3.1 系统编码表--- 每个系统都有"身份证号"

系统名称 编码 你的身份
挂号平台 100 如果你是挂号系统,记下100
互联网医院 101 如果你是互联网医院,记下101
百度灵医 901 常见能力系统
支付宝 902 常见能力系统
集成平台 999 所有请求都要知道它
护理平台 102 其他业务系统

📌 重要:每次调用接口,请求头必须携带你的系统编码!

3.2 通信规则

  • 所有数据都加密:使用SM4加密算法(像给信件加密码锁)

  • 请求格式:

    javascript 复制代码
    {
      "param": "加密后的业务数据"
    }
  • 响应格式:

    javascript 复制代码
    {
      "code": "200",
      "message": "成功",
      "data": "加密后的返回数据"
    }

3.3安全要求

每个请求必须做到

  1. 在请求头写入systemCode(你的系统编码)

  2. 生成24位唯一messageId(不能重复!)

  3. 在加密的param中再次写入相同的messageId

  4. 除Token接口外,其他接口必须携带token参数


四、三大场景详细操作指南(带示例)

场景1:页面重定向(从A系统跳到B系统)

**典型业务:**挂号系统(100) → 跳转到 互联网医院(101)

必须接口:`/iap/interface/token` + `/iap/interface/v1/preauth` + `/iap/interface/v1/authentication`

javascript 复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   系统B     │     │   IAP平台   │     │   系统A     │
└─────┬───────┘     └─────┬───────┘     └─────┬───────┘
      │                    │                    │
      │ 1. 申请Token        │                    │
      │───────────────────>│                    │
      │                    │                    │
      │ 2. 返回Token        │                    │
      │<───────────────────│                    │
      │                    │                    │
      │ 3. 预授权请求       │                    │
      │───────────────────>│                    │
      │                    │ 4. 验证Token        │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 5. 生成Ticket和Session│
      │                    │───────────────────>│
      │                    │                    │
      │ 6. 返回重定向URL     │                    │
      │<───────────────────│                    │
      │                    │                    │
      │ 7. 重定向到系统A     │                    │
      │────────────────────────────────────────>│
      │                    │                    │
      │                    │ 8. 验证Ticket      │
      │                    │<───────────────────│
      │                    │                    │
      │                    │ 9. 返回Session参数   │
      │                    │───────────────────>│
┌─────┴───────┐     ┌─────┴───────┐     ┌─────┴───────┐
│   系统B     │     │   IAP平台   │     │   系统A     │
└─────────────┘     └─────────────┘     └─────────────┘
复制代码
1. 申请Token :系统B调用 /interface/v1/token 接口获取Token 

2. 预授权 :系统B调用 /interface/v1/preauth 接口,提供servCode等参数 

3. 生成Ticket :IAP生成16位ticket,有效期300秒,存储在Redis中 

4. 保存Session :IAP保存会话信息到 iap_session 表,参数到 iap_session_serv_param 表 

5. 返回重定向URL :IAP返回包含sessionId、ticket和redirectUri的响应 

6. 重定向 :系统B重定向到系统A的页面 

7. 验证Ticket :系统A调用IAP的 /interface/v1/authentication 接口验证ticket 

8. 返回Session参数 :IAP返回会话参数给系统A
步骤1:A系统(挂号系统)获取Token
  • 接口POST /iap/interface/token

  • 请求头:

    javascript 复制代码
    systemCode: 100
    messageId: 1719225600100099903011234(24位唯一ID)
  • 请求体(加密后):

    javascript 复制代码
    {
      "clientId": "system_100",
      "clientSecret": "你的密钥"
    }
  • 返回(解密后):

    javascript 复制代码
    {
      "token": "Token_100_abc123",
      "sessionId": "session_123"
    }
步骤2:A系统申请跳转凭证(关键步骤!)
  • 接口POST /iap/interface/v1/preauth

  • 请求头:

    javascript 复制代码
    systemCode: 100
    messageId: 1719225600100099903025678(新ID)
    token: Token_100_abc123(上一步获得)
  • 请求体(加密后):

    javascript 复制代码
    {
      "messageId": "1719225600100099903025678",
      "servCode": "online_hospital",
      "param": {
        "user": {
          "systemUserId": "123",
          "systemUserName": "张三"
        }
      }
    }
  • 返回(解密后):

    javascript 复制代码
    {
      "redirectUrl": "http://hospital.com/chat",
      "ticket": "ticket_xyz789",
      "timestamp": "1719225600",
      "sessionId": "preauth_456"
    }
步骤3:A系统跳转到B系统
  • 操作:浏览器重定向到

    css 复制代码
    http://hospital.com/chat?ticket=ticket_xyz789&timestamp=1719225600&presessionid=preauth_456
步骤4:B系统(互联网医院)验证跳转
  • 接口POST /iap/interface/v1/authentication

  • 请求头:

    javascript 复制代码
    systemCode: 101
    messageId: 1719225600101099903039012(新ID)
    token: Token_101_def456(B系统自己的Token)
  • 请求体:请求集成平台验证ticket是否有效

    javascript 复制代码
    {
      "ticket": "ticket_xyz789",
      "timestamp": "1719225600"
    }
  • 返回:用户信息等业务参数

场景1完整流程: A系统拿Token → A系统申请跳转凭证 → 浏览器跳转 → B系统验证凭证 → 进入业务页面


场景2:HTTP API调用(后台获取数据)

典型业务:互联网医院(101)调用挂号系统(100)的科室列表

必须接口/iap/interface/token + /iap/runtime/v1/{uri}

javascript 复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   系统B     │     │   IAP平台   │     │   系统A     │
└─────┬───────┘     └─────┬───────┘     └─────┬───────┘
      │                    │                    │
      │ 1. 申请Token        │                    │
      │───────────────────>│                    │
      │                    │                    │
      │ 2. 返回Token        │                    │
      │<───────────────────│                    │
      │                    │                    │
      │ 3. 调用服务(带Token)│                    │
      │───────────────────>│                    │
      │                    │ 4. 验证Token        │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 5. 验证订阅关系      │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 6. 转发请求         │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 7. 返回响应         │
      │                    │<───────────────────│
      │                    │                    │
      │ 8. 返回加密响应      │                    │
      │<───────────────────│                    │
┌─────┴───────┐     ┌─────┴───────┐     ┌─────┴───────┐
│   系统B     │     │   IAP平台   │     │   系统A     │
└─────────────┘     └─────────────┘     └─────────────┘

服务发布(系统A)

  1. 在 iap_serv 表配置服务(状态=ENABLE)

  2. 在 iap_serv_http_api 表配置API信息(请求URI、方法等)

  3. 服务订阅(系统B订阅系统A对应的服务)

  4. 调用 IapServSubscribeController.create() 接口

  5. 保存订阅关系到 iap_serv_subscribe 表


描述:

  1. 申请Token :系统B调用 /interface/v1/token 接口,获取有效期为5小时的Token

  2. 调用服务 :系统B使用Token和加密参数调用 /runtime/v1/** 接口

  3. 验证Token :IAP验证Token的有效性和系统匹配性

  4. 验证订阅关系 :IAP检查系统B是否已订阅该服务

  5. 转发请求 :IAP将请求转发给系统A

  6. 返回响应 :系统A返回响应,IAP加密后返回给系统B

步骤1:B系统(互联网医院)获取Token
  • 接口POST /iap/interface/token

  • 请求头:

    javascript 复制代码
    systemCode: 101
    messageId: 1719225600101099903043456(24位ID)
  • 请求体(加密后):

    javascript 复制代码
    {
      "clientId": "system_101",
      "clientSecret": "你的密钥"
    }
  • 返回:

    javascript 复制代码
    {
      "token": "Token_101_def456",
      "sessionId": "session_789"
    }
步骤2:B系统调用服务
  • 接口POST /iap/runtime/v1/departments

    请求头:

    javascript 复制代码
    systemCode: 101
    messageId: 1719225600101099903057890(新ID)
    token: Token_101_def456(上一步获得)

    请求体(加密后):

    javascript 复制代码
    {
      "messageId": "1719225600101099903057890",
      "serviceCode": "get_departments",
      "param": {
        "hospitalId": "123456"
      }
    }
  • 返回(解密后):

    javascript 复制代码
    {
      "departments": [
        {"id": "1", "name": "内科"},
        {"id": "2", "name": "外科"}
      ]
    }

场景2完整流程: B系统拿Token → B系统直接调用服务 → 获取数据

注意 :此场景不调用 /iap/interface/v1/preauth(申请授权码)和/iap/interface/v1/authentication(认证授权)


场景3:消息广播(群发通知)

典型业务:挂号系统(100)发布"新号源",通知所有订阅系统

必须接口/iap/interface/token + /iap/interface/v1/publish/message + /iap/interface/v1/commit/message

javascript 复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   系统A     │     │   IAP平台   │     │   Kafka     │
└─────┬───────┘     └─────┬───────┘     └─────┬───────┘
      │                    │                    │
      │ 1. 申请Token        │                    │
      │───────────────────>│                    │
      │                    │                    │
      │ 2. 返回Token        │                    │
      │<───────────────────│                    │
      │                    │                    │
      │ 3. 发布消息请求      │                    │
      │───────────────────>│                    │
      │                    │ 4. 验证Token        │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 5. 验证发布权限      │
      │                    │───────────────────>│
      │                    │                    │
      │                    │ 6. 发布Kafka消息    │
      │                    │───────────────────>│
      │                    │                    │
      │ 7. 返回发布结果      │                    │
      │<───────────────────│                    │
┌─────┴───────┐     ┌─────┴───────┐     ┌─────┴───────┐
│   系统A     │     │   IAP平台   │     │   Kafka     │
└─────────────┘     └─────────────┘     └─────────────┘

描述:

  1. 申请Token :系统A调用 /interface/v1/token 接口获取Token

  2. 发布消息 :系统A调用 /interface/v1/publish/message 接口,提供topicName和消息内容

  3. 验证Token :IAP验证Token的有效性

  4. 验证发布权限 :IAP检查系统A是否有权发布该服务的消息

  5. 发布Kafka消息 :IAP将消息发布到 IAP_TOPIC_${servCode} 主题

  6. 返回结果 :IAP返回发布结果给系统A

步骤1:发布方(挂号系统)获取Token
  • 接口POST /iap/interface/token

  • 请求头:

    javascript 复制代码
    systemCode: 100
    messageId: 1719225600100099903061234
步骤2:发布方发布消息
  • 接口POST /iap/interface/v1/publish/message

  • 请求头:

    javascript 复制代码
    systemCode: 100
    messageId: 1719225600100099903075678
    token: Token_100_abc123
  • 请求体(加密后):

    javascript 复制代码
    {
      "topicName": "new_appointment",
      "param": {
        "department": "内科",
        "date": "2023-07-25"
      }
    }
步骤3:订阅方处理消息
  • 操作:订阅方(如互联网医院)从Kafka消费消息

    "各订阅方,凭管理员提供的TOPIC和GROUP,订阅和消费消息。"

步骤4:订阅方确认消息
  • 接口POST /iap/interface/v1/commit/message

  • 请求头:

    javascript 复制代码
    systemCode: 101
    messageId: 1719225600101099903089012
    token: Token_101_def456
    presessionid: session_from_kafka
  • 请求体(加密后):

    javascript 复制代码
    {
      "publishMsgId": "消息ID_abc123",
      "ack": "1"  // 1=成功,0=失败
    }

场景3完整流程: 发布方拿Token → 发布方发布消息 → 订阅方消费消息 → 订阅方确认消息

注意 :此场景不调用 /iap/interface/v1/preauth(申请授权码)和/iap/interface/v1/authentication(认证授权)


五、常见错误与解决方案

错误码 错误信息 原因 解决方案
1000 请勿重新调用 messageId重复 每次请求生成24位ID
1001 参数缺失 缺少必填参数 检查文档要求的参数是否都传了
1003 票根无效 用了错误的ticket 重新调用/iap/interface/v1/preauth获取新ticket
1004 票根重复消费 同一个ticket用了两次 每次跳转必须用ticket
1004 票根过期 ticket超过100秒 生成后100秒内必须使用
1005 令牌无效 Token过期或错误 重新调用/iap/interface/token
1006 服务未授权 没订阅这个服务 先在管理平台订阅服务
1009 服务不存在 服务未上架 联系管理员上架服务

🚨 最高频错误

  • messageId重复 (1000):集成平台不做幂等,必须每次生成新ID!

  • Token过期(1005):Token有效期通常30分钟,过期必须重申请!

  • 票根过期 (1004):ticket100秒内必须用,否则重申请!


六、重要安全提醒(必须遵守!)

1. Token使用规则

  • Token是临时凭证,每次调用服务前都要验证是否有效

  • 绝对不能把Token写死在代码里,每次用前检查有效期

  • Token泄露 = 身份被盗用,必须严格保密

2. 数据加密要求

  • 所有业务参数必须SM4加密,不能传明文

  • 加密示例(Java):

    javascript 复制代码
    SM4 sm4 = SmUtil.sm4(HexUtil.decodeHex(secretKey));
    String encrypted = sm4.encryptHex(plaintext);

3. 请求唯一性

  • messageId生成规则

    • 0-12位: 13位时间戳

    • 13-16位: 四位系统编码(不足左补0,如0100)

    • 17-20位: 接口目录编码(如0301)

    • 21-24位: 4位随机数

    • 示例1719225600100010003019876

4. 场景区分

  • 页面跳转 → 用3.1+3.2接口

  • 后台取数据 → 用3.4接口

  • 群发通知 → 用3.5+3.7接口


七、快速自查清单(调用前必看)

通用检查

  • 请求头写了正确的systemCode(100/101/901...)

  • 生成了24位唯一messageId

  • 在加密的param中重复写入 相同的messageId

  • 除Token接口外,其他接口都带了token参数

场景1(页面跳转)检查

  • A系统已调/iap/interface/token

  • A系统已调/iap/interface/v1/preauth(带token!)

  • 重定向URL包含ticket+timestamp+presessionid

  • B系统已调/iap/interface/v1/authentication验证

场景2(API调用)检查

  • B系统已调/iap/interface/token

  • 调用的是/iap/runtime/v1/{uri}不是3.1/3.2接口

  • 请求体包含serviceCode和业务参数

场景3(消息广播)检查

  • 发布方已调/iap/interface/token

  • 调用/iap/interface/v1/publish/message时指定了topicName

  • 订阅方从Kafka消费后,已调/iap/interface/v1/commit/message确认

八、总结

  • IAP集成平台通过统一的入口、严格的安全认证和高效的消息传递机制,实现了不同系统之间的安全、高效通信。

  • 系统间的所有交互都通过IAP进行转发和验证,大大降低了系统间直接连接的复杂度和安全风险。

  • 最后提醒:集成平台是工具,核心业务逻辑仍在各系统自身。


附录:关键接口速查表

场景 接口URL 用途 必填参数
通用 /iap/interface/token 申请Token clientId, clientSecret
页面跳转 /iap/interface/v1/preauth 申请跳转凭证 token, servCode
页面跳转 /iap/interface/v1/authentication 验证跳转 token, ticket, timestamp
API调用 /iap/runtime/v1/{uri} 调用服务 token, serviceCode
消息广播 /iap/interface/v1/publish/message 发布消息 token, topicName
消息广播 /iap/interface/v1/commit/message 确认消息 token, publishMsgId, ack
相关推荐
TsengOnce2 小时前
阿里云ECS多版本JDK切换
java·python·阿里云
wearegogog1232 小时前
基于C#的FTP客户端实现方案
java·网络·c#
听风吟丶2 小时前
Java NIO 深度解析:从核心组件到高并发实战
java·开发语言·jvm
野生技术架构师3 小时前
Java面试题及答案总结(互联网大厂新版)
java·面试·状态模式
a努力。3 小时前
小红书Java面试被问:ThreadLocal 内存泄漏问题及解决方案
java·jvm·后端·算法·面试·架构
此生只爱蛋3 小时前
【Redis】String 字符串
java·数据库·redis
C++业余爱好者3 小时前
Java开发中Entity、VO、DTO、Form对象详解
java·开发语言
超级大只老咪3 小时前
“和”与“或”逻辑判断与条件取反(Java)
java·算法
青云交3 小时前
Java 大视界 -- 基于 Java+Flink 构建实时电商交易风控系统实战(436)
java·redis·flink·规则引擎·drools·实时风控·电商交易