thinkphp5使用easywechat集成微信扫码支付
微信扫码支付用起来还是很方便的,如果使用微信支付官方的sdk开发也是可以的,不过还是选择了easywechat,主要还是因为easywechat集成了各种功能,基本上和微信相关的接口都做了比较不错的封装,因为要同时使用很多功能,索性微信扫码支付也一并用easywechat做了,而且不得不说使用方法是十分的简单,不多说了直接上步骤:
1,使用composer在thinkphp5项目的根目录安装easywechat:
- $ composer require overtrue/wechat:~3.1 -vvv
2,安装好之后在控制器中开始使用,示例代码:
① 配置,我这里的相关配置项是放在extra目录的wechat.php,内容如下:
- return [
- /**
- * Debug 模式,bool 值:true/false
- *
- * 当值为 false 时,所有的日志都不会记录
- */
- 'debug' => true,
- /**
- * 账号基本信息,请从微信公众平台/开放平台获取
- */
- 'app_id' => 'wx851*****5f7e8', // AppID
- 'secret' => 'fdb592c******3828fdfd273', // AppSecret
- 'token' => 'TOKEN', // Token
- 'aes_key' => '', // EncodingAESKey,安全模式下请一定要填写!!!
- /**
- * 日志配置
- *
- * level: 日志级别, 可选为:
- * debug/info/notice/warning/error/critical/alert/emergency
- * permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644)
- * file:日志文件位置(绝对路径!!!),要求可写权限
- */
- 'log' => [
- 'level' => 'debug',
- 'permission' => 0777,
- 'file' => ROOT_PATH . 'runtime/wechat/easywechat.log',
- ],
- /**
- * OAuth 配置
- *
- * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
- * callback:OAuth授权完成后的回调页地址
- */
- 'oauth' => [
- 'scopes' => ['snsapi_userinfo'],
- 'callback' => '/examples/oauth_callback.php',
- ],
- /**
- * 微信支付
- */
- 'payment' => [
- 'merchant_id' => '135*****602',
- 'key' => '80b8682*****8fdac7784',
- 'cert_path' => ROOT_PATH . 'public/certs/wechat/apiclient_cert.pem', // XXX: 绝对路径!!!!
- 'key_path' => ROOT_PATH . 'public/certs/wechat/apiclient_key.pem', // XXX: 绝对路径!!!!
- 'notify_url' => 'http://*******/notify/wxpay',
- ],
- /**
- * Guzzle 全局设置
- *
- * 更多请参考: http://docs.guzzlephp.org/en/latest/request-options.html
- */
- 'guzzle' => [
- 'timeout' => 3.0, // 超时时间(秒)
- //'verify' => false, // 关掉 SSL 认证(强烈不建议!!!)
- ],
- ];
扫码支付主要需要的配置是appid 已经payment相关的配置项,配置好之后,在控制器内开始使用:
②控制器代码:
- <?php
- /**
- * FileName:Pay.php
- * Author:Graent <[email protected]> at www.diyi01.com
- * Copyright:
- * CreateTime:2017/10/12 18:43
- * Description:
- */
- namespace app\payment\controller;
- use EasyWeChat\Foundation\Application;
- use EasyWeChat\Payment\Order;
- use Endroid\QrCode\QrCode;
- use Endroid\QrCode\ErrorCorrectionLevel;
- class Wxpay extends Prepay
- {
- public function index(){
- //获取微信配置
- $wxConf = config('wechat');
- //实例化easyWeChat
- $wxApp = new Application($wxConf);
- //支付订单参数
- $attributes = [
- 'trade_type' => 'NATIVE', // JSAPI,NATIVE,APP...
- 'body' => '这里是body',
- 'detail' => '这里是detail,可选',
- 'out_trade_no' => '自己生成自己站点的唯一单号',
- 'total_fee' => 1 * 100, // 单位:分// 支付结果通知网址,如果不设置则会使用配置里的默认地址
- ];
- //初始化订单
- $order = new Order($attributes);
- //实例化支付
- $payment = $wxApp->payment;
- //预支付
- $result = $payment->prepare($order);
- if ($result->return_code == 'SUCCESS' && $result->result_code == 'SUCCESS'){
- $prepayId = $result->prepay_id;
- $codeUrl = $result->code_url;
- //生成二维码
- $Qr = new QrCode($codeUrl);
- $Qr->setSize(300)
- ->setWriterByName('png')
- ->setMargin(10)
- ->setEncoding('utf-8')
- ->setErrorCorrectionLevel(ErrorCorrectionLevel::HIGH)
- ->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0])
- ->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255])
- // ->setLogoPath(ROOT_PATH . 'template/common/images/wxpay.png')
- // ->setLogoWidth(65)
- ->setValidateResult(false);
- $Qr->writeFile(ROOT_PATH . "uploads/qrcode.png");
- $imgData= imgToBase64(ROOT_PATH . "uploads/qrcode.png");
- return json(['errcode'=>0,'msg'=>'发起支付成功','imgData'=>$imgData]);
- }else{
- return json(['errcode'=>1,'msg'=>'发起支付失败,稍后再试吧']);
- }
- }
- }
代码中使用的是Endroid生成的二维码,预支付成功之后微信支付服务器返回的是用于生成二维码的内容(code_url),可以自己通过一些类库生成二维码展现给客户扫描就可以了,我这里生成二维码之后转换成了base64返回前端的,也可以不这样,看你自己的需求吧,这样发起支付基本就可以工作了,最后就是回调通知,这一步是必须的,用户支付完成后微信支付服务器会发post请求到商户设置的notify_url通知商户支付状态已经传回诸如商户单号等参数,方便商户操作站点内的订单的状态等:
- <?php
- /**
- * FileName:Notify.php
- * Author:Graent <[email protected]> at www.diyi01.com
- * Copyright:
- * CreateTime:2017/10/14 13:18
- * Description:
- */
- namespace app\payment\controller;
- use app\payment\model\MemberFreezingAmount;
- use EasyWeChat\Foundation\Application;
- use think\Db;
- class Notify extends Prepay
- {
- public function notify(){
- $payType = input('paytype');
- if($payType == 'wxpay'){
- //微信支付notify
- $wxConf = config('wechat');
- $wxApp = new Application($wxConf);
- $response = $wxApp->payment->handleNotify(function ($notify,$successful){
- if($successful){
- $rstArr = json_decode($notify,true);
- $ord = (new MemberFreezingAmount())
- ->where('trade_no','=',$rstArr['out_trade_no'])
- ->find();
- if($ord['status'] != 0){
- Db::name('member_freezing_amount')
- ->where('trade_no','=',$rstArr['out_trade_no'])
- ->update([
- 'status' => 0,
- 'transaction_id' => $rstArr['transaction_id'],
- 'pay_time' => time()
- ]);
- Db::name('mht_goods')
- ->where('id','=',$ord['gid'])
- ->setInc('bmnum');
- }
- return true;
- }else{
- return false;
- }
- });
- return $response;
- }else{
- //预留处理
- return false;
- }
- }
- }
easywechat帮我们封装了回调的处理直接使用即可 $response = $wxApp->payment->handleNotify(function ($notify,$successful){})其中$notify就是微信支付返回的信息,$successful是状态,true即为成功,那么商户就可以进行自己的业务操作了,参考上面的带可以实现基本的处理,如果有更多自己的逻辑自己在对应的位置增加自己的处理即可。
注意,在发起支付的时候很多人遇到过签名错误的问题,一般情况仔细检查下商户的支付key是一下是否一致,一般就可以解决这个问题,好了,另外微信返回的二维码有效期是2个小时,朋友们可以自行处理,微信扫码支付就这么做完了,希望可以给一些朋友提供一些参考。
最后贴一张效果截图: