Laravel 下微信小程序支付 API 配置
仅此文章记录一下蛋疼的微信小程序支付?
小程序微信支付基本介绍
小程序支付的文档地址见 (小程序微信支付API)以及 小程序支付业务流程
在业务流程里我们可以看到几个基础的步骤。
- 首先要获取到用户的openid
- 调用微信的统一下单API来生成订单
- 服务器再次进行签名
- 接收支付通知
- 查询支付结果
我在开发过程中碰到的主要问题就是服务器进行再次签名,这里主要是微信的文档写着比较模糊。导致在这里浪费了比较多的精力。
服务器端代码
首先引入 @安正超 大大的 overtrue/laravel-wechat
composer包。当然引入 overtrue/wechat
也是可以的。基础的配置文件就不说了。按照说明配置好就可以了。
获取小程序用户的 openid
在小程序中调用wx.login()
会返回一个code,将code参数传给我们的API中进行处理就可以得到openid了。 示例代码如下
$mini = \EasyWeChat::miniProgram();
$result = $mini->auth->session($code); // $code 为wx.login里的code
// 如果code正确的话,那么此时$result 里就会包含openid, session_key等信息。
// 此时可以将openid存储到自己需要的数据库中
// $result['openid'] = 'your-openid';
统一下单 && 二次签名
通过使用安正超大大封装的包,我们可以很方便的进行统一下单,不过与 easywechat 里的文档示例不太一样的是我们要传的参数要多一些。以及配置文件里的'notify_url'一定要配置正确。 具体代码如下
use function EasyWeChat\Kernel\Support\generate_sign;
$payment = \EasyWeChat::payment(); // 微信支付
$result = $payment->order->unify([
'body' => '你自己想写的名称',
'out_trade_no' => '你自己定义的订单号',
'trade_type' => 'JSAPI', // 必须为JSAPI
'openid' => '在上一步中获取到的openid', // 这里的openid为付款人的openid
'total_fee' => 1, // 总价
]);
// 如果成功生成统一下单的订单,那么进行二次签名
if ($result['return_code'] === 'SUCCESS') {
// 二次签名的参数必须与下面相同
$params = [
'appId' => '你的小程序的appid',
'timeStamp' => time(),
'nonceStr' => $result['nonce_str'],
'package' => 'prepay_id=' . $result['prepay_id'],
'signType' => 'MD5',
];
// config('wechat.payment.default.key')为商户的key
$params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
return $params;
} else {
return $result;
}
// 如果成功二次签名,返回的结果与下面的类似
// $params = {
// "appId": "wxedsadwvsager343df5",
// "timeStamp": 1520515252,
// "nonceStr": "wGs9JOpqKQcJYf7m",
// "package": "prepay_id=wx201803cdsqa2ae1e202110689669353",
// "signType": "MD5",
// "paySign": "398729A0461F5A825DA169CA29721038"
// }
在小程序支付文档中可能对二次签名加密说了很多的步骤,不过我在翻阅了overtrue/wechat
包之后,发现已经将二次签名方法封装了,所以直接引入use function EasyWeChat\Kernel\Support\generate_sign;
后进行调用即可。
最后付款API返回上面的$params供小程序端调用即可,当然,还有回调里的notify_url需要进行处理,可以参照 这里 进行处理。
小程序端代码实现
// 首先使用wx.request来调用上面的Laravel API 返回 data。
// 然后将获取到的参数传入到付款API里面就可以了。
// 如果一切顺利的话,微信小程序支付就成功的跑通了?
wepy.requestPayment({
timeStamp: data.timeStamp.toString(),
nonceStr: data.nonceStr,
package: data.package,
signType: data.signType,
paySign: data.paySign,
success: function(res) {
console.log('付款成功')
console.log(res)
},
fail: function(res) {
console.log('付款失败')
console.log(res)
}
})
本作品采用《CC 协议》,转载必须注明作者和本文链接
原来还有这个方法啊~,前两天写的时候发现返回的参数签名失败,翻了下源码发现没签名,然后就自己动手二次签名了一下
@Seaony 多看看源代码,总归有一些好处?
@Epona 哈哈,稳~
确实文档上没有说明。。刚做的小程序支付也是在源码中bridgeConfig这个方法搞得签名 :joy:
@skywingfs 微信坑的1B?
很好用
调用微信支付order->unify 之后出现下面错误,有人遇到过吗?怎么解决的额
@Li-people 提示你缺少参数了,你应该是哪个参数没有传,仔细看看微信支付的文档,把该传的参数都带上就好了。
Call to undefined function App\Http\Controllers\Api\generate_sign()????这个错误谁遇到啦~~~
@懵圈的开发
注意这个
嗯嗯 已经实现 感谢楼主
$reset['prepay_id'],
$reset['nonce_str'],是什么意思呢 为什么从 $reset里取 $reset也没有定义啊
@懵圈的开发 prepay_id 和nonce_str 是微信统一下单之后返回的结果
@Epona 了解了 非常感谢
感谢,按照 easywechat 文档没成功,按照你这个成功了。我觉得有必要把你这个更新到 easywechat 文档上去。
二次签名中的 'appId' 是不是应该在返回参数中unset掉?
@CreaPlus 是的,不应当暴露给前端
第一步生成订单就提示签名失败,是什么问题,配置没有问题,不知这个扩展要如何调试。
@yuzhewo 那就是没有配置好,再仔细检查一下吧,包括代码和 微信商户的配置
统一下单失败,返回是success,但是err_code_des appid和openid不匹配