在剛剛結束的一個項目中用到了微信支付,從接入微信支付到工具類的封裝,在本文中作個積累,方便往後使用。安全
首先你須要去微信開放平臺註冊帳號,在這裏要吐槽一下,不知道這個微信平臺的帳號密碼驗證機制,忘了之前的密碼,從新登陸,各類找回密碼都不行,實在沒轍,去註冊個Gmail😑,登陸成功後,能夠看到以下界面。bash
點擊右上角的建立移動應用,一步一步填寫必要填入的信息,在這裏就不作多餘的贅述了。 須要注意的是這裏填入的 Bundle ID須要和項目的一一對應服務器
接下來就等一個星期左右,等待微信審覈經過你就能夠將微信支付SDK集成到項目中,詳情能夠看官方給出的 文檔. pod 集成方法pod 'WechatOpenSDK'
複製代碼
在Xcode中,選擇你的工程設置項,選中「TARGETS」一欄,在「info」標籤欄的「URL type「添加「URL scheme」爲你所註冊的應用程序id(以下圖所示)。微信
完成以後能夠獲取到appid(微信開放平臺爲應用生成的惟一識別碼)、商戶id、商戶secretKey。對於app端來講只用到appid,商戶id最好經過接口從server獲取,商戶secretKey是用來簽名的,通常只有server能用到。app
剛開始看這個流程圖可能會以爲很複雜,因此總結了咱們比較關係的流程是:工具
服務器端返回的字段說明:微信支付
在AppDelegate.m
,導入微信SDK頭文件WXApi.h
ui
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[WXApi registerApp:@"註冊得到的appid"];//註冊appid
return YES;
}
//支持全部iOS系統回調
- (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的回調
[self handleOpenURL:url];
}
return YES;
}
- (void)handleOpenURL:(NSURL*)url {
if ([url.host isEqualToString:@"pay"]) { // -- 微信支付
[WXApi handleOpenURL:url delegate:[WXPayService sharedInstance]];
}
}
複製代碼
此處的
WXPayService
就是本身單獨抽出來寫的一個類,遵循WXApiManagerDelegate
協議atom
#import <Foundation/Foundation.h>
#import "WXApi.h"
@interface WXPayService : NSObject <WXApiDelegate>
///單例來接收微信請求的回調
+ (instancetype)sharedInstance;
// -- 根據接口返回的預支付信息,構造支付請求
+ (PayReq *)getPayRequest:(NSDictionary *)prepayData;
///處理非支付請求的回調
- (void)onRespCallBack:(void(^)(BaseResp * resp))callback;
///從服務器端獲取到微信返回的支付請求用到的參數來發起支付請求
- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback;
@end
複製代碼
#import "WXPayService.h"
@interface WXPayService ()
@property (nonatomic,copy) void(^RespCallBack)(BaseResp *);
@end
static WXPayService *sharedInstance;
@implementation WXPayService
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
///單例來接收微信請求的回調
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
// -- 根據接口返回的預支付信息,構造支付請求
+ (PayReq *)getPayRequest:(NSDictionary *)prepayData {
if (prepayData) {
// 此處Tools是本身的另外一個工具類,用來判斷字典的
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;
}
///處理非支付請求的回調
- (void)onRespCallBack:(void(^)(BaseResp * resp))callback {
self.RespCallBack = callback;
}
///從服務器端獲取到微信返回的支付請求用到的參數來發起支付請求
- (void)startPayWithReq:(PayReq *)req callback:(void(^)(BaseResp * resp))callback {
NSAssert(req !=nil , @"未成功建立微信支付請求");
self.RespCallBack = callback;
if ([WXApi isWXAppInstalled]) { // -- 判斷是否安裝微信應用
//發起微信支付,設置參數
[WXApi sendReq:req];
}else {
self.RespCallBack(nil);
}
}
#pragma mark WXApiDelegate
- (void)onResp:(BaseResp *)resp {
if ([resp isKindOfClass:[PayResp class]]) { // -- 判斷是否爲支付的回調
self.RespCallBack(resp);
}
}
@end
複製代碼
在須要支付的ViewController中導入工具類WXPayService
url
系統版本大於等於iOS9的,調起微信客戶端以後,能夠直接點擊狀態欄左側按鈕返回,這時是不走回調方法的。
解決方案: 在AppDelegate.m的applicationWillEnterForeground方法中,調用查詢支付結果接口而後刷新固然頁面。須要設置bool變量做爲標誌,不然每次應用進入前臺都去查詢,就不符合業務要求了。
進入微信支付頁面以後,不作操做,切換到本身應用中,退出當前支付頁面,而後再進入微信客戶端點擊支付或者取消,此時本身的應用會崩潰閃退
緣由:退出頁面後頁面已經出棧被銷燬,但wx回調時仍是去調用其中的代理方法,就會出現野指針。 解決方案:在頁面的viewWillDisappear
方法中加入
[WXPayService sharedManager].delegate = nil;
複製代碼
微信支付簽名建議和服務端協商作二次簽名,以保證支付的安全性。 ps: 若有不對的地方,歡迎批評指正,更多文章請點擊這裏
若有須要,請關注公衆號JackerooChu,瞭解更多文章