老項(xiàng)目在iOS13以上的手機(jī)上跑,支付成功后發(fā)現(xiàn)沒有走回調(diào)(在iOS13以下的版本正常)。查資料發(fā)現(xiàn)是因?yàn)閕OS13的這些支付回調(diào)都在SceneDelegate中。SceneDelegate是Xcode11創(chuàng)建項(xiàng)目后自動生成的,負(fù)責(zé)AppDelegate的某些功能、iPadOS的多窗口功能,這里不作詳細(xì)介紹。
為了弄SceneDelegate中的支付回調(diào),先做好準(zhǔn)備工作:
1.項(xiàng)目的info.list里加上新的key value(也可以新建一個(gè)項(xiàng)目,把新項(xiàng)目里的直接復(fù)制過來),如圖。

info.png
2.AppDelegate.m里的變化
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch
if (@available(iOS 13.0, *)){
NSLog(@"========iOS13========");
}else {
[self baseSetting]; //加載設(shè)置一些第三方庫 支付寶、微信、定位等等
[self initBaseController]; //創(chuàng)建window、導(dǎo)航欄等
}
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0)){
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
if (@available(iOS 13.0, *)){
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}else {
return nil;
}
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0)){
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
3.SceneDelegate.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow * window;
@end
NS_ASSUME_NONNULL_END
4.SceneDelegate.m .m里創(chuàng)建window的方式發(fā)生了變化,這里要注意一下
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions API_AVAILABLE(ios(13.0)){
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
if (@available(iOS 13.0, *)){
[self baseSetting]; //加載設(shè)置一些第三方庫 支付寶、微信、定位等等
[self initBaseControllerWithScene:(UIWindowScene *)scene andWithSession:session options:connectionOptions]; //創(chuàng)建window、導(dǎo)航欄等
}
}
-(void)initBaseControllerWithScene:(UIWindowScene *)scene andWithSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions
API_AVAILABLE(ios(13.0)){
self.window = [[UIWindow alloc] initWithWindowScene:scene];
self.window.frame = scene.coordinateSpace.bounds;
self.window.backgroundColor = WHITE_Color;
[self.window makeKeyAndVisible];
//創(chuàng)建導(dǎo)航欄什么的
//...... self.window.rootViewController = ;
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
API_AVAILABLE(ios(13.0))
{
NSEnumerator *enumerator = [URLContexts objectEnumerator];
UIOpenURLContext *context;
while (context = [enumerator nextObject]) {
NSURL *url = context.URL;
if([[NSString stringWithFormat:@"%@",url] rangeOfString:@"Wechat_Login"].location != NSNotFound)
{ //微信登錄
//#define appDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])
vc //login登錄頁面
[WXApi handleOpenURL:url delegate:vc];
}else if(([url.host isEqualToString:@"pay"] || [url.host isEqualToString:@"resendContextReqByScheme"] || [url.host isEqualToString:@"platformId=wechat"]) && [url.scheme isEqualToString:@"你的微信appid:wx************"]){
//"微信支付分授權(quán)和微信支付等回調(diào)====>我寫在WXPayService.m的delegate方法中了,可以自己封裝一下"
[WXApi handleOpenURL:url delegate:[WXPayService sharedInstance]];
}else if ([url.host isEqualToString:@"safepay"]) { //支付寶登錄和支付
NSString *scope = [NSString getParamByName:@"scope" URLString:[NSString stringWithFormat:@"%@",url]];
if ([scope isEqualToString:@"kuaijie"]) { //支付寶快捷登錄
[[AlipaySDK defaultService] processAuth_V2Result:url standbyCallback:nil];
}else {
//跳轉(zhuǎn)支付寶錢包進(jìn)行支付,處理支付結(jié)果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:nil];
}
}
}
}
NSString的Category
#pragma mark - ==========獲取url中的參數(shù)==========
+ (NSString *)getParamByName:(NSString *)name URLString:(NSString *)url
{
NSError *error;
NSString *regTags=[[NSString alloc] initWithFormat:@"(^|&|\\?)+%@=+([^&]*)(&|$)", name];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regTags
options:NSRegularExpressionCaseInsensitive
error:&error];
// 執(zhí)行匹配的過程
NSArray *matches = [regex matchesInString:url
options:0
range:NSMakeRange(0, [url length])];
for (NSTextCheckingResult *match in matches) {
NSString *tagValue = [url substringWithRange:[match rangeAtIndex:2]]; // 分組2所對應(yīng)的串
return tagValue;
}
return @"";
}
這下就能收到支付成功/失敗的回調(diào)了,有問題或者我寫的哪里有問題歡迎留言指正。