我們很多時候有客戶需要開發微信支付,開發了很多次了 但是一直沒時間記錄分享,為了減少爬坑,也讓自己下次更好的拿來使用,我在這先他享一下我的方法
這里要注意一下支付授權目錄,使用TP很多人都使用的是重寫模式(REWRITE模式)或者在使用REWRITE模式的同時,使用偽靜態模式,這時候生成的鏈接為:[http://serverName/Home/Blog/read/id/1];如果使用的是PATHINFO模式的話,生成的鏈接就是:[http://serverName/index.php/Home/Blog/read/id/1],比如在Home模塊下的Blog控制器中的某個方法進行支付,我們支付的授權目錄應該是[http://serverName/Home/Blog/]或者[http://serverName/index.php/Home/Blog/],這個根據自己的TP的設置的URL模式而定。
首先先把微信支付SDK文件拷至/ThinkPHP/Library/Vendor/WxPayPubHelper/ 內如下圖
這里的文件我自己經過修改過,需要的朋友可以打開此鏈接下載
https://pan.baidu.com/s/1geG6qTd
配置文件添加微信配置信息:config.php
接着新建控制器 :WxpayController.class.php
代碼如下:
<?php namespace Home\Controller; use Think\Controller; //微信支付類 class WxpayController extends Controller { //獲取access_token過程中的跳轉uri,通過跳轉將code傳入jsapi支付頁面 public function js_api_start(){ if(!empty($_GET['order_key_num'])){ // session(array('pay_now_id'=>$_GET['order_key_num'],'expire'=>3600)); S('pay_now_id',$_GET['order_key_num'],3600); } vendor('WxPayPubHelper.WxPayPubHelper'); vendor('WxPayPubHelper.WxPayJsApiPay'); vendor('WxPayPubHelper.log'); //①、獲取用戶openid $tools = new \JsApiPay(); $openId = $tools->GetOpenid(C('WX_APPID'),C('WX_APPSECRET')); $data = session('date'); $data1 = session('data1'); if($data){ $id = $data['balanceid']; $order = M('balance')->where(array('bpid'=>$id))->find(); if($order['remarks'] == '充值成功(微信支付)'){ $this->error('當前訂單已經支付'); } }else{ $this->error("不存在當前訂單編號!"); } $res = array( 'order_sn' => $order['bpno'], 'order_amount' => $order['bpprice'] ); $price = $order['bpprice'] * 100; //②、統一下單 $input = new \WxPayUnifiedOrder(); $input->SetBody("帳戶充值"); //商品名稱 $input->SetAttach("充值"); //附加參數,可填可不填,填寫的話,里邊字符串不能出現空格 $input->SetOut_trade_no($res['order_sn']); //訂單號 //$input->SetTotal_fee($price); //支付金額 $input->SetTotal_fee($price); //支付金額,單位:分 $input->SetTime_start(date("YmdHis")); $input->SetTime_expire(date("YmdHis", time() + 1200)); $input->SetGoods_tag("帳戶充值"); $input->SetNotify_url(C('NOTIFY_URL')); //支付回調驗證地址 $input->SetTrade_type("JSAPI"); $input->SetOpenid($openId); $order = \WxPayApi::unifiedOrder(C('WX_APPID'),C('WX_MCHID'),C('NOTIFY_URL'),$input); /*echo '<font color="#f00"><b>統一下單支付單信息</b></font><br/>'; printf_info($order);*/ $jsApiParameters = $tools->GetJsApiParameters($order); //獲取共享收貨地址js函數參數 $editAddress = $tools->GetEditAddressParameters(); $this->assign('jsApiParameters',$jsApiParameters); $this->assign('editAddress',$editAddress); $this->assign('openid',$openId); $this->assign('res',$res); $this->display('jsapi'); } //異步通知url,商戶根據實際開發過程設定 // //微信支付回調驗證 public function notify_url(){ $xml = $GLOBALS['HTTP_RAW_POST_DATA']; // 這句file_put_contents是用來查看服務器返回的XML數據 測試完可以刪除了 file_put_contents('./Api/wxpay/logs/log.txt',$xml,FILE_APPEND); addlog('log.txt',a,$xml); //將服務器返回的XML數據轉化為數組 //$data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true); $data = $this->xmlToArray($xml); // 保存微信服務器返回的簽名sign $data_sign = $data['sign']; // sign不參與簽名算法 unset($data['sign']); $sign = $this->makeSign($data); // 判斷簽名是否正確 判斷支付狀態 if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) { $result = $data; // 這句file_put_contents是用來查看服務器返回的XML數據 測試完可以刪除了 file_put_contents('./Api/wxpay/logs/log1.txt',$xml,FILE_APPEND); //獲取服務器返回的數據 $order_sn = $data['out_trade_no']; //訂單單號 $order_id = $data['attach']; //附加參數,選擇傳遞訂單ID $openid = $data['openid']; //付款人openID $total_fee = $data['total_fee']/100; //付款金額 //更新數據庫 // 更改訂單狀態 $bpno = $order_sn; // 先查詢訂單是否充值成功 $order = M('balance')->where(array('bpno'=>$bpno,'remarks'=>'充值成功(微信支付)'))->find(); if (!$order) { M('balance')->where(array('bpno'=>$bpno))->save(array('bptime'=>time(),'remarks'=>'充值成功(微信支付)')); //增加用戶付款金額 //先查詢付款用戶 $uid = M('userinfo')->where(array('openid'=>$openid))->getField('uid'); //增加余額 M('accountinfo')->where(array('uid'=>$uid))->setInc('balance',$total_fee); } }else{ $result = false; } // 返回狀態給微信服務器 if ($result) { //$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; $str = "SUCCESS"; }else{ //$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[簽名失敗]]></return_msg></xml>'; $str = "FAIL"; } echo $str; return $result; } /** * 生成簽名 * @return 簽名,本函數不覆蓋sign成員變量 */ protected function makeSign($data){ //獲取微信支付秘鑰 vendor('WxPayPubHelper.WxPayJsApiPay'); $key = \WxPayConfig::KEY; // 去空 $data=array_filter($data); //簽名步驟一:按字典序排序參數 ksort($data); $string_a=http_build_query($data); $string_a=urldecode($string_a); //簽名步驟二:在string后加入KEY //$config=$this->config; $string_sign_temp=$string_a."&key=".$key; //簽名步驟三:MD5加密 $sign = md5($string_sign_temp); // 簽名步驟四:所有字符轉為大寫 $result=strtoupper($sign); return $result; } //將XML轉為array protected function xmlToArray($xml) { //禁止引用外部xml實體 libxml_disable_entity_loader(true); $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $values; } }