首先呢,需要公司去註冊微信平臺上的東西,拿到資質,拿到配置信息纔可以進行測試。
我們程序猿這裏直接從代碼開始,不管前面亂七八糟的程序。
下載好文檔後把文檔放在 exends 目錄下 我將文件改名爲 wechatpay
現在說一下整體的開發流程
1.寫配置文件(APPID,MCHID 等數據) 文檔在文件夾下的example->Wxpay.Config.php
2.配置好後開始更改每個文件上的 require_once 路徑 防止開發時出沒有必要的錯誤
//require_once "../lib/WxPay.Config.Interface.php";
require_once EXTEND_PATH.'wechatpay/lib/WxPay.Config.Interface.php';
3.開始在自己的支付模塊裏寫邏輯,我在下面會附上我的測試代碼片段
4.獲取到參數後請求二維碼並返回到網頁上生成(很關鍵的一步)
5.檢測是否支付成功
直接從第3步開始說起
每個公司的邏輯都不同 但需要獲取到二維碼傳入的參數大致相同,請仔細閱讀下面的代碼。在此之前,可以閱讀一下騰訊給的開發文檔。
//掃碼支付
public function wechat_pay($user_id,$number,$pice)
{
//掃二維碼進行支付
require_once EXTEND_PATH.'wechatpay/lib/WxPay.Api.php'; //載入微信支付相關文件
require_once EXTEND_PATH.'wechatpay/example/WxPay.NativePay.php'; //載入微信支付相關文件
require_once EXTEND_PATH.'wechatpay/example/log.php';//載入微信支付相關文件
require_once EXTEND_PATH.'wechatpay/lib/WxPay.Data.php'; //載入微信支付相關文件
//模式二
/**
* 流程:
* 1、調用統一下單,取得code_url,生成二維碼
* 2、用戶掃描二維碼,進行支付
* 3、支付完成之後,微信服務器會通知支付成功
* 4、在支付成功通知中需要查單確認是否真正支付成功(見:notify.php)
*/
//初始化日誌
$logHandler= new \CLogFileHandler(EXTEND_PATH.'wechatpay/example/log.php'.date('Y-m-d').'.log');
$log = \Log::Init($logHandler, 15);
//
$notify = new \NativePay();
$input = new \WxPayUnifiedOrder();
$input->SetBody("充值使我快樂"); //設置商品或支付單簡要描述
$input->SetAttach($user_id); //設置附加數據,在查詢API和支付通知中原樣返回,該字段主要用於商戶攜帶訂單的自定義數據 我這裏設置成用戶ID?
$input->SetOut_trade_no($number); //設置商戶系統內部的訂單號,32個字符內、可包含字母, 其他說明見商戶訂單號
$input->SetTotal_fee($pice*100); //設置訂單總金額,只能爲整數,詳見支付金額
$input->SetTime_start(date("YmdHi")); //設置訂單生成時間,格式爲yyyyMMddHHmmss,如2009年12月25日9點10分10秒錶示爲20091225091010。其他詳見時間規則
$input->SetTime_expire(date("YmdHis", time() + 180)); //設置訂單失效時間,格式爲yyyyMMddHHmmss,如2009年12月27日9點10分10秒錶示爲20091227091010。其他詳見時間規則
//$input->SetGoods_tag("test"); //設置商品標記,代金券或立減優惠功能的參數,說明詳見代金券或立減優惠
$input->SetNotify_url("http://localhost/huoniao/extends/wechatpay/example/native_notify.php");//設置接收微信支付異步通知回調地址
$input->SetTrade_type("NATIVE"); //設置取值如下:JSAPI,NATIVE,APP,詳細說明見參數規定
$input->SetProduct_id("0"); //設置trade_type=NATIVE,此參數必傳。此id爲二維碼中包含的商品ID,商戶自行定義。
///var_dump($input);die;
$result = $notify->GetPayUrl($input);
//var_dump($result);die;
return urlencode($result['code_url']);
//需要生成變量的值
//1.充值的用戶ID $user_id 用戶表的唯一標識
//2.訂單號 $number
//3.金額(微信是以分爲單位1的) $pice
//4.商品ID 不傳 默認爲0 有業務邏輯需要的朋友可以寫進來
}
接下來在控制器裏調用上述的這個方法,並傳參。這裏把訂單號先寫入session,查詢是否支付成功時用。
//訂單號
$data['number'] = time().str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT);
//將訂單號存入session 做查詢跳轉使用
$_SESSION['user']['user_info']['order_number'] = $data['number'];
$code = $this->wechat_pay($user_id,$data['number'],$data['price']);
if($code)
{
//這裏你們可以在判斷的時候做一些$code的驗證規則
json(['code' => 1 , msg => '$code']);
}else{
json(['code' => 2 , msg => '二維碼獲取失敗,錯誤碼002']);
}
因爲是測試代碼,所以前端請求過來的是死值,你們在開發的時候千萬不要這樣寫,因爲極不安全,容易被他人篡改信息,可能會造成難以挽回的損失。
接下來看前端請求控制器返回生成二維碼與查詢是否交易成功的片段。
寫一下簡單的流程
在用戶輸入金額點擊提交按鈕後,獲取提交數據走Ajax去 wechatpay 成功獲取到二維碼並先顯示後,js不停的請求一個查詢的方法是否支付成功,沒成功就一直停留,成功後提示並跳轉頁面 。
這裏需要在騰訊文檔裏改一個東西,因爲會一直獲取失敗,我找了好久最終發現是他們寫的CURL有點問題 文件應該是wechatpay->lib->WxPay.Api.php 557行 我直接把這個方法複製下來給你們看
private static function postXmlCurl($config, $xml, $url, $useCert = false, $second = 30)
{
$ch = curl_init();
$curlVersion = curl_version();
$ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']." "
.$config->GetMerchantId();
//設置超時
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
$proxyHost = "0.0.0.0";
$proxyPort = 0;
$config->GetProxy($proxyHost, $proxyPort);
//如果有配置代理這裏就設置代理
if($proxyHost != "0.0.0.0" && $proxyPort != 0){
curl_setopt($ch,CURLOPT_PROXY, $proxyHost);
curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort);
}
curl_setopt($ch,CURLOPT_URL, $url);
//curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
//curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//嚴格校驗
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);//嚴格校驗2
curl_setopt($ch,CURLOPT_USERAGENT, $ua);
//設置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求結果爲字符串且輸出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//var_dump($ch);die;
if($useCert == true){
//設置證書
//使用證書:cert 與 key 分別屬於兩個.pem文件
//證書文件請放入服務器的非web目錄下
$sslCertPath = "";
$sslKeyPath = "";
$config->GetSSLCertPath($sslCertPath, $sslKeyPath);
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, $sslKeyPath);
}
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//運行curl
//var_dump(curl_exec($ch));
$data = curl_exec($ch);
//返回結果
if($data){
curl_close($ch);
//var_dump($data);die;
return $data;
}else{
$error = curl_errno($ch);
curl_close($ch);
throw new WxPayException("curl出錯,錯誤碼:$error");
}
}
改完成之後獲取二維碼應該是沒問題了,接下來看HTML代碼。你要是連這都看不懂,那我真的沒脾氣,請出門右拐。
<div class="weui-cell" style="margin-top:300px;">
<div class="weui-cell__hd">
<label class="weui-label">金額:</label>
</div>
<div class="weui-cell__bd">
<input class="weui-input" name="money" id = "money" type="number"placeholder="金額">
</div>
</div>
<img src="" style="widht:200px;height:200px;" class="zhifu" >
<div class="weui-btn-area">
<button class="weui-btn weui-btn_primary" id="chargebtn" type="button">確定</button>
</div>
<script>
$(function(){
$('.weui-btn').on('click',function(){
var money = $('#money').val();
alert(money)
$.post("{:url('Pay/wechatpay')}",{'money':money},function(data){
//這個str
if(data.code == 1){
//這個str 是解析二維碼的路徑,因爲我懶所以偷了百度網盤解析的路徑。你們如果要是不想用,微信文檔裏有寫方法,可以自己調用自己的
var str = 'https://www.baifubao.com/o2o/0/qrcode?size=10&text='
str += data
$('.zhifu').attr('src',str)
function query(){
//這個就是查詢是否支付成功的請求,每2秒請求查詢次,在下面會詳述控制器裏的代碼是怎麼寫的
$.post("{:url('Pay/query')}",{},function(data){
if(data.code == 1){
alert('data.msg')
window.location.reload()
}
},'json')
}
setInterval(query,2000);
}else if(data.code == 2){
alert(data.msg)
}
},'json')
})
})
</script>
接下來看我是怎麼寫這個查詢的方法的,其實很簡單,微信支付文檔已經寫好了,我們直接用就好。主要還是在於session裏的訂單號。
記得一定要在控制器裏寫上這句話,因爲這個文件就是查詢文件
require_once EXTEND_PATH.'wechatpay/example/WxPay.MicroPay.php';//載入微信支付相關文件
public function query()
{
//查詢訂單狀態
$qurey = new \MicroPay();
$order = $_SESSION['user']['user_info']['order_number'];
$num ='';
$data = $qurey->query($order,$num);
//var_dump($data);
//var_dump($_SESSION['user']['user_info']['order_number']);
if($data['trade_state_desc'] == '支付成功'){
return json(['code' => 1,'msg'=>'支付成功']);
}
}
如此大功告成。這裏我在查詢完成之後沒有清楚session數據,你們記得清除一哈。
上面的東西都是我半年前寫過的項目裏的東西了,今天心血來潮,寫了個博客。還望各位大佬們多多指教。