laravel+php+微信扫码支付
2016-02-25 20:52
585 查看
第一个博客
写这个的原因是因为以前配置过很多环境,过一段就会忘掉,当需要在用的时候就要重新花费好久来搞。这词做这个关于微信支付的项目,在如何使用php的laravel框架加入微信扫码支付的功能上花了太久的时间,不希望自己以后再踩同样的坑,也希望可以帮到别人。第一次写博客,可能写不清楚,请大家见谅。
说明:本文说的是微信支付的第二种模式
准备工作:
在微信支付官网的SDK下载中下载对应的php代码配置好laravel需要的基本环境
获得支付所需的配置信息:appid、cmhid、key,获取方式在sdk中有说明
/** * TODO: 修改这里配置为您自己申请的商户信息 * 微信公众号信息配置 * * APPID:绑定支付的APPID(必须配置,开户邮件中可查看) * * MCHID:商户号(必须配置,开户邮件中可查看) * * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置) * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert * * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN * @var string */ const APPID = 'wx8dce35348ad73e3'; const MCHID = '131547990'; const KEY = '5f980c0c9548833f3260e82dc2ce33'; const APPSECRET = '01c6d59a3f9024db6336662ac95c8e74';
配置当然就是写在sdk的这个配置文件中:WxPay.config.php,就是上面贴的那段代码。
重要的坑
sdk中的所有文件引用都是 相对路径,但是laravel的所有相对路径都是以单入口文件public/index.php为当前文件的,所以 要把sdk中所有的require_once 以及log的目录地址,都换成以public/index.php为当前目录的相对路径。比如:我把整个sdk放在了项目路径app/Http/下面,和controller并立(不要吐槽我),那么我的sdk中的相对路径就是require_once "../app/Http/WxPaySDK/lib/WxPay.Exception.php";这样的。其中lib是对应sdk中的lib,当然也有是example的,根据需要换掉就行。换掉所有的相对路径后,就可以开始做支付功能了。
顺便吐槽,本来想用namespace 和 use 来处理的 可是微信的sdk中一个文件里好几个类,还有log这样的很容易冲突的类名,最后懒得处理,就还用require引用了。
生成二维码连接
在sdk中,负责生成二维码的是native.php这个文件,其中的有用代码是://模式一 /** * 流程: * 1、组装包含支付信息的url,生成二维码 * 2、用户扫描二维码,进行支付 * 3、确定支付之后,微信服务器会回调预先配置的回调地址,在【微信开放平台-微信支付-支付配置】中进行配置 * 4、在接到回调通知之后,用户进行统一下单支付,并返回支付信息以完成支付(见:native_notify.php) * 5、支付完成之后,微信服务器会通知支付成功 * 6、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php) */ $notify = new NativePay(); $url1 = $notify->GetPrePayUrl("123456789"); //模式二 /** * 流程: * 1、调用统一下单,取得code_url,生成二维码 * 2、用户扫描二维码,进行支付 * 3、支付完成之后,微信服务器会通知支付成功 * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php) */ $input = new WxPayUnifiedOrder(); $input->SetBody("test"); $input->SetAttach("ljm"); $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis")); $input->SetTotal_fee("1"); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); $input->SetGoods_tag("test"); $input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php"); $input->SetTrade_type("NATIVE"); $input->SetProduct_id("123456789"); $result = $notify->GetPayUrl($input); // var_dump($result);die; $url2 = $result["code_url"];
注意模式一的第一行new的对象,在模式二中最后有用,我用的是模式二的方式。以上代码,其实是用来生成一个$result,这是sdk根据设置的参数生成好的,参数里SetBody是扫码支付时最上面的标题,SetOut_trade_no是设置商户订单号(支付结果会带回来,以便对相应订单状态做更改)。SetTotal_fee是支付金额,单位是分。其他具体参数,参看统一订单(不太需要了)。
知道了怎么配置参数,那接下来就需要把这些代码拷贝到controller的某处,做一个接口来调用,接口传入商家要支付的商品的那个订单号(不是微信的支付号,是商家自己的订单编号),然后用某种方式生成out_trade_no就行了。不废话,贴代码
/** *GET localhost/youge/blog/public/File/getQrcode * *获取付款二维码url的参数 * */ require_once "../app/Http/WxPaySDK/lib/WxPay.Api.php"; require_once "../app/Http/WxPaySDK/example/WxPay.NativePay.php"; //注意引入文件的路径 public function getQrcode(Request $request) { $file_id = $request->input('file_id', ''); $out_trade_no = WxPayConfig::MCHID . date("YmdHis") . $file_id; //我的out_trade_no是这么做的 由于我的file_id(就是我的商家订单)是唯一的,所以无论如何这个结果都是唯一的 $notify = new NativePay(); $input = new WxPayUnifiedOrder(); $input->SetBody("这里写这是什么服务项目的支付"); $input->SetAttach("ljm"); $input->SetOut_trade_no($out_trade_no); $input->SetTotal_fee("600"); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); $input->SetGoods_tag("test"); $input->SetNotify_url("http://127.0.0.1/youge/blog/public/index.php/payNotify"); //这里设置支付成功后的回调接口,不能有参数。还有,这里的127.0.0.1是收不到微信后台发出的回调函数的,只能用服务器来测试了。 $input->SetTrade_type("NATIVE"); $input->SetProduct_id("123456789"); $result = $notify->GetPayUrl($input); $url = $result["code_url"]; $file = File::where('id', $file_id)->first(); if (!empty($file)) { $file->out_trade_no = $out_trade_no; $file->save(); } //这段是把out_trade_no和要处理的订单关联起来 return "http://paysdk.weixin.qq.com/example/qrcode.php?data=" . $url; }
最后的return是一个微信的连接,data后面的值是sdk生成的一小串字符串,用来生成二维码。把这个return的完整字符串放入HTML的img标签,就是一个二维码了。
支付通知获取
根据官网的说明 点这里,支付成功后,微信会发送POST的请求,到上面你设置的通知回调接口,在sdk中,回调接口是example/notify.php但是在laravel中,接口要放在controller中,所以我们新建一个controller,写个route文件接口,从这个controller中调用这个notify.php,怎么调用呢。
首先,把notify中的最下面的几行和最上面的几行不在函数中的代码
$logHandler= new CLogFileHandler("../app/Http/WxPaySDK/logs/".date('Y-m-d').'.log'); $log = Log::Init($logHandler, 15); Log::DEBUG("begin notify"); $notify = new PayNotifyCallBack(); $notify->Handle(false);
然后写个public static function notifyReceive()放进去,这样就可以从controller中直接调用它了
PayNotifyCallBack::notifyReceive(); //PayNotifyCallBack 是notify.php中的类名
至此,应该说扫码支付的模式二就实现了。
此外,在notify.php的回调函数中可以把自己业务的逻辑代码放在这里
public function NotifyProcess($data, &$msg) { Log::DEBUG("call back:" . json_encode($data)); $notfiyOutput = array(); if(!array_key_exists("transaction_id", $data)){ $msg = "输入参数不正确"; return false; } //查询订单,判断订单真实性 if(!$this->Queryorder($data["transaction_id"])){ $msg = "订单查询失败"; return false; } //这里以下//////////////////////// $file = File::where('out_trade_no', $data['out_trade_no'])->first(); if (!empty($file)) { $file->status = File::FILE_PAYED; $file->save(); } //这里以上///////////////////////就是在这个return true之前,表示验证没有问题,支付成功时执行这部分业务逻辑 return true; }
相关文档
微信扫码模式二介绍二维码生成(统一下单接口)
支付结果通知回调接口
相关文章推荐
- php中字符串常用的截取操作
- 黄聪:PHP代码性能加速-开启Zend OPcache-优化CPU
- php7做的一些改变
- ContentProvider 一个应用程序访问另一个应用程序
- PHP内核探索之变量(2)-理解引用
- php内核探索之变量Zval(1)
- php如何实现验证码
- install php
- 改变TPageControl的活动标签颜色
- Yii建立组件
- PHP初学之字符串函数
- PHP初学之字符串
- php四种基础算法:冒泡,选择,插入和快速排序法
- LeetCode_5_LongestPalindromicSubstring(最长回文子序列)
- 黄聪:深入理解PHP Opcode缓存原理
- php 去掉Url里的 index.php
- 高通平台手机开发之TP
- PHP之标准类
- PHP基础
- php中的&