從0開始一步一步用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下的各種文件都打開,裏面只要用到路徑,你就在require_once後面加個“../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" οnclick="callpay()" >立即支付</button>

	</div>

</body>
</html>


5.寫控制器,新建控制器叫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(){ //這裏是你的回調函數,這個很坑,官方都沒有文檔的
     public function notify(Request $request){
        $streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : ''; //拿到微信回調回來的信息判斷支付成功沒

        if(empty($streamData)){
            $streamData = file_get_contents('php://input');
        }

        if($streamData!=''){
            $streamData=xmlToArray($streamData); 
            $Data=json_encode($streamData);
            Log::debug('Alipay notify post data verification fail.', [ //寫入服務器文檔,你不加這個也行
                'data' => $Data.'xxxxxx'
            ]);
            if($streamData['return_code'] == 'SUCCESS' && $streamData['result_code'] == 'SUCCESS'){ //支付成功
                try { //開始事務
                    //支付成功,你要幹些什麼都寫這裏,例如增加餘額的操作什麼的

                } catch (Exception $e) {
                    //如果try裏面的東西出現問題的話,進行數據庫回滾
                    throw $e;         
                }
                
            }
        }else{
            $ret = false; //支付失敗
        }
    }
  }
6.註冊路由(這裏最好用any的方法,因爲發過去是post,回來的是get)
Route::any(‘wechat’,'WechatController@index');  
Route::any(‘wechat/notify’,'WechatController@notify');

7.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;
		}
	}
...


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
/**
  * 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/,反正就是最後那個斜槓後面的別加


哈哈,大功告成~微信支付能用了~大家有不懂的在下面留言,我看到了都會解答的



發佈了55 篇原創文章 · 獲贊 37 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章