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

24 篇文章 0 订阅


目前微信支付集成到框架里面有太多的坑了,项目中刚好遇到一个,把经验和重要的坑写出来,一步一步从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/,反正就是最后那个斜杠后面的别加


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



  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值