swift 5.1和oc双语言 WechatOpenSDK (1.8.7.1)微信登录集成教程封装成支持swift和oc方法调用

54 篇文章 1 订阅
18 篇文章 0 订阅


微信官网的登录demo下载以后运行没跑起来,看文档又说的不全,自己做了demo并且封装成了swift和oc都能调用的工具类,demo放在最后
注意,能复制的地方坚决不要手动输入拼写,我之前自己手动拼写了白名单,结果就错了,找了半天才发现拼写错误,需要复制的地方请直接复制粘贴,我文章最下面的demo里的文本

先看一下demo演示

在这里插入图片描述

安装pod 安装

创建podfile文件,里面添加:pod ‘WechatOpenSDK’
默认安装的是新版的WechatOpenSDK (1.8.7.1)
终端执行pod install,安装完以后打开 项目名.xcworkspace文件

到微信官网注册账户,并获取3个数据

账户后台的3个数据:
app ID
universal link
app Secret

并且获取3个值,如果你没有,只是想试验一下,可以使用我例子里面已经注册号的3个值

添加关联域名 Associated Domains

点击项目名 targets 选择 Signing & Capabilities ->Capability ->Associated Domains ,点击加好 添加域名,以applinks: 开头后面tian’ji universal link里面的值
在这里插入图片描述

info.plist里面 添加 白名单

白名单的key叫:LSApplicationQueriesSchemes
把 info.plist 右键点击 open as-> source code 复制下面的添加到最下面倒数第3行的上面,
LSApplicationQueriesSchemes

weixin
weixinULAPI
wechat

在这里插入图片描述

或者手动info.plist open as ->Property List,复制我demo里面的info.plist 手动粘贴进去,建议复制,手动粘贴容易出错
在这里插入图片描述

添加 URL Schemes

target -> info -> URL Types 点击下面+加号, 添加 URL Schemes ,填写内容是 微信后台注册的app ID,如下图所示
在这里插入图片描述

AppDelegate.swift文件中设置 方法:

唯一要说的是:下面有一个巨大的坑:就是 WXApi.handleOpen(url, delegate: self)这个方法这个方法是oc的+ (BOOL)handleOpenURL:(NSURL *)url delegate:(nullable id)delegate; 方法,在系统自动转换为swift代码的时候会直接转换为WXApi.handleOpen( url, delegate: self,),编译报错提示错误找不到函数上下文,意思是找不到这个函数,当时我解决的方法是放到方法用oc类调用oc的handleOpenURL:(NSURL *)url ,然后再用swift调用oc的类方法, 最终我的解决方法是,先把在swift里面写下面的代码,系统会提示函数名字已经改了,然后点击fix修复,系统会帮我修复成handleOpen方法,再编译,就不提示handleOpen找不到了,这个是swift系统bug
在这里插入图片描述

直接粘贴下面代码就行

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        WXApi.registerApp(WXAPP_ID, universalLink: UNIVERSAL_LINK)
        
        return true
    }
    
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        
        if url.host == "oauth"{//微信登录
            return WXApi.handleOpen(url, delegate: self) //如果handleOpen提示错误,就先用oc原来的方法return WXApi.handleOpenURL(url, delegate: self),然后让系统自动提示rename,这样就能编译通过
        }
        return true
    }
    
    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        return WXApi.handleOpen(url, delegate: self)
    }
}

extension AppDelegate:WXApiDelegate{
    func onReq(_ req: BaseReq) {
        //onReq是微信终端向第三方程序发起请求,要求第三方程序响应。第三方程序响应完后必须调用sendRsp返回。在调用sendRsp返回时,会切回到微信终端程序界面。
        print(req.type)
    }
    func onResp(_ resp: BaseResp) {
        //如果第三方程序向微信发送了sendReq的请求,那么onResp会被回调。sendReq请求调用后,会切到微信终端程序界面。
        
        if resp.isKind(of: SendAuthResp.self) {
            let response = resp as! SendAuthResp
            print("ErrCode : (response.errCode)")
            print("EodeStr : (response.errStr)")
            print("Code : (response.code)")
            print("State : (response.state)")
            print("Lang : (response.lang)")
            print("Country : (response.country)")
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "WXLoginSuccessNotification"), object: response.code)
        }
        
    }
}

oc AppDelegate.m文件中方法使用,oc的例子中没有使用storyboard,而是直接启动VC1.xib

AppDelegate.m内容

//
//  AppDelegate.m
//  wechatLoginOCDemo
//
//  Created by tdw on 2021/3/5.
//

#import "AppDelegate.h"
#import <WXApi.h>
#import <WXApiObject.h>
#import "VC1.h"
@interface AppDelegate ()<WXApiDelegate>

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    
    [WXApi registerApp:WXAPP_ID universalLink:UNIVERSAL_LINK];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
      self.window.backgroundColor = [UIColor whiteColor];
      
    VC1 *root = [[VC1 alloc] initWithNibName:@"VC1" bundle:nil];  //加载nib文件,生成View实例
      [self.window setRootViewController:root];  //将new出来的view实例设置为window的root view。
      
      [self.window makeKeyAndVisible];   //将当前winsow置为当前状态下的key window,并呈现出来。Makes the receiver the key window and visible.
      return YES;
    return YES;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    if ([url.host isEqualToString:@"oauth"]){
        return  [WXApi handleOpenURL:url delegate:self];
    }
    return false;

}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    return  [WXApi handleOpenURL:url delegate:self];
}
- (void)onReq:(BaseReq *)req{
    NSLog(@"req=%@",req);
}
- (void)onResp:(BaseResp *)resp{
    if([resp isKindOfClass:[SendAuthResp class]]){
           SendAuthResp *resp2 = (SendAuthResp *)resp;
           [[NSNotificationCenter defaultCenter] postNotificationName:NotiWxLoginSuucess object:resp2.code];
       }else{
           NSLog(@"授权失败");
       }
}
@end

把后台设置的3个数据添加进全局变量伪装成oc的宏定义给封装的类用

在swift项目中,添加一个用来存储全局变量的文件 common.swift

//
//  common.swift
//  wechatLoginDemo
//
//  Created by tdw on 2021/3/4.
//  Copyright © 2021 谭迪文. All rights reserved.
//

let WXAPP_ID = "wxf1dffab76327aeb6"
let UNIVERSAL_LINK = "https://tmx.zwfw.gswuwei.gov.cn/"
let WX_APPSecret = "648a9644e08eeac108b6b0572e00978e"
let NotiWxLoginSuucess = "NotiWxLoginSuucess"//定义一个微信登录成功以后回调发送的通知

oc项目定义宏定义

在oc中我添加了一个PrefixHeader.pch预处理文件,项目中所有文件都包含他
在这里插入图片描述
预处理文件是包含了3个 微信后台设置的数据,和一个自定义通知的宏定义NotiWxLoginSuucess

//
//  PrefixHeader.pch
//  wechatLoginOCDemo
//
//  Created by tdw on 2021/3/5.
//

#ifndef PrefixHeader_pch
#define PrefixHeader_pch

// Include any system framework and library headers here that should be included in all compilation units.
// You will also need to set the Prefix Header build setting of one or more of your targets to reference this file.
#define WXAPP_ID @"wxf1dffab76327aeb6"
#define  UNIVERSAL_LINK @"https://tmx.zwfw.gswuwei.gov.cn/"
#define  WX_APPSecret @"648a9644e08eeac108b6b0572e00978e"
#define NotiWxLoginSuucess @"NotiWxLoginSuucess"//定义一个微信登录成功以后回调发送的通知
#endif /* PrefixHeader_pch */

添加自定义的微信管理工具类TdwWeChatLoginManager

这个工具类,swift和 oc 项目都要添加,这个支持双语言调用,里面用的到这个 字符串NotiWxLoginSuucess在上面定义了

//
//  TdwWeChatLoginManager.swift
//  wechatLoginDemo
//
//  Created by tdw on 2021/3/4.
//  Copyright © 2021 谭迪文. All rights reserved.
//

import UIKit
//微信的登录类

@objc class TdwWeChatLoginManager: NSObject {
    @objc static var shared:TdwWeChatLoginManager = {
        return TdwWeChatLoginManager()
    }()
    typealias CallBack = ([String:Any])->Void
    var loginAfter:CallBack = { _ in }
    private override init() {
        //添加通知监听
        super.init()
        NotificationCenter.default.addObserver(self, selector: #selector(WXLoginSuccess(notification:)), name: NSNotification.Name(rawValue: NotiWxLoginSuucess), object: nil)
        
    }
    @objc func login( loginAfter:@escaping CallBack) {
        // 微信登录请求
        let urlStr = "weixin://"
        if UIApplication.shared.canOpenURL(URL.init(string: urlStr)!) {
            let red = SendAuthReq.init()
            red.scope = "snsapi_message,snsapi_userinfo,snsapi_friend,snsapi_contact"
            red.state = "wechat_sdk_demo"
            WXApi.send(red)
        }else{
            if #available(iOS 10.0, *) {
                //qUQVDfDEVK0rrbRu9xG7这个数值可以自己随意修改
                UIApplication.shared.open(URL.init(string: "http://weixin.qq.com/r/qUQVDfDEVK0rrbRu9xG7")!, options: [:], completionHandler: nil)
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(URL.init(string: "http://weixin.qq.com/r/qUQVDfDEVK0rrbRu9xG7")!)
            }
        }
        self.loginAfter = loginAfter
    }
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    /**  微信通知  */
    
    @objc func WXLoginSuccess(notification:Notification) {
        let code = notification.object as! String
        //        let requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=\(WXAPP_ID)&secret=\(WX_APPSecret)&code=\(code)&grant_type=authorization_code"
        let APPSecret = WX_APPSecret
        
        let requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=\(WXAPP_ID)&secret=\(APPSecret)&code=\(code)&grant_type=authorization_code"
        DispatchQueue.global().async {
            
            let requestURL: URL = URL.init(string: requestUrl)!
            let data = try? Data.init(contentsOf: requestURL, options: Data.ReadingOptions())
            
            DispatchQueue.main.async {
                let jsonResult = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,Any>
                let openid: String = jsonResult["openid"] as! String
                let access_token: String = jsonResult["access_token"] as! String
                self.getUserInfo(openid: openid, access_token: access_token)
            }
        }
    }
    
    /**  获取用户信息  */
    func getUserInfo(openid:String,access_token:String) {
        let requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=\(access_token)&openid=\(openid)"
        
        DispatchQueue.global().async {
            
            let requestURL: URL = URL.init(string: requestUrl)!
            let data = try? Data.init(contentsOf: requestURL, options: Data.ReadingOptions())
            
            DispatchQueue.main.async {
                [unowned self] in
                let jsonResult = try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as! Dictionary<String,Any>
                self.loginAfter(jsonResult)
            }
        }
    }
}

添加桥接文件

oc

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//


#import <WXApi.h>
#import <WXApiObject.h>
#import "yyModel.h"
#import "UIImageView+WebCache.h"
#import  "PrefixHeader.pch"

swift

#import <WXApi.h>
#import <WXApiObject.h>
#import "VC1.h"
#import "yyModel.h"
#import "UIImageView+WebCache.h"

swift页面调用微信登录并且获取返回值

 // 微信登录请求
        TdwWeChatLoginManager.shared.login { (jsons) in
            print("返回结果jsons=",jsons)
        }

获得返回打印结果,里面包含头像的图片地址,昵称,性别城市,省份,国家等信息:
返回结果jsons= [“unionid”: ou4DdsiJTIo_LaxQZvKDpCKeKjI4, “nickname”: 正义, “sex”: 1, “province”: Heilongjiang, “headimgurl”: https://thirdwx.qlogo.cn/mmopen/vi_32/Ylib33UuwG3SEpLkArOlI3yDKSSvVQPQAAbGDFCKqvrO75jUHn7gHrN3BfRzkOdQkfs2IvpK7Y0mOv6PHPAkZsg/132, “city”: Harbin, “language”: zh_CN, “privilege”: <__NSArrayM 0x283bb6070>(

)
, “country”: CN, “openid”: o-C4n1NbW1Me6CUXieAFxQmVJQMM]

oc页面调用微信登录并且获取返回值

 [[TdwWeChatLoginManager shared] loginWithLoginAfter:^(NSDictionary<NSString *,id> * _Nonnull jsons) {            
        NSLog(@"OC控制器jsons=%@",jsons);
  }];

我在demo例子中添加了把返回值赋值到页面效果如最上面的演示图gif

demo中的点击按钮


    @IBAction func btnLoginClick(_ sender: Any) {
        // 微信登录请求
        TdwWeChatLoginManager.shared.login { [unowned self] (jsons) in
            print("===============================================================")
            print("返回结果jsons=",jsons)
            let item = WeChatLoginItem.yy_model(with: jsons)
            self.item = item
            if let urlStr = item?.headimgurl, let url = URL(string: urlStr) {
                self.imageV.sd_setImage(with:url, placeholderImage: UIImage(named: "questionmark.folder"), options: [], context: nil)
            }
        }
    }

在这里插入图片描述

注意,如果例子运行不了,请把证书选择自己的真机证书,用真机运行

swift demo下载

swift demo下载

oc demo下载

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值