> 技术文档 > 实战:iOS 接入微信登录详细步骤 & 踩坑全记录_weixinurlparamsapi

实战:iOS 接入微信登录详细步骤 & 踩坑全记录_weixinurlparamsapi


一、前言

  • 随着社交媒体的普及,越来越多的应用开始集成社交登录功能,微信登录是最常用的一种。而且国内的用户群体是很大的,也比较喜欢使用微信登录。

  • 微信登录的使用场景:社交、电商、工具类 App 等

  • 本文适用范围 & 技术栈说明:Objective-C、UIKit


二、微信开放平台准备工作

1. 注册并创建应用

  • 登录微信开放平台:https://open.weixin.qq.com

  • 没有开放平台帐号的话需要自行注册哈,可以注册个人/企业(注册企业帐号的话需要营业执照、法人信息的,找你们公司要),还需要交300元的审核费用,使用微信支付就好,后面会有发票发到微信开放平台上面的。

  • 创建移动应用需要提供:
    1)应用名称
    2)应用简介
    3)应用官网
    4)应用图标(28*28像素、108*108像素)
    5)App备案号
    6)应用运行流程图(游戏截图就好)
    7)申请/修改应用说明(申请微信应用,接入微信登录功能)

2. 配置 iOS 应用信息

  • Bundle ID 和 Universal Links 填写正确、测试阶段可以填测试 Bundle ID

  • Universal Links:是用来打开微信的,比较重要。

  • 2.1、配置应用的Universal Links
  • 根据 苹果文档 配置你应用的Universal Links

  • 微信对Universal Links配置要求

  • a)Universal Links必须支持https

  • b)Universal Links配置的paths不能带query参数

  • c)微信使用Universal Links拉起第三方App时,会在Universal Links末尾拼接路径和参数,因此App配置的paths必须加上通配符/*

  • Xcode里面打开 Signing&Capabilities - Associated Domains,将Universal Links域名加到配置上,前面要加上: applinks:

2.2、在域名根目录放这个文件:apple-app-site-association.json
关于apple-app-site-association文件
  1. 文件位置‌:必须严格放置在https:///.well-known/apple-app-site-association

  2. 文件内容‌:需包含正确的appID和paths配置

  3. CMCHM5763: 团队ID(在苹果开发者后台找)

          com.inn.ios.sdk: bundle ID(在苹果开发者后台找)

{ \"applinks\": { \"apps\": [], \"details\": [ { \"appID\": \"CMCHM5763.com.inn.ios.sdk\", \"paths\": [ \"/com.inn.ios.sdk/*\" ] } ] }}
  1. 服务器配置‌:

    • 必须支持HTTPS访问
    • 不应对该文件设置HTTP重定向
    • Content-Type应为application/json
    • 不允许添加.json后缀
  2. 客户端配置‌:

    • 在Xcode项目的Associated Domains中正确配置
    • 格式为:applinks:

三、项目配置(Xcode)

1. 安装微信 SDK

  • 使用 CocoaPods 安装:

    pod \'WechatOpenSDK-XCFramework\'
  • 手动导入:WechatOpenSDK-XCFramework.xcframework

  • 在 `General` - `Frameworks,Libraries,and Embedded Contect` 处将微信的库 `WechatOpenSDK-XCFramework.xcframework` 设置为 `Do Not Embed`.

  • 库下载地址:基本信息 | 微信开放文档

2. 配置 URL Schemes

  • 在 Info.plist 中添加:

    CFBundleURLTypes  CFBundleURLSchemes  wx你的AppID  

3. 配置 LSApplicationQueriesSchemes(iOS 9+)

LSApplicationQueriesSchemes weixin weixinULAPI weixinURLParamsAPI

4. 工程文件中选择 Build Setting,在\"Other Linker Flags\"中加入\"-ObjC -all_load\"


四、实现微信登录流程

1. 在主项目创建一个微信相关操作的管理类(CHWXManager.h、CHWXManager.mm)。相关代码如下:

#import #import \"WechatOpenSDK/WXApi.h\"#define kWXManager [CHWXManager defaultManager]@interface CHWXManager : NSObject+ (instancetype)defaultManager;#pragma mark - 注册APPKEY- (void)registerAppKey;#pragma mark - 微信登陆- (void)weChatLogin;- (void)application:(UIApplication *)application handleOpenURL:(NSURL *)url;- (void)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;- (void)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id> * __nullable restorableObjects))restorationHandler;- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity;@end
#import \"CHWXManager.h\"@implementation CHWXManager+ (instancetype)defaultManager{ static CHWXManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [CHWXManager new]; }); return manager;}#pragma mark - 注册APPKEY- (void)registerAppKey{ [WXApi startLogByLevel:WXLogLevelNormal logBlock:^(NSString *log) { NSLog(@\"WXApilog : %@\", log); }]; NSString *plistPath = [[NSBundle mainBundle] pathForResource:@\"idun\" ofType:@\"plist\"]; NSDictionary *dataDict = [[NSDictionary alloc] initWithContentsOfFile:plistPath]; [WXApi registerApp:[dataDict objectForKey:@\"wxapp_id\"] universalLink:[dataDict objectForKey:@\"universalLink\"]];}#pragma mark - 微信登陆- (void)weChatLogin{ // 1. 判断是否安装微信 if (![WXApi isWXAppInstalled]) { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@\"提示\" message:@\"您未安装微信,请先安装微信App\" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@\"取消\" style:UIAlertActionStyleCancel handler:nil]; [alert addAction:cancelAction]; UIWindow *keyWindow = nil; for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { if ([scene isKindOfClass:[UIWindowScene class]] && scene.activationState == UISceneActivationStateForegroundActive) { UIWindowScene *windowScene = (UIWindowScene *)scene; for (UIWindow *window in windowScene.windows) {  if (window.isKeyWindow) { keyWindow = window; break;  } } } } [keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; return; } // 2. 调起微信登录 SendAuthReq *req = [[SendAuthReq alloc] init]; req.scope = @\"snsapi_userinfo\" ; req.state = @\"login\"; [WXApi sendReq:req completion:^(BOOL success) { if (success) { //NSLog(@\"微信登录请求发送成功\"); } }];}- (void)onResp:(SendAuthResp *)resp{ if ([resp isKindOfClass:[SendAuthResp class]]) { // 微信登录 if (resp.errCode == WXSuccess) { // 登录返回code成功 //将登录结果回传给你的SDK进行校验 [[INrmService initrmService] wxLoginCheck:resp.code]; } }}- (void)application:(UIApplication *)application handleOpenURL:(NSURL *)url { [WXApi handleOpenURL:url delegate:self];}- (void)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { [WXApi handleOpenURL:url delegate:self];}- (void)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id> * __nullable restorableObjects))restorationHandler { [WXApi handleOpenUniversalLink:userActivity delegate:self];}- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity{ [WXApi handleOpenUniversalLink:userActivity delegate:self];}@end

注意:这里我的使用场景是我的SDK和微信SDK是并行存在项目里面的,因为SDK里面不可以集成SDK。由于微信的限制(有些配置只能在项目级进行),微信的登录代码只能放在外面,不可以封装进我的SDK里面。封装进SDK里面的话,报错,死活解决不了。

2. 发起授权请求

   我这里是登录界面在我的SDK里面,所以做了一个点击微信登录的回调出来。

[[INormService iniormService] loginIswx:^(BOOL isWXLogin) { [kWXManager weChatLogin];//调用微信登录} loginCallback:^(NSString * _Nonnull token, NSString * _Nonnull user_id) { }];

    3. 回调处理(iOS 13+:SceneDelegate)

    项目里面没有SceneDelegate这个类的话可以不实现这个方法

    • - (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity { [kWXManager scene:scene continueUserActivity:userActivity];}

    处理回调:AppDelegate

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [kWXManager registerAppKey]; return YES;}- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { [kWXManager application:application handleOpenURL:url]; return YES;}- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { [kWXManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; return YES;}- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray<id> * __nullable restorableObjects))restorationHandler { [kWXManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; return YES;}

    4. 获取登录结果

    • 实现 WXApiDelegate 协议,获取 SendAuthResp 中的 code

    • 从这里回调到SDK里面,换取 access_token 和 openid

    • - (void)onResp:(SendAuthResp *)resp{ if ([resp isKindOfClass:[SendAuthResp class]]) { // 微信登录 if (resp.errCode == WXSuccess) { // 登录返回code成功 [[INrmService iniService] wxLoginCheck:resp.code]; } }}

      SDK里面:wxapp_id 和 wxAppSecret 需要在微信开发者后台创建应用那里获取

      /** 微信登录校验 */- (void)wxLoginCheck:(NSString *)codeStr{// 1. 确定请求路径 NSURL *url = [NSURL URLWithString:@\"https://api.weixin.qq.com/sns/oauth2/access_token?\"]; NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; NSMutableArray *queryItems = [NSMutableArray array]; [queryItems addObject:[NSURLQueryItem queryItemWithName:@\"appid\" value:@\"wxapp_id\"]]; [queryItems addObject:[NSURLQueryItem queryItemWithName:@\"secret\" value:\"wxAppSecret\"]]; [queryItems addObject:[NSURLQueryItem queryItemWithName:@\"code\" value:codeStr]]; [queryItems addObject:[NSURLQueryItem queryItemWithName:@\"grant_type\" value:@\"authorization_code\"]]; components.queryItems = queryItems; // 2. 创建请求对象 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3. 获取会话对象 NSURLSession *session = [NSURLSession sharedSession]; __weak INService *weakSelf = self; // 4. 根据会话对象创建一个Task(发送请求) NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { return; } NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; if ([dic isKindOfClass:[NSDictionary class]]) { NSString *access_token = dic[@\"access_token\"]; NSString *openid = dic[@\"openid\"]; if (access_token != nil && openid != nil) { NSDictionary *userInfo = @{  @\"open_id\": openid,  @\"access_token\": access_token }; NSLog(@\"用户信息:%@\", userInfo); } else { NSLog(@\"access_token 或 openid 不存在!\"); } } else { NSLog(@\"解析失败,dic 不是字典!\"); } }]; // 5. 执行任务 [task resume];}

    五、服务端配合(关键点)

    • 请求 URL:

      https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    • 返回 access_token、openid,推荐:服务端中转,避免 App 直接访问微信 API


    六、实战踩坑记录

    1. URL Schemes 不生效?

    • 是否拼写错误、大小写敏感、缺少前缀 wx

    2. App 无法调起微信?

    • 没安装微信 / 用模拟器(微信不能在模拟器上运行)

    • 没配置 LSApplicationQueriesSchemes

    • 域名根目录没放apple-app-site-association.json文件

    3. 回调无响应?

    • 没正确实现 WXApiDelegate

    • SceneDelegate 没配置 / 回调没有传到 AppDelegate

    4. Universal Link 报错?

    • 忽略 universalLink 先用 URL Schemes 调试

    • 确保 Apple-app-site-association 文件配置无误(生产环境再搞)

    5. 无法获取用户信息?

    • access_token 有效期问题

    • 必须调用正确接口,openid 与 access_token 成对使用