Note: code yourself, do not copy! GitHub 1. Access wechat third-party login preparation. Mobile application wechat login is a wechat OAuth2.0 authorized login system based on OAuth2.0 protocol standard. Before wechat OAuth2.0 authorized login and access, you should register your developer account on wechat open platform and have an approved mobile application, and obtain the corresponding AppID and AppSecret. After applying for wechat login and passing the approval, you can start the access process. (Note) 1. Download the iOS wechat SDK. Download address

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

6, iOS9 new App Transport Security (ATS) feature, mainly to the original request when used HTTP, are transferred to TLS1.2 protocol for transmission. This also means that all HTTP protocols are forced to use HTTPS for transport. Add the following information to the info.plist to control the ATS configuration:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Copy the code

**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.**
Copy the code

7, register the third-party application with wechat terminal program, and introduce the “wxapi. h” header file in appDelegate. m, and write as follows:

#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;
}
// This method is used to return third-party apps from wechat
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {

[WXApi handleOpenURL:url delegate:self];
return YES;
}
Copy the code

8. Request CODE Developers shall cooperate with the SDK provided by wechat Open Platform to authorize login and request access. Access the SDK correctly and have the relevant authorization domain (scope, what is the authorization domain?) After the permission is granted, the developer’s mobile application will pull up the wechat application locally on the terminal for authorized login. After the wechat user confirms, wechat will pull up the developer’s mobile application and bring the authorized temporary bill (code).

#import "LoginViewController.h"
#import "RegisterViewController.h"
#import "MBProgressHUD.h"
#import "AFNetworking.h"
#import "WXApi.h"

#pragma Mark - wechat login
/* At present, wechat login only provides the native login mode, which requires users to install wechat client to cooperate with the use. For iOS applications, considering the relevant regulations in the iOS App Store Review Guide, it is recommended that developers check whether the wechat client has been installed on the user's mobile phone (using isWXAppInstall function in the SDK) when logging in to the wechat app, and hide the wechat login button for users who have not installed it and only provide other login methods. * /
- (IBAction)wechatLoginClick:(id)sender {

if ([WXApi isWXAppInstalled]) {
        SendAuthReq *req = [[SendAuthReq alloc] init];
        req.scope = @"snsapi_userinfo";
        req.state = @"App";
        [WXApi sendReq:req];
    }
    else{[selfsetupAlertController]; }}#pragma mark - Set pop-up prompts
- (void)setupAlertController {
    
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@" Warm tips" message:Please install wechat client first. preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *actionConfirm = [UIAlertAction actionWithTitle:@ "sure" style:UIAlertActionStyleDefault handler:nil];
    [alert addAction:actionConfirm];
    [self presentViewController:alert animated:YES completion:nil];
}
Copy the code

After performing the above step, if the client has installed wechat, it will request corresponding authorization from wechat, as shown below:

// LoginViewController.h
#import <UIKit/UIKit.h>
@interface LoginViewController : BaseViewController
/ * * through the block to perform in the AppDelegate wechatLoginByRequestForUserInfo method * /
@property (copy.nonatomic) void (^requestForUserInfoBlock)();
@end

// LoginViewController.m
#pragma Mark - wechat login
/* At present, wechat login only provides the native login mode, which requires users to install wechat client to cooperate with the use. For iOS applications, considering the relevant regulations in the iOS App Store Review Guide, it is recommended that developers check whether the wechat client has been installed on the user's mobile phone (using isWXAppInstall function in the SDK) when logging in to the wechat app, and hide the wechat login button for users who have not installed it and only provide other login methods. * /
- (IBAction)wechatLoginClick:(id)sender {
    NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:WX_ACCESS_TOKEN];
    NSString *openID = [[NSUserDefaults standardUserDefaults] objectForKey:WX_OPEN_ID];
    // If you have already requested wechat authorization to log in, consider using the access_token you have obtained
    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(Request reAccess response = %@, responseObject);
            NSDictionary *refreshDict = [NSDictionary dictionaryWithDictionary:responseObject];
            NSString *reAccessToken = [refreshDict objectForKey:WX_ACCESS_TOKEN];
            // If reAccessToken is empty, reAccessToken is also expired; otherwise, it is not
            if (reAccessToken) {
                // Update 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];
                / / when is not empty reAccessToken direct execution of AppDelegate wechatLoginByRequestForUserInfo method
                !self.requestForUserInfoBlock ? : self.requestForUserInfoBlock();
            }
            else{[self wechatLogin];
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(Error updating accessToken with refresh_token = %@", error);
        }];
    }
    else{[selfwechatLogin]; }} - (void)wechatLogin {
    if ([WXApi isWXAppInstalled]) {
        SendAuthReq *req = [[SendAuthReq alloc] init];
        req.scope = @"snsapi_userinfo";
        req.state = @"GSTDoctorApp";
        [WXApi sendReq:req];
    }
    else{[selfsetupAlertController]; }}#pragma mark - Set pop-up prompts
- (void)setupAlertController {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@" Warm tips" message:Please install wechat client first. preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *actionConfirm = [UIAlertAction actionWithTitle:@ "sure" style:UIAlertActionStyleDefault handler:nil];
    [alert addAction:actionConfirm];
    [self presentViewController:alert animated:YES completion:nil];
}
Copy the code
Output: when access_token and openID reAccess request * * * * * * * * * * * * * * response = {* * * *"access_token" = "OezXcEiiBSKSxW0eoylIeK3BOTSVaRovFSXb5oysH6dewFfLsQRgU3fphSLkKkhOokra9H-JMZuB5nPoM-Iy5YbFeA1nKMRYCbL0fj_s46oFKOluGoRUY8j yTdrdDiiFdgS2fxgo5odEtpnpFk3EXA"; * * * *"expires_in" = 7200; ** ** openid = oXskgs62CJGFhFX05dSjy9Sjw2KA; * * * *"refresh_token" = "OezXcEiiBSKSxW0eoylIeK3BOTSVaRovFSXb5oysH6dewFfLsQRgU3fphSLkKkhOOWPTKGEjUtuiueutxRjKOlHGZ9b9ogc3KMbibu4eKc4yTMGzSZayjYP mwQ-c4RJE1RzMLrqvjUWgB5roFnjykw"; ** ** scope ="snsapi_base,snsapi_userinfo,"; * * * * * *}Copy the code

Refresh access_token validity period: The validity period of the access_token is short (currently 2 hours). When the access_token times out, refresh_token can be refreshed. The refresh_token refresh results are as follows:

1.If the access_token has timed out, refresh_token will obtain a new access_token with a new timeout period.2.If the access_token does not time out, refresh_token does not change the access_token, but the timeout period is refreshed, which is equivalent to renewing the access_token.Copy the code

Refresh_token has a long validity period (30 days). When refresh_token becomes invalid, users need to reauthorize it. Let the AppDelegate comply with the protocol and implement the protocol method onResp:, where we receive the requested data as follows:

// Callback after authorization
/* HTTP request :GET access_token according to the code in the response result (using the AppID and AppSecret obtained at the time of application) https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code right back  { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "Unionid ":"o6_bmasdasdsad6_2sgVt7hMZOPfL"} Error Return Example {" errCode ":40029,"errmsg":"invalid code"} errCode ERR_OK = 0(agreed by the user) ERR_AUTH_DENIED = -4 (the user denies authorization) ERR_USER_CANCEL = -2 (the user cancels) Code Code used by the user to exchange the access_token, Valid state only when ErrCode is 0. The flag used by the third-party program to identify the uniqueness of its request when it is sent, which is passed in when the third-party program calls sendReq and returned by the wechat terminal. State the value cannot exceed 1K lang current wechat client language country current wechat user country */
Copy the code
- (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];
}
Copy the code
// Callback after authorization
// AppDelegate.m
- (void)onResp:(BaseResp *)resp {
    // After requesting authorization from wechat, the response result is obtained
    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(Request a response from Access = %@, 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];
            // Local persistence for access_token usage, refresh, or persistence
            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]; // Commands are synchronized directly to files to avoid data loss
            }
            [self wechatLoginByRequestForUserInfo];
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@" Error obtaining access_token = %@", error); }]; }}Copy the code

After the code obtained in the previous step, request the following link to obtain the access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
Copy the code

The onResp: method is implemented above the associated code and receives the returned response. Parameter Description:

Appid is the unique identifier of the application. Secret is the application key AppSecret, which can be obtained after the application is submitted and approved on wechat open platform. After the application submitted on wechat open platform is approved, the code obtained is filled in. The code parameter grant_type obtained in the first step is filled in with authorization_codeCopy the code

Return description:

{ 
"access_token":"ACCESS_TOKEN".// Interface call credentials
 "expires_in":7200.// Timeout time for access_token interface to call credentials, in seconds
"refresh_token":"REFRESH_TOKEN".// The user refreshed the access_token
"openid":"OPENID".// Unique identifier of the authorized user
"scope":"SCOPE".// Scope of user authorization, separated by commas (,)
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL" // This field will appear only after the user binds the public account to the wechat open platform account
}
Copy the code

An example error message is returned:

{"errcode":40029."errmsg":"invalid code"}
Copy the code

10. Obtain user’s personal information (UnionID mechanism)

HTTP request mode :GET HTTPS://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
Copy the code
// AppDelegate.m
// Get user's personal information (UnionID mechanism)
- (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];
    // Request user data
    [manager GET:userUrlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(Request user information response = %@, responseObject);
        // NSMutableDictionary *userDict = [NSMutableDictionary dictionaryWithDictionary:responseObject];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(Error getting user info = %@, error);
    }];
}
Copy the code

Json result returned:

Json result returned {"openid":"OPENID"."nickname":"NICKNAME"."sex":1."province":"PROVINCE"."city":"CITY"."country":"COUNTRY"."headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaice qxibJxCfHe/0"."privilege": ["PRIVILEGE1"."PRIVILEGE2"]."unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"} returns an error Json instance {"errcode":40003."errmsg":"invalid openid"
 }
Copy the code

11, finally do the above step should be returned to wechat basic information, and then according to the basic needs of your company background to realize how to log in the App after authorization. Information:

// access_token openid refresh_token unionid
#define WXDoctor_App_ID @"wxd1931d4a0e462***"// The AppID when registering wechat
#define WXDoctor_App_Secret @"d0dd6b58da42cbc4f4b715c70e65c***"// The AppSecret obtained when registering
#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"
Copy the code

12. This is what we need to do: