摘要:開發(fā)流程準(zhǔn)備完成后我們來看一下支付的大體流程商戶應(yīng)用與微信支付主要的交互說明用戶在商戶應(yīng)用移動(dòng)端中選擇商品提交訂單,支付方式選擇微信支付。商戶應(yīng)用后臺(tái)收到用戶支付訂單,調(diào)用微信支付中的統(tǒng)一下單接口。
引言
秋高氣爽,天氣轉(zhuǎn)涼,正是學(xué)習(xí)工作做的好時(shí)候。(~ ̄▽ ̄)~~(~ ̄▽ ̄)~
我是個(gè)phper最近在寫微信支付(APP支付),微信給的官方文檔并不是很詳細(xì)也沒有dome之類的代碼啥的(對于新手來說比較麻煩),本人是新手以前也沒寫過支付,踩了好多坑,所以想寫篇文章給沒寫過支付的新手幾個(gè)建議。
準(zhǔn)備工作這首先呢你得注冊個(gè)開放平臺(tái)以及商戶平臺(tái)的賬號(hào)吧,注冊完成后呢你會(huì)收到一封微信里郵件里面有你的商戶號(hào)等信息,注冊這倆賬號(hào)完你會(huì)擁有商戶號(hào),appid,appkey等需要的東西。
開發(fā)流程準(zhǔn)備完成后我們來看一下支付的大體流程
商戶APP應(yīng)用與微信支付主要的交互說明:
用戶在商戶APP應(yīng)用(移動(dòng)端)中選擇商品提交訂單,支付方式選擇微信支付。
商戶APP應(yīng)用(后臺(tái))收到用戶支付訂單,調(diào)用微信支付中的統(tǒng)一下單接口。
商戶APP應(yīng)用(后臺(tái))統(tǒng)一下單接口調(diào)用成功后,返回的數(shù)據(jù)中有我們需要的prepay_id,按照簽名規(guī)范重新生成一個(gè)簽名,然后把這個(gè)重新生成的簽名及app需要的數(shù)據(jù)返回給商戶APP應(yīng)用(移動(dòng)端)。
商戶APP應(yīng)用(移動(dòng)端)收到商戶APP應(yīng)用(后臺(tái))的數(shù)據(jù)調(diào)起微信支付,用戶進(jìn)行支付
商戶APP應(yīng)用(后臺(tái))的回調(diào)接口會(huì)收到微信發(fā)來的支付結(jié)果通知
商戶APP應(yīng)用(后臺(tái))查詢支付結(jié)果通知
附:1,4是移動(dòng)端所要做的事情,2,3,5是我們PHP服務(wù)端后臺(tái)要做的6也是,但我沒做,這個(gè)根據(jù)情況而定如果需要的話就做。
開始干活步驟1由移動(dòng)端完成
步驟2. 調(diào)用同一下單接口:
先要做的是流程中的第二步,調(diào)用同一下單接口。官方文檔里說了請求的地址與參數(shù),其中有一些是必填參數(shù),有
appid
應(yīng)用ID 固定值,你申請賬號(hào)時(shí)就給你了
mch_id
商戶號(hào) 固定值,你申請賬號(hào)時(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ù)不對,老是出錯(cuò)。但不用擔(dān)心我在文章的最后會(huì)貼出代碼里面有簽名函數(shù)直接調(diào)用就可以了。(注意看我寫的函數(shù)使用規(guī)則)
body
商品描述 固定值 商品描述交易字段格式根據(jù)不同的應(yīng)用場景按照以下格式:APP——需傳入應(yīng)用市場上的APP名字-實(shí)際商品名稱,天天愛消除-游戲充值。
out_trade_no
商戶訂單號(hào) 我們自己定義的訂單號(hào),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è)類不是我寫的我也忘了從哪找的了,我從百度搜的然后整理的做了些改動(dòng)╮(╯▽╰)╭ -_-|||-_-|||-_-!好吧好吧好吧沒做改動(dòng),只是加了點(diǎn)注釋而已,感謝寫這個(gè)類的大神謝謝O(∩_∩)O謝謝O(∩_∩)O謝謝)
好了抽完瘋了,開是干正事!
我們先來new下wechatAppPay類
$wxappid = "wx0000000000000";//應(yīng)用ID 字符串 $mch_id = "1000000000";//商戶號(hào) 字符串 $notify_url = "http://www.xxx.com/xxxx.php/xxxx/xxxx";//接收微信支付異步通知回調(diào)地址 字符串 $wxkey = "00000000000000000000000";//這個(gè)是在商戶中心設(shè)置的那個(gè)值用來生成簽名時(shí)保證安全的 字符串 $this->wechatAppPay = new wechatAppPay($wxappid, $mch_id, $notify_url, $wxkey);
調(diào)用wechatAppPay類中的unifiedOrder()函數(shù)。unifiedOrder()需要的參數(shù)是個(gè)數(shù)組我們定義為$params
$params = array(); $params["body"] = "APP-在線支付"; //必填項(xiàng) 商品描述 $params["out_trade_no"] = time()."$member"; //必填項(xiàng) 自定義的訂單號(hào) $params["total_fee"] = ($money*100); //必填項(xiàng) 訂單金額 單位為分所以要*100 $params["trade_type"] = "APP"; //必填項(xiàng) 交易類型固定寫 APP $params["根據(jù)自己情況定的值"] = "根據(jù)自己情況定的值" //非必填項(xiàng) 根據(jù)自己情況定的值 這個(gè)可有好多個(gè)可以參看開發(fā)文檔中的參數(shù) $result = $this->wechatAppPay->unifiedOrder( $params );
注:如果你加了$params["根據(jù)自己情況定的值"] wechatAppPay類里要做相應(yīng)的改動(dò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ù)支付交易會(huì)話ID),其他都不重要了
步驟2完畢
步驟3 把數(shù)據(jù)返回給商戶APP應(yīng)用(移動(dòng)端)調(diào)起支付接口
現(xiàn)在我們要把調(diào)用統(tǒng)一下單接口返回的數(shù)據(jù)$resutl里的幾個(gè)值返回給移動(dòng)端
那幾個(gè)值呢?這幾個(gè):
appid
應(yīng)用ID 這個(gè)是固定的 可以自己寫也可以從$resutl里拿 可以讓移動(dòng)端寫死 就不用每次返回了
partnerid
商戶號(hào) 這個(gè)也是固定的 可以自己寫也可以從$resutl里拿 可以讓移動(dòng)端寫死 就不用每次返回了
prepayid
預(yù)支付交易會(huì)話ID 這個(gè)很重要必須返回給移動(dòng)端 是必須從$resutl里拿的
package
擴(kuò)展字段 可以自己寫也可以從$resutl里拿 暫填寫固定值"Sign=WXPay" 可以讓移動(dòng)端寫死 就不用每次返回了
noncestr
隨機(jī)字符串 這個(gè)可以自己寫也可以從$resutl里拿
timestamp
時(shí)間戳 自己生成 標(biāo)準(zhǔn)北京時(shí)間,時(shí)區(qū)為東八區(qū)注意:部分系統(tǒng)取到的值為毫秒級(jí),需要轉(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è)! $sign_array = array(); $sign_array["appid"] = $wx_result["appid"]; //注意 $sign_array["appid"] 里的參數(shù)名必須是appid $sign_array["partnerid"] = $wx_result["mch_id"]; //注意 $sign_array["partnerid"] 里的參數(shù)名必須是partnerid $sign_array["prepayid"] = $wx_result["prepay_id"];//注意 $sign_array["prepayid"] 里的參數(shù)名必須是prepayid $sign_array["package"] = "Sign=WXPay"; //注意 $sign_array["package"] 里的參數(shù)名必須是package $sign_array["noncestr"] = $wx_result["nonce_str"];//注意 $sign_array["noncestr"] 里的參數(shù)名必須是noncestr $sign_array["timestamp"] = time(); //注意 $sign_array["timestamp"] 里的參數(shù)名必須是timestamp $sign_two = $this->wechatAppPay->MakeSign($sign_array);//調(diào)用wechatAppPay類里的MakeSign()函數(shù)生成sign
現(xiàn)在就可以把重新生成的sign($sign_two)以及其他參數(shù)返回給移動(dòng)端了,一共返回七個(gè)值,有三個(gè)之可以讓前端寫死(appid,partnerid,package),其余四個(gè)必須由服務(wù)器返回給移動(dòng)端。
步驟3完畢
步驟4由移動(dòng)端完成
步驟5 回調(diào)接口 支付結(jié)果通用通知
還記得步驟2中我們設(shè)置的$notify_url嗎,對現(xiàn)在就要對這個(gè)微信返回到這個(gè)接口的數(shù)據(jù)進(jìn)行一系列的邏輯處理了
官方是這樣寫的:
支付完成后,微信會(huì)把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應(yīng)答。 對后臺(tái)通知交互時(shí),如果微信收到商戶的應(yīng)答不是成功或超時(shí),微信認(rèn)為通知失敗,微信會(huì)通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒) 注意:同樣的通知可能會(huì)多次發(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ù)
$data = $this->wechatAppPay->getNotifyData();//獲取數(shù)據(jù) 用wechatAppPay類里的getNotifyData()方法,這里數(shù)據(jù)也被getNotifyData()由xml轉(zhuǎn)化成了數(shù)組。
然后官方說要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,這個(gè)我不懂所以沒寫(如果你懂你會(huì)的話請給我留言私信告訴我,在這謝謝了),對數(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)兀?br>把返回的數(shù)據(jù)$data里除去sign剩下的值都參與重新簽名我們把這次簽名叫做驗(yàn)簽簽名,驗(yàn)簽簽名生成后再與$data里的sign對比,如果相同驗(yàn)簽通過,否則不通過。這次簽名的參數(shù)名與二次簽名時(shí)的參數(shù)名不同,$data數(shù)組里叫什么參數(shù)名就驗(yàn)簽時(shí)叫什么參數(shù)名。聽亂了吧?(~ ̄▽ ̄)~(~ ̄▽ ̄)~沒關(guān)系請看代碼
//假如$data里有如下參數(shù) $w_sign = array(); //參加驗(yàn)簽簽名的參數(shù)數(shù)組 $w_sign["appid"] = $data["appid"]; $w_sign["bank_type"] = $data["bank_type"]; $w_sign["cash_fee"] = $data["cash_fee"]; $w_sign["fee_type"] = $data["fee_type"]; $w_sign["is_subscribe"] = $data["is_subscribe"]; $w_sign["mch_id"] = $data["mch_id"]; $w_sign["nonce_str"] = $data["nonce_str"]; $w_sign["openid"] = $data["openid"]; $w_sign["out_trade_no"] = $data["out_trade_no"]; $w_sign["result_code"] = $data["result_code"]; $w_sign["return_code"] = $data["return_code"]; $w_sign["time_end"] = $data["time_end"]; $w_sign["total_fee"] = $data["total_fee"]; $w_sign["trade_type"] = $data["trade_type"]; $w_sign["transaction_id"] = $data["transaction_id"]; $verify_sign = $this->wechatAppPay->MakeSign($w_sign);//生成驗(yàn)簽簽名
好了現(xiàn)在假設(shè)你的驗(yàn)簽已經(jīng)通過了接下里就是你自己的邏輯處理了
/////////////////////////////////////////////////////// 商戶APP應(yīng)用(后臺(tái))處理邏輯代碼 //////////////////////////////////////////////////////
自己的邏輯處理已經(jīng)處理完之后,還得告訴微信一下,別再一直發(fā)結(jié)果通用通知啦,我已經(jīng)收到通知并處理完啦!
$this->wechatAppPay->replyNotify();//商戶處理后同步返回給微信參數(shù)
步驟5結(jié)束
步驟6根據(jù)自己情況而定
至此微信支付處理完成~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦
寫的有不對的方還請大家多多指導(dǎo)指教!!!給我留言!!b( ̄▽ ̄)db( ̄▽ ̄)db( ̄▽ ̄)d
交流學(xué)習(xí):QQ群 634574190 (請認(rèn)真看完文章再加(¬_¬)(¬_¬)(¬_¬))
還有感謝在我寫微信支付地時(shí)候 那些被我問煩了的大神們! !謝謝啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦~(≧▽≦)/~啦啦啦O(∩_∩)O哈哈~O(∩_∩)O哈哈~O(∩_∩)O哈哈~<( ̄︶ ̄)><( ̄︶ ̄)><( ̄︶ ̄)>
代碼wechatAppPay類
class wechatAppPay { //接口API URL前綴 const API_URL_PREFIX = "https://api.mch.weixin.qq.com"; //下單地址URL const UNIFIEDORDER_URL = "/pay/unifiedorder"; //查詢訂單URL const ORDERQUERY_URL = "/pay/orderquery"; //關(guān)閉訂單URL const CLOSEORDER_URL = "/pay/closeorder"; //公眾賬號(hào)ID private $wxappid; //商戶號(hào) private $mch_id; //隨機(jī)字符串 private $nonce_str; //簽名 private $sign; //商品描述 private $body; //商戶訂單號(hào) private $out_trade_no; //支付總金額 private $total_fee; //終端IP private $spbill_create_ip; //支付結(jié)果回調(diào)通知地址 private $notify_url; //交易類型 private $trade_type; //支付密鑰 private $key; //證書路徑 private $SSLCERT_PATH; private $SSLKEY_PATH; //所有參數(shù) private $params = array(); public function __construct($wxappid, $mch_id, $notify_url, $key) { $this->appid = $wxappid; $this->mch_id = $mch_id; $this->notify_url = $notify_url; $this->key = $key; } /** * 下單方法 * @param $params 下單參數(shù) */ public function unifiedOrder( $params ){ $this->body = $params["body"]; $this->out_trade_no = $params["out_trade_no"]; $this->total_fee = $params["total_fee"]; $this->trade_type = $params["trade_type"]; $this->nonce_str = $this->genRandomString(); $this->spbill_create_ip = $_SERVER["REMOTE_ADDR"]; $this->params["appid"] = $this->appid; $this->params["mch_id"] = $this->mch_id; $this->params["nonce_str"] = $this->nonce_str; $this->params["body"] = $this->body; $this->params["out_trade_no"] = $this->out_trade_no; $this->params["total_fee"] = $this->total_fee; $this->params["spbill_create_ip"] = $this->spbill_create_ip; $this->params["notify_url"] = $this->notify_url; $this->params["trade_type"] = $this->trade_type; //獲取簽名數(shù)據(jù) $this->sign = $this->MakeSign( $this->params ); $this->params["sign"] = $this->sign; $xml = $this->data_to_xml($this->params); $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::UNIFIEDORDER_URL); if( !$response ){ return false; } $result = $this->xml_to_data( $response ); if( !empty($result["result_code"]) && !empty($result["err_code"]) ){ $result["err_msg"] = $this->error_code( $result["err_code"] ); } return $result; } /** * 查詢訂單信息 * @param $out_trade_no 訂單號(hào) * @return array */ public function orderQuery( $out_trade_no ){ $this->params["appid"] = $this->appid; $this->params["mch_id"] = $this->mch_id; $this->params["nonce_str"] = $this->genRandomString(); $this->params["out_trade_no"] = $out_trade_no; //獲取簽名數(shù)據(jù) $this->sign = $this->MakeSign( $this->params ); $this->params["sign"] = $this->sign; $xml = $this->data_to_xml($this->params); $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::ORDERQUERY_URL); if( !$response ){ return false; } $result = $this->xml_to_data( $response ); if( !empty($result["result_code"]) && !empty($result["err_code"]) ){ $result["err_msg"] = $this->error_code( $result["err_code"] ); } return $result; } /** * 關(guān)閉訂單 * @param $out_trade_no 訂單號(hào) * @return array */ public function closeOrder( $out_trade_no ){ $this->params["appid"] = $this->appid; $this->params["mch_id"] = $this->mch_id; $this->params["nonce_str"] = $this->genRandomString(); $this->params["out_trade_no"] = $out_trade_no; //獲取簽名數(shù)據(jù) $this->sign = $this->MakeSign( $this->params ); $this->params["sign"] = $this->sign; $xml = $this->data_to_xml($this->params); $response = $this->postXmlCurl($xml, self::API_URL_PREFIX.self::CLOSEORDER_URL); if( !$response ){ return false; } $result = $this->xml_to_data( $response ); return $result; } /** * * 獲取支付結(jié)果通知數(shù)據(jù) * return array */ public function getNotifyData(){ //獲取通知的數(shù)據(jù) $xml = $GLOBALS["HTTP_RAW_POST_DATA"]; $data = array(); if( empty($xml) ){ return false; } $data = $this->xml_to_data( $xml ); if( !empty($data["return_code"]) ){ if( $data["return_code"] == "FAIL" ){ return false; } } return $data; } /** * 接收通知成功后應(yīng)答輸出XML數(shù)據(jù) * @param string $xml */ public function replyNotify(){ $data["return_code"] = "SUCCESS"; $data["return_msg"] = "OK"; $xml = $this->data_to_xml( $data ); echo $xml; die(); } /** * 生成APP端支付參數(shù) * @param $prepayid 預(yù)支付id */ public function getAppPayParams( $prepayid ){ $data["appid"] = $this->appid; $data["partnerid"] = $this->mch_id; $data["prepayid"] = $prepayid; $data["package"] = "Sign=WXPay"; $data["noncestr"] = $this->genRandomString(); $data["timestamp"] = time(); $data["sign"] = $this->MakeSign( $data ); return $data; } /** * 生成簽名 * @return 簽名 */ public function MakeSign( $params ){ //簽名步驟一:按字典序排序數(shù)組參數(shù) ksort($params); $string = $this->ToUrlParams($params); //簽名步驟二:在string后加入KEY $string = $string . "&key=".$this->key; //簽名步驟三:MD5加密 $string = md5($string); //簽名步驟四:所有字符轉(zhuǎn)為大寫 $result = strtoupper($string); return $result; } /** * 將參數(shù)拼接為url: key=value&key=value * @param $params * @return string */ public function ToUrlParams( $params ){ $string = ""; if( !empty($params) ){ $array = array(); foreach( $params as $key => $value ){ $array[] = $key."=".$value; } $string = implode("&",$array); } return $string; } /** * 輸出xml字符 * @param $params 參數(shù)名稱 * return string 返回組裝的xml **/ public function data_to_xml( $params ){ if(!is_array($params)|| count($params) <= 0) { return false; } $xml = "都看到這里了,給順手點(diǎn)個(gè)贊唄!(~ ̄▽ ̄)~<( ̄︶ ̄)>"; foreach ($params as $key=>$val) { if (is_numeric($val)){ $xml.="<".$key.">".$val."".$key.">"; }else{ $xml.="<".$key.">".$key.">"; } } $xml.=" "; return $xml; } /** * 將xml轉(zhuǎn)為array * @param string $xml * return array */ public function xml_to_data($xml){ if(!$xml){ return false; } //將XML轉(zhuǎn)為array //禁止引用外部xml實(shí)體 libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)), true); return $data; } /** * 獲取毫秒級(jí)別的時(shí)間戳 */ private static function getMillisecond(){ //獲取毫秒的時(shí)間戳 $time = explode ( " ", microtime () ); $time = $time[1] . ($time[0] * 1000); $time2 = explode( ".", $time ); $time = $time2[0]; return $time; } /** * 產(chǎn)生一個(gè)指定長度的隨機(jī)字符串,并返回給用戶 * @param type $len 產(chǎn)生字符串的長度 * @return string 隨機(jī)字符串 */ private function genRandomString($len = 32) { $chars = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ); $charsLen = count($chars) - 1; // 將數(shù)組打亂 shuffle($chars); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars[mt_rand(0, $charsLen)]; } return $output; } /** * 以post方式提交xml到對應(yīng)的接口url * * @param string $xml 需要post的xml數(shù)據(jù) * @param string $url url * @param bool $useCert 是否需要證書,默認(rèn)不需要 * @param int $second url執(zhí)行超時(shí)時(shí)間,默認(rèn)30s * @throws WxPayException */ private function postXmlCurl($xml, $url, $useCert = false, $second = 30){ $ch = curl_init(); //設(shè)置超時(shí) curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2); //設(shè)置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求結(jié)果為字符串且輸出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if($useCert == true){ //設(shè)置證書 //使用證書:cert 與 key 分別屬于兩個(gè).pem文件 curl_setopt($ch,CURLOPT_SSLCERTTYPE,"PEM"); //curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); curl_setopt($ch,CURLOPT_SSLKEYTYPE,"PEM"); //curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); } //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //運(yùn)行curl $data = curl_exec($ch); //返回結(jié)果 if($data){ curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } /** * 錯(cuò)誤代碼 * @param $code 服務(wù)器輸出的錯(cuò)誤代碼 * return string */ public function error_code( $code ){ $errList = array( "NOAUTH" => "商戶未開通此接口權(quán)限", "NOTENOUGH" => "用戶帳號(hào)余額不足", "ORDERNOTEXIST" => "訂單號(hào)不存在", "ORDERPAID" => "商戶訂單已支付,無需重復(fù)操作", "ORDERCLOSED" => "當(dāng)前訂單已關(guān)閉,無法支付", "SYSTEMERROR" => "系統(tǒng)錯(cuò)誤!系統(tǒng)超時(shí)", "APPID_NOT_EXIST" => "參數(shù)中缺少APPID", "MCHID_NOT_EXIST" => "參數(shù)中缺少M(fèi)CHID", "APPID_MCHID_NOT_MATCH" => "appid和mch_id不匹配", "LACK_PARAMS" => "缺少必要的請求參數(shù)", "OUT_TRADE_NO_USED" => "同一筆交易不能多次提交", "SIGNERROR" => "參數(shù)簽名結(jié)果不正確", "XML_FORMAT_ERROR" => "XML格式錯(cuò)誤", "REQUIRE_POST_METHOD" => "未使用post傳遞參數(shù) ", "POST_DATA_EMPTY" => "post數(shù)據(jù)不能為空", "NOT_UTF8" => "未使用指定編碼格式", ); if( array_key_exists( $code , $errList ) ){ return $errList[$code]; } } }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/65138.html
摘要:開發(fā)流程準(zhǔn)備完成后我們來看一下支付的大體流程商戶應(yīng)用與微信支付主要的交互說明用戶在商戶應(yīng)用移動(dòng)端中選擇商品提交訂單,支付方式選擇微信支付。商戶應(yīng)用后臺(tái)收到用戶支付訂單,調(diào)用微信支付中的統(tǒng)一下單接口。 引言 秋高氣爽,天氣轉(zhuǎn)涼,正是學(xué)習(xí)工作做的好時(shí)候。(~ ̄▽ ̄)~~(~ ̄▽ ̄)~ 我是個(gè)phper最近在寫微信支付(APP支付),微信給的官方文檔并不是很詳細(xì)也沒有dome之類的代碼啥的(...
摘要:文檔注開放平臺(tái)的微信支付和公眾號(hào)的微信支付是不一樣的,公眾平臺(tái)和開放平臺(tái)的支付申請下來之后會(huì)有各自對應(yīng)的商戶平臺(tái)賬號(hào)注意區(qū)分公眾號(hào)和商戶號(hào)不同隨機(jī)數(shù)自己定義一個(gè)不重復(fù)訂單號(hào)微信通過微信授權(quán)登錄獲取注意這里傳給微信的單位是分商戶后臺(tái)自定義的超 文檔注:開放平臺(tái)的微信支付和公眾號(hào)的微信支付是不一樣的,公眾平臺(tái)和開放平臺(tái)的支付申請下來之后會(huì)有各自對應(yīng)的商戶平臺(tái)賬號(hào) function wech...
摘要:這個(gè)坑就是要注意回調(diào)結(jié)束要返回成功的響應(yīng)這幾天做微信支付暫時(shí)遇到的問題就這么多,只能說注意細(xì)節(jié)吧,爬過的坑記錄下來以后遇到就懂處理了。 前言 其實(shí)任何接口開發(fā)只要按照給出來的接口文檔和例子開發(fā)基本上不會(huì)有太大問題的,一些問題都是出在雜七雜八的小細(xì)節(jié)上,現(xiàn)在分享一下微信支付開發(fā)中自己遇到的小細(xì)節(jié)。按照文檔做完開發(fā)前配置,比如JS安全域名配置、網(wǎng)頁授權(quán)域名、公眾號(hào)授權(quán)目錄等等... 坑一:...
摘要:微信說明文檔分享的坑根據(jù)的文檔,很多人都是在初始化的配置的時(shí)候,傳入的當(dāng)前的地址不正確。同樣的,給微信初始化的加入對應(yīng)的參數(shù)。 date: 2018-12-13 15:23:09 用于記錄接入微信JS-SDK的坑,以后方便查詢第一次接入公眾號(hào)微信支付、分享、定位等等的坑的時(shí)候,心里是迷茫而又恐懼。因?yàn)椋犝f坑特別多,后來發(fā)現(xiàn)自己的親身體驗(yàn)到了這一點(diǎn)。 支付的坑 1、當(dāng)前URL未注冊 ...
摘要:微信說明文檔分享的坑根據(jù)的文檔,很多人都是在初始化的配置的時(shí)候,傳入的當(dāng)前的地址不正確。同樣的,給微信初始化的加入對應(yīng)的參數(shù)。 date: 2018-12-13 15:23:09 用于記錄接入微信JS-SDK的坑,以后方便查詢第一次接入公眾號(hào)微信支付、分享、定位等等的坑的時(shí)候,心里是迷茫而又恐懼。因?yàn)椋犝f坑特別多,后來發(fā)現(xiàn)自己的親身體驗(yàn)到了這一點(diǎn)。 支付的坑 1、當(dāng)前URL未注冊 ...
閱讀 3941·2021-11-17 09:33
閱讀 3288·2021-10-08 10:05
閱讀 3117·2021-09-22 15:36
閱讀 1143·2021-09-06 15:02
閱讀 2774·2019-08-29 12:45
閱讀 1594·2019-08-26 13:40
閱讀 3404·2019-08-26 13:37
閱讀 425·2019-08-26 13:37