从0开始一步一步用Laravel5.2集成原生微信支付

来源:互联网 发布:ubuntu 14.04 16.04 编辑:程序博客网 时间:2024/06/16 03:12

目前微信支付集成到框架里面有太多的坑了,项目中刚好遇到一个,把经验和重要的坑写出来,一步一步从0开始,大家有什么不会的可以留言。

1.首先,我们要去官方下载人家做好的DEMO,链接是https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
2.下载好以后,我们可以把里面的东西放到app\Wechat里(文件夹需要新建)
3.打开lib/WxPay.Config.php,把里面四个重要参数改成自己的,下面有两个证书路径,如果有退款什么的才需要,光支付就不管他


[php] view plain copy
  1. const APPID = '在你的公众号里看';  
  2. const MCHID = '商户ID';  
  3. const KEY = '自己在公众号设置的32位';  
  4. const APPSECRET = '也在公众号里看';  


4.在resource/view/下新建文件夹wechat,里面视图就把app\Wechat里面的jsapi.php改名为jsapi.blade.php放进去,这里要说一下,引用的文件路径,必须是我这种格式“../app/Wechat”下才能正确读取,而且把所有app/Wechat下的各种文件都打开,里面只要用到路径,你就在require_once后面加个“../app/Wechat/”

[php] view plain copy
  1. <?php   
  2.   
  3. ini_set('date.timezone','Asia/Shanghai');  
  4. //error_reporting(E_ERROR);  
  5. require_once "../app/Wechat/lib/WxPay.Api.php";  
  6. require_once "../app/Wechat/example/WxPay.JsApiPay.php";  
  7. require_once '../app/Wechat/example/log.php';  
  8.   
  9.   
  10. //①、获取用户openid  
  11. $tools = new JsApiPay();  
  12.   
  13. $openId = $tools->GetOpenid("/wechat?money=".$money); //传参要这样传,还要改一下example/WxPay.JsApiPay.php文件  
  14.   
  15. //②、统一下单  
  16. $input = new WxPayUnifiedOrder();  
  17. $input->SetBody("微信支付");  
  18. $input->SetAttach("微信支付");  
  19. $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));  
  20. $input->SetTotal_fee($money);  
  21. $input->SetTime_start(date("YmdHis"));  
  22. $input->SetTime_expire(date("YmdHis", time() + 600));  
  23. $input->SetGoods_tag("");  
  24. $input->SetNotify_url("http://aaa.com/wechat/notify");//这里填你的回调路径,是绝对路径,例如http://aaa.com/wechat/notify  
  25. $input->SetTrade_type("JSAPI");  
  26. $input->SetOpenid($openId);  
  27. $order = WxPayApi::unifiedOrder($input);  
  28. // echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';  
  29. // printf_info($order);  
  30. $jsApiParameters = $tools->GetJsApiParameters($order);  
  31.   
  32. //获取共享收货地址js函数参数  
  33. $editAddress = $tools->GetEditAddressParameters();  
  34.   
  35. //③、在支持成功回调通知中处理成功之后的事宜,见 notify.php  
  36. /** 
  37.  * 注意: 
  38.  * 1、当你的回调地址不可访问的时候,回调通知会失败,可以通过查询订单来确认支付是否成功 
  39.  * 2、jsapi支付时需要填入用户openid,WxPay.JsApiPay.php中有获取openid流程 (文档可以参考微信公众平台“网页授权接口”, 
  40.  * 参考http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html) 
  41.  */  
  42.   
  43.   
  44. ?>  
  45.   
  46. <html>  
  47. <head>  
  48.     <meta http-equiv="content-type" content="text/html;charset=utf-8"/>  
  49.     <meta name="viewport" content="width=device-width, initial-scale=1"/>   
  50.     <title>微信支付</title>  
  51.   
  52.     <script src="http://7xwdxi.com1.z0.glb.clouddn.com/lib/js/jquery-2.0.3.min.js"></script>  
  53.       
  54.     <script type="text/javascript">  
  55.     //调用微信JS api 支付  
  56.     function jsApiCall()  
  57.     {  
  58.         WeixinJSBridge.invoke(  
  59.             'getBrandWCPayRequest',  
  60.             <?php echo $jsApiParameters; ?>,  
  61.             function(res){      
  62.                                 //这底下的东西就是上面$input->SetNotify_url("http://aaa.com/notify");这个传过来的  
  63.                 WeixinJSBridge.log(res.err_msg);  
  64.                 // alert(res.err_code+res.err_desc+res.err_msg);  
  65.                 if (res.err_msg == "get_brand_wcpay_request:ok") { //如果微信支付成功  
  66.                     // message: "微信支付成功!"  
  67.                     alert("支付成功!");  
  68.                     window.location.href="/wechat/do;//你成功后要跳转的页面或控制器  
  69.                 }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ //如果取消微信支付  
  70.                     alert("您已取消支付");  
  71.                       
  72.                 }  
  73.             }  
  74.         );  
  75.     }  
  76.   
  77.     function callpay()  
  78.     {  
  79.         if (typeof WeixinJSBridge == "undefined"){  
  80.             if( document.addEventListener ){  
  81.                 document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);  
  82.             }else if (document.attachEvent){  
  83.                 document.attachEvent('WeixinJSBridgeReady', jsApiCall);   
  84.                 document.attachEvent('onWeixinJSBridgeReady', jsApiCall);  
  85.             }  
  86.         }else{  
  87.             jsApiCall();  
  88.         }  
  89.     }  
  90.     </script>  
  91.     <script type="text/javascript">  
  92.     //获取共享地址  
  93.     function editAddress()  
  94.     {  
  95.         WeixinJSBridge.invoke(  
  96.             'editAddress',  
  97.             <?php echo $editAddress; ?>,  
  98.             function(res){  
  99.                 var value1 = res.proviceFirstStageName;  
  100.                 var value2 = res.addressCitySecondStageName;  
  101.                 var value3 = res.addressCountiesThirdStageName;  
  102.                 var value4 = res.addressDetailInfo;  
  103.                 var tel = res.telNumber;  
  104.                   
  105.                 alert(value1 + value2 + value3 + value4 + ":" + tel);  
  106.             }  
  107.         );  
  108.     }  
  109.       
  110.     window.onload = function(){  
  111.         if (typeof WeixinJSBridge == "undefined"){  
  112.             if( document.addEventListener ){  
  113.                 document.addEventListener('WeixinJSBridgeReady', editAddress, false);  
  114.             }else if (document.attachEvent){  
  115.                 document.attachEvent('WeixinJSBridgeReady', editAddress);   
  116.                 document.attachEvent('onWeixinJSBridgeReady', editAddress);  
  117.             }  
  118.         }else{  
  119.             editAddress();  
  120.         }  
  121.     };  
  122.       
  123.     </script>  
  124.   
  125.   
  126. </head>  
  127. <body>  
  128.     <div class="title-bar">  
  129.         <span><a href="/home/student/pay"><img src="http://7xwdxi.com1.z0.glb.clouddn.com/images/back-icon.png"></a></span>  
  130.         <h1>充值</h1>  
  131.     </div>  
  132.     <br/>  
  133.     <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px"><?php $sum=$money/100; ?>{{$sum}}</span>元钱</b></font><br/><br/>  
  134.       
  135.     <div align="center">  
  136.         <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>  
  137.   
  138.     </div>  
  139.   
  140. </body>  
  141. </html>  


5.写控制器,新建控制器叫WechatController,主要是回调函数里写好你的逻辑(官方无回调文档,很坑)

[php] view plain copy
  1. ...  
  2. public function index(Request $request){  
  3.         if(!is_numeric(Input::get('money'))){  
  4.             return Redirect::back();  
  5.         }  
  6.         $money = Input::get('money')*10;   
  7. //因为微信的钱是按分为单位,所以传进来,先*10,然后微信会回调回来,在执行一次这个方法,所以再*10,如果是5元,传个5就变成500分,就是5元钱了  
  8.   
  9.         return view("home.student.jsapi")  
  10.             ->withMoney($money);//把money作为参数带到jsapi.blade.php  
  11.     }  
  12.   
  13. public function notify(){ //这里是你的回调函数,这个很坑,官方都没有文档的  
  14.      public function notify(Request $request){  
  15.         $streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : ''//拿到微信回调回来的信息判断支付成功没  
  16.   
  17.         if(empty($streamData)){  
  18.             $streamData = file_get_contents('php://input');  
  19.         }  
  20.   
  21.         if($streamData!=''){  
  22.             $streamData=xmlToArray($streamData);   
  23.             $Data=json_encode($streamData);  
  24.             Log::debug('Alipay notify post data verification fail.', [ //写入服务器文档,你不加这个也行  
  25.                 'data' => $Data.'xxxxxx'  
  26.             ]);  
  27.             if($streamData['return_code'] == 'SUCCESS' && $streamData['result_code'] == 'SUCCESS'){ //支付成功  
  28.                 try { //开始事务  
  29.                     //支付成功,你要干些什么都写这里,例如增加余额的操作什么的  
  30.   
  31.                 } catch (Exception $e) {  
  32.                     //如果try里面的东西出现问题的话,进行数据库回滚  
  33.                     throw $e;           
  34.                 }  
  35.                   
  36.             }  
  37.         }else{  
  38.             $ret = false; //支付失败  
  39.         }  
  40.     }  
  41.   }  
6.注册路由(这里最好用any的方法,因为发过去是post,回来的是get)
[php] view plain copy
  1. Route::any(‘wechat’,'WechatController@index');    
  2. Route::any(‘wechat/notify’,'WechatController@notify');  

7.app/Wechat/example/WxPay.JsApiPay.php里面的getopenid方法还要改一下,否则不能传参数
[php] view plain copy
  1. ...  
  2. public function GetOpenid($addUrl="")  
  3.     {  
  4.         //通过code获得openid  
  5.         if (!isset($_GET['code'])){  
  6.             //触发微信返回code码  
  7.   
  8.              $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$addUrl);  
  9.   
  10.              $url = $this->__CreateOauthUrlForCode($baseUrl);  
  11.              Header("Location: $url");  
  12.              exit();  
  13.          } else {  
  14.             //获取code码,以获取openid  
  15.                 $code = $_GET['code'];  
  16.             $openid = $this->getOpenidFromMp($code);  
  17.             return $openid;  
  18.         }  
  19.     }  
...

8.这样程序这块基本就完事了,访问时你要花的钱要这么传http://aaa.com/wechat?money=5(这样的话是充5元钱)

9.下面就要说说微信公众平台上,一共要改3个地方

(1)在开发者工具下面,修改网页账号(否则通过不了Oauth2.0验证会报redirect_url错误)

(2)验证你的URL,URL就是这个验证文件在项目中的位置,如果放到public文件夹下,你就直接写http://aaa.com/wx_sample.php

验证文件如下:

wx_sample.php

[php] view plain copy
  1. <?php  
  2. /** 
  3.   * wechat php test 
  4.   */  
  5.   
  6. //define your token  
  7. define("TOKEN""weixin");//和你在公众号中填的TOKEN相同  
  8. $wechatObj = new wechatCallbackapiTest();  
  9. $wechatObj->valid();  
  10.   
  11. class wechatCallbackapiTest  
  12. {  
  13.     public function valid()  
  14.     {  
  15.         $echoStr = $_GET["echostr"];  
  16.   
  17.         //valid signature , option  
  18.         if($this->checkSignature()){  
  19.             echo $echoStr;  
  20.             exit;  
  21.         }  
  22.     }  
  23.   
  24.     public function responseMsg()  
  25.     {  
  26.         //get post data, May be due to the different environments  
  27.         $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];  
  28.   
  29.         //extract post data  
  30.         if (!empty($postStr)){  
  31.                 /* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection, 
  32.                    the best way is to check the validity of xml by yourself */  
  33.                 libxml_disable_entity_loader(true);  
  34.                 $postObj = simplexml_load_string($postStr'SimpleXMLElement', LIBXML_NOCDATA);  
  35.                 $fromUsername = $postObj->FromUserName;  
  36.                 $toUsername = $postObj->ToUserName;  
  37.                 $keyword = trim($postObj->Content);  
  38.                 $time = time();  
  39.                 $textTpl = "<xml>  
  40.                             <ToUserName><![CDATA[%s]]></ToUserName>  
  41.                             <FromUserName><![CDATA[%s]]></FromUserName>  
  42.                             <CreateTime>%s</CreateTime>  
  43.                             <MsgType><![CDATA[%s]]></MsgType>  
  44.                             <Content><![CDATA[%s]]></Content>  
  45.                             <FuncFlag>0</FuncFlag>  
  46.                             </xml>";               
  47.                 if(!empty$keyword ))  
  48.                 {  
  49.                     $msgType = "text";  
  50.                     $contentStr = "Welcome to wechat world!";  
  51.                     $resultStr = sprintf($textTpl$fromUsername$toUsername$time$msgType$contentStr);  
  52.                     echo $resultStr;  
  53.                 }else{  
  54.                     echo "Input something...";  
  55.                 }  
  56.   
  57.         }else {  
  58.             echo "";  
  59.             exit;  
  60.         }  
  61.     }  
  62.           
  63.     private function checkSignature()  
  64.     {  
  65.         // you must define TOKEN by yourself  
  66.         if (!defined("TOKEN")) {  
  67.             throw new Exception('TOKEN is not defined!');  
  68.         }  
  69.           
  70.         $signature = $_GET["signature"];  
  71.         $timestamp = $_GET["timestamp"];  
  72.         $nonce = $_GET["nonce"];  
  73.                   
  74.         $token = TOKEN;  
  75.         $tmpArr = array($token$timestamp$nonce);  
  76.         // use SORT_STRING rule  
  77.         sort($tmpArr, SORT_STRING);  
  78.         $tmpStr = implode( $tmpArr );  
  79.         $tmpStr = sha1( $tmpStr );  
  80.           
  81.         if$tmpStr == $signature ){  
  82.             return true;  
  83.         }else{  
  84.             return false;  
  85.         }  
  86.     }  
  87. }  
  88.   
  89. ?>  


(3)修改开发配置(支付授权目录和测试授权目录),这里要注意,如果你的支付路径是http://aaa.com/index.php/wechat,你就填http://aaa.com/index.php/,反正就是最后那个斜杠后面的别加

原创粉丝点击