后端接口对接的模式范本:

概念澄清:
【下单】是个广义上的叫法,并不仅限于支付订单的订单。因为整个过程都围绕一个【seqNo】订单号或流水号这个唯一标识展开,因而统称【下单】。
【下单】可以是派发一个优惠券、申请一个支付订单、申请一个发票、发一张卡、申请一个业务等等。
【seqNo】也可以叫orderNo,有唯一性,每次请求都不一样,唯一标识一笔业务。
后端接口需要考虑的点:
即客户端验证服务端证书。例如:浏览器验证网站证书。
我们需要做的就是服务端的证书一定是要第三方授信CA签的证书。
这样浏览器拿到证书可以在本地找到该授信的第三方ca证书来验证网站证书的真伪。
如果网站的证书自己签名的证书,客户端需要在浏览器中配置该证书自签名使用的的CA证书。
https单向相比于双向实现方便,也是最基础的保障。不可能http直接在公网上跑,那样业务报文都是明文暴露状态,非常不安全。
一般后端交互https双向,基本都是使用自签名的证书。
客户端需要配置服务端的ca证书,用于解开服务端给我们的其自身的证书。
服务端同时也需要配置客户端的ca证书,用于解开客户端给服务端的其自身的证书。
如果是代码实现发送双向https请求,你会发现有两个证书配置,一个是请求方自身的证书,一个是服务端的ca证书。
https双向优点就是更加安全,通过证书能互相确认彼此身份。在后端交互中常见。单向https在浏览器/服务端中常见。
接口或者header中有类似于sign的字段,用于验证签名。
签名的作用就两个:防篡改;防抵赖
sign = sha256WithRSA(报文,私钥)等方法的模式为【私钥签名、公钥验签】的方式,可以防篡改,防抵赖.但是实现相对较重,需要生成和管理公私钥。
使用appkey/secretKey模式,使用类似于sign=MD5(报文,secretkey)只能防篡改,因为这个secretKey是双方都知道的.但是实现方式较轻量,也很普遍。
签名方式:推荐对报文json字符串做base64,然后对base64字符串进行签名。这样避免约定字段顺序,还有字段增删时对签名的影响。
通信层https只能保证数据在网络或者公网中是密文传输的。
但是一旦数据过了nginx这关,即解除https证书验证之后,报文数据在内网中就是明文在传输。对应敏感数据不能明文显示。
复杂安全点的模式可以使用数字信封模式:
即提供两个字段:
partnerData:敏感数据的加密值,使用对称加密的,例如:AES算法。
dekey:随机对称密钥的加密值,使用非对称加密的,例如:RSA算法
partnerData=AES(敏感数据,随机对称密钥)
dekey=RSA(随机对称密钥,接收方的公钥)
解密的过程就是加密的逆过程,先用自己的私钥解出对称密钥,再使用对称密钥解开敏感数据。
因为基于公私钥,所以只有私钥持有者才能解开这个数字信封。安全性非常好。但是效率偏低,
因为有对称和非对称的计算。对称秘钥建议添加校验数据,在解开时用于业务级别的校验。
原则上敏感数据不准走前端传递,传递也必须加密或脱敏。某些复杂业务需要很多服务交互的后端系统也遵循该原则。
一般做法是借鉴Oauth,前端或者系统间传递的是一个令牌token, 最终使用数据的系统,通过token向数据提供方获取数据。
这个token既可以作为整个业务流程的日志串联标志,同时也可以保护敏感数据。
条件允许的情况下,尽量使用等效数据替代真实数据,避免安全合规的问题。
例如:
利用使用用户手机号hash代替用户手机号;
对外提供的用户标识为系统映射过的用户openId而非真实用户标识。
作为中间系统传递的数据,约定由源头加密或编码,目标端负责解密或解码。中间系统不需要理解数据也不做任何处理。

密钥的管理推荐使用KMS,对称密钥需要由密钥树逐级分散产生(例如3DES分散算法),子密钥可以由上级母密钥加分散因子计算得出,
但是子密钥无法推算出上级母密钥。使用时通过传入不同分散因子实现【一次一密】【一人一密】【一卡一密】等。
如遇火灾等毁灭性打击,通过rootKey恢复所有子密钥。唯一管理成本即rootKey的管理保护,一般放在银行保险箱中,且多地备份。
通信层可以进来,验签能通过。但是业务授权也要鉴别,例如:同样可以调用派发优惠券接口,但是商户A只能发商户A商品的优惠券。
接口或者header中有类似于appkey/appCode/authCode等类似功能字段,该字段和验签绑定。通过该字段查询配置,确认该请求是否有该业务的权限。
https单向中多见,https双向中少见。主要预防攻击不要流到业务层。
1.防止错误的报文重复攻击,一般错误报文验签直接可以过滤。
2.防止正确的报文重复攻击
一般在接口或者header中有timestamp/nonce/messageId等字段,这些字段每次请求都会不一致。
推荐使用时戳,如果报文被截获,重放攻击,可能由于timestamp时间和服务器时间相差很远,或者相关nonce字段已经被缓存过,无法通过。
同时可以结合幂等措施,即被处理过的业务不会重复执行。
接口中有seqNo字段,可以叫订单号/流水号。
一个seqNo就对应了一次业务下单,同样的流水号无论请求多少次,结果都是一样的,不会重复做。
防止请求在通信中丢失,主要防止timeout类型的异常,请求方无法判断该业务的实际状态,是【请求还未送达就丢了】或【对方处理完毕,处理结果在回程时丢失】
实现幂等后,请求方可以使用相同seqNo进行下单,服务端如果处理过该seqNo订单,就将之前的处理结果返回,如果没处理就收单继续处理。
为什么提供了幂等还要提供查询?
查询和幂等的作用区别就在于,很多时候请求方请求出现异常,没有明确的答案,如果希望业务继续,则可以幂等请求。
例如该用户派发优惠券,如果发生异常则继续幂等派发即可。
如果需要根据实际业务状态决定如何操作,则需要先查询。
例如:很多有时效的业务,抢购业务,用户下单异常,最终没抢到货。
肯定是先查询,如果刚才订单实际成功,则给用户退款。如果刚才订单未成功,则直接关闭业务,这单子不用继续做下去了。
一般业务查询我们至少提供【成功】【失败】【进行中】三个状态。用于对方处理发生异常时,进行查询使用。
下单接口如果是同步接口,肯定没有实现异步通知的必要。
很多下单接口是异步接口,真正的业务状态在同步中无法返回,同步仅仅返回【已收单】,后续查询订单显示【进行中】,直到异步工作完成,订单才会翻转为【成功or失败】。(订单或任务表中有字段记录异步结果及异常,供查询使用)
异步通知的作用:能增强业务的时效性,同时也能减少请求方轮询查询导致的压力。
如果收到明确通知,请求方当即可以触发下一步操作,如果没有通知或通知丢失,请求方只能挂单等待异常处理时主动查询确认状态。
一般后端对接的业务接口,基本都需要对账。
对账最大的问题是【跨天】,例如:请求方请求时间为凌晨:23:59:59.但是接收方收到的时间为次日:00:00:04
假如按照T+1对账,那在T日临界点,总可能出现对不平的情况。请求方有该笔账,但是接收方没有。
我们不讨论【勾对】等其他实现方式。
如果可能,在定义接口的时候,可以讨论清楚对账方式及以哪方时间为准。避免后续对账开发困难。
例如:在下单接口中添加objectData字段,以请求方的该字段作为对账时间依据。
对接的任何一方都有在业务进行中要升级接口的可能。但是要避免需要停服、及互相依赖的局面,例如:大家约定一个时间,半夜你先升级,我在升级。
场景1:公私钥泄露需要更换。
可以在接口中添加keyIndex来标识密钥的版本或者signType字段来标识签名的算法。
这样请求方报文中使用什么版本的密钥,接收方就使用什么版本的密钥解密。互相不依赖。提前配置好即可。
场景2:接口字段升级
下单接口有新增字段,选择升级接口版本号,形成一个新接口。老接口仍保留。接收方先升级,请求方择机升级,互不影响。
查询同理。
接口业务策略上有区分的。 一种是完全掌握主动权,一种是将决定权让渡给请求方。
例如:
方式1:派发一个券的时候,有效期是请求方在接口中指定,按照请求方的有效期设定有效期。
方式2:接收方通过产品配置有效期生效策略。
区别在于有效期的生成方式可能是多种多样的,如果将这个能力让渡给请求方,业务变化时,就不用升级。由请求方修改。
业务异常基本分为3大类:
1.没有明确错误原因。例如对方返回unknow error / inner error 等错误。对方内部可能是异步的,保险起见需要挂单后续查询确认业务状态。
2.有明确错误原因。例如对方返回phoneNo invalid / cardNo error 。无需挂单,直接处理掉。
3.timeout 类型。访问超时是最常见的异常。需要挂单,后续时幂等还是查询在处理,根据业务情况制定。
考虑后续多服务及系统需要根据日志定位问题,建议报文中或header中添加类似于traceId 字段。用于后续追踪整条业务链。
其他异常:
网络异常、网络波动、今天我灾备、明天他机房维护等。这些单个事件都是小概率,但是这样的事件非常多。
网络异常也导致很多业务异常,我们要充分考虑的异常导致的挂单和中断的情况,做好异常处理和自愈功能。
例如:对账往ftp上投送对账文件。可能网络异常,今天的文件没放上去;或者今天的放上去了,但是出问题需要重新放;可能灾备停了两天,在进行对账等等
ps:不要忽略这些小概率事件,没有预案,只要发生一次,造成的异常业务笔数可能手动处理很久。
对于很多字典值,建议使用小写中划线模式,不要大小写混合或者驼峰。既然是字典值,来回传输的,如不涉密,建议见名知意,不要使用"魔法数字",或晦涩难懂的代码。
例如:海尔设备品牌方:device-brand-haier;
考虑这个接口的负载是很关键的步骤。同步接口压力大点,异步接口可以使用MQ进行削峰填谷相对压力小点。
提升效率,控制并发是一个非常庞大的体系。常见的方式:
1.共享数值字段,我们只做累加
2.每个用户独立有一条记录,将并发化解。
4.用插入代替更新,分段锁库存等,使用<=0代替=0,防止极限情况击穿等。
5.分库分表,避免热点表和数据的阻塞。
6.注意风控,报警等情况。
...............
最好不要使用文档维护,维护成本很高,推荐使用一个平台进行管理。例如:YApi
如果你不是故意想故弄玄虚,一般接口需要描述使用场景、典型使用案例、可能的情况下使用图形辅助描述。
如有加解密签名或特殊算法等,需要提供示例、源码、或者SDK。减少联调成本。原则上谁定义加密或签名等算法,谁负责提供实现类。不存在口头约定,各自实现,联调在确认,不然联调光对齐这些算法可能要花非常多的时间。
如果有特殊异常或需要关注的点,最好明示及解决方案。
本质:你要站在使用者角度,来描述你的接口如何使用。相当于你已经帮对方做了一个最佳实践。
“防呆式”的开箱即用是好传统。
如果你的接口是物联网相关,例如控制设备、远程控制洗衣机、各种设备。建议做一个paas 平台,控制方通过paas与设备进行交互。
而非直接给设备发指令。如果直接和设备直接交互,每个控制方都要开发一套设备管理后台管理,诸如位置、状态、库存等功能,这无形增加了对接的难度和成本。
通过paas平台的后台对接模式,平台可以提供状态、库存、位置等功能,控制方开发更加方便,同时你还可以收取平台使用费,一举多得。
选取合适的在线方案文档维护工具,能展示修改记录和版本。
推荐对接的方案及接口使用在线文档或网站等方式,非特殊需要不要使用word,pdf等作为交流方式。 因为方案从制定-讨论-定版-联调-上线等过程中肯定需要频繁修改,
如果通过文档维护,一版一版的更新维护成本很高,而且可能涉及的相关方很多或者对方纵向传达层级很深(例如:总公司-分公司-事业部-小组-外包-最终实现者)。
导致文档同步效率很差,可能每个人手里版本都有差异。
{
"authCode": "123", 业务认证码
"appCode": "123", 请求方
"deKey":"frfferdfa" 对称密钥加密值
"partnerData": "22", 敏感数据加密值
"seqNo": "123",请求流水
"timestamp": "202107201653123", 时戳
"keyIndex": "1", 加密密钥版本
"sign": "123" 签名
}
后端一般都是业务接口,相对来说更加复杂,且参数组成和路径命名没有一个统一的模式,每家都不一样,尤其很多传统厂商。
前端接口相对规范的多,基本都是RESTFUL风格。
前端接口定义示例:
接口路径:http://ip:port/sapo/biz/1/0/users/{user-uuid}/orders
请求方法:GET
l 说明:查询用户订单详情
l 请求方:小程序
l 接收方:服务端
请求头:
|
Location |
Name |
Type |
Description |
Required |
Example |
|
Header |
authorization |
str |
用户token |
1 |
|
|
Header |
Content-Type |
str |
application/json |
1 |
application/json |
请求路径参数:
|
Location |
Name |
Type |
Description |
Required |
Example |
|
Path |
user-uuid |
str |
用户uuid |
1 |
请求参数:
|
Name |
Type |
Description |
Required |
Example |
|
createTime |
str |
创建时间 [格式:yyyyMMddHHmmss] |
1 |
|
|
lastUpdateTime |
str |
最后更新时间 [格式:yyyyMMddHHmmss] |
1/0 |
|
|
status |
num |
状态:0-无效,1-有效 |
1 |
1 |
返回参数:
|
Name |
Type |
Description |
Required |
Example |
|
resCode |
str |
应答码 |
1 |
0000 |
|
resDesc |
str |
应答信息 |
1/0 |
success |
|
resData |
obj |
应答数据 |
1/0 |
resData结构:
|
Name |
Type |
Description |
Required |
Example |
|
total |
num |
总个数 |
1 |
|
|
orderInfoList |
list |
订单对象实体集合 |
1 |
|
orderInfo结构:
|
Name |
Type |
Description |
Required |
Example |
|
createTime |
str |
创建时间 [格式:yyyyMMddHHmmss] |
1 |
|
|
orderNo |
str |
订单号 |
1 |
|
|
serviceSpecInfo |
obj |
[服务规格]对象实体 |
1 |
|
|
status |
num |
状态:1-待支付,2-已支付,3-待执行,4-执行中,5-已完成,6-已取消,7-已下单 |
1 |
7 |
|
expireTime |
str |
失效时间,格式:yyyyMMddHHmmss |
1/0 |
|
|
invoiceFlag |
num |
是否开过发票标识,0-未开发票,1-已开发票 |
1 |
0 |
|
totalFee |
num |
订单总价,单位:分 |
1 |
|
|
payFee |
num |
最终支付金额(单位:分) |
1/0 |
serviceSpecInfo结构:
|
Name |
Type |
Description |
Required |
Example |
|
code |
str |
规格类型代码 |
1 |
|
|
name |
str |
规格名(30分钟速洗\20分钟烘干) |
1 |
|
|
detail |
str |
规格描述(30分钟速洗\20分钟烘干) |
1/0 |
请求示例:
GET 192.168.1.11:9032/sapo/biz/1/0/users/123/orders
返回示例:
{
"resCode": "0000",
"resDesc": "success",
"resData": {
"total": 2,
"orderInfoList": [
{
"createTime": "20220517194521",
"deviceExeRemainTime": 23,
"expireTime": null,
"orderNo": "456",
"payFee": 0,
"serviceSpecInfo": {
"code": "washSpec1",
"detail": null,
"name": "washSpec1"
},
"status": 1,
"totalFee": 0
}
]
}
}
本文来自博客园,作者:wanglifeng,转载请注明原文链接:https://www.cnblogs.com/wanglifeng717/p/16213202.html
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐
我一直在为使用acts_as_list的模型实现一些不错的交互界面,这些界面可以对我的mRails应用程序中的列表进行排序。我有一个排序函数,在每次拖放之后使用sortable_elementscript.aculo.us函数调用并设置每条记录的位置。这是在拖放完成后处理排序的Controller操作示例:defsortparams[:documents].each_with_indexdo|id,index|Document.update_all(['position=?',index+1],['id=?',id])endend现在我正在尝试对嵌套集模型(acts_as_nested
最近在工作中,看到一些新手测试同学,对接口测试存在很多疑问,甚至包括一些从事软件测试3,5年的同学,在聊到接口时,也是一知半解;今天借着这个机会,对接口测试做个实战教学,顺便总结一下经验,分享给大家。计划拆分成4个模块跟大家做一个分享,(接口测试、接口基础知识、接口自动化、接口进阶)感兴趣的小伙伴记得关注,希望对你的日常工作和求职面试,带来一些帮助。注:文章较长有5000多字,希望小伙伴们认真看完,当然有些内容对小白同学不是太友好,如果你需要详细了解其中的一些概念或者名词,请在文章之后留言,后续我将针对大家的疑问,整理输出一些大家感兴趣的文章。随着开发模式的迭代更新,前后端分离已不是新的概念,
我正在尝试在我的Rails应用程序中使用模型来从外部API检索信息。我想做的是以类似于ActiveRecord模型提供的方式(特别是关联,以及相同风格的可链接查询方法)访问我的数据模型(可能包含来自多个API调用的信息)。我最初的直觉是重新创建我想要的ActiveRecord部分并合并此API。不想“重新发明轮子”并确切地看到添加更多功能需要多少工作让我退后一步并重新评估如何处理这个问题。我找到了在没有表的情况下使用ActiveRecord的方法(请参阅:Railscast#193TablelessModel和博客文章here)并研究了ActiveRecord。因为ActiveMode
原文:UsetheIComparableandIComparerinterfacesinVisualCSharp本文介绍了在VisualC#中如何使用IComparer和IComparable接口。概要本文同时讨论了IComparable和IComparer接口,原因有两点。这两个接口经常一起使用。虽然接口类似且名称相似,但它们却有不同的用途。如果你有一个支持IComparer的类型数组(例如字符串或整数),你可以对它进行排序而不需要提供任何对IComparer的显式引用(译注:意思是把一个IComparer的实现类作为参数传递给排序方法)。在这种情况下,数组元素会被转换为IComparer的
有很多文档介绍如何构建和创建以Rails作为后端的Ember.js应用程序。流行的解决方案是使用gems作为ember-rails和ember-source或合二为一的ember-appkit-rails。但是我正在尝试创建一个简单的Sinatra应用程序,该应用程序以Ember.js作为前端来处理仅JSON后端。我发现的少数资源似乎有点过时,所以我正在寻找简单的方法来做到这一点。所以我的问题是:我如何将Ember.js与简单的Sinatra后端集成?如何执行此操作的示例将不胜感激。 最佳答案 有一个verysimplerepoon
如果你想在自己的应用中使用淘宝的数据,那么对接淘宝数据接口是必不可少的一步。本文将介绍如何对接API淘宝数据接口,以便你能够顺利获取和使用淘宝的数据。步骤一:获取AppKey和AppSecret首先,在淘宝开放平台申请API接口之前,需要先注册为淘宝开发者并创建应用。创建应用后,你将得到一个AppKey和AppSecret,这两个参数需要在调用API接口时用于身份验证。步骤二:确定需要调用的API接口在淘宝开放平台的开发文档中,你将找到所有可用的API接口。你需要根据你的需求找到需要调用的API接口,例如查询商品、店铺等信息。在找到需要的API接口后,你需要了解该接口的请求参数和返回结
我正在使用delayed_job_webgem来监控延迟的作业。https://github.com/ejschmitt/delayed_job_web可以使用我的routes.rb中的这一行访问它:match"/delayed_job"=>DelayedJobWeb,:anchor=>false我站点的每个其他区域都需要使用Devisegem登录。我如何使它也需要登录?在自述文件中,他们建议将以下内容添加到config.rb:ifRails.env.production?DelayedJobWeb.useRack::Auth::Basicdo|username,password|us
根据officialrubyAboutpage用C扩展Ruby比用Perl更容易。我不是(perl)XS专家,但我发现使用Inline::C快速简单地编写一些东西非常简单,那么为什么在Ruby中更容易呢?WritingCextensionsinRubyiseasierthaninPerlorPython,withaveryelegantAPIforcallingRubyfromC.ThisincludescallsforembeddingRubyinsoftware,foruseasascriptinglanguage.ASWIGinterfaceisalsoavailable.那些做