近來期間比較忙, 忙完以後發現最近有挺多的東西沒有整理,因而乎。就將之前用到的一些小東西整理了一下。javascript
若是對您有幫助,則是我最大的幸運。php
本篇主要是說了一下整合TP5的微信公衆號支付。html
不過因爲最近TP6已經出了,小夥伴們要記得向最新的進發哦。前端
好了,廢話很少說了。開始。java
首先呢,須要引入咱們封裝好的類庫:數據庫
一樣在 extend/ 下json
由於會將支付類庫放在一塊兒,因而就在extend 文件夾下建立了一個pay文件夾用來存儲全部類文件。api
如下內容爲wxpay類的內容:數組
namespace pay; class Wxpay { private $config =[ "appid" => "********", // 公衆號ID "mch_id" => "********", // 商戶號 "notify_url" => "********", // 回調地址 "key" => "********", // 微信支付 商戶祕鑰KEY ]; public function index($param,$openid) { $order=array( 'body' => $param['body'],// 商品描述 'total_fee' => intval($param['total']*100),// 訂單金額 以(分)爲單位 // 'total_fee' => 1, 'out_trade_no' => $param['order_sn'],// 訂單號 'trade_type' => 'JSAPI',// JSAPI公衆號支付 'openid' => $openid// 獲取到的openid ); $userip = $param['userip']; // 統一下單 獲取prepay_id $unified_order=$this->unifiedOrder($order,$userip); // 獲取當前時間戳 $time=time(); // 組合jssdk須要用到的數據 $data=array( 'appId' =>$this->config['appid'], //appid 'timeStamp' =>strval($time), //時間戳 'nonceStr' =>$unified_order['nonce_str'],// 隨機字符串 'package' =>'prepay_id='.$unified_order['prepay_id'],// 預支付交易會話標識 'signType' =>'MD5' //加密方式 ); // 生成簽名 $data['paySign']=$this->makeSign($data); return $data; } /** * 統一下單 * @param array $order 訂單 必須包含支付所須要的參數 body(產品描述)、total_fee(訂單金額)、out_trade_no(訂單號)、product_id(產品id)、trade_type(類型:JSAPI,NATIVE,APP) */ public function unifiedOrder($order,$userip) { $config=array( 'appid' => $this->config['appid'], //appid 'mch_id' => $this->config['mch_id'], //商戶號ID 'nonce_str' => $this->getNonceStr(), 'spbill_create_ip' => $userip, //你的IP 'notify_url' => $this->config['notify_url'], //'notify_url' =>$url ); // 合併配置數據和訂單數據 $data=array_merge($order,$config); // 生成簽名 $sign=$this->makeSign($data); $data['sign']=$sign; //轉換成xml $xml=$this->toXml($data); $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml數據的文件 $header[] = "Content-type: text/xml";//定義content-type爲xml,注意是數組 $ch = curl_init ($url); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地沒有指定curl.cainfo路徑的錯誤 curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); $response = curl_exec($ch); if(curl_errno($ch)){ // 顯示報錯信息;終止繼續執行 die(curl_error($ch)); } curl_close($ch); //轉換成數組 $result=$this->toArray($response); //dump($result); // 顯示錯誤信息 if ($result['return_code']=='FAIL') { die($result['return_msg']); } $result['sign']=$sign; $result['nonce_str']=$this->getNonceStr(); return $result; } /** * 生成簽名 * @return 簽名,本函數不覆蓋sign成員變量,如要設置簽名須要調用SetSign方法賦值 */ public function makeSign($data) { // 去空 $data=array_filter($data); //簽名步驟一:按字典序排序參數 ksort($data); //將數組轉成url形式 $string_a=http_build_query($data); $string_a=urldecode($string_a); //簽名步驟二:在string後加入KEY $string_sign_temp=$string_a."&key=".$this->config['key']; //簽名步驟三:MD5加密 $sign = md5($string_sign_temp); // 簽名步驟四:全部字符轉爲大寫 $result=strtoupper($sign); return $result; } /** * 將xml轉爲array * @param string $xml xml字符串 * @return array 轉換獲得的數組 */ public function toArray($xml){ //禁止引用外部xml實體 libxml_disable_entity_loader(true); $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $result; } /** * * 產生隨機字符串,不長於32位 * @param int $length * @return 產生的隨機字符串 */ public function getNonceStr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str =""; for ( $i = 0; $i < $length; $i++ ) { $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1); } return $str; } /** * 輸出xml字符 * @throws WxPayException */ public function toXml($data){ if(!is_array($data) || count($data) <= 0){ throw new WxPayException("數組數據異常!"); } $xml = "<xml>"; foreach ($data as $key=>$val){ if (is_numeric($val)){ $xml.="<".$key.">".$val."</".$key.">"; }else{ $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"; } } $xml.="</xml>"; return $xml; } /** * 驗證 * @return array 返回數組格式的notify數據 */ public function notify(){ // 獲取xml $xml=file_get_contents('php://input', 'r'); // 轉成php數組 $data=$this->toArray($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; }else{ $result=false; } // 返回狀態給微信服務器 if ($result) { $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; }else{ $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[簽名失敗]]></return_msg></xml>'; } // file_put_contents("./Public/aaa.text",$result); // echo $str; return $result; } public function https_request($url, $data = null) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); // var_dump($output); curl_close($curl); return $output; } }
而後就是調用方法了:服務器
namespace app\index\controller; use pay\Wxpay; class Index extends Base { /** *調用支付接口 * */ public function getorder() { $param = input('get.'); $pays = model('pay')->where('id',$id)->find(); $wxpay = [ 'order_sn' => $pays['pay_sn'], //支付訂單號 'total' => $pays['money'], //支付總額 'body' => $pays['body'], //支付說明 'userip' => $pays['userip'], //用戶IP ]; $openid = $this->_user['openid']; $pay = new Wxpay(); $data = $pay->index($wxpay,$openid); $logUrl = "********"; //支付完成跳轉地址 $this->assign([ 'data'=>json_encode($data), 'logUrl'=>$logUrl, ]); return $this->fetch(); } }
其次是對應的調用空白頁面:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>訂單提交成功</title> <style> .info{ text-align: center; margin-top: 40px; } </style> </head> <body> <div class="info">支付進行中,請稍候...</div> <script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> <script type="text/javascript"> //調用微信JS api 支付 function onBridgeReady(){ var data = {$data}; WeixinJSBridge.invoke( 'getBrandWCPayRequest', data, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { // 使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在用戶支付成功後返回 ok,但並不保證它絕對可靠。 window.location.href="{$logUrl}"; }else{ alert('支付失敗'); // alert(res.err_code+res.err_desc+res.err_msg); // 顯示錯誤信息 } } ); } if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } }else{ onBridgeReady(); } </script> </body> </html>
最後就是回調了(拿到回調在此控制器匯中進行數據庫操做):
namespace app\index\controller; use Think\Controller;
/** * 支付回調 -- 接收並處理調整數據庫 */ class ClassName extends AnotherClass { private $config =[ "key" => "*******", //微信支付 商戶祕鑰KEY ]; /** * notify_url接收頁面 */ public function wxpaynotify() { $result=$this->notify(); if ($result) {//如下爲處理數據庫操做等 操做完成後輸出success echo "SUCCESS"; } } /** * 一下驗證類 活獲取 token 等可寫入至 common 公告類中 * 驗證 * @return array 返回數組格式的notify數據 */ public function notify(){ // 獲取xml $xml=file_get_contents('php://input', 'r'); // 轉成php數組 $data=$this->toArray($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; }else{ $result=false; } // 返回狀態給微信服務器 if ($result) { $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; }else{ $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[簽名失敗]]></return_msg></xml>'; } // file_put_contents("./Public/aaa.text",$result); // echo $str; return $result; } /** * 將xml轉爲array * @param string $xml xml字符串 * @return array 轉換獲得的數組 */ public function toArray($xml){ //禁止引用外部xml實體 libxml_disable_entity_loader(true); $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $result; } /** * 生成簽名 * @return 簽名,本函數不覆蓋sign成員變量,如要設置簽名須要調用SetSign方法賦值 */ public function makeSign($data) { // 去空 $data=array_filter($data); //簽名步驟一:按字典序排序參數 ksort($data); //將數組轉成url形式 $string_a=http_build_query($data); $string_a=urldecode($string_a); //簽名步驟二:在string後加入KEY $string_sign_temp=$string_a."&key=".$this->config['key']; //簽名步驟三:MD5加密 $sign = md5($string_sign_temp); // 簽名步驟四:全部字符轉爲大寫 $result=strtoupper($sign); return $result; } }
以上就是微信公衆號支付的所有內容。
若有疑問,請評論或留言。
感謝您的查看。
2019年05月31日