關(guān)于微信支付
1. 生活中的微信支付
??目前我們?nèi)粘I钪薪佑|得比較多的線上電子支付方式主要有兩種,一種是支付寶岳悟,另一種就是微信支付了强饮,微信支付是集成在微信客戶端的支付功能娶耍,所謂微信客戶端梧疲,主要是微信的移動(dòng)應(yīng)用,例如安卓(Android)微信APP排惨、IOS微信APP吭敢,用戶可以通過手機(jī)的微信APP完成快速的支付流程,當(dāng)然暮芭,其他的移動(dòng)應(yīng)用也可以接入微信支付的接口來達(dá)到完成微信支付的所有功能鹿驼。
2. 微信支付方式
??主要的支付方式有:公眾號(hào)支付或稱網(wǎng)頁(yè)支付,掃描二維碼支付,APP支付辕宏,除此之外還有刷卡支付等蠢沿,還有一點(diǎn)就是,微信支付以綁定銀行卡的快捷支付為基礎(chǔ)的匾效。
3. 為什么要掌握
??對(duì)于我們開發(fā)者而言舷蟀,熟練地掌握微信支付的接口功能是必不可少的,因?yàn)橐院笪业囊龅幕ヂ?lián)網(wǎng)產(chǎn)品中面哼,可能是網(wǎng)頁(yè)野宜,亦可能是移動(dòng)應(yīng)用APP,都可能會(huì)集成微信支付魔策,那么接下來讓我們來學(xué)習(xí)如果使用PHP版的微信支付接口吧匈子。
4. 關(guān)于本節(jié)課
?? 本門課程主要針對(duì)已經(jīng)開通了微信商戶號(hào)且開通微信公眾平臺(tái)微信支付功能系統(tǒng)的學(xué)員,那我沒有開通這些東西怎么學(xué)習(xí)闯袒?如果沒有開通虎敦,也沒關(guān)系,可以直接使用本課程的代碼政敢,因?yàn)楸竟?jié)課程使用的是所有支付配置信息使用的都是測(cè)試賬號(hào)提供的其徙,在你學(xué)習(xí)了調(diào)起支付后,如果使用支付功能喷户,那么會(huì)產(chǎn)生每次一分錢的費(fèi)用唾那,支付到微信PHP開發(fā)包代碼中提供的測(cè)試商戶號(hào)中,測(cè)試賬號(hào)歸屬于微信系統(tǒng)褪尝。
下載SDK
1. 復(fù)制下面的鏈接在瀏覽器中打開
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
2. 在所打開的頁(yè)面中選擇PHP版本的SDK下載
??目前的壓縮包名為:WxpayAPI_php_v3闹获,下載完畢后,解壓到桌面河哑,里面一共含有5個(gè)文件夾避诽,和一個(gè) index.php 文件
cert、doc璃谨、example沙庐、lib、logs、index.php
為了方便大家學(xué)習(xí)轨功,我已經(jīng)在右邊的文件管理處上傳了對(duì)應(yīng)的一份SDK,大家可以參考學(xué)習(xí)容达,不過最好還是在自己的電腦下載一份古涧,首先大家先在右邊的編輯框中按照順序,輸入命令ls,然后看下輸出的是不是下圖花盐,如果輸出的是wxPay,那么就輸入命令cd wxPay
然后輸入命令:sudo php -S 0.0.0.0:80羡滑,看輸出的是不是下圖的內(nèi)容,是的話算芯,那么就可以往下面看了柒昏,如果不是的話,再重復(fù)上面的步驟熙揍,刷新頁(yè)面即可职祷。
上面的操作完成后,大家點(diǎn)擊右邊的訪問測(cè)試就可以進(jìn)入到支付樣例主頁(yè)面了届囚,如下圖所示:
?頁(yè)面顯示出了三種支付方式有梆,第一種jsapi是網(wǎng)頁(yè)支付,第二種刷卡支付意系,第三種掃碼支付泥耀,這時(shí)候如果你點(diǎn)擊jsapi支付的話,網(wǎng)頁(yè)會(huì)提示請(qǐng)?jiān)谖⑿趴蛻舳舜蜷_鏈接蛔添,為什么會(huì)這樣呢痰催?這個(gè)我會(huì)在后面的課程說到,除此之外迎瞧,掃碼支付如果你用微信的掃描二維碼掃描了的話夸溶,是真的會(huì)進(jìn)入到支付頁(yè)面的哦。
文件說明
1. index.php
??這個(gè)是官方提供的所有支付功能集成化的入口凶硅,不過需要注意的是:如果使用到我們自己的項(xiàng)目中蜘醋,記得修改對(duì)應(yīng)的鏈接。
2. cert-證書存放路徑
??證書是商家在使用微信支付功能的時(shí)候咏尝,進(jìn)行身份驗(yàn)證用到的压语,起到一種安全的作用,但是编检,目前微信支付僅僅只在使用退款接口或者撤銷訂單的時(shí)候需要可能會(huì)用到證書胎食,為什么是可能呢?因?yàn)樵诮涌诤瘮?shù)中允懂,我們可以選擇是否使用證書厕怜,不使用也能使用退款或撤銷訂單接口,在我們下載的SDK中,文件夾cert里面的證書對(duì)應(yīng)的是微信的測(cè)試賬號(hào)的粥航,如果琅捏,我們擁有自己的微信商戶平臺(tái)的賬號(hào),那么我們就可以登錄商戶平臺(tái)递雀,來下載我們自己的證書放到這個(gè)目錄柄延。
3. doc-官方文檔目錄
??里面含有一些的SDK使用指南信息
4. example-官方接口例子目錄
??在為完全掌握微信支付接口功能實(shí)現(xiàn)之前,我們主要依賴官方的例子代碼來進(jìn)行學(xué)習(xí)缀程,進(jìn)而進(jìn)行修改搜吧,含有:
文件夾-phpqrode存放了二維碼功能相關(guān)文件
jsapi.php"網(wǎng)頁(yè)調(diào)起支付頁(yè)面;"
notify.php"網(wǎng)頁(yè)支付后的回調(diào)的頁(yè)面杨凑;"
native.php"付款二維碼信息組裝頁(yè)面滤奈;"
qrcode.php"生成二維碼的頁(yè)面"
native_notify.php"掃描所生成二維碼進(jìn)入的頁(yè)面;"
notify.php"網(wǎng)頁(yè)支付后的回調(diào)頁(yè)面;"
orderquery.php"訂單查詢頁(yè)面撩满;"
download.php"查退款單頁(yè)面蜒程;"
refund.php"退款的頁(yè)面;"
refundquery.php"退款單查詢的頁(yè)面伺帘;"
WxPay.JsApiPay.php"網(wǎng)頁(yè)支付核心類搞糕;"
WxPay.NativePay.php和WxPay.MicroPay.php"是刷卡支付類"
5. lib-核心庫(kù)
前兩個(gè)很重要!
WxPay.Api.php"接口訪問類曼追,包含所有微信支付API列表的封裝"
WxPay.Config.php"配置信息所在文件"
WxPay.Data.php"簽名相關(guān)類窍仰,含簽名生成"
WxPay.Exception.php"異常類"
WxPay.Notify.php"回調(diào)函數(shù)的父類"
6. logs-這個(gè)主要用來存放在支付過程中生成的各種日志文件
接下來我們進(jìn)行文件配置
lib文件夾下的WxPay.Config.php
??對(duì)應(yīng)文件管理中l(wèi)ib文件夾下的WxPay.Config.php文件
1,公眾號(hào)與商戶平臺(tái)
??首先礼殊,我們簡(jiǎn)單了解一下微信公眾號(hào)和微信商戶平臺(tái)在微信支付中扮演的角色驹吮,公眾號(hào)是我們?cè)诰W(wǎng)頁(yè)要進(jìn)行支付的場(chǎng)所,而用戶支付了的錢晶伦,我們?cè)鯓訉?duì)它進(jìn)行操作呢碟狞,這就需要商戶平臺(tái)了,我們?cè)谏虘羝脚_(tái)里能夠進(jìn)行支付賬單查詢婚陪、款數(shù)提現(xiàn)等操作族沃,現(xiàn)在我們采用軟件打開lib文件下的WxPay.Config.php,可以采用 PhpStorm泌参,sublime脆淹,記事本,或者參照右邊的文件管理沽一,由于cert文件夾和doc文件夾里面的內(nèi)容目前不支持上傳盖溺,所以右邊文件管理處,沒有上傳這2個(gè)文件夾里面的文件铣缠。
2烘嘱,AppId和AppSecret
??微信公眾號(hào)的AppId和公眾號(hào)秘鑰,AppId是用來唯一標(biāo)識(shí)公眾號(hào)用戶,AppSecret可以理解為密碼昆禽,如果沒有公眾號(hào),那么我們就使用微信的測(cè)試AppId,如果我們有的話蝇庭,那么我們可以先登錄微信公眾,在這里醉鳖,還要求我們的公眾號(hào)必須已經(jīng)開通微信支付的接口權(quán)限,否則我們的AppId是不具備支付權(quán)限的。然后在左邊的菜單欄滑到最低哮内,找到并點(diǎn)擊開發(fā)->基本配置->找到AppId 和 AppSecret
constAPPID='wx426b3015555a46be';//這個(gè)是微信提供的測(cè)試AppId,我們學(xué)習(xí)用它足以
constAPPSECRET='01c6d59a3f9024db6336662ac95c8e74';//也是微信提供的測(cè)試AppSecret
lib文件夾下的WxPay.Config.php
1盗棵,商戶號(hào)MCHID
??商戶號(hào)MCHID,它用來唯一標(biāo)識(shí)微信商戶用戶,它在我們注冊(cè)成功成為商戶的時(shí)候,官方會(huì)發(fā)來一封開戶郵件,在這封郵件中可查看,如果沒有商戶號(hào),我們一樣可以使用微信的測(cè)試商戶號(hào),如果有的話,那么我們可以登陸微信商戶平臺(tái)牍蜂。
constMCHID='1225312702';//這個(gè)也是微信提供的測(cè)試商戶號(hào)
2,商戶支付密鑰KEY
??商戶支付密鑰KEY,必須由商戶自己設(shè)置,如果我們有自己的商戶泰涂,那么可以在商戶平臺(tái)的:賬戶設(shè)置->API安全中可以設(shè)置鲫竞,沒有的話也可以使用微信提供的來測(cè)試和學(xué)習(xí)逼蒙。
constKEY='e10adc3949ba59abbe56e057f20f883e';//微信提供的測(cè)試支付密鑰
1社搅,證書文件apiclient_cert與apiclient_key
??下面的是支付所用的存儲(chǔ)私鑰文件[apiclient_cert]淌实、存儲(chǔ)公鑰文件[apiclient_key],在前面文件說明這節(jié)課中有說到,證書是商家在使用微信支付功能的時(shí)候侠仇,進(jìn)行身份驗(yàn)證用到的炊昆,起到一種安全的作用留美,但是,目前微信支付僅僅只在使用退款接口或者撤銷訂單的時(shí)候需要可能會(huì)用到證書挚币,為什么是可能呢郎笆?因?yàn)樵诮涌诤瘮?shù)中,我們可以選擇是否使用證書忘晤,不使用也能使用退款或撤銷訂單接口宛蚓。
證書下載:證書不是在公眾平臺(tái)下載的,是在商戶平臺(tái)的賬戶設(shè)置->API安全里面下載设塔。下面的是微信提供的測(cè)試證書,我們測(cè)試和學(xué)習(xí)可以使用它們凄吏。?
constSSLCERT_PATH='../cert/apiclient_cert.pem';//測(cè)試提供的私鑰
constSSLKEY_PATH='../cert/apiclient_key.pem';//測(cè)試提供的公鑰
2,代理服務(wù)器和錯(cuò)誤上報(bào)
??下面的為代理服務(wù)器和程序錯(cuò)誤信息上報(bào)等級(jí)相關(guān)設(shè)置,如無特殊情況闰蛔,默認(rèn)即可痕钢。
constCURL_PROXY_HOST="0.0.0.0";// 代理的IP,不需要代理,請(qǐng)?jiān)O(shè)置為0.0.0.0和0
constCURL_PROXY_PORT=0;//代理的端口,此時(shí)不開啟代理(如有需要才設(shè)置)
constREPORT_LEVENL=1;//錯(cuò)誤信息上報(bào)等級(jí)序六,0.關(guān)閉上報(bào); 1.僅錯(cuò)誤出錯(cuò)上報(bào); 2.全量上報(bào)
網(wǎng)頁(yè)設(shè)置
1,OpenId簡(jiǎn)介
??OpenId是微信用來唯一標(biāo)識(shí)用戶的一串字符,通俗來說就是微信用戶的id任连。在前面的課程中我們知道了在微信支付中調(diào)起支付需要在代碼設(shè)置參數(shù),而且要設(shè)置的還不止一個(gè),其中還要設(shè)置的就有用戶的OpenId,哪個(gè)用戶呢?我們知道每一次的交易,都有一個(gè)付款者,那么在這次交易中,我們要設(shè)置的OpenId就是他的,上面談到,OpenId是微信唯一標(biāo)識(shí)用戶的,我們不可能隨便就獲取到,因此微信提供了一個(gè)專門用來獲取用戶OpenId的接口給我們。
2,獲取OpenId的準(zhǔn)備
??如果我們有自己的公眾號(hào),而且公眾號(hào)開通了微信支付權(quán)限的話,那么為了獲取OpenId,我們需要登錄公眾平臺(tái),然后在左邊的菜單欄滑到最低例诀,找到并點(diǎn)擊開發(fā)->接口權(quán)限
再到右邊的功能列表中找到網(wǎng)頁(yè)授權(quán)獲取用戶基本信息,然后點(diǎn)擊修改字體
然后在輸入框中輸入我們要獲取用戶OpenId的網(wǎng)頁(yè)頁(yè)面的所在路徑的域名即可,記住,輸入域名就行了,前面不用再添加協(xié)議字符,即http://或https://的字符,還有不要填域名的ip哦
1,支付相關(guān)代碼路徑授權(quán)
??現(xiàn)在我們已經(jīng)下載好了微信支付 PHP 的 SDK,默認(rèn)所有配置信息都是微信提供的,如果我們有自己的公眾號(hào)且開通了支付權(quán)限,除了上面的獲取OpenId的準(zhǔn)備工作之外,我們還要把我們寫好了的微信支付的相關(guān)代碼,放到我們自己的服務(wù)器里面,然后需要到公眾平臺(tái)授權(quán)該路徑随抠。
??首先,在公眾號(hào)的左邊菜單欄找到微信支付并點(diǎn)擊,然后在右邊點(diǎn)擊開發(fā)配置
這里有兩個(gè)目錄,一個(gè)是支付授權(quán)目錄,另一個(gè)是支付測(cè)試目錄,支付授權(quán)目錄和支付測(cè)試目錄的區(qū)別僅僅在于:支付測(cè)試目錄中可以設(shè)置測(cè)試微信號(hào),也就是說,在這個(gè)目錄里只有我設(shè)置了的賬號(hào)才可以支付,而授權(quán)目錄是所有人都可以支付的裁着。在測(cè)試白名單里設(shè)置微信號(hào)。
點(diǎn)擊支付授權(quán)目錄的修改,我們就可以設(shè)置授權(quán)目錄了,需要注意的是:發(fā)起支付請(qǐng)求的鏈接地址拱她,都必須在支付授權(quán)目錄之下,例如:我們把PHP版的SDK全部放在一個(gè)叫做 WeChatPay 的文件夾下,那么我們的授權(quán)目錄路徑就是:www.xxxx.com:xx/WeChatPay,為了保證路徑?jīng)]錯(cuò),拿SDK的文件夾 example 為例,因?yàn)榘l(fā)起支付的文件 jsapi.php 在example里面二驰,所以,我們還可以添加多一個(gè)目錄為:www.xxxx.com:xx/WeChatPay/example。
測(cè)試支付目錄的修改參照授權(quán)目錄,如果你設(shè)置了測(cè)試授權(quán)目錄,記得到測(cè)試白名單中添加測(cè)試賬號(hào)
下面的課程我們講從代碼的角度去學(xué)習(xí)微信支付
example文件夾下的 WxPay.JsApiPay.php
??對(duì)應(yīng)文件管理中example文件夾下的 WxPay.JsApiPay.php文件
1秉沼,靜態(tài)函數(shù) unifiedOrder
??它負(fù)責(zé)統(tǒng)一下單桶雀,除刷卡支付外的支付都是由它進(jìn)行,如果我們是在網(wǎng)頁(yè)中進(jìn)行支付的話唬复,這個(gè)函數(shù)是先行的矗积,所傳入的參數(shù)是 lib文件夾下WxPay.Data.php的WxPayUnifiedOrder?類,它主要負(fù)責(zé)設(shè)置一些訂單的信息敞咧,例如設(shè)置商戶訂單號(hào):
$input->SetOut_trade_no("32個(gè)字符內(nèi)棘捣、可包含字母的商戶訂單號(hào)");
返回值是一個(gè)數(shù)組,包含的狀態(tài)碼和支付信息,但是不能由這個(gè)來判斷是否支付成功!官方文檔
??還有一個(gè)要注意的是:要設(shè)置的訂單信息項(xiàng),不止一個(gè),下面是一個(gè)例子,在下面的課程我會(huì)逐個(gè)解釋妄均。
$input=newWxPayUnifiedOrder();
$input->SetOut_trade_no("32個(gè)字符內(nèi)柱锹、可包含字母的商戶訂單號(hào)");
//其他的設(shè)置
$order=WxPayApi::unifiedOrder($input);
2哪自,靜態(tài)函數(shù) refund
??它負(fù)責(zé)退款丰包,所有支付方式的退款都是由它進(jìn)行,它所傳入的參數(shù)是 lib文件夾下WxPay.Data.php的WxPayRefund?類壤巷,它主要負(fù)責(zé)設(shè)置一些要退款的訂單的信息*邑彪,例如設(shè)置要退款的商戶訂單號(hào)。
注意:每次退款的商戶訂單號(hào)或微信訂單號(hào)胧华,都是和下單時(shí)候的一樣寄症,它們是配對(duì)的。
$input->SetOut_trade_no("對(duì)應(yīng)下單時(shí)的訂單號(hào)");
返回值是一個(gè)數(shù)組矩动,款數(shù)數(shù)目有巧、時(shí)間、退款結(jié)果等,下面是一個(gè)例子悲没。
$input=newWxPayRefund();
$input->SetOut_trade_no("下單時(shí)的商戶訂單號(hào)");
//其他的設(shè)置
$order=WxPayApi::refund($input);
example文件下的WxPay.MicroPay.php
??對(duì)應(yīng)文件管理中example文件夾下的WxPay.MicroPay.php文件
3篮迎,刷卡支付 pay
??它負(fù)責(zé)刷卡支付下訂單,所傳入的參數(shù)是 lib文件夾下WxPay.Data.php的WxPayMicroPay?類示姿,它主要負(fù)責(zé)設(shè)置要刷卡支付的訂單信息,例子如下甜橱。
$input->SetOut_trade_no("下單時(shí)的商戶訂單號(hào)");
返回值是一個(gè)數(shù)組,含有訂單下單時(shí)間栈戳、支付的狀態(tài)結(jié)果等,下面是一個(gè)例子岂傲。
$input=newWxPayMicroPay();
$input->SetOut_trade_no("下單時(shí)的訂單號(hào)");
//其他的設(shè)置
$microPay=newMicroPay();
$order=$microPay->pay($input);
1,靜態(tài)函數(shù) orderQuery
??它負(fù)責(zé)查詢訂單子檀,所有支付方式的訂單都可以調(diào)用它來查詢镊掖,它所傳入的參數(shù)是 lib文件夾下WxPay.Data.php的WxPayOrderQuery?類乃戈,它主要負(fù)責(zé)設(shè)置要查詢的訂單的信息,除此之外堰乔,我們還可以利用它來判斷商戶號(hào)偏化、AppId等信息是否存在,根據(jù)商戶訂單號(hào)查詢,設(shè)置如下镐侯。
注意:每次查詢的訂單侦讨,它所設(shè)置的商戶訂單號(hào)或微信訂單號(hào),都是和下單時(shí)候的一樣苟翻,它們是配對(duì)的韵卤。
$input->SetOut_trade_no("對(duì)應(yīng)下單時(shí)的訂單號(hào)");
返回值是一個(gè)數(shù)組,含有訂單下單時(shí)間崇猫、支付的狀態(tài)結(jié)果沈条、訂單是否存在等,下面是一個(gè)例子。
$input=newWxPayOrderQuery();
$input->SetOut_trade_no("下單時(shí)的商戶訂單號(hào)");
//其他的設(shè)置
$order=WxPayApi::orderQuery($input);
2诅炉,靜態(tài)函數(shù) refundQuery
??它負(fù)責(zé)查詢退款訂單蜡歹,相比于orderQuery,我們可以理解為是相比于orderQuery的一部分,它所傳入的參數(shù)是 lib文件夾下WxPay.Data.php的WxPayRefundQuery?類涕烧,它主要負(fù)責(zé)設(shè)置要查詢的退款訂單的信息月而,除此之外,我們還可以利用它來判斷商戶號(hào)议纯、AppId等信息是否存在父款,這部分和WxPayOrderQuery幾乎一樣,根據(jù)商戶訂單號(hào)查詢,設(shè)置如下瞻凤。
注意:每次查詢的退款訂單憨攒,它所設(shè)置的商戶訂單號(hào)或微信訂單號(hào),都是和下單時(shí)候的一樣阀参,它們是配對(duì)的肝集。
$input->SetOut_trade_no("下單時(shí)的商戶訂單號(hào)");
返回值是一個(gè)數(shù)組,含有訂單下單時(shí)間蛛壳、支付的狀態(tài)結(jié)果杏瞻、訂單是否存在等,下面是一個(gè)例子。
$input=newWxPayRefundQuery();
$input->SetOut_trade_no("下單時(shí)的訂單號(hào)");
//其他的設(shè)置
$order=WxPayApi::refundQuery($input);
注意事項(xiàng)
1,參數(shù)設(shè)置個(gè)數(shù)
??無論是下訂單還是發(fā)起退款等操作,其設(shè)置的信息都限制了不能只有一個(gè)炕吸。
2,參數(shù)設(shè)置要求
??1)商戶訂單號(hào)是由用戶設(shè)置的,對(duì)應(yīng)每條訂單必須唯一;
??2)下單中的款數(shù)設(shè)置,是int類型,微信規(guī)定了其單位是分,也就是說如果我們?cè)O(shè)置了100,事實(shí)付款1元,退款結(jié)果中的款數(shù)也是分作單位,切記;
??3)下單中的貨幣類型,默認(rèn)是CNY即人民幣,若設(shè)置了其他的幣種,要注意換算!
3,訂單唯一性
??每條訂單可以由商戶訂單號(hào),這個(gè)我們?cè)诿看蜗聠我淮紊梢淮蔚奶?hào)碼確定之外伐憾,還可以由微信訂單號(hào)唯一確定,但是,微信訂單號(hào)由微信支付自己生成,我們可以通過查詢訂單獲得或者登陸商戶平臺(tái)查看。
在JavaScript處理支付結(jié)果
在發(fā)起支付請(qǐng)求后,我們需要如果可以通過下面兩種方式來判斷是否支付成功赫模。第一種是在JavaScript回調(diào)函數(shù)中處理树肃。
??在jsapi.php文件的下面有幾個(gè)JavaScript函數(shù),他們分別是jsApiCall(),callpay(),editAddress()
??editAddress()的功能是獲取用戶的位置信息,具體表現(xiàn)是,當(dāng)用戶進(jìn)入支付頁(yè)面,如果調(diào)用這個(gè)函數(shù),那么就會(huì)調(diào)起選擇地址的界面,等用戶選擇完成后,才返回進(jìn)入下一步,對(duì)于它,我們默認(rèn)即可
//獲取用戶地址
function?editAddress()
{
WeixinJSBridge.invoke(
'editAddress',
,
function(res)
{
var?value1?=?res.proviceFirstStageName;
var?value2?=?res.addressCitySecondStageName;
var?value3?=?res.addressCountiesThirdStageName;
var?value4?=?res.addressDetailInfo;
var?tel?=?res.telNumber;
alert(value1?+?value2?+?value3?+?value4?+?":"?+?tel);
}
);
}
??callpay()的功能是在確保WeixinJSBridge對(duì)象存在的情況下再進(jìn)入jsApiCall()函數(shù),此時(shí)把支付接口返回的數(shù)據(jù)進(jìn)行解析并回調(diào)支付結(jié)果,在這里我們就能大致判斷下用戶支付是否成功,為什么是大致判斷呢,因?yàn)槲⑿艌F(tuán)隊(duì)告知了我們,在這里處理支付結(jié)果不可靠!切記瀑罗。
//調(diào)用微信JS?api?支付
function?jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
,
function(res){
WeixinJSBridge.log(res.err_msg);
alert(res.err_code+res.err_desc+res.err_msg);
//?使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:
//?res.err_msg將在用戶支付成功后返回ok胸嘴,但并不保證它絕對(duì)可靠雏掠。
if(res.err_msg?==?"get_brand_wcpay_request:ok"?)?{
//?支付成功
}else?if((res.err_msg?=="get_brand_wcpay_request:fail"){
//?支付失敗
}else?if((res.err_msg?=="get_brand_wcpay_request:cancel"){
//?支付過程中用戶取消
}
}
);
}
在回調(diào)鏈接中處理結(jié)果的入口
?? 在發(fā)起訂單組合訂單參數(shù)的時(shí)候,我們有下面的一個(gè)設(shè)置,它就是用來在支持成功回調(diào)通知中處理成功之后事宜的,也就是說,我們可以在這個(gè)代碼文件里面可靠地處理支付結(jié)果,下面的鏈接設(shè)置是默認(rèn)的測(cè)試路徑。
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
notify.php的例子文件在example文件夾下面劣像,對(duì)應(yīng)文件管理中example文件夾下的notify.php文件乡话。
必須引入的頭文件,以SDK的路徑為例子
require_once?"../lib/WxPay.Api.php";
require_once?'../lib/WxPay.Notify.php';
回調(diào)信息處理的入口
$notify?=?new?PayNotifyCallBack();
$notify->Handle(false);
現(xiàn)在打開lib文件夾下的WxPay.Notify.php文件,找到WxPayNotify類,入口函數(shù)Handler如下。
/**
*?回調(diào)入口
*?@param?bool?$needSign?是否需要簽名輸出
*/
final?public?function?Handle($needSign?=?true)
{
$msg?=?"OK";
//當(dāng)返回false的時(shí)候耳奕,表示notify中調(diào)用NotifyCallBack回調(diào)失敗
//若傳入需要簽名即傳入true,獲取簽名校驗(yàn)失敗绑青,此時(shí)直接返回失敗
//notify函數(shù)里面?zhèn)魅肓薔otifyCallBack回調(diào)函數(shù)名,這時(shí)候它會(huì)被調(diào)用
//$msg作為變量也傳入了NotifyCallBack回調(diào)函數(shù)里面,$msg包含有支付信息
$result?=?WxpayApi::notify(array($this,?'NotifyCallBack'),?$msg);
if($result?==?false)
{
$this->SetReturn_code("FAIL");
$this->SetReturn_msg($msg);
$this->ReplyNotify(false);
return;
}else{
//該分支在成功回調(diào)到NotifyCallBack方法,處理完成之后流程
$this->SetReturn_code("SUCCESS");
$this->SetReturn_msg("OK");
}
$this->ReplyNotify($needSign);
}
重寫回調(diào)函數(shù)自定義處理
?? notify的回調(diào)方法在lib文件夾下的WxPay.Notify.php文件中,在NotifyCallBack函數(shù)里面屋群,它調(diào)用了NotifyProcess闸婴,注意,此時(shí)就相當(dāng)于調(diào)用了notify.php中的PayNotifyCallBack類里面的NotifyProcess函數(shù)芍躏。
/**
*?notify的回調(diào)方法邪乍,該方法中需要賦值需要輸出的參數(shù)
*?@param?array?$data
*?@return?true回調(diào)出來完成不需要繼續(xù)回調(diào),false回調(diào)處理未完成需要繼續(xù)回調(diào)
*/
final?public?function?NotifyCallBack($data)?//?$msg傳進(jìn)來
{
$msg?=?"OK";
"http://NotifyProcess就是我們要重寫的函數(shù)"
$result?=?$this->NotifyProcess($data,?$msg);
if($result?==?true){
$this->SetReturn_code("SUCCESS");
$this->SetReturn_msg("OK");
}else{
$this->SetReturn_code("FAIL");
$this->SetReturn_msg($msg);
}
return?$result;
}
在notify.php中重寫,NotifyProcess函數(shù)对竣。
class?PayNotifyCallBack?extends?WxPayNotify
{
//查詢訂單
public?function?Queryorder($transaction_id)
{
$input?=?new?WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$result?=?WxPayApi::orderQuery($input);
Log::DEBUG("query:"?.?json_encode($result));
if(array_key_exists("return_code",?$result)
&&?array_key_exists("result_code",?$result)
&&?$result["return_code"]?==?"SUCCESS"
&&?$result["result_code"]?==?"SUCCESS")
{
return?true;
}
return?false;
}
//重寫回調(diào)處理函數(shù)
public?function?NotifyProcess($data,&$msg)
{
//"$data"?是NotifyCallBack函數(shù)傳進(jìn)來的含有支付信息的參數(shù)
$notfiyOutput?=?array();
//?下面這句判斷支付參數(shù)中是否含有微信訂單號(hào)transaction_id
if(!array_key_exists("transaction_id",?$data)){
$msg?=?"輸入?yún)?shù)不正確";
return?false;
}
//查詢訂單庇楞,判斷訂單真實(shí)性,二重判斷
if(!$this->Queryorder($data["transaction_id"])){
$msg?=?"訂單查詢失敗";
return?false;
}
//?"這里返回真,證明支付成功了"
//?"我們也可以直接在這里做支付成功后的操作"
return?true;
}
}
訂單查詢
??對(duì)應(yīng)文件管理中example文件夾下的orderquery.php文件
1,頭文件引入
必須引入的頭文件,以SDK的路徑為例子
require_once"../lib/WxPay.Api.php";
可選的頭文件引入,該頭文件只是微信支付用于記錄操作日志
require_once'log.php';
2,查詢條件
?? 每條訂單可以由商戶訂單號(hào),這個(gè)我們?cè)诿看蜗聠我淮紊梢淮蔚奶?hào)碼確定之外,還可以由微信訂單號(hào)唯一確定,那么查詢訂單的時(shí)候也需要這兩個(gè)參數(shù)之中的一個(gè),由于微信訂單的獲取比較麻煩,所以一般我們采用商戶訂單號(hào)來進(jìn)行查詢,微信訂單號(hào)和商戶訂單號(hào)最少填一個(gè)否纬,微信訂單號(hào)優(yōu)先吕晌。
3,采用商戶訂單號(hào)查詢
?? 首先我們要這這個(gè)頁(yè)面里面獲取到要查詢的商戶訂單號(hào),例如通過get的形式來獲取。
$tradeId?=?$_GET["out_trade_no"];
然后就能調(diào)用接口函數(shù)來進(jìn)行查詢了烦味。
if(isset($tradeId)?&&?$tradeId?!=?"")
{
$input?=?new?WxPayOrderQuery();
$input->SetOut_trade_no($tradeId);?//?設(shè)置好要查詢的訂單
$order?=?WxPayApi::orderQuery($input));?//?進(jìn)行查詢
var_dump($order);?//?打印出訂單信息
}
常用的訂單信息:
if($order['err_code_des']?=="order?not?exist"){
//?訂單不存在
}else{
$money?=?$order['total_fee'];?//所付款數(shù),單位分
if($order['trade_state']?=="SUCCESS"){
//支付成功
}else?if($order['trade_state']?=="REFUND"){
//已退款
}else?if($order['trade_state']?=="NOTPAY"){
//用戶還沒支付
}else?if($order['trade_state']?=="CLOSED"){
//訂單關(guān)閉
}else?if($order['trade_state']?=="REVOKED"){
//已撤銷(刷卡支付)
}else?if($order['trade_state']?=="USERPAYING"){
//用戶支付中
}else?if($order['trade_state']?=="PAYERROR"){
//支付失敗(其他原因聂使,例如銀行返回失敗)
}
}
更多查詢訂單返回值,參考官方文檔
4,采用微信訂單號(hào)查詢
$wxId?=?$_GET["transaction_id"];
if(isset($wxId)?&&?$wxId?!=?"")
{
$input?=?new?WxPayOrderQuery();
$input->SetOut_trade_no($wxId);?//?設(shè)置好要查詢的訂單
$order?=?WxPayApi::orderQuery($input));?//?進(jìn)行查詢
var_dump($order);?//?打印出訂單信息
}
申請(qǐng)退款
??對(duì)應(yīng)文件管理中example文件夾下的refund.php文件
1,頭文件引入
必須引入的頭文件,以SDK的路徑為例子
require_once"../lib/WxPay.Api.php";
可選的頭文件引入,該頭文件只是微信支付用于記錄操作日志
require_once'log.php';
2,退款參數(shù)
?? 除了要輸入要退款的訂單號(hào)之外,退款還需要商戶號(hào)壁拉、退款的款數(shù)谬俄、商戶訂單號(hào)、為該次退款設(shè)置一個(gè)退款單號(hào)等,在這里要注意退款的款數(shù)要化為單位分,例如要退款2元,那么設(shè)置時(shí)要設(shè)置為200弃理。
2,發(fā)起退款
?? 這里我們以REQUEST的方式獲取傳過來的參數(shù)為例子,這種方式對(duì)發(fā)送端是get還是post沒要求溃论,無論是get的方式還是post方式,都能接收到,在安全方面不夠post形式好痘昌。
if(isset($_REQUEST["out_trade_no"])?&&?$_REQUEST["out_trade_no"]?!=?""){
$out_trade_no?=?$_REQUEST["out_trade_no"];?//?要退款的訂單的商戶訂單號(hào)
$total_fee?=?$_REQUEST["total_fee"];?//?該訂單的一共支付總額
$refund_fee?=?$_REQUEST["refund_fee"];?//?要退款的錢數(shù)
$input?=?new?WxPayRefund();
/**?SetOut_trade_no?設(shè)置該訂單的商戶訂單號(hào),憑借這個(gè)唯一確定?*/
$input->SetOut_trade_no($out_trade_no);
/**?SetTotal_fee?設(shè)置訂單的當(dāng)時(shí)支付的總額?*/
$input->SetTotal_fee($total_fee);
/**?SetRefund_fee?設(shè)置要退款多少錢?*/
$input->SetRefund_fee($refund_fee);
/**?SetOut_refund_no?設(shè)置此次商戶退款的單號(hào),它不是商戶訂單號(hào)?*/
$input->SetOut_refund_no(WxPayConfig::MCHID.date("YmdHis"));
/**?SetOp_user_id?設(shè)置商戶號(hào)?*/
$input->SetOp_user_id(WxPayConfig::MCHID);
/**?發(fā)起退款?*/
$order?=?WxPayApi::refund($input);
/**?在返回的數(shù)組中,我們能夠獲取鍵名return_code?*/
if($order["return_code"]=="SUCCESS"){
//?退款申請(qǐng)成功
}else?if($order["return_code"]=="FAIL"){
//?退款申請(qǐng)失敗
}else{
//?未知狀態(tài)
}
var_dump($order);
}
3,退款效果
??一旦申請(qǐng)退款成功钥勋,那么該訂單號(hào)對(duì)應(yīng)的用戶便會(huì)在微信客戶端收到退款的憑據(jù),同時(shí)在商家的商戶平臺(tái)也會(huì)有該退款記錄生成辆苔。
查詢退款
??對(duì)應(yīng)文件管理中example文件夾下的refundquery.php文件
1,頭文件引入
必須引入的頭文件,以SDK的路徑為例子
require_once"../lib/WxPay.Api.php";
可選的頭文件引入,該頭文件只是微信支付用于記錄操作日志
require_once'log.php';
2,根據(jù)微信訂單號(hào)查詢
?? 微信訂單號(hào)在上面提到算灸,它是微信支付系統(tǒng)自己幫我們生成的,如果要獲知的話驻啤,目前我們可以在查詢訂單處獲得菲驴,或者直接登錄微信商戶平臺(tái)查看獲得,由微信訂單號(hào)查退款的靈活度不高,下面是例子代碼骑冗。
if(isset($_REQUEST["transaction_id"])?&&?$_REQUEST["transaction_id"]?!=?""){
$transaction_id?=?$_REQUEST["transaction_id"];
$input?=?new?WxPayRefundQuery();
$input->SetTransaction_id($transaction_id);
$order?=?WxPayApi::refundQuery($input);
var_dump($order)$order;
};
3,根據(jù)商戶訂單號(hào)查詢
?? 商戶訂單號(hào)查詢的靈活性高赊瞬,因?yàn)樯虘粲唵翁?hào)是我們自己生成的先煎,在下訂單生成的時(shí)候,我們?cè)谔幚硐聠谓Y(jié)果確認(rèn)支付成功后巧涧,就可以把它存到數(shù)據(jù)庫(kù)薯蝎,查詢的時(shí)候再讀取出來。
if(isset($_REQUEST["out_trade_no"])?&&?$_REQUEST["out_trade_no"]?!=?""){
$out_trade_no?=?$_REQUEST["out_trade_no"];
$input?=?new?WxPayRefundQuery();
$input->SetOut_trade_no($out_trade_no);
$order?=?WxPayApi::refundQuery($input);
var_dump($order)$order;
}
4,根據(jù)商戶退款單號(hào)查詢
?? 還記得在退款操作的時(shí)候有這么一句設(shè)置嗎谤绳,如下所示占锯,它就是設(shè)置商戶退款單號(hào)的,也是由我們生成缩筛,一樣要確保它對(duì)于每條退款的唯一性烟央。
/**?SetOut_refund_no?設(shè)置此次退款的商戶單號(hào),它不是商戶訂單號(hào)?*/
$input->SetOut_refund_no(WxPayConfig::MCHID.date("YmdHis"));
if(isset($_REQUEST["out_refund_no"])?&&?$_REQUEST["out_refund_no"]?!=?""){
$out_refund_no?=?$_REQUEST["out_refund_no"];
$input?=?new?WxPayRefundQuery();
$input->SetOut_refund_no($out_refund_no);
$order?=?WxPayApi::refundQuery($input);
var_dump($order)$order;
}
5,根據(jù)退款單號(hào)查詢
?? 退款單號(hào)的生成和微信訂單號(hào)一樣,也是微信支付系統(tǒng)幫我們生成的歪脏。
if(isset($_REQUEST["refund_id"])?&&?$_REQUEST["refund_id"]?!=?""){
$refund_id?=?$_REQUEST["refund_id"];
$input?=?new?WxPayRefundQuery();
$input->SetRefund_id($refund_id);
$order?=?WxPayApi::refundQuery($input);
var_dump($order)$order;
}
?? 上面的四種退款查詢方式疑俭,各有所長(zhǎng),我們可以根據(jù)我們的實(shí)際情況的選擇使用婿失,一般來說钞艇,微信支付系統(tǒng)幫我們生成的單號(hào)的優(yōu)先級(jí)別是大于我們自己生成的。
使用環(huán)境
?? 一定要記住豪硅,微信支付的網(wǎng)頁(yè)版支付方式只能在微信的內(nèi)置瀏覽器里面進(jìn)行哩照,如果你在電腦瀏覽器打開了鏈接支付,它是會(huì)提示你錯(cuò)誤的懒浮,那么怎么在電腦使用呢飘弧?可以安裝手機(jī)虛擬機(jī),例如Genymotion或者夜神虛擬機(jī)砚著,再到手機(jī)虛擬機(jī)里面安裝一個(gè)微信APP次伶,就可以了。
???測(cè)試的時(shí)候稽穆,你可以直接通過發(fā)送測(cè)試鏈接到你的微信里面冠王,再打開就行了。
支付憑據(jù)
?? 在每一次的訂單支付成功后舌镶,微信都會(huì)發(fā)一條電子支付憑據(jù)給所付款的用戶柱彻,支付憑據(jù)中的重要信息有微信訂單號(hào)和商戶訂單號(hào),除此之外還有商品名稱餐胀,下單時(shí)間哟楷,支付狀態(tài)。其中商戶訂單號(hào)由我們代碼設(shè)置否灾,商品名稱也是卖擅,商品名稱對(duì)應(yīng)的是$input->SetBody("test");,下單時(shí)間對(duì)應(yīng)的是$input->SetTime_start(date("YmdHis"));。
?? 支付憑據(jù)可以讓用戶自己恢復(fù)訂單磨镶。想象一下溃蔫,用戶購(gòu)買了商品且支付成功,但是我們自己的數(shù)據(jù)庫(kù)系統(tǒng)卻因?yàn)槠渌麊栴}漏單了琳猫,這時(shí)候我們可以在我們的網(wǎng)頁(yè)中設(shè)置一個(gè)訂單恢復(fù)系統(tǒng)伟叛,由用戶輸入訂單號(hào),然后我們后臺(tái)進(jìn)行訂單查詢脐嫂,若訂單的確支付成功了统刮,而數(shù)據(jù)庫(kù)沒對(duì)應(yīng)記錄,那么我們就進(jìn)而恢復(fù)訂單账千。
?? 微信支付嚴(yán)格要求支付的錢數(shù)最少是 1 分侥蒙,在代碼里面少于這個(gè)數(shù)會(huì)支付失敗。
獲取 OpenId
?? 還記得獲取OpenId的時(shí)候匀奏,頁(yè)面會(huì)怎樣嗎鞭衩?沒錯(cuò),它會(huì)重定向的娃善,為了不丟失我們傳過去的數(shù)據(jù)论衍,最好的方法就是改寫。
lib文件夾下的?WxPay.Api.php?函數(shù)
public?function?GetOpenid($userName,$userSex)
{
//通過code獲得openid
//code在微信服務(wù)處理完成之后重定向時(shí)帶回來的
if?(!isset($_GET['code']))
{
//?假設(shè)現(xiàn)在我的支付代碼文件的鏈接是:
//?http://hubwiz.com/WeChatPay/example/jsapi.php,那么下面就是
$baseUrl?=?urlencode("http://hubwiz.com/WeChatPay/example/jsapi.php?userName=".$userName."&userSex=".$userSex);
$url?=?$this->__CreateOauthUrlForCode($baseUrl);
Header("Location:?$url");?//?重定向
exit();
}else{
//獲取code碼聚磺,以獲取openid
$code?=?$_GET['code'];
$openid?=?$this->getOpenidFromMp($code);
return?$openid;//?返回OpenId
}
}
確保已下訂單
?? 在處理支付結(jié)果回調(diào)之后坯台,建議再進(jìn)行一次訂單查詢,以確保萬無一失瘫寝,除此之外蜒蕾,設(shè)置一個(gè)訂單恢復(fù)系統(tǒng)也是可以的,例如下面的例子。
if(isset($tradeId)?&&?$tradeId?!=?"")
{
$input?=?new?WxPayOrderQuery();
$input->SetOut_trade_no($tradeId);?//?設(shè)置好要查詢的訂單
$order?=?WxPayApi::orderQuery($input));?//?進(jìn)行查詢
if($order['err_code_des']?=="order?not?exist"){
//?訂單不存在
}else{
$money?=?$order['total_fee'];?//所付款數(shù),單位分
if($order['trade_state']?=="SUCCESS"){
//支付成功
//數(shù)據(jù)庫(kù)操作
//兩者對(duì)比
//若數(shù)據(jù)庫(kù)中沒記錄焕阿,就恢復(fù)訂單
}else?if($order['trade_state']?=="REFUND"){
//已退款
}else?if($order['trade_state']?=="NOTPAY"){
//用戶還沒支付
}else?if($order['trade_state']?=="CLOSED"){
//訂單關(guān)閉
}else?if($order['trade_state']?=="REVOKED"){
//已撤銷(刷卡支付)
}else?if($order['trade_state']?=="USERPAYING"){
//用戶支付中
}else?if($order['trade_state']?=="PAYERROR"){
//支付失敗(其他原因咪啡,例如銀行返回失敗)
}
}
}
基于SDK修改的Demo
?? 用法:先到 index.php 的上面修改鏈接數(shù)據(jù),再把整個(gè)工程放到你的服務(wù)器,就可以測(cè)試使用了捣鲸。
? 下載好之后瑟匆,在index.php 文件里面配置下路徑信息闽坡,如下面所示栽惶,當(dāng)然,如果你不使用微信自帶的測(cè)試支付配置疾嗅,別忘了還要到lib文件夾下修改WxPay.Config.php文件里面的配置信息外厂。
/**?請(qǐng)?jiān)谙旅嬖O(shè)置你服務(wù)器的路徑,默認(rèn)是測(cè)試的,如果您沒有自己的服務(wù)器代承,可以使用測(cè)試的?*/
$jsApiPay?=?"http://paysdk.weixin.qq.com/example/jsapi.php";
/**?刷卡支付?*/
$micropyPay?=?"http://paysdk.weixin.qq.com/example/micropay.php";
/**?掃碼支付?*/
$nativePay?=?"http://paysdk.weixin.qq.com/example/native.php";
/**?訂單查詢?*/
$orderQuery?=?"http://paysdk.weixin.qq.com/example/orderquery.php";
/**?退款?*/
$refundPay?=?"http://paysdk.weixin.qq.com/example/refund.php";
/**?退款查詢?*/
$refundQueryPay?=?"http://paysdk.weixin.qq.com/example/refundquery.php";
?>