1. 準備
微信平台分為微信公衆平台和微信開放平台,公衆平台是營運微信公衆号的管理系統,開放平台主要針對app、網站開發,提供登入、分享、支付等功能。
注冊開放平台之後,建立應用,填寫應用資訊(Android、iOS等資訊),建立之後需要等待稽核(這個稽核很快的,幾個小時就通過了)。
然後是為該應用申請支付功能,要注意個人是無法申請的,具體可參考微信支付申請條件和資格。這裡牽涉到一系列公司資質的稽核和費用支付,需要幾個工作日的時間
完成之後可以擷取到appid(微信開放平台為應用生成的唯一識别碼)、商戶id、商戶secretKey。對于app端來說隻用到appid,商戶id最好通過接口從server擷取,商戶secretKey是用來簽名的,一般隻有server能用到。
2. 支付流程
先上一個開放平台給出的流程圖:
支付流程.png
這個圖很實用很詳細很清晰,但一開始看可能會覺得複雜。其實對開發者來說,比較關心的流程是:
app向server發起支付請求
server收到請求後向微信背景調用統一下單API,獲得預付單資訊
server生成帶簽名的用戶端支付資訊并傳回給app
使用者确認支付,app調起微信用戶端進行支付
app獲得支付結果後向server查詢最終結果并顯示
流程了解之後,了解下需要定義的接口和前後端的具體工作:
新接口:
app向server發起請求,獲得簽名後的app支付資訊
app支付之後向server查詢支付結果(微信回調的結果不可信,必須以server的結果為準)
app需要做的:
項目接入微信支付sdk
向server請求支付資訊
用支付資訊調起微信用戶端,然後支付
收到微信回調之後向server查詢支付結果
根據支付結果展示頁面
server需要做的:
收到app端支付請求後調用統一下單API向微信背景擷取預支付資訊
将app端需要的支付資訊簽名之後傳回給app
接收微信背景回調資訊(支付結果),以供app查詢
3. iOS開發
開發文檔:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1
下載下傳并運作demo
其實把demo看明白了,直接運用到自己的app裡,也不是不可以的
設定項目
在Xcode中,projectName-->Info-->URL Types 添加appid。設定之後才能實作應用間跳轉
urltypes.png
導入sdk
sdk.png
如果使用了pod,直接在Podfile中添加pod 'WechatOpenSDK' 然後執行 pod update即可。如果沒有使用pod,在添加了sdk檔案包之後,需要在pojectName-->General-->Linked Frameworks and Libraries 中添加相應内容
libs.png
代碼
AppDelegate.m
didFinishLaunchingWithOptions方法中
[WXApi registerApp:@"wx000999888777"];//注冊appid
openUrl、handleOpenURL方法
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];}
- (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation {
return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];
}
//NOTE:9.0以後使用新API接口
- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary *)options{
return[WXApi handleOpenURL:url delegate:[PaymentManager sharedManager]];
}
如果之前項目中使用了友盟等第三方架構,直接并排寫就可以:
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url{ [WXApi handleOpenURL:url delegate:[PaymentAction sharedPayment]]; [UMSocialSnsService handleOpenURL:url];returnYES;}
另外,這個地方的delegate也可以直接設定成nil,表示用目前AppDelegate作為微信支付的代理,這樣一來支付回調寫在AppDelegate.m中即可。
但不推薦這種做法,我是設定了PaymentManager作為代理,這是項目中專門管理支付的一個類,包括之前的支付寶支付。這也是微信demo中的做法。(支付寶是用block擷取回調的,個人感覺代碼更緊湊,不容易亂;微信是用的代理,剛開始看暈乎乎的)
PaymentManager
首先是遵守協定WXApiDelegate
然後在PayVC中通過接口擷取支付資訊
然後調起微信用戶端:
- (void)weiXinPayWithDic:(NSDictionary *)wechatPayDic {
PayReq *req = [[PayReq alloc] init];
req.openID = [wechatPayDic objectForKey:@"appId"];
req.partnerId = [wechatPayDic objectForKey:@"partnerId"];
req.prepayId = [wechatPayDic objectForKey:@"prepayId"];
req.package= [wechatPayDic objectForKey:@"packages"];
req.nonceStr = [wechatPayDic objectForKey:@"nonceStr"];
req.timeStamp = [[wechatPayDic objectForKey:@"timesTamp"] intValue];
req.sign = [wechatPayDic objectForKey:@"sign"];
[WXApi sendReq:req];
}
這裡的資料wechatPayDic一定是server經過二次簽名的
回調
// 微信支付傳回結果回調
- (void)onResp:(BaseResp *)resp {if([resp isKindOfClass:[PayRespclass]]) {
PayResp *response = (PayResp *)resp;
if(_delegate && [_delegate respondsToSelector:@selector(managerDidRecvPaymentResponse:)]) {
[_delegate managerDidRecvPaymentResponse:response];
}
}}
當然前提是在PaymentManager.h中已經定義了代理:
@[email protected]
- (void)managerDidRecvPaymentResponse:(PayResp *)response;@[email protected]:[email protected](nonatomic,assign)id delegate;
這個代理是用來處理回調結果,展示頁面的,是以設定成PayVC控制器
處理回調結果
PayVC.m
遵守協定WXApiManagerDelegate
在viewDidLoad中設定[PaymentManager sharedManager].delegate = self;
- (void)managerDidRecvPaymentResponse:(PayResp *)response {switch(response.errCode) {
caseWXSuccess: [selfcheckWechatPayResult];break;caseWXErrCodeUserCancel:
[[HintManager shareManager] showHint:@"中途取消"];break;default:{
[[HintManager shareManager]showHint:@"支付失敗"];
}break;
}}
然後在checkWechatPayResult向server查詢支付結果,重新整理頁面
哦了~~ 潑佛客特
4. 出現的問題
當然了,并不潑佛客特
系統版本大于等于iOS9的,調起微信用戶端之後,可以直接點選狀态欄左側按鈕傳回,這時是不走回調方法的。
這樣在支付成功之後,不走回調方法,就無法知道支付狀态,目前頁面無法給出提示。
解決方案是,在AppDelegate.m的applicationWillEnterForeground方法中,調用查詢支付結果接口然後重新整理當然頁面。需要設定bool變量作為标志,否則每次應用進入前台都去查詢,就不符合業務要求了。
進入微信支付頁面之後,不做操作,切換到自己應用中,退出目前支付頁面,然後再進入微信用戶端點選支付或者取消,此時自己的應用會崩潰閃退
原因是退出頁面後頁面已經出棧被銷毀,但wx回調時還是去調用其中的代理方法,就會出現野指針。
解決方法是,在頁面的viewWillDisappear方法中加入[PaymentManager sharedManager].delegate = nil;。
5. 需要注意的點
一定設定好scheme,否則應用無法跳轉
在調起微信支付使用的PayReq類,一定要用WXApi中自帶的類,不要自己建立新類。我之前自己建立的類,定義了同樣的變量,同樣繼承了BaseReq,然并卵,sendReq方法一直傳回false
調起微信支付的資料,一定是server經過二次簽名的,不要把調用統一下單API擷取到的資料直接返給app
雖然類中的變量命名是駝峰式,但簽名時的key值全部是小寫的,簽名時不要忘了後面加上商戶key。
6. 簽名
可能某些server端由于這樣那樣的原因不願意做二次簽名,app可以自己做。(不過因為簽名需要用到secretKey,讓app端做簽名是有風險的)
下面是簽名代碼:
個人建議像微信支付、支付寶支付最後都由背景完成,送出相應的資料給背景,讓背景生成訂單并傳回以下參數就可以了,這樣微信就會異步通知背景 支付完成後傳回APP 由APP直接向背景請求訂單支付成功了沒有, 這樣可以保證支付不會出現一些小問題