iOS 微信和QQ分享显示“未验证应用”问题处理(尤其是Swift 中 continueUserActivity 不执行问题)

由于在iOS13引入了UniversalLink导致微信好友、朋友圈分享时显示未验证引用。而且该问题会反反复复出现,很是头疼。最终得以解决,现将过程和思路以及部分参考代码列出如下,供参考对照。

第一步,在服务器配置UniversalLink文件以及设置相应地址:
具体可参考 微信iOS接入指南 和 苹果官方文档 Support Universal Links ,接入成功后,在手机浏览器访问配置的UniversalLink地址出现如下界面即表示成功:

服务器端根目录配置的文件信息(appID 值为团队编号.BundleIdentifier): 

第二步,集成微信SDK 和QQSDK(如果app支持微信和QQ都需要配置,本文以微信SDK配置说明为主)

下文中之前使用的友盟SDK集成微信精简不能分享,由于该SDK不支持 UniversalLink,详见:友盟分享微信iOS精简版 说明

第三步,配置信息

集成SDK及配置SSO白名单,可以参考:iOS接入说明 

项目中也需要配置Associated Domains(一、在对应证书中开启 Associated Domains,二、在项目配置之前设置好的 UniversalLink,只有地址),如下图:
 

第四步,注册信息并验证接入

在app didFinishLaunchingWithOptions 中注册,OC和Swift 版参考代码如下:

[WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString * _Nonnull log) {
        NSLog(@"WeChatSDK: %@",log);
    }];
    
    [WXApi registerApp:WXAppInfo[kWXAppInfoAppIdKeyName] universalLink:@"https://app.shlingzhang.com/app/"];
    NSLog(@"WXApi-Version:%@",[WXApi getApiVersion]);
    
//生产环境需要注释如下代码,仅测试使用
    [WXApi checkUniversalLinkReady:^(WXULCheckStep step, WXCheckULStepResult * _Nonnull result) {
        NSLog(@"checkUniversalLinkReady:%@, %u, %@, %@", @(step), result.success, result.errorInfo, result.suggestion);
    }];
//微信验证注册
        let _result = WXApi.registerApp(K_APP_WECHART_APP_ID,universalLink:K_APP_UNIVERSAL_LINK)
        print("WXApi.registerApp:\(_result ? "OK":"Fail")")
        
        //在register之前打开log, 后续可以根据log排查问题
        WXApi.startLog(by: .detail) { log in
            print("WeChatSDK-Version: \(WXApi.getVersion())")
            print("WeChatSDK: \(log)")
        }
        
        //调用自检函数(生产环境需要注释如下代码,仅测试使用)
        WXApi.checkUniversalLinkReady({ (step,result) in
            print("checkUniversalLinkReady:\(step.rawValue), \(result.success), \(result.errorInfo), \(result.suggestion)")
        })
        
        /* 设置友盟appkey */
        UMConfigure.initWithAppkey(K_APP_UMENG_APP_KEY, channel: "App Store")
        
        // [S] 友盟相关设置
        UMSocialGlobal.shareInstance()?.universalLinkDic = [
            UMSocialPlatformType.wechatSession:K_APP_UNIVERSAL_LINK,
            UMSocialPlatformType.QQ:K_APP_QQ_UNIVERSAL_LINK
        ]

//QQ验证注册
        _ = TencentOAuth.init(appId:K_APP_QQ_APP_ID,andUniversalLink:K_APP_QQ_UNIVERSAL_LINK,andDelegate:self)

检测结果如下图(检测返回了7个日志即表示成功,之前包括网上很多开发者只返回了第五步就没有,这表明协议回调有问题,请参考第五步。相应的控制台打印日志也有提示,具体参考:SDK自检函数排查):

*第五步:指定协议及设置返回值(此处是全文最重要环节,SDK自检不通过或者分享没有拉取相应页面直接返回等都是这个步骤出了问题)
OC版完整参考代码:

//MARK: - 分享
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    
    __weak typeof(self) weakSelf = self;
    
    //QQ
    if ([url.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        [TencentOAuth HandleOpenURL:url];
    }
    //微信
    else if([url.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenURL:url delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleOpenURL:url];
    }
    
    return YES;
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    __weak typeof(self) weakSelf = self;
    
    //QQ
    if ([url.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        [TencentOAuth HandleOpenURL:url];
    }
    //微信
    else if([url.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenURL:url delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleOpenURL:url];
    }
    
    return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    __weak typeof(self) weakSelf = self;
    //QQ
    if ([url.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        [TencentOAuth HandleOpenURL:url];
    }
    //微信
    else if([url.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenURL:url delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];
    }
    
    return YES;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler{
    
    __weak typeof(self) weakSelf = self;
    
    //QQ
    if ([userActivity.webpageURL.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        if(userActivity.activityType == NSUserActivityTypeBrowsingWeb && [TencentOAuth CanHandleUniversalLink:userActivity.webpageURL]){
            [TencentOAuth HandleUniversalLink:userActivity.webpageURL];
        }
    }
    //微信
    else if([userActivity.webpageURL.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenUniversalLink:userActivity delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleUniversalLink:userActivity options:nil];
    }
    
    return YES;
}

- (void) scene:(UIScene *)scene openURLContexts:(nonnull NSSet<UIOpenURLContext *> *)URLContexts  API_AVAILABLE(ios(13.0)){
    __weak typeof(self) weakSelf = self;
    
    NSURL *url = URLContexts.allObjects.firstObject.URL;
    
    //QQ
    if ([url.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        [TencentOAuth HandleOpenURL:url];
    }
    //微信
    else if([url.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenURL:url delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleOpenURL:url];
    }
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0)){
    __weak typeof(self) weakSelf = self;
    
    //QQ
    if ([userActivity.webpageURL.absoluteString containsString:K_APP_CONFIG_INFO[kQQAppInfoKeyName][kAppIdKeyName]]) {
        if(userActivity.activityType == NSUserActivityTypeBrowsingWeb && [TencentOAuth CanHandleUniversalLink:userActivity.webpageURL]){
            [TencentOAuth HandleUniversalLink:userActivity.webpageURL];
        }
    }
    //微信
    else if([userActivity.webpageURL.absoluteString containsString:K_APP_CONFIG_INFO[kWXAppInfoKeyName][kAppIdKeyName]]){
        [WXApi handleOpenUniversalLink:userActivity delegate:weakSelf];
    }
    else{
        [[UMSocialManager defaultManager] handleUniversalLink:userActivity options:nil];
    }
}


#pragma mark - WXApiDelegate
-(void)onReq:(BaseReq*)req {
    // just leave it here, WeChat will not call our app
}

-(void)onResp:(BaseResp*)resp {
    
}

#pragma mark - TencentSessionDelegate
- (void)tencentDidLogout{
    
}

- (void)tencentDidNotLogin:(BOOL)cancelled {
    
}

- (void)tencentDidNotNetWork {
    
}

Swift版完整参考代码:

@objc
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  
//MARK: - 分享
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
        if url.absoluteString.contains(K_APP_QQ_APP_ID) {
            TencentOAuth.handleOpen(url)
        }
        else if url.absoluteString.contains(K_APP_WECHART_APP_ID){
            WXApi.handleOpen(url,delegate:self)
        }
        else{
            UMSocialManager.default().handleOpen(url)
        }
        
        return true
    }
    
    func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
        
        // 其他如支付等SDK的回调
        if url.absoluteString.contains(K_APP_QQ_APP_ID) {
            TencentOAuth.handleOpen(url)
        }
        else if url.absoluteString.contains(K_APP_WECHART_APP_ID){
            WXApi.handleOpen(url,delegate:self)
        }
        else{
            UMSocialManager.default().handleOpen(url)
        }
        
        return true
    }
    
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        
        //6.3的新的API调用,是为了兼容国外平台(例如:新版facebookSDK,VK等)的调用[如果用6.2的api调用会没有回调],对国内平台没有影响
        // 其他如支付等SDK的回调
        if url.absoluteString.contains(K_APP_QQ_APP_ID) {
            TencentOAuth.handleOpen(url)
        }
        else if url.absoluteString.contains(K_APP_WECHART_APP_ID){
            WXApi.handleOpen(url,delegate:self)
        }
        else{
            UMSocialManager.default().handleOpen(url,sourceApplication:sourceApplication,annotation:annotation)
        }
        
        return true
    }
    
    @available(iOS 13.0, *)
    func scene(_ scene:UIScene, continueUserActivity userActivity:NSUserActivity){
        
        let _strUrl = userActivity.webpageURL!.absoluteString
        
        //QQ
        if _strUrl.contains(K_APP_QQ_APP_ID),let _url = userActivity.webpageURL {
            if userActivity.activityType == NSUserActivityTypeBrowsingWeb && TencentOAuth.canHandleUniversalLink(_url) {
                if userActivity.activityType == NSUserActivityTypeBrowsingWeb && TencentOAuth.canHandleUniversalLink(_url) {
                    TencentOAuth.handleUniversalLink(_url)
                    QQApiInterface.handleOpenUniversallink(_url,delegate:QQApiShareEntry.init() as? QQApiInterfaceDelegate)
                }
            }
        }
        //微信
        else if _strUrl.contains(K_APP_WECHART_APP_ID) {
            WXApi.handleOpenUniversalLink(userActivity,delegate:self)
        }
        else{
            UMSocialManager.default().handleUniversalLink(userActivity,options:nil)
        }
    }
    
    @available(iOS 13.0, *)
    func scene(_ scene:UIScene,openURLContexts URLContexts:Set<UIOpenURLContext>){
        if let _url = URLContexts.first?.url {
            //QQ
            if _url.absoluteString.contains(K_APP_QQ_APP_ID) {
                TencentOAuth.handleOpen(_url)
            }
            //微信
            else if _url.absoluteString.contains(K_APP_WECHART_APP_ID) {
                WXApi.handleOpen(_url,delegate:self)
            }
            else{
                UMSocialManager.default().handleOpen(_url)
            }
            
        }
    }
    
    //Swift 项目此处要添加支持OC 调用,否则回调不触发
    @objc(application:continueUserActivity:restorationHandler:)
    func application(_ application:UIApplication,continue userActivity:NSUserActivity, restorationHandler:@escaping (_ restorableObjects:Any)->Void) -> Bool {
        
        let _strUrl = userActivity.webpageURL!.absoluteString
        
        //QQ
        if _strUrl.contains(K_APP_QQ_APP_ID),let _url = userActivity.webpageURL {
            if userActivity.activityType == NSUserActivityTypeBrowsingWeb && TencentOAuth.canHandleUniversalLink(_url) {
                TencentOAuth.handleUniversalLink(_url)
                QQApiInterface.handleOpenUniversallink(_url,delegate:QQApiShareEntry.init() as? QQApiInterfaceDelegate)
            }
        }
        //微信
        else if _strUrl.contains(K_APP_WECHART_APP_ID) {
            WXApi.handleOpenUniversalLink(userActivity,delegate:self)
        }
        else{
            UMSocialManager.default().handleUniversalLink(userActivity,options:nil)
        }
        
        return true
    }
}

//MARK: - WXApiDelegate
extension AppDelegate : WXApiDelegate {
    
    func onReq(reqonReq:BaseReq) {
        print("onReq:\(reqonReq)")
    }
    
    private func onResp(resp:BaseResp) {
        print("onResp:\(resp)")
        
        if resp is SendMessageToWXResp {
            let send = resp as? SendMessageToWXResp
            if let sm = send {
                if sm.errCode == 0 {
                    print("分享成功")
                } else {
                    print("分享失败")
                }
            }
        }
    }
}

//MARK: - TencentSessionDelegate
extension AppDelegate : TencentSessionDelegate {
    
    func tencentDidLogin() {
        print("tencentDidLogin")
    }
    
    func tencentDidNotLogin(_ cancelled: Bool) {
        print("tencentDidNotLogin")
    }
    
    func tencentDidNotNetWork() {
        print("tencentDidNotNetWork")
    }
    
}

如果是用的SceneDelegate 做法稍有不同,请参考官方文档,本文结束。

如需Demo或相关问题咨询可留言

猜你喜欢

转载自blog.csdn.net/yimiyuangguang/article/details/117465659