|
<h2 id="ooexf">前言</h2>
无论是面向**<font style="background-color:#FADB14;">ToB、ToG</font>**的业务,都离不开与第三方对接的需求,例如:**短信对接平台**、**视频平台**、**业务系统**还有**单点对接**等等,大到相对成熟的平台对接,小到一个接口的调用,基本上所有的开发都避免不了对接,已经充斥在日常的工作中,如何做好与第三方的对接,降低对接风险,按时保质的完成对接任务,已经成为一个很重要的问题。
我司项目服务端主要以Java为主,通常需要通过第三方的集成与被集成来扩展对应的项目业务,但看似简单的发送/接收请求却包含了**Http请求,数据加密/解密,签名加签/验签,数据处理**等内容。
<h2 id="sW8Sw">要求</h2>
本文面向**项目业务人员、产品设计人员、开发人员。**
本文目的是为了减少沟通成本,确定**各节点的责任主体**,并形成有迹可循,项目移交或转接的**事后可追溯**。
以下内容需要完成
【xxx项目总进度计划-7.重大技术支持需求】需填写每个对接的厂商系统名称,列出**计划/实际**对接的接口名称,对接人,**计划/实际**对接时间
【功能流程图】项目列出粗流程图,产品列出细流程图
【xxx项目接口文档】需与过程中实际对接改动内容的及时同步更新,**最终版**需交由项目人员项目归档提交至**项目管理系统【暂定】**
<font style="color:#E8323C;background-color:#FADB14;">以上完成人员由项目组内部商议分配决定。</font>
<h2 id="MdN6k">对接说明</h2>
<h3 id="W1bMk">对接是什么</h3>
一定要从宏观到微观的搞清楚我们自己的业务系统是做什么业务,有哪些数据、哪些字段;需要提供给三方的数据、字段是哪些,需要从第三方获取的数据、字段是哪些。
> 这里的宏观和微观指的是宏观的系统物理架构、逻辑架构、部署架构、业务架构,微观的指系统模块、功能点的实现细节、涉及的表和其他三方对接历史。
>
同样也要掌握第三方系统大致业务流程,部署架构等等。
<h3 id="CujhX">为什么对接</h3>
比如说我们经常对接**短信平台**、**视频平台**,我们不可能自己开发个短信平台或视频平台系统,可以让我们自己更加专注于自己的业务开发。
总结:基本上都是自己公司想做一件事情,不可能分散**物力、人力、精力**去实现,那么就需要找市面上成熟的解决方案,专业的功能专业的厂商去做,最小化的成本去实现需求。
<h2 id="GrGRY">怎么进行对接</h2>
这里以**对接前、对接中、对接后**这三个阶段,来分阶段讨论下每个阶段要怎么做,才能稳步推进需求对接。
<h3 id="rwYnz">对接前</h3>
+ 明确需求,以及**对接的价值**(是否真的有必要做以及实现的意义)
+ 搞清楚我们与第三方的大致交互流程和双方**所需的数据**。(切忌鸡蛋里挑骨头,没有的数据一般难以实现)
+ 评估大致所需**花费的成本**(我方估算为所需人天),对接的部分情况下是需要花钱的(太多反而得不偿失)
+ 确定双方相关的业务负责人、技术负责人,以及确定一个**总负责人**来推动双方稳步前进,团队成员相对专一稳定(切忌都是放羊模式以及频繁换人)
+ 指定一个**合理的计划**,确定联调时间、上线时间、试运行时间(一定要制定相对合理的计划)
<h3 id="oe4Xy">对接中</h3>
<h4 id="Dl1Dl">非技术对接</h4>
<font style="background-color:#FADB14;">1.【重要】画出流程图,时序图,一图胜千言,双方确认</font>
这里最好避免太多中间人,必须有真正熟悉业务和技术,减少沟通损耗
**泳道图示例:**
泳道图可以清晰的看到对接双方的交互流程,各方职责划分清晰

**时序图示例:**
时序图可以清晰看到消息传递的时间顺序

2.文档先行、积极沟通(双方按照文档来开发,统一规范,对接过程中的约定也需要同步写到文档里面去)
3.本公司接口文档和图发对方确认,一定要得到对方的明确答复
<h4 id="SGukL">技术对接</h4>
1.网络协议方面:
确认接口对接的网络协议,http/https 端口号、tcp端口号webservice或其他
2.接口请求方面:
尽量提前全部约定,数据传参+响应格式+数据访问方式,如:application/json,post请求等
3.接口安全方面:
考虑是否需要安全考虑,比如内网,外网的情况下务必有认证机制
<font style="background-color:#FADB14;">4.【重要】幂等校验方面:</font>
确保 本公司接口和第三方公司接口都有唯一校验功能,防止重复提交
<font style="background-color:#FADB14;">5.【重要】重试机制方面:</font>
一定要确认是否需要接口调用失败后的重试机制,保证数据传输的最终一致性。重试机制包括 实施重试调用指定次数+调用失败持久化数据库定时任务重试等
6.接口地址方面:
双机热备情况下可能导致死循环调用
<font style="background-color:#FADB14;">7.【重要】接口版本方面:</font>
接口升级,尽量做到影响最小,不要修改原接口协议,如果必须要动,尽量做到接口**向下兼容**老版本
<font style="background-color:#FADB14;">8.【注意】接口服务方面:</font>
**第三方对接模块做成单独服务**最好独立出来,尽最大努力保证服务的高可用、稳定性
<h4 id="JGamr">关键细节</h4>
| 关键细节 | 事项 | 备注 |
| --- | --- | --- |
| <font style="color:rgb(79, 79, 79);">字段内容</font> | <font style="color:rgb(79, 79, 79);">双方确定需要提供什么字段、需要获取哪些字段</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">接口版本</font> | <font style="color:rgb(79, 79, 79);">接口版本规范,</font><font style="color:rgb(79, 79, 79);background-color:#FADB14;">【推荐】url中/v1/xxx</font><font style="color:rgb(79, 79, 79);">,还有header中version=1,以及协商版本具体规范细节</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">大量数据</font> | <font style="color:rgb(79, 79, 79);">是分页返回,还是以文件的形式,例如csv等</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">异常处理</font> | <font style="color:rgb(79, 79, 79);">定义错误码,以及其对应的相应操作,有什么兜底补偿方案没</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">调用方式</font> | <font style="color:rgb(79, 79, 79);">主动拉取还是被动等待推送</font> | <font style="color:rgb(79, 79, 79);">建议双向即可主动式,又可被动式</font> |
| <font style="color:rgb(79, 79, 79);">通信协议</font> | <font style="color:rgb(79, 79, 79);">Restful、Webservice、MQ、Websocket等,复杂的对接,是否可以考虑提供sdk</font> | <font style="color:rgb(79, 79, 79);">一般建议Restful</font> |
| <font style="color:rgb(79, 79, 79);">报文协议</font> | <font style="color:rgb(79, 79, 79);">json、yaml、xml、自定义等</font> | <font style="color:rgb(79, 79, 79);">一般建议Json</font> |
| <font style="color:rgb(79, 79, 79);">接口方式</font> | <font style="color:rgb(79, 79, 79);">同步接口还是异步接口</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">接口安全</font> | <font style="color:rgb(79, 79, 79);">Oauth2.0 sign token等,注意内外网、以及业务的保密级别</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">幂等性</font> | <font style="color:rgb(79, 79, 79);">确保双方接口是否都是幂等的,防止重复提交</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">重试机制</font> | <font style="color:rgb(79, 79, 79);">一定要确认是否需要接口调用失败后的重试机制,保证数据传输的最终一致性</font><font style="color:rgb(79, 79, 79);"> </font><font style="color:rgb(79, 79, 79);">重试机制包括 实时重试调用:指定次数 + 调用失败持久化,数据库定时任务重试</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">接口文档</font> | <font style="color:rgb(79, 79, 79);">要有详尽的说明和丰富的示例代码</font> | <font style="color:rgb(79, 79, 79);"></font> |
| <font style="color:rgb(79, 79, 79);">联调环境</font> | <font style="color:rgb(79, 79, 79);">可以随便折腾的那种</font> | <font style="color:rgb(79, 79, 79);"></font> |
<h3 id="TAokv">对接后</h3>
持续跟踪一段时间系统的使用情况,然后进行总结,看看是否可以将此处的对接流程规范化,做标准接口,将自己的能力或者数据标准化出去,类似于开放平台,然后让别人按照自己的标准来做。
<h3 id="rZsXW">对接风险以及必要措施</h3>
<h4 id="gDG8f">对接风险</h4>
+ 对方不配合(低层次不配合可以考虑适当人情处理,若不行要沟通升级,让上级或业主推动)
+ 对接要从源头留痕,防止后面对方扯皮,要留证据(对外的尽量以公司邮箱形式发送文档)
+ 对方服务升级,接口变了,未通知升级(接口版本号指定号,接口做到向下兼容)
+ 对方服务不稳定影响自有系统(【微服务化后】服务熔断、降级处理)
+ 调用并发频率过高等(【微服务化后】控制频率)
<h4 id="nVKlw">必要措施</h4>
+ 完善的文档及时归档,防止后面对方扯皮以及新同事交接
+ 需要自己有对接模拟接口,防止三方公司接口迟迟未完成,影响整个项目的进度
+ 尽量最小数量系统对接,至少本公司一套程序(每增加一个系统对接成本翻倍)
+ 日志记录接口接收到的数据,以及解析之后的参数值,都要用日志记录下来,方便查看原因
<h2 id="RYxkD">附录</h2>
<h3 id="wO1x5">【业务向】对接指南</h3>
<h3 id="hq2Yz">【业务向】API及SDK对接的差异及利弊</h3>
第三方对接技术分类主要为**API对接、SDK对接**
| 对比 | API | SDK |
| --- | --- | --- |
| 对接周期 | 几天or一二周,根据对接文档,理解大致流程再开发,联调测试上线 | 几个小时,一般支持自助式对接测试 |
| 稳定性 | 若临时定制化开发,设计会存在一定缺陷,稳定性较差,开发过程中会出现bug,上线后也会暴露 | 较为成熟,稳定性好,一般对接成功不容易出错。 |
| 安全性 | 安全性好。传输的数据相对透明,不会泄漏其他数据,也没有其他客户端权限 | 潜在风险高,SDK一般存在权限黑箱,内部逻辑黑箱。安装SDK前最好大致看下文档背调了解 |
| 灵活性 | 灵活性高,对接测试完成后,可以上线或关闭,可以根据需要进行二次开发,功能升级 | 较差,更新周期较慢 |
| 客户端 | 无需改动 | SDK本身依赖的jar包较多,会增加包的体量 |
| 服务端 | 需要服务端技术支持,小微开发者后端系统很薄弱,会感到相对吃力 | 不需要服务端开发支持,不需要太多的开发支持 |
---
<h3 id="glCvX">【开发向】常见错误问题解决</h3>
**HTTP**
1.404
IP地址端口、接口名称大小写,特殊字符、全角模式下字符(将URL字符串复制到doc命令行可以看出特殊字符)
2.400
请求的数据和接收的数据无法匹配,提示METHOD错误,查看传输的参数是否格式正确,需要date却传递string等(可以考虑将对方发送的完整的参数拷贝进行测试,不只测试一点点参数)
3.415
查看contentType是否正确,前后台媒体类型不一致
4.320
临时重定向,看看是否配置了https强制跳转导致的问题
5.401
一般是未登录,用户名密码错误
6.403
无权限操作,用户登录了但该用户无权限操作该功能
---
<h3 id="jvajd">【开发向】业务逻辑及幂等性的思考总结</h3>
---
<h3 id="vPXct">【开发向】单独服务及业务逻辑异步、降级操作(业务逻辑降级)</h3>
举例说明:把第三方对接模块做成单独服务的好处、以及做好对外服务降级操作
之前项目中有个需求,需要对接一个友商的服务,大致流程是调用一个**实时**接口,输入**组织编码**,返回这个组织编码的最新所有档案信息。
<h4 id="Ak4c4">第一阶段</h4>
一开始直接将对接代码写入业务系统,这个为最常规普通的操作
<h4 id="VzNaP">第二阶段【独立服务化】</h4>
使用一段时间后,公司的另一个开发或小组需要通过对接这个厂商的同类接口做同类服务或次生服务,那么现在是否也**复制一份同样的代码作为新单链对接**呢?显然并不应该这么做,第三方接口如果升级的话,那么两段代码都需要改,耦合性太强,如果再有其他团队需要对接呢?不可能都用这种方式进行对接。
所以合理的做法应该是把这个对接**模块独立出来**,做成一个单独的服务,供所有团队使用,作为**微服务的一部分**。
架构示意图如下:

<h4 id="AJy7w">第三阶段【对外服务异步、降级操作】</h4>
平稳运行一段时间后,突然的某一天第三方厂商的服务down掉了,导致我们这里所有相关的业务出现类似“档案查询接口不可用”的提示报错。改模块无法顺利加载。
> 这里前提需要做异步加载,断路器,服务通用降级,返回信息“档案查询接口不可用”
>
虽然是第三方的问题,也有提示的降级操作,但是,**用户体验**还是不够友好,这时候回归需求-我们需求是返回**实时档案信息。**
这时候思路可以调整为,如果第三方服务down了,返回之前查询过的非实时数据,并给个不是最新数据的提示,也总比“档案查询接口不可用”要优雅的多。
于是我们可以在每个组织查询到档案后,本地数据库存一份,当第三方服务不可用的时候去**降级到本地数据中间件查询使用。**
架构示意图如下:

---
|
|