前置步骤h1
在接入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引用h1
我们可以使用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桥接swifth1
因为微信sdk为oc的代码,这里我们通过桥接Bridging_Header来将代码import进去,具体步骤如下:
新建HeaderFile文件,添加import:
#ifndef WeChatLoginDemo_Bridging_Header_h#define WeChatLoginDemo_Bridging_Header_h
#import "WXApi.h"#import "WXApiObject.h"#import "WechatAuthSDK.h"#import "WebKit/WebKit.h"
#endif /* WeChatLoginDemo_Bridging_Header_h */选中“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:
import Foundationimport 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) //需要用到微信开放平台注册移动应用的AppID和universalLink,然后注册id let isReg = WXApi.registerApp(Utiliy.AppID, universalLink: "https://xxx") print("注册:\(isReg)")
return isReg }
func onReq(_ req: BaseReq) { //微信终端向第三方程序发起请求,要求第三方程序响应。第三方程序响应完后必须调用 sendRsp 返回。在调用 sendRsp 返回时,会切回到微信终端程序界面。 }
func onResp(_ resp: BaseResp) { //如果第三方程序向微信发送了sendReq的请求,那么onResp会被回调。sendReq请求调用后,会切到微信终端程序界面。 //微信返回的code 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:
import SwiftUI
@mainstruct 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方法就行:
import SwiftUI
struct ContentView: View { @ObservedObject var model: Model = Model()
var urlString: String = "" @ObservedObject var imageLoader = ImageLoader() @State var image: UIImage = UIImage()
//onResp拿到code后的通知界面 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 //code拿access_token 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 //通过access_token拿微信登录信息 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) } }}