这篇文章主要介绍了iOS微信第三方登录实现的全过程,一步一步告诉大家iOS微信实现第三方登录的方法,感兴趣的小伙伴们可以参考一下
 

一、接入微信第三方登录准备工作。
移动应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。
在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的移动应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。(注意)
1、下载iOS微信SDK。
下载地址

2、将SDK放到工程目录中。

3、补充导入一些依赖框架。

4、添加URL Types

5、添加iOS9 URL Schemes.

注意:如果没有做这步的话会出现以下错误.

1
-canOpenURL: failed for URL: "weixin://app/wx9**********dfd30/" - error: "This app is not allowed to query for scheme weixin"

6、iOS9中新增App Transport Security(简称ATS)特性, 主要使到原来请求的时候用到的HTTP,都转向TLS1.2协议进行传输。这也意味着所有的HTTP协议都强制使用了HTTPS协议进行传输。需要在Info.plist新增一段用于控制ATS的配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

如果我们在iOS9下直接进行HTTP请求是会收到如下错误提示:

1
**App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.**

7、向微信终端程序注册第三方应用,并在第三方应用实现从微信返回
在AppDelegate.m中引入"WXApi.h"头文件,然后写入如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "AppDelegate.h"
#import "LoginViewController.h"
#import "WXApi.h"
 
#pragma mark - application delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
[WXApi registerApp:@"wxd1931d4a0e46****" withDescription:@"Wechat"];
return YES;
}
// 这个方法是用于从微信返回第三方App
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
 
[WXApi handleOpenURL:url delegate:self];
return YES;
}

8、请求CODE
开发者需要配合使用微信开放平台提供的SDK进行授权登录请求接入。正确接入SDK后并拥有相关授权域(scope,什么是授权域?)权限后,开发者移动应用会在终端本地拉起微信应用进行授权登录,微信用户确认后微信将拉起开发者移动应用,并带上授权临时票据(code)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#import "LoginViewController.h"
#import "RegisterViewController.h"
#import "MBProgressHUD.h"
#import "AFNetworking.h"
#import "WXApi.h"
 
#pragma mark - 微信登录
/*
 目前移动应用上德微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用。
 对于iOS应用,考虑到iOS应用商店审核指南中的相关规定,建议开发者接入微信登录时,先检测用户手机是否已经安装
 微信客户端(使用sdk中的isWXAppInstall函数),对于未安装的用户隐藏微信 登录按钮,只提供其他登录方式。
 */
- (IBAction)wechatLoginClick:(id)sender {
 
if ([WXApi isWXAppInstalled]) {
    SendAuthReq *req = [[SendAuthReq alloc] init];
    req.scope = @"snsapi_userinfo";
    req.state = @"App";
    [WXApi sendReq:req];
  }
  else {
    [self setupAlertController];
  }
}
 
#pragma mark - 设置弹出提示语
- (void)setupAlertController {
 
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请先安装微信客户端" preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *actionConfirm = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:actionConfirm];
  [self presentViewController:alert animated:YES completion:nil];
}

执行完上面那一步后,如果客户端安装了微信,那么就会向微信请求相应的授权,图如下:

还有在实际的使用中我们还要结合需求做一些改变。因为微信授权后access_token(2小时)之类的字段都是有效期的在有效期范围内,我们是没必要让用户再次授权的,很可能你的实现,会如我下面所写的(LoginViewController)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// LoginViewController.h
#import <UIKit/UIKit.h>
@interface LoginViewController : BaseViewController
/** 通过block去执行AppDelegate中的wechatLoginByRequestForUserInfo方法 */
@property (copy, nonatomic) void (^requestForUserInfoBlock)();
@end
 
// LoginViewController.m
#pragma mark - 微信登录
/*
 目前移动应用上德微信登录只提供原生的登录方式,需要用户安装微信客户端才能配合使用。
 对于iOS应用,考虑到iOS应用商店审核指南中的相关规定,建议开发者接入微信登录时,先检测用户手机是否已经安装
 微信客户端(使用sdk中的isWXAppInstall函数),对于未安装的用户隐藏微信 登录按钮,只提供其他登录方式。
 */
- (IBAction)wechatLoginClick:(id)sender {
  NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:WX_ACCESS_TOKEN];
  NSString *openID = [[NSUserDefaults standardUserDefaults] objectForKey:WX_OPEN_ID];
  // 如果已经请求过微信授权登录,那么考虑用已经得到的access_token
  if (accessToken && openID) {
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    NSString *refreshToken = [[NSUserDefaults standardUserDefaults] objectForKey:WX_REFRESH_TOKEN];
    NSString *refreshUrlStr = [NSString stringWithFormat:@"%@/oauth2/refresh_token?appid=%@&grant_type=refresh_token&refresh_token=%@", WX_BASE_URL, WXPatient_App_ID, refreshToken];
    [manager GET:refreshUrlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
      NSLog(@"请求reAccess的response = %@", responseObject);
      NSDictionary *refreshDict = [NSDictionary dictionaryWithDictionary:responseObject];
      NSString *reAccessToken = [refreshDict objectForKey:WX_ACCESS_TOKEN];
      // 如果reAccessToken为空,说明reAccessToken也过期了,反之则没有过期
      if (reAccessToken) {
        // 更新access_token、refresh_token、open_id
        [[NSUserDefaults standardUserDefaults] setObject:reAccessToken forKey:WX_ACCESS_TOKEN];
        [[NSUserDefaults standardUserDefaults] setObject:[refreshDict objectForKey:WX_OPEN_ID] forKey:WX_OPEN_ID];
        [[NSUserDefaults standardUserDefaults] setObject:[refreshDict objectForKey:WX_REFRESH_TOKEN] forKey:WX_REFRESH_TOKEN];
        [[NSUserDefaults standardUserDefaults] synchronize];
        // 当存在reAccessToken不为空时直接执行AppDelegate中的wechatLoginByRequestForUserInfo方法
        !self.requestForUserInfoBlock ? : self.requestForUserInfoBlock();
      }
      else {
        [self wechatLogin];
      }
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      NSLog(@"用refresh_token来更新accessToken时出错 = %@", error);
    }];
  }
  else {
    [self wechatLogin];
  }
}
- (void)wechatLogin {
  if ([WXApi isWXAppInstalled]) {
    SendAuthReq *req = [[SendAuthReq alloc] init];
    req.scope = @"snsapi_userinfo";
    req.state = @"GSTDoctorApp";
    [WXApi sendReq:req];
  }
  else {
    [self setupAlertController];
  }
}
#pragma mark - 设置弹出提示语
- (void)setupAlertController {
  UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请先安装微信客户端" preferredStyle:UIAlertControllerStyleAlert];
  UIAlertAction *actionConfirm = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
  [alert addAction:actionConfirm];
  [self presentViewController:alert animated:YES completion:nil];
}

当有access_token和openID时输出:

1
2
3
4
5
6
7
**请求****reAccess****的****response = {**
**  "access_token" = "OezXcEiiBSKSxW0eoylIeK3BOTSVaRovFSXb5oysH6dewFfLsQRgU3fphSLkKkhOokra9H-JMZuB5nPoM-Iy5YbFeA1nKMRYCbL0fj_s46oFKOluGoRUY8jyTdrdDiiFdgS2fxgo5odEtpnpFk3EXA";**
**  "expires_in" = 7200;**
**  openid = oXskgs62CJGFhFX05dSjy9Sjw2KA;**
**  "refresh_token" = "OezXcEiiBSKSxW0eoylIeK3BOTSVaRovFSXb5oysH6dewFfLsQRgU3fphSLkKkhOOWPTKGEjUtuiueutxRjKOlHGZ9b9ogc3KMbibu4eKc4yTMGzSZayjYPmwQ-c4RJE1RzMLrqvjUWgB5roFnjykw";**
**  scope = "snsapi_base,snsapi_userinfo,";**
**}**

刷新access_token有效期:
access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:

  • 1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
  • 2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。

refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。
让AppDelegate遵守<WXApiDelegate>协议,并实现协议方法onResp:
 我们在该方法中接收请求回来的数据,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//授权后回调
/*
 http请求方式:GET
 // 根据响应结果中的code获取access_token(要用到申请时得到的AppID和AppSecret)
 正确返回
 {
 "access_token":"ACCESS_TOKEN",
 "expires_in":7200,
 "refresh_token":"REFRESH_TOKEN",
 "openid":"OPENID",
 "scope":"SCOPE",
 "unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
 }
 错误返回样例
 {"errcode":40029,"errmsg":"invalid code"}
 ErrCode ERR_OK = 0(用户同意)
 ERR_AUTH_DENIED = -4(用户拒绝授权)
 ERR_USER_CANCEL = -2(用户取消)
 code  用户换取access_token的code,仅在ErrCode为0时有效
 state  第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K
 lang  微信客户端当前语言
 country 微信用户当前国家信息
 */
1
2
3
4
5
6
7
8
9
10
11
12
-(void)showLoginController:(BOOL)shouldAnimation
{
  LoginViewController *loginController=[[LoginViewController alloc]initWithNibName:@"LoginViewController" bundle:nil];
 
  loginController.requestForUserInfoBlock = ^() {
 
    [[AppDelegate sharedInstance] wechatLoginByRequestForUserInfo];
  };
 
  BaseNavigationController *baseNavController=[[BaseNavigationController alloc]initWithRootViewController:loginController];
  [kAppDelegate.window.rootViewController presentViewController:baseNavController animated:shouldAnimation completion:NULL];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 授权后回调
// AppDelegate.m
- (void)onResp:(BaseResp *)resp {
  // 向微信请求授权后,得到响应结果
  if ([resp isKindOfClass:[SendAuthResp class]]) {   
    SendAuthResp *temp = (SendAuthResp *)resp;
    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    NSString *accessUrlStr = [NSString stringWithFormat:@"%@/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code", WX_BASE_URL, WXPatient_App_ID, WXPatient_App_Secret, temp.code];
    [manager GET:accessUrlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
      NSLog(@"请求access的response = %@", responseObject);
      NSDictionary *accessDict = [NSDictionary dictionaryWithDictionary:responseObject];
      NSString *accessToken = [accessDict objectForKey:WX_ACCESS_TOKEN];
      NSString *openID = [accessDict objectForKey:WX_OPEN_ID];
      NSString *refreshToken = [accessDict objectForKey:WX_REFRESH_TOKEN];
      // 本地持久化,以便access_token的使用、刷新或者持续
      if (accessToken && ![accessToken isEqualToString:@""] && openID && ![openID isEqualToString:@""]) {
        [[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:WX_ACCESS_TOKEN];
        [[NSUserDefaults standardUserDefaults] setObject:openID forKey:WX_OPEN_ID];
        [[NSUserDefaults standardUserDefaults] setObject:refreshToken forKey:WX_REFRESH_TOKEN];
        [[NSUserDefaults standardUserDefaults] synchronize]; // 命令直接同步到文件里,来避免数据的丢失
      }
      [self wechatLoginByRequestForUserInfo];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
      NSLog(@"获取access_token时出错 = %@", error);
    }];
  }
}

9、通过code获取access_token
通过上一步获取的code后,请求以下链接获取access_token:

相关代码上面实现onResp:方法,接收返回的响应。
参数说明:

参数           是否必须        说明
appid           是             应用唯一标识,在微信开放平台提交应用审核通过后获得
secret          是             应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code            是             填写第一步获取的code参数
grant_type      是             填authorization_code
返回说明:

1
2
3
4
5
6
7
8
{
"access_token":"ACCESS_TOKEN", // 接口调用凭证
 "expires_in":7200, // access_token接口调用凭证超时时间,单位(秒)
"refresh_token":"REFRESH_TOKEN", // 用户刷新access_token
"openid":"OPENID", // 授权用户唯一标识
"scope":"SCOPE", // 用户授权的作用域,使用逗号(,)分隔
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL" // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
}

错误返回样例:

{"errcode":40029,"errmsg":"invalid code"}
10、获取用户个人信息(UnionID机制)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// AppDelegate.m
// 获取用户个人信息(UnionID机制)
- (void)wechatLoginByRequestForUserInfo {
  AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
  NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:WX_ACCESS_TOKEN];
  NSString *openID = [[NSUserDefaults standardUserDefaults] objectForKey:WX_OPEN_ID];
  NSString *userUrlStr = [NSString stringWithFormat:@"%@/userinfo?access_token=%@&openid=%@", WX_BASE_URL, accessToken, openID];
  // 请求用户数据
  [manager GET:userUrlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"请求用户信息的response = %@", responseObject);
    // NSMutableDictionary *userDict = [NSMutableDictionary dictionaryWithDictionary:responseObject];
  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"获取用户信息时出错 = %@", error);
  }];
}

返回的Json结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
返回的Json结果
 {
 "openid":"OPENID",
 "nickname":"NICKNAME",
 "sex":1,
 "province":"PROVINCE",
 "city":"CITY",
 "country":"COUNTRY",
 "privilege":[
 "PRIVILEGE1",
 "PRIVILEGE2"
 ],
 "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
 }
 返回错误的Json事例
 {
 "errcode":40003,"errmsg":"invalid openid"
 }

11、最后
做到上面一步就应该得到返回微信的基本信息,然后根据你公司后台的基本需求去实现授权后如何登录App.
资料:

1
2
3
4
5
6
7
8
9
10
// access_token openid refresh_token unionid
#define WXDoctor_App_ID @"wxd1931d4a0e462***" // 注册微信时的AppID
#define WXDoctor_App_Secret @"d0dd6b58da42cbc4f4b715c70e65c***" // 注册时得到的AppSecret
#define WXPatient_App_ID @"wxbd02bfeea4292***"
#define WXPatient_App_Secret @"4a788217f363358276309ab655707***"
#define WX_ACCESS_TOKEN @"access_token"
#define WX_OPEN_ID @"openid"
#define WX_REFRESH_TOKEN @"refresh_token"
#define WX_UNION_ID @"unionid"
#define WX_BASE_URL @"https://api.weixin.qq.com/sns"

12.这是我司需求的做法:

1.首先获取到微信的openID,然后通过openID去后台数据库查询该微信的openID有没有绑定好的手机号.
2.如果没有绑定,首相第一步就是将微信用户的头像、昵称等等基本信息添加到数据库;然后通过手机获取验证码;最后绑定手机号。然后就登录App.
3.如果有,那么后台就返回一个手机号,然后通过手机登录App.

以上就是本文的全部内容,希望对大家的学习有所帮助。

iOS微信实现第三方登录的方法的更多相关文章

  1. 拾人牙慧篇之———QQ微信的第三方登录实现

    一.写在前面 关于qq微信登录的原理之流我就不一一赘述了,对应的官网都有,在这里主要是展示我是怎么实现出来的,看了好几个博客,有的是直接复制官网的,有的不知道为什么实现不了.我只能保证我的这个是我实现 ...

  2. iOS开发之第三方登录微信-- 史上最全最新第三方登录微信方式实现

    项目地址 :    https://github.com/zhonggaorong/weixinLoginDemo 最新版本的微信登录实现步骤实现: 1.在进行微信OAuth2.0授权登录接入之前,在 ...

  3. PHP实现微信第三方登录的方法

    本文实例讲述了PHP版微信第三方实现一键登录及获取用户信息的方法.分享给大家供大家参考,具体如下: 注意,要使用微信在第三方网页登录是需要“服务号”才可以哦,所以必须到官方申请 一开始你需要进入微信公 ...

  4. iOS - Share 分享/第三方登录

    1.系统方式创建分享 按照下图在 Info.plist 文件中将 Localization native development region 的值改为 China.如果不设置此项弹出的分享页面中显示 ...

  5. Android通过微信实现第三方登录并使用OKHttp获得Token及源码下载

    这里对于App在微信开放平台上申请AppID和secret在这里就略过了,我们微信的授权登录流程,腾讯官网给的流程如下: 1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用 ...

  6. iOS开发之第三方登录微博-- 史上最全最新第三方登录微博方式实现

    相关资源地址: 本项目demo地址 :  https://github.com/zhonggaorong/weiboSDKDemo 最新SDK下载:  最新微博SDK 官网注册地址:点击打开链接 最新 ...

  7. iOS 微信打开第三方应用(Universal Links 和 URL Schemes)

    一.前言 项目中时常有这种需求, 是通过链接跳转到应用内部,现在iOS主流的方案有两个 Schema: 常用在于一个应用跳转到另一个应用内部,属于应用间的跳转.当然ios9以下,网页可以通过schem ...

  8. ios 友盟第三方登录遇到的各种坑。

    //未使用pod的点友盟官方文档 http://dev.umeng.com/social/ios/quick-integration 首先pod导入 pod 'UMengSocialCOM', '~& ...

  9. iOS开发之第三方登录QQ -- 史上最全最新第三方登录QQ方式实现

    项目地址 :  https://github.com/zhonggaorong/QQLoginDemo/tree/master 最新版本的qq登录实现步骤实现: 1. 首先,你需要去向腾讯申请账号. ...

随机推荐

  1. 【算法】MD5加密

    1.什么是MD5 MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍 ...

  2. 【Android开发】之Fragment生命周期

    上一篇博客我们讲到了,Fragment的基本使用,相信大家都已经了解怎么去使用了.如果还有不懂得同学可以去看一下,传送门.现在我们来讲解一下Fragment的生命周期. 一.Fragment的事务 再 ...

  3. Android的 EditText的inputType类型

    android开发过程中突然发现的warning EditText 报出 “This text field does not specify an inputType or a hint”   原因: ...

  4. Android KLog源代码分析

    Android KLog源代码分析 Android KLog源代码分析 代码结构 详细分析 BaseLog FileLog JsonLog XmlLog 核心文件KLogjava分析 遇到的问题 一直 ...

  5. CTreeCtrl获得鼠标点击时的节点

    原文链接: http://blog.csdn.net/lcalqf/article/details/21321923 1.添加图标 HICON icon[10]; icon[0]=AfxGetApp( ...

  6. Oracle的执行计划(来自百度文库)

    如何开启oracle执行计划 http://wenku.baidu.com/view/7d1ff6bc960590c69ec37636.html怎样看懂Oracle的执行计划 http://wenku ...

  7. VB通用数据库操作方法

    1.VB通用数据操作方法. 2.通用数据库查询方法. 3.通用数据库操作方法. 'ERP查询数据库 Public Function YZQuery(sqls As String, msgstring ...

  8. 如何在"Visual Studio Code"中使用" Git" 进行版本控制

    如何在"Visual Studio Code"中使用" Git" 进行版本控制 本来认为此类教程,肯定是满网飞了.今天首次使用VS Code的Git功能,翻遍了 ...

  9. 双系统(win8.1+ubuntu14.04)删除win下分区导致grub rescue解决方案

    几个grub rescue下的命令的含义: set 设置环境变量 ls 查看设备 insmod 加载模块 root 指定用于启动系统的分区 prefix 设定grub启动路径 操作流程: 1.  先使 ...

  10. Keepalived介绍以及在Linux系统下的安装与配置

    一.简介 Keepalived是一个免费开源的,用C编写的类似于layer3, 4 & 7交换机制软件,具备我们平时说的第3层.第4层和第7层交换机的功能.主要提供loadbalancing( ...