小程序支付金额被“篡改”,0.01元支付任意订单,怎么防?

根据真实案例

前言

在论坛里,看到一位前端开发者的求助贴。

他做的小程序中,有订单支付页面,用户输入 200 元,确认支付。然后调用后端接口,传递参数。

在开发者工具里,可以清晰地看到,请求的链接地址,请求参数体数据。

他担心,有中间人攻击,直接绕过小程序端,针对接口直接下单,把金额改成 0.01 元,是不是 1 分钱就可以获得 200 元的订单。

真实案例截图1

真实案例截图2

解读

这是小程序开发中,带有支付模块,常见的问题之一。

微信小程序支付的一般流程

微信小程序发起支付的流程,主要包括以下步骤:

1. 小程序端:用户向商户服务器发起支付请求

当用户点击支付按钮时,给后端接口发起一个请求,携带必要的参数(如:body, total_fee 等)。例如:

1
2
3
4
5
6
7
import http from "../utils";

// 向后端发请请求
const res = await http.post("/payment/order", {
  body: "腾讯QQ-购买会员", // 商品描述
  total_fee: 998, // 总金额,单位为分
});

如果接口返回的状态为200,那么得到接口返回的数据,然后向微信发起支付。

2. 后端:调用统一下单接口得到 prepay_id

在后端,需要调用微信的统一下单接口,获取到prepay_id,然后将支付所需参数返回前端。

3. 小程序端:向微信服务器发起请求

前端根据后端返回的参数,调用微信的wx.requestPayment()接口,唤起支付界面。

4. 小程序端:根据不同的支付结果给用户不同的提示

前端根据支付结果,给用户不同的提示。例如,支付成功后显示“支付成功”,支付失败后显示“支付失败”。

5. 微信服务器:支付结果通知

在第2步中,统一下单接口发起请求时,附带了一个notify_url,此地址一定要是可公网访问的接口地址,由微信服务器调用该接口,不管支付成功与否,此接口都会调用,并返回相应数据。

商户可以在此接口中编写相关业务逻辑,如支付成功后写入数据库等操作。

问题

结合上述流程,提问者担心的,其实是第 1 步中的 total_fee,被中间人攻击给篡改了。

其实,对于前端下单、后端校验的订单,大可不必担心。

payment

1,固定金额

比如会员卡支付界面,固定的几个卡,金额标记好了。下单的时候,不需要传金额,直接给卡片ID。

后端接到 ID 之后,拿到配置的商品金额,对服务器预下单。回传 prepay_id 给小程序端之后,小程序端已经没办法修改任何参数了。

vip卡

2,手动输入

手动输入的金额,比较不好控制。但尽量做到数据校验。

小程序端,保证输入的是约定好范围的整数、小数,比如 1.78 元,285.90 元,做数据有效的初步拦截。

后端程序,则验证传过来的数据,是否符合有效性。如果无效,无需下单,直接返回前端:“参数错误”。

3,签名与验签

签名流程

小程序的请求,为什么会有“域名白名单”?

因为,小程序内的请求 wx.request(), 不是直接从小程序,发给服务器地址的,而是借助微信SDK,转一手发出去的。不在白名单的域名,在SDK这个环节就拦截了。

提问者遇到的问题,就是安全检测机构,使用检测工具,抓取到了SDK发送到服务器的参数和地址。通过修改金额,顺利使用 10 元购买了 200 元的产品。

大家可能就想了,要是给 SDK 发出去的参数都加密,就好了。微信官方,一直就有最佳实践。文档地址在这里

公钥私钥

加密之前,data 的原始数据:

1
2
3
4
5
6
{
    "appid": "wxbxxx",
    "openid": "oE4Y9gJAM",
    "scene": 0,
    "client_ip": "127.0.0.1",
}

经过加密之后的参数:

1
2
3
4
5
{
    "iv": "fmW/zNxXlytUZBgj",
    "data": "0IDVdrPtSPF/Oe2CTXCV2vVNPbVJdJlP2WaTMQnoYLh5iCrrSNfQFh25EnStDMf0hLlVNBCZQtf9NaV0m4aRA4AAYIO7oR/Ge+4yY4EmZp5EVPB42xjScgMx5X3D4VdLCfynXIUKUtZHZvk1zmLVE3RauzJgiM1BB1CPmwcENo3MTJ0z8Vfkf5tMv54kOXobDLlV5rfqKdAX7gM/rP82DgZdt9vvZX44ipdbHIjJvw83ZXAFtvftdVw2Qd8=",
    "authtag": "5qeM/2vZv+6KtScN94IpMg=="
}

可以看到,data 经过加密之后,安全性大大提升了。

最后

本文从开发者常见的支付下单场景,简要说了说支付的流程。不唯前端,后端支付校验、回调验证、参数验证、订单去重等等功能,需要很多环节,给予安全保证。

我是@程序员小助手,专注编程知识,圈子动态的IT领域原创作者。