iOS 【微信登录流程以及遇到的一些坑】

最近公司中为了降低登录门槛,让用户不再每次都输入账号密码进行登录。所以引入了微信登录和QQ登录,让用户更加便捷的登录操作。大多数的第三方登录都是相仿的,按照集成文档一步步的集成就好了,仔细阅读文档一般没有太大问题。集成的步骤我不一一赘述,将我遇到的一些坑列举出来,供大家参考。

微信登录集成的主要流程:

授权微信三方登录,请求 code ——> 通过 code 获取 access_token 以及 openId ——> 拿到 openId 进行登录

再次请求 ——> access_token 未过期 ——> 直接拿到 openId 进行登录

或 再次请求 ——> access_token 过期 ——> 重新通过 refresh_token 进行刷新 access_token 和 openId ——> 再次拿到 openId 进行登录

或 再次请求 ——>  access_token 过期 && refresh_token 过期 ——> 重新进行授权请求

具体步骤大家可以参照这篇博客:http://www.jianshu.com/p/0c3df308bcb3

(code 相当于是一个兑换码,而 access_token 相当于是一个验证码,为了安全,才有这两个设定。而 openId 才是我们要的,因为他是用户的唯一标示符。这里注意,在同一个微信开发者账户下如果同时集成了 安卓 和 iOS 的程序,这在不同平台上的两个程序是完全不同的,我们用同一个 微信 或者 QQ 分别去登录安卓程序和iOS程序,得到的 openId 是完全不同的,这时需要开发者账户去发送一个邮件去数据打通,用于关联 iOS 和 安卓 两个程序,用于保证用同一第三方账号登录两个程序时返回的 openId 是一致的。申请方式如下图。)


上面集成流程一般用于只有第三方登录的 app,请求步骤完全交由第三方平台认证。我司 app 含自有账号密码进行登录,所以集成步骤并没有那么复杂。

我司集成步骤:

① 首先获取到微信的 openId,然后通过 openId 去后台数据库查询该微信的 openId 有没有绑定好的我司自有账号;

② 如果没有绑定我司自有账号,就跳转注册绑定界面,通过手机获取验证码,填写密码,最后绑定手机号(手机号作为我司自有账号)。然后就登录App。

③ 如果该微信用户 openId 已经绑定我司自有账号。 那么就通过 openId 和 authName(授权类型“weixin”或“QQ”)进行登录 或者 通过 我司自有账号 和 密码 进行登录。(也就是将 openId 和 authName 与 自有账号 和 密码 建立一对一的关系,随便二选一进行登录)

这样做的原因是降低了用户二次登录的门槛,不需要输入自有账号和密码进行登录。每次登录请求 openId,拿到 openId 进行登录。实质上是在我们自有账号和微信登录之间建立唯一桥梁罢了。方便了用户的操作。


遇到的一点坑:

① onResp 这个方法是在向微信请求授权之后回调的,但可能代码按照文档集成之后并没有来到这个方法。如果遇到这种情况应先检查 onResp 的位置,一般来说是在 AppDelegate.m 进行调用的,因为代理是在 AppDelegate.m 的方法中设置的,具体方法如下:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url NS_DEPRECATED_IOS(2_0, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED;
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation NS_DEPRECATED_IOS(4_2, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED;


在文档中声明要同时集成上面两个方法,但是这两个方法只支持到 iOS 9,在方法中也提醒我们了:

"Please use application:openURL:options:"


所以说如今我们应该集成如下方法:

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options NS_AVAILABLE_IOS(9_0); // no equiv. notification. return NO if the application can't open for some reason


建议大家将这三个方法同时集成,避免一些未知的麻烦。集成方法如下:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    if ([TencentOAuth HandleOpenURL:url]) {
        return [TencentOAuth HandleOpenURL:url];
    }
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    if ([TencentOAuth HandleOpenURL:url]) {
        return [TencentOAuth HandleOpenURL:url];
    }
    return [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options {
    if ([TencentOAuth HandleOpenURL:url]) {
        return [TencentOAuth HandleOpenURL:url];
    }
    return [WXApi handleOpenURL:url delegate:self];
}
同时集成QQ和微信三方登录时要注意区分不同的第三方授权回调。

② 在 onResp 中,我们会拿到用于请求 access_token 和 openId 的 code,然后发送网络请求,如下代码:

/*
 * 发送一个sendReq后,收到微信的回应
 */
- (void)onResp:(BaseResp *)resp {
    NSLog(@"onResp");
    // 向微信请求授权后,得到响应结果
    if ([resp isKindOfClass:[SendAuthResp class]]) {
        SendAuthResp *authResp = (SendAuthResp *)resp;
        NSLog(@"code --- %@", authResp.code);
        if (authResp.code && authResp.code.length != 0) { // 微信取消授权后会再次调用这个方法,然后code为空,必须判断一下,不然崩掉。
            NSString *path = @"https://api.weixin.qq.com/sns/oauth2/access_token";
            NSDictionary *params = @{
                                     @"appid":@"412b********08w9",
                                     @"secret":@"dh32********g09l",
                                     @"code":authResp.code,
                                     @"grant_type":@"authorization_code",
                                     };
            AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
            manager.requestSerializer.timeoutInterval = 10;
            manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/javascript", @"text/plain", nil];
            __weak typeof(self) weakSelf = self;
            [manager GET:path parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                NSLog(@"responseObject -- %@", responseObject);
                
                NSString *openId = responseObject[@"openid"];
                NSString *authName = @"weixin";
                NSString *access_token = responseObject[@"access_token"];
                
                if (access_token && [access_token length] != 0) { // 通过验证才可继续登录,如果只有 openId 是不行的,保险起见。
                    BPBLoginViewController *loginVc = [[BPBLoginViewController alloc] init];
                    weakSelf.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:loginVc];
                    // 第三方登录
                    [loginVc thirdLoginWithOpenId:openId authName:authName];
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                [SVProgressHUD showErrorWithStatus:[NSString stringWithFormat:@"错误码:%ld", error.code]];
            }];
        
        } else {
            [SVProgressHUD showErrorWithStatus:@"您取消了微信登录授权!"];
        }
    }
}

上面有几处需要注意的地方:

① 获取 code 的对象应是 BaseResp 的子类。

SendAuthResp *authResp = (SendAuthResp *)resp;

② acceptableContentTypes 要设置上 @"text/plain" 和 @"text/html",便于服务器端的解析。如果不设置,可能会返回如下乱码:

<7b226163 63657373 5f746f6b 656e223a 226d5965 725a3165 65484858 43396776 355a4933 35684146 34535f5a 2d632d79 6d724668 416e594e 774e704c 41776f6c 526d4b6b 70716b57 746f5748 394f6351 424f736e 58327947 4231756d 49447068 51395f50 33616252 7258772d 65445632 42526650 5f72366a 4f684834 222c2265 78706972 65735f69 6e223a37 3230302c 22726566 72657368 5f746f6b 656e223a 222d766f 5a7a4530 796d6a50 6a356455 59686a55 67555763 434c7659 30564b32 59365f2d 42547531 67373342 50796f55 65564363 4a7a674e 37724962 576a7678 4a327747 55466e71 61566b7a 4945334e 6f4f5834 576d4e51 7a49566c 49424f4b 67383851 31595a49 57444967 222c226f 70656e69 64223a22 6f324c34 56755074 77732d6b 4d71306f 63454b4e 66434f50 65797563 222c2273 636f7065 223a2273 6e736170 695f7573 6572696e 666f222c 22756e69 6f6e6964 223a226f 61686233 747a6659 43583143 4f4a6852 4f73326a 51526959 6a766722 7d>

③ 要对 code 进行判空操作。
④ 要对 access_token 进行判空操作。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值