目前微信支付集成到框架裏面有太多的坑了,項目中剛好遇到一個,把經驗和重要的坑寫出來,一步一步從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/,反正就是最後那個斜槓後面的別加
哈哈,大功告成~微信支付能用了~大家有不懂的在下面留言,我看到了都會解答的