自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何應(yīng)對微信支付這一步一個(gè)坑的APP支付

開發(fā) 前端
我是個(gè)phper最近在寫微信支付(APP支付),微信給的官方文檔并不是很詳細(xì)也沒有dome之類的代碼啥的(對于新手來說比較麻煩),本人是新手以前也沒寫過支付,踩了好多坑,所以想寫篇文章給沒寫過支付的新手幾個(gè)建議。

引言

秋高氣爽,天氣轉(zhuǎn)涼,正是學(xué)習(xí)工作做的好時(shí)候。(~ ̄▽ ̄)~~(~ ̄▽ ̄)~

我是個(gè)phper最近在寫微信支付(APP支付),微信給的官方文檔并不是很詳細(xì)也沒有dome之類的代碼啥的(對于新手來說比較麻煩),本人是新手以前也沒寫過支付,踩了好多坑,所以想寫篇文章給沒寫過支付的新手幾個(gè)建議。

準(zhǔn)備工作

這首先呢你得注冊個(gè)開放平臺以及商戶平臺的賬號吧,注冊完成后呢你會收到一封微信里郵件里面有你的商戶號等信息,注冊這倆賬號完你會擁有商戶號,appid,appkey等需要的東西。

開發(fā)流程

準(zhǔn)備完成后我們來看一下支付的大體流程

商戶APP應(yīng)用與微信支付主要的交互說明:

  1. 用戶在商戶APP應(yīng)用(移動端)中選擇商品提交訂單,支付方式選擇微信支付。
  2. 商戶APP應(yīng)用(后臺)收到用戶支付訂單,調(diào)用微信支付中的統(tǒng)一下單接口。
  3. 商戶APP應(yīng)用(后臺)統(tǒng)一下單接口調(diào)用成功后,返回的數(shù)據(jù)中有我們需要的prepay_id,按照簽名規(guī)范重新生成一個(gè)簽名,然后把這個(gè)重新生成的簽名及app需要的數(shù)據(jù)返回給商戶APP應(yīng)用(移動端)。
  4. 商戶APP應(yīng)用(移動端)收到商戶APP應(yīng)用(后臺)的數(shù)據(jù)調(diào)起微信支付,用戶進(jìn)行支付
  5. 商戶APP應(yīng)用(后臺)的回調(diào)接口會收到微信發(fā)來的支付結(jié)果通知
  6. 商戶APP應(yīng)用(后臺)查詢支付結(jié)果通知

附:1,4是移動端所要做的事情,2,3,5是我們PHP服務(wù)端后臺要做的6也是,但我沒做,這個(gè)根據(jù)情況而定如果需要的話就做。

開始干活

步驟1.由移動端完成

步驟2. 調(diào)用同一下單接口

先要做的是流程中的第二步,調(diào)用同一下單接口。官方文檔里說了請求的地址與參數(shù),其中有一些是必填參數(shù),有

  • appid
    應(yīng)用ID 固定值,你申請賬號時(shí)就給你了
  • mch_id
    商戶號 固定值,你申請賬號時(shí)就給你了
  • nonce_str
    隨機(jī)字符串 這個(gè)是自己寫的要求不能長于32位,參見官方給的[標(biāo)準(zhǔn)][8]
  • sign
    簽名 我們把這個(gè)簽名叫做第一次簽名,注意這個(gè)是個(gè)坑,得自己寫了,官方只給了如何寫的[標(biāo)準(zhǔn)][9]沒有代碼,這個(gè)就比較蛋疼了。好多人掉進(jìn)這個(gè)坑里,寫的簽名函數(shù)不對,老是出錯。但不用擔(dān)心我在文章的最后會貼出代碼里面有簽名函數(shù)直接調(diào)用就可以了。(注意看我寫的函數(shù)使用規(guī)則)
  • body
    商品描述 固定值 商品描述交易字段格式根據(jù)不同的應(yīng)用場景按照以下格式:APP——需傳入應(yīng)用市場上的APP名字-實(shí)際商品名稱,天天愛消除-游戲充值。
  • out_trade_no
    商戶訂單號 我們自己定義的訂單號,32個(gè)字符內(nèi)、可包含字母。
  • total_fee
    總金額 這個(gè)就是你要支付的錢數(shù)了,由前端返回。注意一下這里的貨幣單位是分!
  • spbill_create_ip
    終端IP 這個(gè)用戶的IP地址,寫個(gè)取IP地址的函數(shù)一調(diào)用就行
  • notify_url
    通知地址 這又是一個(gè)坑,好多人不理解是干嘛的,這是接收微信支付異步通知回調(diào)地址用的,通知url必須為直接可訪問的url,不能攜帶參數(shù)! 也可以這樣理解,這個(gè)是給微信支付的接口,微信來調(diào)用的接口,微信調(diào)這接口干嘛用呢?就是告訴你用戶付款成功啦或者用戶付款失敗了,然后你就可以在這個(gè)接口里通過微信給你返回的信息來做邏輯處理了。
  • trade_type
    固定值 寫 “APP” 因?yàn)樵蹖懙氖茿PP支付嘛,所以就填A(yù)PP。

好了就是這些必選參數(shù)了,剩下就可以自己選擇是否要用的參數(shù)了根據(jù)自己情況而定。

參數(shù)選完了就要發(fā)送參數(shù)了唄,如何發(fā)呢?

我們來調(diào)用wechatAppPay類中的unifiedOrder()函數(shù)。

啊哈啥!!!!!!??????

(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?(⊙o⊙)?

wechatAppPay類???unifiedOrder()函數(shù)???

對就這這倆東西,不要驚訝,不要著急看最后有代碼,有這個(gè)類,有代碼的O(∩_∩)O哈哈~,

你只需在你的項(xiàng)目中加載這個(gè)類就可以調(diào)用這個(gè)方法了!不要崇拜我( ╯▽╰)(因?yàn)檫@個(gè)類不是我寫的我也忘了從哪找的了,我從百度搜的然后整理的做了些改動╮(╯▽╰)╭ -_-|||-_-|||-_-!好吧好吧好吧沒做改動,只是加了點(diǎn)注釋而已,感謝寫這個(gè)類的大神謝謝O(∩_∩)O謝謝O(∩_∩)O謝謝)

好了抽完瘋了,開是干正事!

我們先來new下wechatAppPay類

  1. $wxappid           = 'wx0000000000000';//應(yīng)用ID 字符串 
  2. $mch_id            = '1000000000';//商戶號 字符串 
  3. $notify_url        = 'http://www.xxx.com/xxxx.php/xxxx/xxxx';//接收微信支付異步通知回調(diào)地址 字符串 
  4. $wxkey             = '00000000000000000000000';//這個(gè)是在商戶中心設(shè)置的那個(gè)值用來生成簽名時(shí)保證安全的 字符串 
  5.  
  6. $this->wechatAppPay = new wechatAppPay($wxappid, $mch_id, $notify_url, $wxkey);  

調(diào)用wechatAppPay類中的unifiedOrder()函數(shù)。unifiedOrder()需要的參數(shù)是個(gè)數(shù)組我們定義為$params

  1. $params                     = array(); 
  2.         $params['body']             = 'APP-在線支付';      //必填項(xiàng) 商品描述 
  3.         $params['out_trade_no']     =  time()."$member";  //必填項(xiàng) 自定義的訂單號 
  4.         $params['total_fee']        = ($money*100);       //必填項(xiàng) 訂單金額 單位為分所以要*100 
  5.         $params['trade_type']       = 'APP';              //必填項(xiàng) 交易類型固定寫  APP   
  6.         $params['根據(jù)自己情況定的值'] = "根據(jù)自己情況定的值" //非必填項(xiàng) 根據(jù)自己情況定的值 這個(gè)可有好多個(gè)可以參看開發(fā)文檔中的參數(shù) 
  7.          
  8.         $result = $this->wechatAppPay->unifiedOrder( $params );  

注:如果你加了$params['根據(jù)自己情況定的值'] wechatAppPay類里要做相應(yīng)的改動,文章的最后有代碼,你一看代碼就明白了

現(xiàn)在$result就是我們調(diào)用統(tǒng)一下單接口返回的數(shù)據(jù)了,這個(gè)$resutl通過unifiedOrder()函數(shù)的處理已經(jīng)把xml格式變成數(shù)組了。$result 里有return_code,return_msg,appid,mch_id,nonce_str,sign,result_code,prepay_id,trade_type。這里面就用一個(gè)prepay_id(預(yù)支付交易會話ID),其他都不重要了

步驟2完畢

步驟3. 把數(shù)據(jù)返回給商戶APP應(yīng)用(移動端)調(diào)起支付接口

現(xiàn)在我們要把調(diào)用統(tǒng)一下單接口返回的數(shù)據(jù)$resutl里的幾個(gè)值返回給移動端那幾個(gè)值呢?這幾個(gè):

  • appid
    應(yīng)用ID 這個(gè)是固定的 可以自己寫也可以從$resutl里拿 可以讓移動端寫死 就不用每次返回了
  • partnerid
    商戶號 這個(gè)也是固定的 可以自己寫也可以從$resutl里拿 可以讓移動端寫死 就不用每次返回了
  • prepayid
    預(yù)支付交易會話ID 這個(gè)很重要必須返回給移動端 是必須從$resutl里拿的
  • package
    擴(kuò)展字段 可以自己寫也可以從$resutl里拿 暫填寫固定值"Sign=WXPay" 可以讓移動端寫死 就不用每次返回了
  • noncestr
    隨機(jī)字符串 這個(gè)可以自己寫也可以從$resutl里拿
  • timestamp
    時(shí)間戳 自己生成 標(biāo)準(zhǔn)北京時(shí)間,時(shí)區(qū)為東八區(qū)注意:部分系統(tǒng)取到的值為毫秒級,需要轉(zhuǎn)換成秒(10位數(shù)字),這里有個(gè)坑,ISO端接收的時(shí)候好像得強(qiáng)行轉(zhuǎn)化一下,因?yàn)榉祷氐氖亲址皇菙?shù)字,還有什么幾位的數(shù)字之類的,我也不太懂,反正就是寫的時(shí)候提醒下iOS工程師就行。安卓不清楚。
  • sign
    簽名 又來一個(gè)坑,我們把這個(gè)簽名叫做二次簽名,但是這個(gè)簽名不是從$resutl里拿的,而是自己寫的,如何寫呢,又有坑!因?yàn)閰⑴c簽名的參數(shù)值是那幾個(gè)不清楚,參數(shù)名寫不對!不怕我有代碼!貼給你看!需要參與簽名的值有六個(gè)!
    1. $sign_array              = array(); 
    2.       $sign_array['appid']     = $wx_result['appid'];    //注意 $sign_array['appid'] 里的參數(shù)名必須是appid 
    3.       $sign_array['partnerid'] = $wx_result['mch_id'];   //注意 $sign_array['partnerid'] 里的參數(shù)名必須是partnerid 
    4.       $sign_array['prepayid']  = $wx_result['prepay_id'];//注意 $sign_array['prepayid'] 里的參數(shù)名必須是prepayid 
    5.       $sign_array['package']   = 'Sign=WXPay';           //注意 $sign_array['package'] 里的參數(shù)名必須是package 
    6.       $sign_array['noncestr']  = $wx_result['nonce_str'];//注意 $sign_array['noncestr'] 里的參數(shù)名必須是noncestr 
    7.       $sign_array['timestamp'] = time();                 //注意 $sign_array['timestamp'] 里的參數(shù)名必須是timestamp 
    8.        
    9.       $sign_two = $this->wechatAppPay->MakeSign($sign_array);//調(diào)用wechatAppPay類里的MakeSign()函數(shù)生成sign 
    現(xiàn)在就可以把重新生成的sign($sign_two)以及其他參數(shù)返回給移動端了,一共返回七個(gè)值,有三個(gè)之可以讓前端寫死(appid,partnerid,package),其余四個(gè)必須由服務(wù)器返回給移動端。

步驟3完畢

步驟4.由移動端完成

步驟5. 回調(diào)接口 支付結(jié)果通用通知

還記得步驟2中我們設(shè)置的$notify_url嗎,對現(xiàn)在就要對這個(gè)微信返回到這個(gè)接口的數(shù)據(jù)進(jìn)行一系列的邏輯處理了官方是這樣寫的:

支付完成后,微信會把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應(yīng)答。

對后臺通知交互時(shí),如果微信收到商戶的應(yīng)答不是成功或超時(shí),微信認(rèn)為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)

注意:同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復(fù)的通知。

推薦的做法是,當(dāng)收到通知進(jìn)行處理時(shí),首先檢查對應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進(jìn)行處理,如果處理過直接返回結(jié)果成功。在對業(yè)務(wù)數(shù)據(jù)進(jìn)行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。

特別提醒:商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗(yàn)證,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。

首先來接收數(shù)據(jù)

  1. $data = $this->wechatAppPay->getNotifyData();//獲取數(shù)據(jù) 用wechatAppPay類里的getNotifyData()方法,這里數(shù)據(jù)也被getNotifyData()由xml轉(zhuǎn)化成了數(shù)組。 

然后官方說要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,這個(gè)我不懂所以沒寫(如果你懂你會的話請給我留言私信告訴我,在這謝謝了),對數(shù)據(jù)進(jìn)行狀態(tài)檢查這個(gè)寫了,如何寫的呢?很簡單微信返回的值有好多其中就可以判斷result_code(業(yè)務(wù)結(jié)果)和return_code(返回狀態(tài)碼)是否為SUCCESS就可以了代碼就不寫了。

然后驗(yàn)簽,這個(gè)很重要因?yàn)檫@是保證數(shù)據(jù)沒有被第三方人為篡改的標(biāo)準(zhǔn)!

如何驗(yàn)簽?zāi)?

把返回的數(shù)據(jù)$data里除去sign剩下的值都參與重新簽名我們把這次簽名叫做驗(yàn)簽簽名,驗(yàn)簽簽名生成后再與$data里的sign對比,如果相同驗(yàn)簽通過,否則不通過。這次簽名的參數(shù)名與二次簽名時(shí)的參數(shù)名不同,$data數(shù)組里叫什么參數(shù)名就驗(yàn)簽時(shí)叫什么參數(shù)名。聽亂了吧?(~ ̄▽ ̄)~(~ ̄▽ ̄)~沒關(guān)系請看代碼

  1. //假如$data里有如下參數(shù) 
  2.  $w_sign = array();           //參加驗(yàn)簽簽名的參數(shù)數(shù)組                      
  3.  $w_sign['appid']             = $data['appid']; 
  4.  $w_sign['bank_type']         = $data['bank_type']; 
  5.  $w_sign['cash_fee']          = $data['cash_fee']; 
  6.  $w_sign['fee_type']          = $data['fee_type']; 
  7.  $w_sign['is_subscribe']      = $data['is_subscribe']; 
  8.  $w_sign['mch_id']            = $data['mch_id']; 
  9.  $w_sign['nonce_str']         = $data['nonce_str']; 
  10.  $w_sign['openid']            = $data['openid']; 
  11.  $w_sign['out_trade_no']      = $data['out_trade_no']; 
  12.  $w_sign['result_code']       = $data['result_code']; 
  13.  $w_sign['return_code']       = $data['return_code']; 
  14.  $w_sign['time_end']          = $data['time_end']; 
  15.  $w_sign['total_fee']         = $data['total_fee']; 
  16.  $w_sign['trade_type']        = $data['trade_type']; 
  17.  $w_sign['transaction_id']    = $data['transaction_id']; 
  18.  
  19.  $verify_sign = $this->wechatAppPay->MakeSign($w_sign);//生成驗(yàn)簽簽名  

好了現(xiàn)在假設(shè)你的驗(yàn)簽已經(jīng)通過了接下里就是你自己的邏輯處理了

///////////////////////////////////////////////////////

商戶APP應(yīng)用(后臺)處理邏輯代碼

//////////////////////////////////////////////////////

自己的邏輯處理已經(jīng)處理完之后,還得告訴微信一下,別再一直發(fā)結(jié)果通用通知啦,我已經(jīng)收到通知并處理完啦!

  1. $this->wechatAppPay->replyNotify();//商戶處理后同步返回給微信參數(shù) 

步驟5結(jié)束步驟6根據(jù)自己情況而定

結(jié)束語

至此微信支付處理完成~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦

寫的有不對的方還請大家多多指導(dǎo)指教!!!給我留言!!b( ̄▽ ̄)db( ̄▽ ̄)db( ̄▽ ̄)d

還有感謝在我寫微信支付地時(shí)候 那些被我問煩了的大神們! !謝謝啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦O(∩_∩)O哈哈~O(∩_∩)O哈哈~O(∩_∩)O哈哈~<( ̄︶ ̄)><( ̄︶ ̄)><( ̄︶ ̄)>

代碼

wechatAppPay類

  1. class wechatAppPay  
  2. {    
  3.     //接口API URL前綴 
  4.     const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'
  5.     //下單地址URL 
  6.     const UNIFIEDORDER_URL = "/pay/unifiedorder"
  7.     //查詢訂單URL 
  8.     const ORDERQUERY_URL = "/pay/orderquery"
  9.     //關(guān)閉訂單URL 
  10.     const CLOSEORDER_URL = "/pay/closeorder"
  11.     //公眾賬號ID 
  12.     private $wxappid; 
  13.     //商戶號 
  14.     private $mch_id; 
  15.     //隨機(jī)字符串 
  16.     private $nonce_str; 
  17.     //簽名 
  18.     private $sign; 
  19.     //商品描述 
  20.     private $body; 
  21.     //商戶訂單號 
  22.     private $out_trade_no; 
  23.     //支付總金額 
  24.     private $total_fee; 
  25.     //終端IP 
  26.     private $spbill_create_ip; 
  27.     //支付結(jié)果回調(diào)通知地址 
  28.     private $notify_url; 
  29.     //交易類型 
  30.     private $trade_type; 
  31.     //支付密鑰 
  32.     private $key
  33.     //證書路徑 
  34.     private $SSLCERT_PATH; 
  35.     private $SSLKEY_PATH; 
  36.     //所有參數(shù) 
  37.     private $params = array(); 
  38.     public function __construct($wxappid, $mch_id, $notify_url, $key
  39.     { 
  40.         $this->appid = $wxappid; 
  41.         $this->mch_id = $mch_id; 
  42.         $this->notify_url = $notify_url; 
  43.         $this->key = $key
  44.     } 
  45.     /** 
  46.      * 下單方法 
  47.      * @param   $params 下單參數(shù) 
  48.      */ 
  49.     public function unifiedOrder( $params ){ 
  50.         $this->body = $params['body']; 
  51.         $this->out_trade_no = $params['out_trade_no']; 
  52.         $this->total_fee = $params['total_fee']; 
  53.         $this->trade_type = $params['trade_type']; 
  54.         $this->nonce_str = $this->genRandomString(); 
  55.         $this->spbill_create_ip = $_SERVER['REMOTE_ADDR']; 
  56.         $this->params['appid'] = $this->appid; 
  57.         $this->params['mch_id'] = $this->mch_id; 
  58.         $this->params['nonce_str'] = $this->nonce_str; 
  59.         $this->params['body'] = $this->body; 
  60.         $this->params['out_trade_no'] = $this->out_trade_no; 
  61.         $this->params['total_fee'] = $this->total_fee; 
  62.         $this->params['spbill_create_ip'] = $this->spbill_create_ip; 
  63.         $this->params['notify_url'] = $this->notify_url; 
  64.         $this->params['trade_type'] = $this->trade_type; 
  65.  
  66.          
  67.         //獲取簽名數(shù)據(jù) 
  68.         $this->sign = $this->MakeSign( $this->params ); 
  69.         $this->params['sign'] = $this->sign; 
  70.         $xml = $this->data_to_xml($this->params); 
  71.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::UNIFIEDORDER_URL); 
  72.         if( !$response ){ 
  73.             return false
  74.         } 
  75.         $result = $this->xml_to_data( $response ); 
  76.         if( !empty($result['result_code']) && !empty($result['err_code']) ){ 
  77.             $result['err_msg'] = $this->error_code( $result['err_code'] ); 
  78.         } 
  79.         return $result; 
  80.     } 
  81.     /** 
  82.      * 查詢訂單信息 
  83.      * @param $out_trade_no     訂單號 
  84.      * @return array 
  85.      */ 
  86.     public function orderQuery( $out_trade_no ){ 
  87.         $this->params['appid'] = $this->appid; 
  88.         $this->params['mch_id'] = $this->mch_id; 
  89.         $this->params['nonce_str'] = $this->genRandomString(); 
  90.         $this->params['out_trade_no'] = $out_trade_no; 
  91.         //獲取簽名數(shù)據(jù) 
  92.         $this->sign = $this->MakeSign( $this->params ); 
  93.         $this->params['sign'] = $this->sign; 
  94.         $xml = $this->data_to_xml($this->params); 
  95.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::ORDERQUERY_URL); 
  96.         if( !$response ){ 
  97.             return false
  98.         } 
  99.         $result = $this->xml_to_data( $response ); 
  100.         if( !empty($result['result_code']) && !empty($result['err_code']) ){ 
  101.             $result['err_msg'] = $this->error_code( $result['err_code'] ); 
  102.         } 
  103.         return $result; 
  104.     } 
  105.     /** 
  106.      * 關(guān)閉訂單 
  107.      * @param $out_trade_no     訂單號 
  108.      * @return array 
  109.      */ 
  110.     public function closeOrder( $out_trade_no ){ 
  111.         $this->params['appid'] = $this->appid; 
  112.         $this->params['mch_id'] = $this->mch_id; 
  113.         $this->params['nonce_str'] = $this->genRandomString(); 
  114.         $this->params['out_trade_no'] = $out_trade_no; 
  115.         //獲取簽名數(shù)據(jù) 
  116.         $this->sign = $this->MakeSign( $this->params ); 
  117.         $this->params['sign'] = $this->sign; 
  118.         $xml = $this->data_to_xml($this->params); 
  119.         $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::CLOSEORDER_URL); 
  120.         if( !$response ){ 
  121.             return false
  122.         } 
  123.         $result = $this->xml_to_data( $response ); 
  124.         return $result; 
  125.     } 
  126.     /** 
  127.      *  
  128.      * 獲取支付結(jié)果通知數(shù)據(jù) 
  129.      * return array 
  130.      */ 
  131.     public function getNotifyData(){ 
  132.         //獲取通知的數(shù)據(jù) 
  133.         $xml = $GLOBALS['HTTP_RAW_POST_DATA']; 
  134.         $data = array(); 
  135.         if( empty($xml) ){ 
  136.             return false
  137.         } 
  138.         $data = $this->xml_to_data( $xml ); 
  139.         if( !empty($data['return_code']) ){ 
  140.             if( $data['return_code'] == 'FAIL' ){ 
  141.                 return false
  142.             } 
  143.         } 
  144.         return $data; 
  145.     } 
  146.     /** 
  147.      * 接收通知成功后應(yīng)答輸出XML數(shù)據(jù) 
  148.      * @param string $xml 
  149.      */ 
  150.     public function replyNotify(){ 
  151.         $data['return_code'] = 'SUCCESS'
  152.         $data['return_msg'] = 'OK'
  153.         $xml = $this->data_to_xml( $data ); 
  154.         echo $xml; 
  155.         die(); 
  156.     } 
  157.      /** 
  158.       * 生成APP端支付參數(shù) 
  159.       * @param  $prepayid   預(yù)支付id 
  160.       */ 
  161.      public function getAppPayParams( $prepayid ){ 
  162.          $data['appid'] = $this->appid; 
  163.          $data['partnerid'] = $this->mch_id; 
  164.          $data['prepayid'] = $prepayid; 
  165.          $data['package'] = 'Sign=WXPay'
  166.          $data['noncestr'] = $this->genRandomString(); 
  167.          $data['timestamp'] = time(); 
  168.          $data['sign'] = $this->MakeSign( $data );  
  169.          return $data; 
  170.      } 
  171.     /** 
  172.      * 生成簽名 
  173.      *  @return 簽名 
  174.      */ 
  175.     public function MakeSign( $params ){ 
  176.         //簽名步驟一:按字典序排序數(shù)組參數(shù) 
  177.         ksort($params); 
  178.         $string = $this->ToUrlParams($params); 
  179.         //簽名步驟二:在string后加入KEY 
  180.         $string = $string . "&key=".$this->key
  181.         //簽名步驟三:MD5加密 
  182.         $string = md5($string); 
  183.         //簽名步驟四:所有字符轉(zhuǎn)為大寫 
  184.         $result = strtoupper($string); 
  185.         return $result; 
  186.     } 
  187.  
  188.     /** 
  189.      * 將參數(shù)拼接為url: key=value&key=value 
  190.      * @param   $params 
  191.      * @return  string 
  192.      */ 
  193.     public function ToUrlParams( $params ){ 
  194.         $string = ''
  195.         if( !empty($params) ){ 
  196.             $array = array(); 
  197.             foreach( $params as $key => $value ){ 
  198.                 $array[] = $key.'='.$value; 
  199.             } 
  200.             $string = implode("&",$array); 
  201.         } 
  202.         return $string; 
  203.     } 
  204.     /** 
  205.      * 輸出xml字符 
  206.      * @param   $params     參數(shù)名稱 
  207.      * return   string      返回組裝的xml 
  208.      **/ 
  209.     public function data_to_xml( $params ){ 
  210.         if(!is_array($params)|| count($params) <= 0) 
  211.         { 
  212.             return false
  213.         } 
  214.         $xml = "<xml>"
  215.         foreach ($params as $key=>$val) 
  216.         { 
  217.             if (is_numeric($val)){ 
  218.                 $xml.="<".$key.">".$val."</".$key.">"
  219.             }else
  220.                 $xml.="<".$key."><![CDATA[".$val."]]></".$key.">"
  221.             } 
  222.         } 
  223.         $xml.="</xml>"
  224.         return $xml;  
  225.     } 
  226.     /** 
  227.      * 將xml轉(zhuǎn)為array 
  228.      * @param string $xml 
  229.      * return array 
  230.      */ 
  231.     public function xml_to_data($xml){   
  232.         if(!$xml){ 
  233.             return false
  234.         } 
  235.         //將XML轉(zhuǎn)為array 
  236.         //禁止引用外部xml實(shí)體 
  237.         libxml_disable_entity_loader(true); 
  238.         $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);         
  239.         return $data; 
  240.     } 
  241.     /** 
  242.      * 獲取毫秒級別的時(shí)間戳 
  243.      */ 
  244.     private static function getMillisecond(){ 
  245.         //獲取毫秒的時(shí)間戳 
  246.         $time = explode ( " ", microtime () ); 
  247.         $time = $time[1] . ($time[0] * 1000); 
  248.         $time2 = explode( ".", $time ); 
  249.         $time = $time2[0]; 
  250.         return $time
  251.     } 
  252.     /** 
  253.      * 產(chǎn)生一個(gè)指定長度的隨機(jī)字符串,并返回給用戶  
  254.      * @param type $len 產(chǎn)生字符串的長度 
  255.      * @return string 隨機(jī)字符串 
  256.      */ 
  257.     private function genRandomString($len = 32) { 
  258.         $chars = array( 
  259.             "a""b""c""d""e""f""g""h""i""j""k"
  260.             "l""m""n""o""p""q""r""s""t""u""v"
  261.             "w""x""y""z""A""B""C""D""E""F""G"
  262.             "H""I""J""K""L""M""N""O""P""Q""R"
  263.             "S""T""U""V""W""X""Y""Z""0""1""2"
  264.             "3""4""5""6""7""8""9" 
  265.         ); 
  266.         $charsLen = count($chars) - 1; 
  267.         // 將數(shù)組打亂  
  268.         shuffle($chars); 
  269.         $output = ""
  270.         for ($i = 0; $i < $len; $i++) { 
  271.             $output .= $chars[mt_rand(0, $charsLen)]; 
  272.         } 
  273.         return $output
  274.     } 
  275.     /** 
  276.      * 以post方式提交xml到對應(yīng)的接口url 
  277.      *  
  278.      * @param string $xml  需要post的xml數(shù)據(jù) 
  279.      * @param string $url  url 
  280.      * @param bool $useCert 是否需要證書,默認(rèn)不需要 
  281.      * @param int $second   url執(zhí)行超時(shí)時(shí)間,默認(rèn)30s 
  282.      * @throws WxPayException 
  283.      */ 
  284.     private function postXmlCurl($xml, $url, $useCert = false, $second = 30){        
  285.         $ch = curl_init(); 
  286.         //設(shè)置超時(shí) 
  287.         curl_setopt($ch, CURLOPT_TIMEOUT, $second); 
  288.         curl_setopt($ch,CURLOPT_URL, $url); 
  289.         curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); 
  290.         curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2); 
  291.         //設(shè)置header 
  292.         curl_setopt($ch, CURLOPT_HEADER, FALSE); 
  293.         //要求結(jié)果為字符串且輸出到屏幕上 
  294.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 
  295.         if($useCert == true){ 
  296.             //設(shè)置證書 
  297.             //使用證書:cert 與 key 分別屬于兩個(gè).pem文件 
  298.             curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM'); 
  299.             //curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); 
  300.             curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM'); 
  301.             //curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); 
  302.         } 
  303.         //post提交方式 
  304.         curl_setopt($ch, CURLOPT_POST, TRUE); 
  305.         curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
  306.         //運(yùn)行curl 
  307.         $data = curl_exec($ch); 
  308.         //返回結(jié)果 
  309.         if($data){ 
  310.             curl_close($ch); 
  311.             return $data; 
  312.         } else {  
  313.             $error = curl_errno($ch); 
  314.             curl_close($ch); 
  315.             return false
  316.         } 
  317.     } 
  318.     /** 
  319.       * 錯誤代碼 
  320.       * @param  $code       服務(wù)器輸出的錯誤代碼 
  321.       * return string 
  322.       */ 
  323.      public function error_code( $code ){ 
  324.          $errList = array( 
  325.             'NOAUTH'                =>  '商戶未開通此接口權(quán)限'
  326.             'NOTENOUGH'             =>  '用戶帳號余額不足'
  327.             'ORDERNOTEXIST'         =>  '訂單號不存在'
  328.             'ORDERPAID'             =>  '商戶訂單已支付,無需重復(fù)操作'
  329.             'ORDERCLOSED'           =>  '當(dāng)前訂單已關(guān)閉,無法支付'
  330.             'SYSTEMERROR'           =>  '系統(tǒng)錯誤!系統(tǒng)超時(shí)'
  331.             'APPID_NOT_EXIST'       =>  '參數(shù)中缺少APPID'
  332.             'MCHID_NOT_EXIST'       =>  '參數(shù)中缺少M(fèi)CHID'
  333.             'APPID_MCHID_NOT_MATCH' =>  'appid和mch_id不匹配'
  334.             'LACK_PARAMS'           =>  '缺少必要的請求參數(shù)'
  335.             'OUT_TRADE_NO_USED'     =>  '同一筆交易不能多次提交'
  336.             'SIGNERROR'             =>  '參數(shù)簽名結(jié)果不正確'
  337.             'XML_FORMAT_ERROR'      =>  'XML格式錯誤'
  338.             'REQUIRE_POST_METHOD'   =>  '未使用post傳遞參數(shù) '
  339.             'POST_DATA_EMPTY'       =>  'post數(shù)據(jù)不能為空'
  340.             'NOT_UTF8'              =>  '未使用指定編碼格式'
  341.          );  
  342.          if( array_key_exists( $code , $errList ) ){ 
  343.             return $errList[$code]; 
  344.          } 
  345.      } 
  346. }   
責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2024-05-06 09:02:57

數(shù)據(jù)分析標(biāo)簽模型

2020-06-10 12:32:33

微信寄快遞支付分

2020-12-15 10:32:46

自動化運(yùn)維監(jiān)控平臺集群

2015-02-09 10:27:46

2018-02-28 14:05:36

2021-03-17 07:07:21

系統(tǒng)程序員SDI

2015-03-19 10:37:04

2020-05-07 09:25:20

數(shù)據(jù)庫MySQL代碼

2013-11-25 13:30:47

微信開發(fā)

2012-12-24 13:25:59

微信App

2019-07-19 06:41:19

數(shù)據(jù)驅(qū)動數(shù)據(jù)分析數(shù)據(jù)決策

2016-03-04 10:29:51

微信支付源碼

2017-02-28 09:40:16

移動支付

2022-11-30 10:09:03

5G無線網(wǎng)絡(luò)

2020-06-10 10:24:51

微信支付分用戶微信

2012-03-22 10:33:33

思杰XenDesktop

2013-11-28 11:15:43

微信支付寶支付戰(zhàn)爭

2018-03-07 15:24:41

PythonMySQL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號