Laravel 下微信小程序支付 API 配置

仅此文章记录一下蛋疼的微信小程序支付?

小程序微信支付基本介绍

小程序支付的文档地址见 (小程序微信支付API)以及 小程序支付业务流程

在业务流程里我们可以看到几个基础的步骤。

  1. 首先要获取到用户的openid
  2. 调用微信的统一下单API来生成订单
  3. 服务器再次进行签名
  4. 接收支付通知
  5. 查询支付结果

我在开发过程中碰到的主要问题就是服务器进行再次签名,这里主要是微信的文档写着比较模糊。导致在这里浪费了比较多的精力。

服务器端代码

首先引入 @安正超 大大的 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 协议》,转载必须注明作者和本文链接
There's nothing wrong with having a little fun.
本帖由系统于 5年前 自动加精
Epona
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 20

原来还有这个方法啊~,前两天写的时候发现返回的参数签名失败,翻了下源码发现没签名,然后就自己动手二次签名了一下

5年前 评论
Epona

@Seaony 多看看源代码,总归有一些好处?

5年前 评论

确实文档上没有说明。。刚做的小程序支付也是在源码中bridgeConfig这个方法搞得签名 :joy:

5年前 评论
Epona

@skywingfs 微信坑的1B?

5年前 评论
ThinkQ

很好用

5年前 评论

调用微信支付order->unify 之后出现下面错误,有人遇到过吗?怎么解决的额

Argument 2 passed to EasyWeChat\Payment\Kernel\BaseClient::resolveResponse() must be of the type string, null given, called in /home/wwwroot/dev.pinkr.com/vendor/overtrue/wechat/src/Payment/Kernel/BaseClient.php on line 86
5年前 评论
Epona

@Li-people 提示你缺少参数了,你应该是哪个参数没有传,仔细看看微信支付的文档,把该传的参数都带上就好了。

5年前 评论

Call to undefined function App\Http\Controllers\Api\generate_sign()????这个错误谁遇到啦~~~

5年前 评论
Epona

@懵圈的开发

use function EasyWeChat\Kernel\Support\generate_sign;

注意这个

5年前 评论

嗯嗯 已经实现 感谢楼主

5年前 评论

file
$reset['prepay_id'],
$reset['nonce_str'],是什么意思呢 为什么从 $reset里取 $reset也没有定义啊

5年前 评论
Epona

@懵圈的开发 prepay_id 和nonce_str 是微信统一下单之后返回的结果

5年前 评论

感谢,按照 easywechat 文档没成功,按照你这个成功了。我觉得有必要把你这个更新到 easywechat 文档上去。

5年前 评论
CreaPlus

二次签名中的 'appId' 是不是应该在返回参数中unset掉?

5年前 评论
Epona

@CreaPlus 是的,不应当暴露给前端

5年前 评论

第一步生成订单就提示签名失败,是什么问题,配置没有问题,不知这个扩展要如何调试。

4年前 评论
Epona

@yuzhewo 那就是没有配置好,再仔细检查一下吧,包括代码和 微信商户的配置

4年前 评论

统一下单失败,返回是success,但是err_code_des appid和openid不匹配

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!