thinkphp3.2微信公眾號支付(jsapi支付)開發過程
第一次做微信支付(網頁版本的),折騰了兩天,記錄一下方便下次自己再次使用,也希望能幫和我一樣初次接觸的朋友踩一下坑。
前期準備
1.開通微信認證服務號,並且開通商戶平臺
2.下載微信支付dome,下載地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1,解壓php版本如圖
a.doc資料夾說明文件 b.example一些dome示例 c.lib最重要的檔案介面檔案 d.logs日誌檔案
第一步dome檔案處理
1.解壓後獲得php_sdk_v3.0.9這個資料夾改名為WxPay整個複製到核心框架ThinkPHP\Library\Vendor中方便呼叫
2.開啟lib資料夾下的WxPay.Api.php檔案,在537行有一段curl網路請求配置程式碼:
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
改為:
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
為了禁止 cURL 驗證證書
3.開啟example中的WxPay.Config.php配置GetAppId函式和GetMerchantId兩項(一個是公眾號APPID,一個是商戶號)
第二步配置公眾號後臺授權路徑
1.網頁授權路徑,公眾號設定->功能設定->網頁授權域名(這個是為了獲取使用者openid的),直接填你的根目錄就OK
2.配置商戶授權路徑,登陸商戶->產品中心->開發配置,用於付款資料互動(微信伺服器與自己伺服器之間的)
這裡有一個大坑要注意一下,他這個配置不支援pathinfo模式,比如
https://www.xxx.com/fukuan/index.php/Home/wxpay/notify
這種模式是不支援的,解決方法如下
根目錄(fukuan)中建立payment.php作為入口檔案,然後跳轉到相應頁面
https://www.xxx.com/fukuan/payment.php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <[email protected]>
// +----------------------------------------------------------------------
// 應用入口檔案
// 檢測PHP環境
if(version_compare(PHP_VERSION,'5.3.0','<')) die('require PHP > 5.3.0 !');
// 開啟除錯模式 建議開發階段開啟 部署階段註釋或者設為false
define('APP_DEBUG',True);
//指定模組控制器和方法
$_GET['m']='Home';
$_GET['c']='Wxpay';
$_GET['a']='notify';
// 定義應用目錄
define('APP_PATH','./Application/');
// 引入ThinkPHP入口檔案
require './ThinkPHP/ThinkPHP.php';
// 親^_^ 後面不需要任何程式碼了 就是如此簡單
第三步前端程式碼
<script type="text/javascript">
$('.btns').click(function(){
var moneys = ($('.moneys').val());
var openids = "<?php echo I('openid')?>";
$.ajax({
url: "{:U('wxpay')}", //請求的url地址
dataType: "json", //返回格式為json
async: true, //請求是否非同步,預設為非同步,這也是ajax重要特性
data: {
'moneys': moneys,
'openids': openids
},//引數值
type: "POST", //請求方式
success: function(req) {
//console.log(req);
function jsApiCall(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
req,
function(res){
WeixinJSBridge.log(res.err_msg);
//alert(res.err_code+res.err_desc+res.err_msg);
if(res.err_msg == "get_brand_wcpay_request:ok"){
window.location.reload();
}
}
);
}
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();
}
}
callpay();
},
error: function() {
alert('請求錯誤');
}
});
})
</script>
第四步後端程式碼
//付款呼叫
public function wxpay(){
$money = abs(I('moneys'))*100; //單位為分
$openid = I('openids');
if(empty($money)){
return 0;
}
if(empty($openid)){
return 0;
}
//echo $money;
Vendor('WxPayAPI.lib.WxPay#Api');
Vendor('WxPayAPI.example.WxPay#Config');
Vendor('WxPayAPI.example.WxPay#JsApiPay');
//②、統一下單
$tools = new \JsApiPay();
$input = new \WxPayUnifiedOrder();
$input->SetBody("微信還款"); //這裡是支付內容
$input->SetAttach(I('fq')); //此處可傳值,待支付成功後可取這部分的值
$input->SetOut_trade_no("3".date("YmdHis")); //訂單編號
$input->SetTotal_fee($money); //金額
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url("https://wechat.labao168.com/fukuan/payment.php");
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openid);
$config = new \WxPayConfig();
$order = \WxPayApi::unifiedOrder($config, $input);
$jsApiParameters = $tools->GetJsApiParameters($order);
echo $jsApiParameters;
}
第五步支付成功後入庫處理(這裡真的是操碎了心),回撥地址就是上面在商戶號上配置地址,支付成功後微信伺服器會訪問這個地址
a.坑1這個地址是不允許有許可權管理的,就是說你在網頁上能直接訪問,否則微信伺服器無法傳值到這個地址
b.坑2微信伺服器為了將訊息準確送到我們的伺服器,會對這個地址請求多次,頻率從高到低(導致一條資料被插入很多次資料庫),我的解決方法比較笨,就是插入資料庫之前檢測一下訂單是否存在,存在的話就直接跳過插入資料
c.坑3由於是伺服器與伺服器間的請求,無法在頁面上顯示,就是說你丫沒辦法在頁面上除錯,解決辦法將接受到的資料寫入文字中,然後檢視文字是否有問題
d.傳值問題,支付後端中$input->SetAttach(I('fq'));是可以傳值的
<?php
namespace Home\Controller;
use Think\Controller;
class WxpayController extends Controller{
public function notify(){
//獲取返回的xml
$testxml = file_get_contents("php://input");
//將xml轉化為json格式
$jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
//轉成陣列
$result = json_decode($jsonxml,true);
//file_put_contents('test.txt',$jsonxml); --這裡是除錯方法根目錄中test.txt中可檢視資料情況
if($result){
//如果成功返回了
if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//file_put_contents('test.txt',$data);
//獲取伺服器返回的資料
$order_sn = $result['transaction_id']; //訂單單號
$openid = $result['openid']; //付款人openID
$total_fee = ($result['total_fee']/100); //付款金額
$fq = $result['attach']; //分期數
//判斷訂單是否已經入庫
$results = M('zhangdan')->where(array('tranid'=>$order_sn))->find();
if($results){
exit();
}
//更新資料庫
$uid = M('user')->where(array('openid'=>$openid))->getField('id');
//判斷是否滿足分期
M('fqjl')->where(array('uid'=>$uid,'fq'=>$fq))->setInc('yhk',$total_fee); // 使用者的積分加3
//file_put_contents('test.txt',$datast['yhk']);
$sj['money'] = $total_fee;
$sj['ztime'] = strtotime(date('Y-m-d'));
$sj['contents'] = "微信還款";
$sj['uid'] = $uid;
$sj['tranid'] = $order_sn;
//file_put_contents('test.txt',$sj);
$res = M('zhangdan')->add($sj);
echo exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
}
}
}
}
至此支付就完成了,希望有一點對第一次接觸的朋友有一點小小的幫助