前言
在论坛里,看到一位前端开发者的求助贴。
他做的小程序中,有订单支付页面,用户输入 200 元,确认支付。然后调用后端接口,传递参数。
在开发者工具里,可以清晰地看到,请求的链接地址,请求参数体数据。
他担心,有中间人攻击,直接绕过小程序端,针对接口直接下单,把金额改成 0.01 元,是不是 1 分钱就可以获得 200 元的订单。
解读
这是小程序开发中,带有支付模块,常见的问题之一。
微信小程序支付的一般流程
微信小程序发起支付的流程,主要包括以下步骤:
1. 小程序端:用户向商户服务器发起支付请求
当用户点击支付按钮时,给后端接口发起一个请求,携带必要的参数(如:body, total_fee 等)。例如:
|
|
如果接口返回的状态为200,那么得到接口返回的数据,然后向微信发起支付。
2. 后端:调用统一下单接口得到 prepay_id
在后端,需要调用微信的统一下单接口,获取到prepay_id,然后将支付所需参数返回前端。
3. 小程序端:向微信服务器发起请求
前端根据后端返回的参数,调用微信的wx.requestPayment()
接口,唤起支付界面。
4. 小程序端:根据不同的支付结果给用户不同的提示
前端根据支付结果,给用户不同的提示。例如,支付成功后显示“支付成功”,支付失败后显示“支付失败”。
5. 微信服务器:支付结果通知
在第2步中,统一下单接口发起请求时,附带了一个notify_url
,此地址一定要是可公网访问的接口地址,由微信服务器调用该接口,不管支付成功与否,此接口都会调用,并返回相应数据。
商户可以在此接口中编写相关业务逻辑,如支付成功后写入数据库等操作。
问题
结合上述流程,提问者担心的,其实是第 1 步中的 total_fee
,被中间人攻击给篡改了。
其实,对于前端下单、后端校验的订单,大可不必担心。
1,固定金额
比如会员卡支付界面,固定的几个卡,金额标记好了。下单的时候,不需要传金额,直接给卡片ID。
后端接到 ID 之后,拿到配置的商品金额,对服务器预下单。回传 prepay_id
给小程序端之后,小程序端已经没办法修改任何参数了。
2,手动输入
手动输入的金额,比较不好控制。但尽量做到数据校验。
小程序端,保证输入的是约定好范围的整数、小数,比如 1.78 元,285.90 元,做数据有效的初步拦截。
后端程序,则验证传过来的数据,是否符合有效性。如果无效,无需下单,直接返回前端:“参数错误”。
3,签名与验签
小程序的请求,为什么会有“域名白名单”?
因为,小程序内的请求 wx.request()
, 不是直接从小程序,发给服务器地址的,而是借助微信SDK,转一手发出去的。不在白名单的域名,在SDK这个环节就拦截了。
提问者遇到的问题,就是安全检测机构,使用检测工具,抓取到了SDK发送到服务器的参数和地址。通过修改金额,顺利使用 10 元购买了 200 元的产品。
大家可能就想了,要是给 SDK 发出去的参数都加密,就好了。微信官方,一直就有最佳实践。文档地址在这里
加密之前,data 的原始数据:
|
|
经过加密之后的参数:
|
|
可以看到,data 经过加密之后,安全性大大提升了。
最后
本文从开发者常见的支付下单场景,简要说了说支付的流程。不唯前端,后端支付校验、回调验证、参数验证、订单去重等等功能,需要很多环节,给予安全保证。
我是@程序员小助手,专注编程知识,圈子动态的IT领域原创作者。