ios 微信支付

今天看了一篇微信支付的文章 感覺說的很詳細(xì),記錄一下,以備不時(shí)之需
1.開始接入微信支付的準(zhǔn)備工作

image

首先你需要去微信開放平臺(tái)注冊(cè)賬號(hào),在這里要吐槽一下,不知道這個(gè)微信平臺(tái)的賬號(hào)密碼驗(yàn)證機(jī)制,忘了以前的密碼,重新登錄,各種找回密碼都不行,實(shí)在沒轍,去注冊(cè)個(gè)Gmail??,登錄成功后,可以看到如下界面。

image

點(diǎn)擊右上角的創(chuàng)建移動(dòng)應(yīng)用,一步一步填寫必要填入的信息,在這里就不做多余的贅述了。

需要注意的是這里填入的Bundle ID需要和項(xiàng)目的一一對(duì)應(yīng)

image

接下來就等一個(gè)星期左右,等待微信審核通過你就可以將微信支付SDK集成到項(xiàng)目中,詳情可以看官方給出的文檔.

pod 集成方法

pod 'WechatOpenSDK'

在Xcode中,選擇你的工程設(shè)置項(xiàng),選中“TARGETS”一欄,在“info”標(biāo)簽欄的“URL type“添加“URL scheme”為你所注冊(cè)的應(yīng)用程序id(如下圖所示)。

image.gif

完成之后可以獲取到appid(微信開放平臺(tái)為應(yīng)用生成的唯一識(shí)別碼)、商戶id、商戶secretKey。對(duì)于app端來說只用到appid,商戶id最好通過接口從server獲取,商戶secretKey是用來簽名的,一般只有server能用到。

2.支付流程

image.gif

剛開始看這個(gè)流程圖可能會(huì)覺得很復(fù)雜,所以總結(jié)了我們比較關(guān)系的流程是:

  1. app客戶端向服務(wù)器發(fā)送支付請(qǐng)求

  2. 服務(wù)器在收到客戶端請(qǐng)求之后向微信后臺(tái)調(diào)用統(tǒng)一下單API,獲得預(yù)付單信息

  3. 服務(wù)端生成帶簽名的客戶端支付信息給app

  4. app客戶端用戶確認(rèn)支付,app喚醒微信客戶端進(jìn)行支付

  5. app獲得支付結(jié)果后向服務(wù)端查詢最終的結(jié)果并顯示

app端的工作:

  • 接入微信支付SDK

  • 向服務(wù)器發(fā)送支付請(qǐng)求

  • 支付信息喚醒微信app,然后進(jìn)行支付

  • 收到微信支付回調(diào)后向服務(wù)器確認(rèn)支付結(jié)果

  • 根據(jù)查詢結(jié)果展示結(jié)果頁面告知用戶支付結(jié)果

服務(wù)器端的工作:

  • 收到app客戶端支付請(qǐng)求后向微信后臺(tái)請(qǐng)求預(yù)支付訂單

  • 服務(wù)器端簽名并返回信息給app客戶端

  • 接收微信后臺(tái)返回的支付結(jié)果,用來app端查詢

服務(wù)器端返回的字段說明:

appId:返回的appid

partnerId: 父級(jí)id

prepayId: 支付id

packages: 包名(微信默認(rèn)的為“Sign=WXPay”)

nonceStr: 生成的隨機(jī)字符串

timesTamp: 時(shí)間戳

sign: 簽名

image.gif

3.iOS端使用

在AppDelegate.m,導(dǎo)入微信SDK頭文件WXApi.h

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"注冊(cè)獲得的appid"];//注冊(cè)appid    
return YES;
} 
//支持所有iOS系統(tǒng)回調(diào)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
//    [self handleOpenURL:url];   
 BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];    if (!result) {        // 其他如支付等SDK的回調(diào)        [self handleOpenURL:url];    
}   
 return YES;
}- (void)handleOpenURL:(NSURL*)url {   
 if ([url.host isEqualToString:@"pay"]) { // -- 微信支付
[WXApi handleOpenURL:url delegate:[WXPayService sharedInstance]];    
}
}

此處的WXPayService就是自己?jiǎn)为?dú)抽出來寫的一個(gè)類,遵循WXApiManagerDelegate協(xié)議

WXPayService.h

#import <Foundation/Foundation.h>
#import "WXApi.h"
@interface WXPayService : NSObject <WXApiDelegate>
///單例來接收微信請(qǐng)求的回調(diào)
+ (instancetype)sharedInstance;
// -- 根據(jù)接口返回的預(yù)支付信息,構(gòu)造支付請(qǐng)求
+ (PayReq *)getPayRequest:(NSDictionary *)prepayData;
///處理非支付請(qǐng)求的回調(diào)
- (void)onRespCallBack:(void(^)(BaseResp * resp))callback;
///從服務(wù)器端獲取到微信返回的支付請(qǐng)求用到的參數(shù)來發(fā)起支付請(qǐng)求
- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback; @end

WXPayService.m

#import "WXPayService.h"
@interface WXPayService ()
@property (nonatomic,copy) void(^RespCallBack)(BaseResp *);
@endstatic WXPayService *sharedInstance;
@implementation WXPayService
+ (instancetype)allocWithZone:(struct _NSZone *)zone{    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedInstance = [super allocWithZone:zone];    });    return sharedInstance;}///單例來接收微信請(qǐng)求的回調(diào)+ (instancetype)sharedInstance {    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        sharedInstance = [[self alloc] init];    });    return sharedInstance;}// -- 根據(jù)接口返回的預(yù)支付信息,構(gòu)造支付請(qǐng)求+ (PayReq *)getPayRequest:(NSDictionary *)prepayData {    if (prepayData) {//  此處Tools是自己的另一個(gè)工具類,用來判斷字典的        PayReq *req = [[PayReq alloc] init];        if ([Tools dicContain:prepayData withKey:@"partnerid"]) {            req.partnerId = prepayData[@"partnerid"];        }        if ([Tools dicContain:prepayData withKey:@"prepayid"]) {            req.prepayId = prepayData[@"prepayid"];        }        if ([Tools dicContain:prepayData withKey:@"noncestr"]) {            req.nonceStr = prepayData[@"noncestr"];        }        if ([Tools dicContain:prepayData withKey:@"timestamp"]) {            req.timeStamp = [prepayData[@"timestamp"] intValue];        }        req.package =@"Sign=WXPay";        req.sign =  @"null";        //日志輸出        NSLog(@"appid=%@/npartid=%@/nprepayid=%@/nnoncestr=%@/ntimestamp=%ld/npackage=%@/nsign=%@",[prepayData objectForKey:@"appid"],req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign);        return req;    }    return nil;}///處理非支付請(qǐng)求的回調(diào)- (void)onRespCallBack:(void(^)(BaseResp * resp))callback {    self.RespCallBack = callback;}///從服務(wù)器端獲取到微信返回的支付請(qǐng)求用到的參數(shù)來發(fā)起支付請(qǐng)求- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback {    NSAssert(req !=nil , @"未成功創(chuàng)建微信支付請(qǐng)求");    self.RespCallBack = callback;    if ([WXApi isWXAppInstalled]) { // -- 判斷是否安裝微信應(yīng)用        //發(fā)起微信支付,設(shè)置參數(shù)        [WXApi sendReq:req];    }else {        self.RespCallBack(nil);    }}#pragma mark WXApiDelegate- (void)onResp:(BaseResp *)resp {    if ([resp isKindOfClass:[PayResp class]]) { // -- 判斷是否為支付的回調(diào)        self.RespCallBack(resp);    }}@end

在需要支付的ViewController中導(dǎo)入工具類WXPayService

image

4.注意點(diǎn)及問題

注意點(diǎn):

  • 設(shè)置好scheme,否則應(yīng)用無法跳轉(zhuǎn)到微信客戶端

  • 支付簽名時(shí)的key值全部是小寫的

  • 如果支付顯示驗(yàn)證簽名失敗的時(shí)候,可以將packages設(shè)為默認(rèn)值(Sign=WXPay)試試

問題:

系統(tǒng)版本大于等于iOS9的,調(diào)起微信客戶端之后,可以直接點(diǎn)擊狀態(tài)欄左側(cè)按鈕返回,這時(shí)是不走回調(diào)方法的。

解決方案:

在AppDelegate.m的applicationWillEnterForeground方法中,調(diào)用查詢支付結(jié)果接口然后刷新當(dāng)然頁面。需要設(shè)置bool變量作為標(biāo)志,否則每次應(yīng)用進(jìn)入前臺(tái)都去查詢,就不符合業(yè)務(wù)要求了。

進(jìn)入微信支付頁面之后,不做操作,切換到自己應(yīng)用中,退出當(dāng)前支付頁面,然后再進(jìn)入微信客戶端點(diǎn)擊支付或者取消,此時(shí)自己的應(yīng)用會(huì)崩潰閃退

原因:退出頁面后頁面已經(jīng)出棧被銷毀,但wx回調(diào)時(shí)還是去調(diào)用其中的代理方法,就會(huì)出現(xiàn)野指針。

解決方案:在頁面的viewWillDisappear方法中加入

[WXPayService sharedManager].delegate = nil;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容