我的手机没有网络,但我仍然可以付款。 重点是什么?
如今,生活已经离不开微信/支付宝电子支付。 出去吃饭或者购物的时候,只需要带一部手机就可以解决一切,所以我已经很久没有碰它了。
有一次出去吃饭,要排队付钱。 等待的过程非常无聊。 我正准备掏出手机玩荒野乱斗,却发现这个地方并没有联网。
看手机,明明信号满格,却显示网络未通。 这对苹果手机用户来说是一种痛苦,谁知道呢。
画外音:如果真要diss一下基带,那就惨了,没事就断网了~
回到正题,由于没有网络,我也没有钱,我担心我付款的时候,因为我的手机不能上网,所以无法用支付宝扣钱。 当我这么想着的时候,我已经在排队了。 不管怎样,我先尝试使用支付宝。 如果没效果我就不吃了。
然而没想到,当商家扫描支付宝上的支付码进行支付时,虽然我的手机没有弹出支付成功页面,但商家却显示支付成功,并成功打印出收据。 不一会儿,我的手机就收到了一条支付宝扣款短信。
因为我最近的工作是和微信/支付宝相关的,所以整体的支付流程比较清晰,但是不太清楚为什么支付码可以线下支付,所以我做了一些研究,得出了今天的这篇文章。

流行的付款方式
在讲支付码离线原理之前,我们先给不熟悉支付宝/微信支付方式的同学介绍一下常见的两种支付方式。
常用的支付方式有微信和支付宝线下支付两种。 一是打开手机主动扫描商家提供的码盘。 这种支付方式一般称为主扫码支付(用户主动扫码)。
以支付宝为例,支付流程如图:

第二种是我们打开手机,显示我们的支付码,然后商家使用扫码枪等工具获取支付码,完成支付。 这种支付方式一般称为扫码支付(用户扫码)。
以支付宝为例,支付流程如图:

第一种方式,需要在手机APP上扫码,然后弹出确认支付窗口。 这种方式在手机无网络的情况下无法完成支付,所以上面我们所说的无网络的情况特指支付码支付。 场景。
支付码支付流程
在讲支付码线下支付之前,我们先来看看支付码的整体流程。 以超市购物为例,一次性支付码的支付信息流程如图:

在此过程中,商户后台系统需要调用支付宝条码支付接口来完成支付。
由于商户后台需要在线与支付宝后台进行通信,所以支付码离线支付是指客户端没有网络的情况。 商家实际上必须实时在线。
一次性支付代码接口调用流程如图:

通过上面两张图,我们对支付码交互流程有了一个整体的了解。
支付码的技术方案其实可以分为线上和线下两种情况。 我们来看看两种方案的具体实现方法。
在线代码解决方案
客户的在线代码方案应该比较容易想到。 只要登录支付宝/微信,点击支付按钮,客户端就会调用后端系统的支付码申请接口。
后台系统收到请求后,生成支付码,然后将支付码与用户的关系保存在数据库中,返回给客户端。
只要客户端在有效期内显示支付码即可完成支付,否则二维码将过期。
使用这种方案相对安全,因为服务器每次都会生成代码,并且服务器可以控制幂等性,不存在客户端伪造的风险。
另外,即使支付码规则需要调整,比如支付码位数增加一位,我们只需要调整服务器端代码,客户端不需要升级。
然而,这种解决方案的缺点也很明显。 客户端必须实时连接到互联网。 如果没有互联网,就无法获取支付码。
此外,现在部分智能设备也开始支持支付宝支付。 这些设备很大一部分不具备连接互联网的能力(例如小米手环4)。 在这种情况下,无法使用在线代码解决方案。

基于这种情况,启动了离线打码解决方案。
离线代码解决方案
你可能对离线码比较陌生,但实际上如果仔细观察的话,离线码其实在很多场景下都会用到。
比如我以前去黑网吧玩梦幻西游的时候,账号总是被盗。
没办法,我花了很多钱买了一个网易通用通证。 每次登录时,除了输入用户名和密码外,还需要输入动态密码。 此后,该账户很少被盗。

再比如,我们每次在网易上支付时,除了输入银行卡密码外,还需要输入网银盾上的动态码才能完成支付。

画外音:
我想在这里再次抱怨。 以前网银盾真的很难用,动不动就驱动不兼容。 还记得我用网银给黄钻充值的时候,试了一下午都没有成功——!
当然,上面这些可能都是老古董了,很多人可能都没用过。 现在比较流行的是手机验证器APP,比如等等。

这种分词器动态生成一次性密码(OTP,One-time),可以防止密码被盗带来的安全风险。
其实支付码离线解决方案的技术原型就是基于这个方案的,所以我们来看看基于它的原理。
动态密码技术原理
首先,如果我们需要使用它,我们需要在网站上启用两步验证功能。 以账户为例,您可以找到以下设置两步验证的设置:

当我们点击设置时,会弹出一个二维码,然后使用APP扫码进行绑定。

绑定后,APP会显示动态代码。
我们来解析一下这个二维码,它对应的字符串如下:
://totp/%?=xxxx&= 复制代码
上面的字符串中,最重要的就是这一串key。 这是一个编码字符串。 实际使用时需要进行解码。 伪代码如下:
= xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx = ((())) 复制代码
客户端和服务器会同时保存这个密钥的副本,两端会使用相同的算法进行计算,以比较动态代码的正确性。
我们以客户端为例,生成动态代码。 首先我们需要执行一个签名函数。 这里**使用了HMAC-SHA1,它是一种基于哈希的消息验证码,可以与更安全的单向哈希函数(例如SHA1)一起使用来生成签名。
签名函数的伪代码如下:
hmac = SHA1( + SHA1( + )) 复制代码
在上面的函数中,使用了当前时间除以 30 的值。
= () / 30 复制代码
这里时间作为动态可变参数,可以连续生成动态代码。
另外,这里除以30是为了让验证码的有效期为30秒。
这样,用户可以有足够的时间准备输入动态代码。 另外,客户端和服务器之间可能存在时间偏差。 30秒的间隔可以大概率屏蔽这种差异。
画外音:这个有效时间其实是非常需要考虑的。 如果时间较长,安全性就会较差。
如果比较短,用户体验会很差,输入和准备也会比较困难。
通过HMAC-SHA1签名函数后,我们得到一个长度为40的字符串,我们还需要将其转换为6位数字,以方便用户输入。 处理的伪代码如下:
= hmac[(hmac):(hmac) + 4] = INT() = % 1,000,000 复制代码
完整的算法伪代码如下:
= xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx = ((())) = () / 30 hmac = SHA1( + SHA1( + )) = hmac[(hmac):(hmac) + 4] = INT() = % 1,000,000 复制代码
当客户端上传动态码到服务器时,服务器查询数据库获取用户对应的密钥,然后使用相同的算法处理生成动态码,最后比较客户端上传的动态码是否为与服务器生成的一致。
支付码离线解决方案
上面我们了解了动态密码的实现方案,支付码生成的原理也大致相同。
但支付码离线方案采用动态密钥(全局唯一),定期请求服务器更换密钥,以保证更高的安全性。
另外,在一次性动态密码方案中,双方需要基于相同的密钥,因此服务器需要清楚地知道其背后的正确用户。 以上面的登录场景为例,登录过程中输入用户名,服务器可以据此在数据库中查询对应的key。
然而,在支付码的支付场景中,支付流程仅通过支付码向对应的用户扣款。 不用说,这个支付码必须包含相应的用户信息。
因此,支付码对应的算法会比动态码更加复杂,从而可以有效保证安全性。
看到这里,不知道你是否想了解一下这个算法呢?

哈哈,开个玩笑,我们怎样才能掌握这个算法呢?
我们不知道支付宝的核心算法,但是我们可以从别人公开的设计方案中得到一个大概的了解。
这里我给大家提供一个知乎网友@反方向钟回答的离线二维码实现方法,给大家看看。

支付码离线码的缺点
最后我们看一下支付码离线方案的缺点:
首先,算法调整不灵活。 如果相关算法有较大调整,客户端可能需要升级,在此期间,服务器也需要兼容新旧算法生成的支付代码。
其次,存在安全问题。 一般情况下,普通用户无法获得相关密钥,但有兴趣的人却无法使用。 他们可能会获取手机用户的root权限或越狱手机,利用恶意程序获取密钥,然后随意生成支付码。
看到这里,大家可能会担心自己钱包的安全。 不过,我认为我对此并不过分担心。 蚂蚁集团的大牌不仅仅是为了谋生。 他们必须有很多措施来确保支付安全。
第三个数据碰撞问题是用户A生成的支付码和用户B生成的支付码是一样的,这和Hash算法是一样的。 不管算法有多好,都有可能产生相同的哈希值。
这就导致本来钱是从用户A身上扣的,最后却扣到了用户B身上。 这样看来,确实是一个错误。 对于用户B来说,钱被莫名其妙的扣了。

不过别担心,到现在为止,我觉得这种事情还是比中彩票低的,所以你不用太担心这种事情。
即使误扣了,也不用担心,支付宝因为规模大,肯定会给客户赔钱。
终于
最后总结一下,我们通常都是使用支付码来支付的。 其实原理就是商家获取我们手机APP的支付码(实际上是一串数字),然后在后台调用支付宝支付接口完成扣款。
对于这个过程,商家的后台程序必须是在线的,但是对于我们的客户端来说,可以是在线的,也可以是离线的。
如果我们的客户端在线,我们可以通过服务器将支付码发送给客户端。 这种方式比较安全灵活,但在弱网环境下体验很差。
如果我们的客户端没有互联网连接,那么客户端将通过一定的算法生成支付代码。 服务器会收到相关验证并确认是哪个用户,确认代码的有效性,并完成扣费。 这种方式适用于客户端没有网络的情况,但灵活性相对较差,安全性稍差。
呵呵,明白了原理之后,是不是觉得挺有趣的呢~
下次排队缴费的时候,不用担心手机无法上网的尴尬,拿出手机就可以缴费啦~
参考…/2014/09/14/…作者:楼下哥哥
关联: