<!-- Space: qifu -->
<!-- Parent: 后端技术&知识&规范 -->
<!-- Parent: 技术方案 -->
<!-- Parent: 企赋网关（外部能力对接） -->
<!-- Parent: 企赋网关技术方案 -->
<!-- Title: 20241105-外部能力接入服务技术方案 -->

<!-- Macro: :anchor\((.*)\):
     Template: ac:anchor
     Anchor: ${1} -->
<!-- Macro: \!\[.*\]\((.+)\)\<\!\-\- width=(.*) \-\-\>
     Template: ac:image
     Url: ${1}
     Width: ${2} -->
<!-- Macro: \<\!\-\- :toc: \-\-\>
     Template: ac:toc
     Printable: 'false'
     MinLevel: 2 
     MaxLevel: 4 -->
<!-- Include: 杂项/声明文件.md -->

<!-- :toc: -->

# 外部能力接入技术方案
## 一、现状
### 业务背景
为了统一南北流量，规划开放平台和企赋网关。
其中企赋网关负责外部能力的统一接入。
本方案就是争对企赋网关做的设计

## 二、需求
### 业务需求
现在需要对接外部的物流能力（具体对接什么服务商需要根据 小冰 的调研结果来接入）。
当前只是企赋网关的一个技术架构

## 三、设计目标
### 实现的功能
- 外部能力的接入
  - 主动请求接口接入
  - 外部信息回调接收
  - 签名验签
- 内部标准接口
  - 同步异步请求
  - 异步回调业务服务
- 接口适配
  - 匹配内部标准接口和外部请求
- 接口聚合
    - 对能力的组合
- 其余能力组件
  - 熔断限流
  - 异步队列
  - 失败重试
  - 异常告警

## 四、整体设计
### 整体架构
![](https://picture.texous.cn/blog/外部能力接入服务位置.png)

### 交互流程
![](https://picture.texous.cn/blog/外部能力接入处理流程.png)

## 五、详细设计
### 功能模块设计
#### 功能列表
- 挡板功能（开关切换是否发起正式请求）
- 推单和拉单（给三方提交订单，从三方拉订单回来）
- 白名单梳理，那些第三方是需要白名单的
- 三方接口并发流量限制（第三方有限流的需要做控制）
- 报文存储（什么时候发起存储）
  - 业务请求参数（拦截器）
  - 业务返回结果（拦截器）
  - 三方请求参数（方法保存）
  - 三方返回结果（方法保存）
  - 三方回调参数（方法保存）
  - 三方回调结果（方法保存）
- 回调消费异步
  - 回调消息发MQ

#### 技术划分
![](https://picture.texous.cn/blog/20241211-企赋网关技术架构.png)

#### 技术交互
![](https://picture.texous.cn/blog/20241211-企赋网关主流程.png)

#### 模块划分
![](https://picture.texous.cn/blog/外部能力接入技术架构.png)

#### 模块说明
- 内部SDK
  - 给业务用来快速接入外部服务能力
- 接入层
  - 主要用来对接外部服务的接口
  - 包括授权，验签等步骤
- 适配层
  - 主要是用来将外部接口返回参数映射为标准信息
- 聚合层
  - 主要用来聚合一些操作：比如有些操作是需要多个接口协作完成的，将会在聚合层处理
- 标准接口层
  - 对内部提供标准能力接口
  - 对外部提供标准回调接口
- 异步队列
  - 处理异步请求（MQ）
- 重试组件
  - 处理失败或者可预知异常重试
- 限流降级
  - 正对一些上游接口策略来定制
- 异常处理
  - 对一些异常进行分类处理，执行实际需要的操作，重试/失败等

### 存储设计
要考虑存储节点（什么时候发起存储）

#### 数据库（DB）
```sql
CREATE TABLE `default`.`eg_request_info`
(
    `id`             bigint(20) NOT NULL,
    `tenant_id`      bigint(20) NOT NULL COMMENT '租户id',
    `request_id`     bigint(20) NOT NULL COMMENT '请求id：客户端生成',
    `trx_id`         bigint(20) NOT NULL COMMENT '请求记录id：服务端生成',
    `request_time`   bigint(20) NOT NULL COMMENT '请求时间',
    `request_type`   int(4) NOT NULL COMMENT '请求类型：比如下运单，查物流等',
    `exec_type`      int(2) NOT NULL DEFAULT 1 COMMENT '执行类型：1=同步，2=异步',
    `request_status` int(2) NOT NULL DEFAULT 1 COMMENT '请求状态',
    `attach_info`    text          NOT NULL COMMENT '附加信息',
    `callback_url`   varchar(1000) NOT NULL DEFAULT '' COMMENT '异步回调链接',
    `create_user_id` bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`      varchar(32)   NOT NULL COMMENT '创建人名称',
    `create_time`    bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id` bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`      varchar(32)   NOT NULL COMMENT '更新人名称',
    `update_time`    bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`        bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX            `idx_eg_reqeust_info_request_id`(`request_id`, `request_type`) USING BTREE,
    INDEX            `idx_eg_request_info_trx_id`(`trx_id`, `request_type`) USING BTREE
) COMMENT = '请求信息表';
CREATE TABLE `default`.`eg_request_info_detail`
(
    `id`             bigint(20) NOT NULL,
    `trx_id`         bigint(20) NOT NULL COMMENT '请求记录id：服务端生成',
    `request_info`   text         NOT NULL COMMENT '请求信息',
    `response_info`  text NULL COMMENT '结果信息',
    `status`         varchar(255) NOT NULL DEFAULT '20000' COMMENT '请求状态',
    `error_message`  varchar(255) NULL COMMENT '错误信息',
    `create_user_id` bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`      varchar(32)  NOT NULL COMMENT '创建人名称',
    `create_time`    bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id` bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`      varchar(32)  NOT NULL COMMENT '更新人名称',
    `update_time`    bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`        bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX            `idx_eg_request_info_detail_trx_id`(`trx_id`) USING BTREE
) COMMENT = '请求信息详情表';
CREATE TABLE `default`.`eg_request_flow_control`
(
    `id`             bigint(20) NOT NULL,
    `biz_code`       varchar(50) NOT NULL COMMENT '业务编码',
    `biz_name`       varchar(50) NOT NULL COMMENT '业务名称',
    `limit_type`     int(4) NOT NULL DEFAULT 1 COMMENT '限制类型：1=令牌桶',
    `limit_time`     int(8) NOT NULL DEFAULT 1 COMMENT '限制时间',
    `limit_unit`     int(4) NOT NULL DEFAULT 1 COMMENT '限制时间单位：1=秒',
    `limit_quantity` int(8) NOT NULL DEFAULT 1 COMMENT '限制请求量',
    `create_user_id` bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`      varchar(32) NOT NULL COMMENT '创建人名称',
    `create_time`    bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id` bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`      varchar(32) NOT NULL COMMENT '更新人名称',
    `update_time`    bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`        bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX            `idx_eg_request_info_detail_trx_id`((trx_id)) USING BTREE
) COMMENT = '请求流量控制表';
CREATE TABLE `default`.`eg_express`
(
    `id`                  bigint(20) NOT NULL,
    `channel`             varchar(20)  NOT NULL COMMENT '渠道编码',
    `company`             varchar(50)  NOT NULL COMMENT '公司编码',
    `number`              varchar(50)  NOT NULL COMMENT '订单号',
    `send_man_mobile`     varchar(20)  NOT NULL DEFAULT '' COMMENT '发送人手机号',
    `send_man_name`       varchar(50)  NOT NULL DEFAULT '' COMMENT '发送人名称',
    `send_man_print_addr` varchar(255) NOT NULL DEFAULT '' COMMENT '发送人地址',
    `rec_man_mobile`      varchar(20)  NOT NULL DEFAULT '' COMMENT '接收人手机号',
    `rec_man_name`        varchar(50)  NOT NULL DEFAULT '' COMMENT '接收人名称',
    `rec_man_print_addr`  varchar(255) NOT NULL DEFAULT '' COMMENT '接收人地址',
    `cargo`               varchar(255) NOT NULL DEFAULT '' COMMENT '物流物品名称',
    `send_country`        varchar(255) NOT NULL DEFAULT '' COMMENT '发送国家',
    `send_province`       varchar(255) NOT NULL DEFAULT '' COMMENT '发送省',
    `send_city`           varchar(255) NOT NULL DEFAULT '' COMMENT '发送市',
    `send_district`       varchar(255) NOT NULL DEFAULT '' COMMENT '发送街道',
    `rec_country`         varchar(255) NOT NULL DEFAULT '' COMMENT '接收国家',
    `rec_province`        varchar(255) NOT NULL DEFAULT '' COMMENT '接收省',
    `rec_city`            varchar(255) NOT NULL DEFAULT '' COMMENT '接收市',
    `rec_district`        varchar(255) NOT NULL DEFAULT '' COMMENT '接收街道',
    `create_user_id`      bigint(20) NOT NULL COMMENT '创建人ID',
    `create_by`           varchar(32)  NOT NULL COMMENT '创建人名称',
    `create_time`         bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id`      bigint(20) NOT NULL COMMENT '更新人id',
    `update_by`           varchar(32)  NOT NULL COMMENT '更新人名称',
    `update_time`         bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`             bigint(20) NOT NULL DEFAULT 0 COMMENT '是否删除：0=否，id=是',
    PRIMARY KEY (`id`),
    INDEX                 `idx_eg_request_info_detail_trx_id`((trx_id)) USING BTREE
) COMMENT = '物流信息表';
CREATE TABLE `default`.`eg_express_tracking`
(
    `id`             bigint(20) NOT NULL,
    `channel`        varchar(20)  NOT NULL COMMENT '来源渠道',
    `company`        varchar(50)  NOT NULL COMMENT '公司编码',
    `number`         varchar(50)  NOT NULL COMMENT '订单号',
    `time`           varchar(50)  NOT NULL DEFAULT '' COMMENT '请求状态',
    `time_long`      bigint(20) NOT NULL DEFAULT 0 COMMENT '错误信息',
    `context`        varchar(255) NOT NULL COMMENT '节点事件内容',
    `address`        varchar(500) NOT NULL COMMENT '详细地址',
    `country`        varchar(50)  NOT NULL DEFAULT '' COMMENT '国家',
    `province`       varchar(50)  NOT NULL DEFAULT '' COMMENT '省',
    `city`           varchar(50)  NOT NULL DEFAULT '' COMMENT '市',
    `district`       varchar(50)  NOT NULL DEFAULT '' COMMENT '街道',
    `create_user_id` bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`      varchar(32)  NOT NULL COMMENT '创建人名称',
    `create_time`    bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id` bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`      varchar(32)  NOT NULL COMMENT '更新人名称',
    `update_time`    bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`        bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX            `idx_eg_request_info_detail_trx_id`((trx_id)) USING BTREE
) COMMENT = '物流追踪表';
CREATE TABLE `default`.`eg_express_order`
(
    `id`              bigint(20) NOT NULL,
    `request_id`      bigint(20) NOT NULL COMMENT '请求id',
    `trx_id`          bigint(20) NOT NULL COMMENT '流水id',
    `channel`         varchar(20) NOT NULL COMMENT '来源渠道',
    `company`         varchar(50) NOT NULL COMMENT '公司编码',
    `number`          varchar(50) NOT NULL COMMENT '订单号',
    `send_man_mobile` varchar(50) NOT NULL DEFAULT '' COMMENT '发送人手机',
    `rec_man_mobile`  varchar(50) NOT NULL DEFAULT '' COMMENT '接收人手机',
    `create_user_id`  bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`       varchar(32) NOT NULL COMMENT '创建人名称',
    `create_time`     bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id`  bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`       varchar(32) NOT NULL COMMENT '更新人名称',
    `update_time`     bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`         bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX             `idx_eg_request_info_detail_trx_id`(`trx_id`) USING BTREE
) COMMENT = '物流下单表';
CREATE TABLE `default`.`eg_express_company_mapping`
(
    `id`             bigint(20) NOT NULL,
    `channel`        varchar(20) NOT NULL COMMENT '来源渠道',
    `code`           varchar(50) NOT NULL COMMENT '公司编码',
    `out_code`       varchar(50) NOT NULL COMMENT '外部公司编码',
    `cn_name`        varchar(50) NOT NULL DEFAULT '' COMMENT '公司名称',
    `us_name`        bigint(50) NOT NULL DEFAULT '' COMMENT '公司名称英文',
    `out_cn_name`    varchar(50) NOT NULL DEFAULT '' COMMENT '外部公司名称',
    `out_us_name`    varchar(50) NOT NULL DEFAULT '' COMMENT '外部公司名称英文',
    `create_user_id` bigint(20) NOT NULL COMMENT '创建人id',
    `create_by`      varchar(32) NOT NULL COMMENT '创建人名称',
    `create_time`    bigint(20) NOT NULL COMMENT '创建时间',
    `update_user_id` bigint(20) NOT NULL COMMENT '更新人ID',
    `update_by`      varchar(32) NOT NULL COMMENT '更新人名称',
    `update_time`    bigint(20) NOT NULL COMMENT '更新时间',
    `deleted`        bigint(20) NOT NULL DEFAULT 0 COMMENT '删除标识：0=未删除，id=以删除',
    PRIMARY KEY (`id`),
    INDEX            `idx_eg_request_info_detail_trx_id`((trx_id)) USING BTREE
) COMMENT = '物流追踪表';
```

#### ES
- 由于请求会比较多，对数据库压力会比较大， 所以想把请求信息，回调信息存储到ES中
- 对外部服务的请求报文也放入 ES, 后续好做查询追踪

### 接口设计
**实际开始接入第三方后补充**。大体可以划分为几种类型
1. 请求外部能力相关接口
   - 下运单
   - 查物流
   - ......
2. 结果查询相关接口
   - 请求状态查询
   - ......
3. 管理端管理相关接口
   - 请求报文查询
   - .....

### 潜在风险

## 六、工作量和排期
### 开发时间
### 联调时间
### 提测时间
### 上线时间


## 七、设计评审意见

## 八、参考文档