最近在做一个微信小程序,然后里面涉及到了支付的内容,本来以为微信支付挺简单的,当我开始写支付后台去看微信提供的支付文档的时候我就崩溃了,文档写了跟没写一样。
本来是准备原生的php写后来觉得还是不太安全,而且真的文档不全很麻烦,就去找了一个类库。一会也会介绍一下这个类库的坑。
1 . 微信支付流程
好了,这大概就是微信支付的流程了。下面来具体的说一下:
首先是小程序调用 wx.login 获取用户当前登陆的 code 这个code是会变化的,并不能作为用户的标识
1
2
3
4
5wx.login({
success(res) {
console.log(res.code); //获取的code
}
}然后把 code 当做参数请求微信接口获取 opencode 这个就是用户的标识。这一步操作我把它放在了服务端,也就是我们的服务器会去请求微信的接口获取 opencode 返回给小程序。
后端做的就是请求微信接口:
1
$ret = curl_get_https("https://api.weixin.qq.com/sns/jscode2session?appid={$config['appId']}&secret={$config['secret']}&js_code=$code&grant_type=authorization_code");
可以看到这里后台就是请求了这个 url 里面带了三个动态参数,有appid,secret都是在小程序的管理界面能看到的。code就是我们上一步获取到的,最后一个参数固定的。
获取到用户的opencode之后就可以让后台请求微信支付接口进行订单生成了。
后台请求支付接口,生成订单:
请求地址为:
https://api.mch.weixin.qq.com/pay/unifiedorder
一些常见的必传参数是:1
2
3
4
5
6
7
8
9
10
11
12'appid' 微信支付分配的公众账号ID(企业号corpid即为此appId)
'mch_id' 微信支付分配的商户号,这个需要登录商户平台,申请通过以后直接就能看到的
'prepayid' $prepay_id
'noncestr' 随机字符串,长度要求在32位以内,这个随便生成。
'sign' 通过签名算法计算得出的签名值,这个就是把请求的所有参数按照key的字典序拼串key1=val1&key2=val2,最后拼上密钥key 的key和value
'package' prepay_id=$prepay_id
'body' 商品简单描述
'total_fee' 订单总金额,单位为分
'notify_url' 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
'out_trade_no' 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母
'spbill_create_ip' 支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
'trade_type ' JSAPI -JSAPI支付NATIVE -Native支付APP -APP支付上述的操作完成以后,需要写一个通知回调的地址,这个地址里面的逻辑代码就是处理我们数据库订单的内容,比如把订单状态设置为已支付,或者创建订单将货物设置为已发货。这个回调在不出任何问题的情况下我们需要返回一段特定的字符串,否则微信认为逻辑没有执行成功,他会继续回调这个回调地址。如果你发现你的逻辑是错的他一直回调这个地址貌似没有办法让他停止回调,他可能有自己的策略在一定时间后停止回调。成功的字符串是:
1
echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
注意不要再有其他的任何输出,并且字符串中不要有空格。
最后会返回订单的信息,此时只需要调用微信小程序的 wx.requestPayment 并且传递以下必要参数:
1
2
3
4
5'timeStamp': data['timestamp'],
'nonceStr': data['noncestr'],
'package': data['package'],
'signType': 'MD5',
'paySign': data['sign'],这时小程序会自动拉起微信支付进行支付。