从零开始一步一步用Laravel5.2集成原生微信支付
目前微信支付集成到框架里面有太多的坑了,项目中刚好遇到一个,把经验和重要的坑写出来,一步一步从0开始,大家有什么不会的可以留言。
1.首先,我们要去官方下载人家做好的DEMO,链接是https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
2.下载好以后,我们可以把里面的东西放到app\Wechat里(文件夹需要新建)
3.打开lib/WxPay.Config.php,把里面四个重要参数改成自己的,下面有两个证书路径,如果有退款什么的才需要,光支付就不管他
const APPID = '在你的公众号里看'; const MCHID = '商户ID'; const KEY = '自己在公众号设置的32位'; const APPSECRET = '也在公众号里看';
4.在resource/view/下新建文件夹wechat,里面视图就把app\Wechat里面的jsapi.php改名为jsapi.blade.php放进去,这里要说一下,引用的文件路径,必须是我这种格式
“../app/Wechat”下才能正确读取,而且把所有app/Wechat下的文件都打开,里面只要用到路径,你就在前面加个“../app/Wechat/”。
<?php ini_set('date.timezone','Asia/Shanghai'); //error_reporting(E_ERROR); require_once "../app/Wechat/lib/WxPay.Api.php"; require_once "../app/Wechat/example/WxPay.JsApiPay.php"; require_once '../app/Wechat/example/log.php'; //①、获取用户openid $tools = new JsApiPay(); $openId = $tools->GetOpenid("/wechat?money=".$money); //传参要这样传,还要改一下example/WxPay.JsApiPay.php文件 //②、统一下单 $input = new WxPayUnifiedOrder(); $input->SetBody("微信支付"); $input->SetAttach("微信支付"); $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis")); $input->SetTotal_fee($money); $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 600)); $input->SetGoods_tag(""); $input->SetNotify_url("http://aaa.com/wechat/notify");//这里填你的回调路径,是绝对路径,例如http://aaa.com/wechat/notify $input->SetTrade_type("JSAPI"); $input->SetOpenid($openId); $order = WxPayApi::unifiedOrder($input); // echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>'; // printf_info($order); $jsApiParameters = $tools->GetJsApiParameters($order); //获取共享收货地址js函数参数 $editAddress = $tools->GetEditAddressParameters(); //③、在支持成功回调通知中处理成功之后的事宜,见 notify.php /** * 注意: * 1、当你的回调地址不可访问的时候,回调通知会失败,可以通过查询订单来确认支付是否成功 * 2、jsapi支付时需要填入用户openid,WxPay.JsApiPay.php中有获取openid流程 (文档可以参考微信公众平台“网页授权接口”, * 参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html) */ ?> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>微信支付</title> <script src="http://7xwdxi.com1.z0.glb.clouddn.com/lib/js/jquery-2.0.3.min.js"></script> <script type="text/javascript"> //调用微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, function(res){ //这底下的东西就是上面$input->SetNotify_url("http://aaa.com/notify");这个传过来的 WeixinJSBridge.log(res.err_msg); // alert(res.err_code+res.err_desc+res.err_msg); if (res.err_msg == "get_brand_wcpay_request:ok") { //如果微信支付成功 // message: "微信支付成功!" alert("支付成功!"); window.location.href="/wechat/do;//你成功后要跳转的页面或控制器 }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ //如果取消微信支付 alert("您已取消支付"); } } ); } function callpay() { if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } } </script> <script type="text/javascript"> //获取共享地址 function editAddress() { WeixinJSBridge.invoke( 'editAddress', <?php echo $editAddress; ?>, function(res){ var value1 = res.proviceFirstStageName; var value2 = res.addressCitySecondStageName; var value3 = res.addressCountiesThirdStageName; var value4 = res.addressDetailInfo; var tel = res.telNumber; alert(value1 + value2 + value3 + value4 + ":" + tel); } ); } window.onload = function(){ if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', editAddress, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', editAddress); document.attachEvent('onWeixinJSBridgeReady', editAddress); } }else{ editAddress(); } }; </script> </head> <body> <div class="title-bar"> <span><a href="/home/student/pay"><img src="http://7xwdxi.com1.z0.glb.clouddn.com/images/back-icon.png"></a></span> <h1>充值</h1> </div> <br/> <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px"><?php $sum=$money/100; ?>{{$sum}}</span>元钱</b></font><br/><br/> <div align="center"> <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >立即支付</button> </div> </body> </html>
5.把example/notify.php复制一下,放到view/wechat/下,改名为notify.blade.php
6.写控制器,新建控制器叫WechatController
... public function index(Request $request){ if(!is_numeric(Input::get('money'))){ return Redirect::back(); } $money = Input::get('money')*10; //因为微信的钱是按分为单位,所以传进来,先*10,然后微信会回调回来,在执行一次这个方法,所以再*10,如果是5元,传个5就变成500分,就是5元钱了 return view("home.student.jsapi") ->withMoney($money);//把money作为参数带到jsapi.blade.php } public function notify(){ return view("home.wechat.notify"); }7.注册路由(这里最好用any的方法,因为发过去是post,回来的是get)
Route::any(‘wechat’,'WechatController@index'); Route::any(‘wechat/notify’,'WechatController@notify');
8.app/Wechat/example/WxPay.JsApiPay.php里面的getopenid方法还要改一下,否则不能传参数
... public function GetOpenid($addUrl="") { //通过code获得openid if (!isset($_GET['code'])){ //触发微信返回code码 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$addUrl); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = $this->getOpenidFromMp($code); return $openid; } }...
9.这样程序这块基本就完事了,访问时你要花的钱要这么传http://aaa.com/wechat?money=5(这样的话是充5元钱)
10.下面就要说说微信公众平台上,一共要改3个地方
(1)在开发者工具下面,修改网页账号(否则通过不了Oauth2.0验证会报redirect_url错误)
(2)验证你的URL,URL就是这个验证文件在项目中的位置,如果放到public文件夹下,你就直接写http://aaa.com/wx_sample.php
验证文件如下:
wx_sample.php
<?php /** * wechat php test */ //define your token define("TOKEN", "weixin");//和你在公众号中填的TOKEN相同 $wechatObj = new wechatCallbackapiTest(); $wechatObj->valid(); class wechatCallbackapiTest { public function valid() { $echoStr = $_GET["echostr"]; //valid signature , option if($this->checkSignature()){ echo $echoStr; exit; } } public function responseMsg() { //get post data, May be due to the different environments $postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //extract post data if (!empty($postStr)){ /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection, the best way is to check the validity of xml by yourself */ libxml_disable_entity_loader(true); $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $fromUsername = $postObj->FromUserName; $toUsername = $postObj->ToUserName; $keyword = trim($postObj->Content); $time = time(); $textTpl = "<xml> <ToUserName><![CDATA[%s]]></ToUserName> <FromUserName><![CDATA[%s]]></FromUserName> <CreateTime>%s</CreateTime> <MsgType><![CDATA[%s]]></MsgType> <Content><![CDATA[%s]]></Content> <FuncFlag>0</FuncFlag> </xml>"; if(!empty( $keyword )) { $msgType = "text"; $contentStr = "Welcome to wechat world!"; $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); echo $resultStr; }else{ echo "Input something..."; } }else { echo ""; exit; } } private function checkSignature() { // you must define TOKEN by yourself if (!defined("TOKEN")) { throw new Exception('TOKEN is not defined!'); } $signature = $_GET["signature"]; $timestamp = $_GET["timestamp"]; $nonce = $_GET["nonce"]; $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); // use SORT_STRING rule sort($tmpArr, SORT_STRING); $tmpStr = implode( $tmpArr ); $tmpStr = sha1( $tmpStr ); if( $tmpStr == $signature ){ return true; }else{ return false; } } } ?>
(3)修改开发配置(支付授权目录和测试授权目录),这里要注意,如果你的支付路径是http://aaa.com/index.php/wechat,你就填http://aaa.com/index.php/,反正就是最后那个斜杠后面的别加
哈哈,大功告成~微信支付能用了~