微信支付的流程
- 注冊(cè)微信開放平臺(tái)少漆,創(chuàng)建應(yīng)用獲取appid厅须,appSecret豆拨,申請(qǐng)支付功能直奋,申請(qǐng)成功之后會(huì)返回一些參數(shù).
- 下載微信支付sdk
- 客戶端請(qǐng)求訂單,后臺(tái)與微信后臺(tái)交互施禾,返回給客戶端支付參數(shù)
- 調(diào)用微信客戶端,由微信客戶端和微信服務(wù)器打交道搁胆;
- 客戶端和服務(wù)端都會(huì)收到支付結(jié)果弥搞;(前臺(tái)消息不可靠,我們需要去后臺(tái)驗(yàn)證渠旁,如果后臺(tái)沒有收到支付通知攀例,后臺(tái)去微信服務(wù)器驗(yàn)證然后將結(jié)果返回給客戶端)
微信支付流程圖
支付流程圖@2x.png
開發(fā)步驟
- 去微信開放平臺(tái)注冊(cè)應(yīng)用
(https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN&token=2c0fee9c43e1eb8f9febcc7cb73abf598e2d4011)
創(chuàng)建移動(dòng)應(yīng)用并成功之后會(huì)收到騰訊發(fā)來的郵件
審核通過信息@2x.png -
通過郵件我們能獲得重要的參數(shù)
(1):AppID
(2):微信支付商戶號(hào)
(3):前往商戶平臺(tái)完成入駐
(4):API秘鑰(自己設(shè)置即可,注意一定要32位字母加
數(shù)字的組合)記得保存好秘鑰顾腊,以后要使用
入駐@2x.png
下載證書.png - 有了這些參數(shù)后,我們就可以開發(fā)自己的項(xiàng)目了.
接下來, 我們就新建一個(gè)微信工程吧.
創(chuàng)建好工程以后呢, 我們?nèi)ノ⑿牌脚_(tái)下載sdk
鏈接:
https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5#
下載SDK@2x.png -
下載好以后呢, 我們就開始集成SDK
集成SDK@2x.png -
把左邊的SDK拉到工程里面粤铭,大家會(huì)看到文件夾里面有集成SDK的步驟
readMe@2x.png
(1)在info.plist添加如下代碼
1@2x.png
(2)添加需要的框架和依賴庫(kù) (ps: 官方文檔沒讓添加libc++.tbd, 這點(diǎn)也是工程報(bào)錯(cuò)的時(shí)候發(fā)現(xiàn)的...)
2@2x.png -
剩下的事情, 我們只需要按照官方文檔來做就行了
APP端開發(fā)步驟@2x.png -
項(xiàng)目中設(shè)置APPID ,商戶在微信開放平臺(tái)申請(qǐng)開發(fā)APP應(yīng)用后杂靶,微信開放平臺(tái)會(huì)生成APP的唯一標(biāo)識(shí)APPID梆惯。在Xcode中打開項(xiàng)目,設(shè)置項(xiàng)目屬性中的URL Schemes為您的APPID(微信:APPID:wx.........69)
添加URL Schemes@2x.png -
注冊(cè)APPID,商戶APP工程中引入微信lib庫(kù)和頭文件吗垮,調(diào)用API前垛吗,需要先向微信注冊(cè)您的APPID
注冊(cè)APPID - 調(diào)起支付
商戶服務(wù)器生成支付訂單,先調(diào)用【統(tǒng)一下單API】生成預(yù)付單烁登,獲取到prepay_id后將參數(shù)再次簽名傳輸給APP發(fā)起支付怯屉。以下是調(diào)起微信支付的關(guān)鍵代碼:
現(xiàn)在我們只需要在控制器上添加一個(gè)button, 名字改成微信支付就可以了
button事件:
- (IBAction)weChatPayButtonAction:(id)sender
{
PayReq *request = [[PayReq alloc] init];
/** 商家向財(cái)付通申請(qǐng)的商家id */
request.partnerId = @"122****201";
/** 預(yù)支付訂單 */
request.prepayId= @"8201038****be9c4c063c30";
/** 商家根據(jù)財(cái)付通文檔填寫的數(shù)據(jù)和簽名 */
request.package = @"Sign=WXPay";
/** 隨機(jī)串,防重發(fā) */
request.nonceStr= @"lUu5qloVJV7rrJlr";
/** 時(shí)間戳饵沧,防重發(fā) */
request.timeStamp= 145****985;
/** 商家根據(jù)微信開放平臺(tái)文檔對(duì)數(shù)據(jù)做的簽名 */
request.sign= @"b640c1a4565b4****4b8a9e71960b0123";
/*! @brief 發(fā)送請(qǐng)求到微信锨络,等待微信返回onResp
*
* 函數(shù)調(diào)用后,會(huì)切換到微信的界面狼牺。第三方應(yīng)用程序等待微信返回onResp羡儿。微信在異步處理完成后一定會(huì)調(diào)用onResp。支持以下類型
* SendAuthReq锁右、SendMessageToWXReq失受、PayReq等。
* @param req 具體的發(fā)送請(qǐng)求咏瑟,在調(diào)用函數(shù)后拂到,請(qǐng)自己釋放。
* @return 成功返回YES码泞,失敗返回NO兄旬。
*/
[WXApi sendReq: request];
}
- 支付結(jié)果回調(diào)
按照微信SDKSample,在類實(shí)現(xiàn)onResp函數(shù),支付完成后领铐,微信APP會(huì)返回到商戶APP并回調(diào)onResp函數(shù)悯森,開發(fā)者需要在該函數(shù)中接收通知,判斷返回錯(cuò)
誤碼绪撵,如果支付成功則去后臺(tái)查詢支付結(jié)果再展示用戶實(shí)際支付結(jié)果瓢姻。注意
一定不能以客戶端返回作為用戶支付的結(jié)果,應(yīng)以服務(wù)器端的接收的支付通知或查詢API返回的結(jié)果為準(zhǔn)音诈。
這是最后一步了, 我們?cè)谥Ц俄?yè)面支付完成以后呢要知道支付結(jié)果, 怎么做呢?
首先, 在AppDelegate.m里面實(shí)現(xiàn)該方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
/*! @brief 處理微信通過URL啟動(dòng)App時(shí)傳遞的數(shù)據(jù)
*
* 需要在 application:openURL:sourceApplication:annotation:或者application:handleOpenURL中調(diào)用幻碱。
* @param url 微信啟動(dòng)第三方應(yīng)用時(shí)傳遞過來的URL
* @param delegate WXApiDelegate對(duì)象,用來接收微信觸發(fā)的消息细溅。
* @return 成功返回YES褥傍,失敗返回NO。
*/
return [WXApi handleOpenURL:url delegate:self];
}
-
接下來我們需要遵守下協(xié)議
遵守協(xié)議@2x.png - 最后一步, 就等支付結(jié)果出來以后回調(diào)一個(gè)函數(shù)了
/*發(fā)送一個(gè)sendReq后喇聊,收到微信的回應(yīng)收到一個(gè)來自微信的處理結(jié)果恍风。
* 調(diào)用一次sendReq后會(huì)收到onResp。
* 可能收到的處理結(jié)果有SendMessageToWXResp誓篱、SendAuthResp等朋贬。
* @param resp具體的回應(yīng)內(nèi)容,是自動(dòng)釋放的
*/
- (void)onResp:(BaseResp *)resp{
//支付返回結(jié)果燕鸽,實(shí)際支付結(jié)果需要去微信服務(wù)器端查詢
NSString *strMsg = [NSString stringWithFormat:@"支付結(jié)果"];
switch (resp.errCode) {
case WXSuccess:
strMsg = @"支付結(jié)果:成功兄世!";
NSLog(@"支付成功-PaySuccess,retcode = %d", resp.errCode);
break;
default:
strMsg = [NSString stringWithFormat:@"支付結(jié)果:失敯⊙小御滩!retcode = %d, retstr = %@", resp.errCode,resp.errStr];
NSLog(@"錯(cuò)誤,retcode = %d, retstr = %@", resp.errCode,resp.errStr);
break;
}
}