前置步骤
在接入openSDK之前,我们需要做几个前置步骤:
首先需要去Apple开发者账号中配置Universal Link,这是为了手机中如果安装了支持该链接的App就会直接进入到App中;如果没有安装APP则会跳转到Safari浏览器中,展示H5页面。 这样可以通过HTTPS链接来无缝启动APP。
在微信开放平台创建一个移动应用,创建的时候需要用到上面的Universal Link。
创建完成后,开通微信登录及分享功能。
应用详情中查看你的Universal Link、Bundle id、AppID、AppSecret,后续需要使用。
apple-app-site-association记录下来(可以通过 https://your_UniversalLink/apple-app-site-association 来查看你的配置)
微信openSDK引用
我们可以使用CocoaPods来引用微信的sdk并加以配置,具体步骤如下:
在项目下pod init生成Podfile文件,添加pod ‘WechatOpenSDK’,然后pod install
打开项目,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册的应用程序 id。
选中“TARGETS”一栏,在“Signing&Capabilities”下面,点击 +Capability,打开Associated Domains开关,将Universal Links域名加到配置上。
在info.plst中添加LSApplicationQueriesSchemes,LSApplicationQueriesSchemes 类型选array,添加item0 value为weixin,添加item1,value为weixinULAPI
微信sdk中oc桥接swift
因为微信sdk为oc的代码,这里我们通过桥接Bridging_Header来将代码import进去,具体步骤如下:
新建HeaderFile文件,添加import:
1 2 3 4 5 6 7 8 9
| #ifndef WeChatLoginDemo_Bridging_Header_h #define WeChatLoginDemo_Bridging_Header_h
#import "WXApi.h" #import "WXApiObject.h" #import "WechatAuthSDK.h" #import "WebKit/WebKit.h"
#endif
|
选中“TARGETS”一栏,在“Build Settings”下面Objective-C Bridging Header下面把新建的HeaderFile路径配上去。
调用微信openSDK完成登录和分享功能
我们要完成该功能,需要:
在代码中向微信终端注册你的 id
实现 WXApiDelegate 协议的两个方法 onReq 和 onResp
重写 AppDelegate 和 openURL 方法
最后调用 WXApi 的 sendReq 函数
拿到微信返回的code,通过微信接口来拿access_token,再通过access_token拿具体信息,更新界面
不要忘记将之前配置的apple-app-site-association的json文件加入你的项目(可以通过 https://your_UniversalLink/apple-app-site-association 来查看你的配置)
具体代码如下:
因为Swiftui没有Appdelegate,所以我们自己新建一个Appdelegate,实现WXApiDelegate协议的两个方法,并在初始化时注册id:
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
| import Foundation import UIKit
class AppDelegate: NSObject, UIApplicationDelegate , WXApiDelegate, WXApiLogDelegate{ func onLog(_ log: String, logLevel level: WXLogLevel) { print(log) } func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { WXApi.startLog(by: WXLogLevel.detail, logDelegate: self) let isReg = WXApi.registerApp(Utiliy.AppID, universalLink: "https://xxx") print("注册:\(isReg)") return isReg }
func onReq(_ req: BaseReq) { }
func onResp(_ resp: BaseResp) { if resp.isKind(of: SendAuthResp.self){ let arsp = resp as! SendAuthResp if !(arsp.code?.isEmpty ?? true) { NotificationCenter.default.post(name: Notification.Name("code"), object: arsp.code) } } }
deinit { NotificationCenter.default.removeObserver(self) }
}
|
在view入口处调用onOpenURL接口,并Adaptor你的AppDelegate,这样就能够初始化时调用AppDelegate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import SwiftUI
@main struct WeChatLoginDemoApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { ContentView() .onOpenURL{url in WXApi.handleOpen(url, delegate: appDelegate) } } } }
|
然后就拿到微信code后,通过微信api拿access_token和登录信息,分享就直接调用send方法就行:
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| import SwiftUI
struct ContentView: View { @ObservedObject var model: Model = Model() var urlString: String = "" @ObservedObject var imageLoader = ImageLoader() @State var image: UIImage = UIImage()
let pub = NotificationCenter.default .publisher(for: NSNotification.Name("code"))
var body: some View { VStack(alignment: .leading, spacing: 20){ Text("openid: \(model.openid)") .padding() Text("nickname: \(model.nickname)") .padding() Text("sex: \(model.sex) (1 为男性,2 为女性, 0为空)") .padding() Text("province: \(model.province)") .padding() Text("city: \(model.city)") .padding() Text("country: \(model.country)") .padding() Text("unionid: \(model.unionid)") .padding() Image(uiImage: image) .resizable() .frame(width: 64, height: 64, alignment: .center) .onReceive(imageLoader.$data) { data in guard let data = data else { return } self.image = UIImage(data: data) ?? UIImage() } Button("微信登录信息", action: { getCode() }).padding() Button("微信分享信息", action: { sendText(text: "test", inScene: WXSceneSession) }).padding() } .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading) .onReceive(pub) { (output) in let code = output.object as! String self.getInfo(code: code) } }
func getInfo(code: String){ let urlString = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=\(Utiliy.AppID)&secret=\(Utiliy.AppSecret)&code=\(code)&grant_type=authorization_code" var request = URLRequest(url: URL(string: urlString)!) request.httpMethod = "GET" URLSession.shared.dataTask(with: request) { data, response, error in DispatchQueue.main.async(execute: { if error == nil && data != nil { do { let dic = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: Any] let access_token = dic["access_token"] as! String let openID = dic["openid"] as! String requestUserInfo(access_token, openID) } catch { print(#function) } return } }) }.resume() }
func requestUserInfo(_ token: String, _ openID: String) { let urlString = "https://api.weixin.qq.com/sns/userinfo?access_token=\(token)&openid=\(openID)" var request = URLRequest(url: URL(string: urlString)!) request.httpMethod = "GET" URLSession.shared.dataTask(with: request) { data, response, error in DispatchQueue.main.async(execute: { if error == nil && data != nil { do { let dic = try JSONSerialization.jsonObject(with: data!, options: []) as! [String: Any] self.model.openid = dic["openid"] as! String self.model.nickname = dic["nickname"] as! String self.model.sex = dic["sex"] as! Int self.model.province = dic["province"] as! String self.model.city = dic["city"] as! String self.model.country = dic["country"] as! String self.model.headimgurl = dic["headimgurl"] as! String self.model.unionid = dic["unionid"] as! String imageLoader.loadData(from: self.model.headimgurl) } catch { print(#function) } return } }) }.resume() }
func sendText(text:String, inScene: WXScene){ let req = SendMessageToWXReq() req.text=text req.bText=true req.scene=Int32(inScene.rawValue) WXApi.send(req) }
func getCode(){ let req = SendAuthReq() req.scope = "snsapi_userinfo" req.state = "wx_oauth_authorization_state" DispatchQueue.main.async{ WXApi.send(req,completion: nil) } } }
|