一、接入微信第三方登錄準備工作。
移動應用微信登錄是基于OAuth2.0協(xié)議標準構建的微信OAuth2.0授權登錄系統(tǒng)絮姆。
1. 在微信開放平臺注冊開發(fā)者帳號,并擁有一個已審核通過的移動應用秩霍,并獲得相應的AppID和AppSecret篙悯,申請微信登錄且通過審核后,可開始接入流程
注意:
1.審核需要提供一個28*28和108*108的圖標
2.審核需要提供Bundle ID
3.審核需要一點時間铃绒,我之前一天就審核通過了
2. 下載iOS微信SDK
下載最新的SDK 地址: 點擊打開鏈接
Paste_Image.png
3. 將SDK放到工程目錄中
Paste_Image.png
4. 補充導入一些依賴框架:Target - Build Phases - Link Binary With Libraries
Paste_Image.png
5. 添加URL Types:Target - Info - URL Types
Paste_Image.png
6. 添加iOS9 URL Schemes
**注意: 當程序出現(xiàn)以下錯誤鸽照,說明沒有針對iOS9 增加白名單。在info.plist文件中加入 LSApplicationQueriesSchemes **
-canOpenURL: failed for URL: "weixin://app/wx9**********dfd30/" - error: "This app is not allowed to query for scheme weixin"
Paste_Image.png
7. iOS9中新增App Transport Security(簡稱ATS)特性, 主要使到原來請求的時候用到的HTTP匿垄,都轉向TLS1.2協(xié)議進行傳輸移宅。這也意味著所有的HTTP協(xié)議都強制使用了HTTPS協(xié)議進行傳輸。需要在Info.plist新增App Transport Security Settings用于控制ATS的配置:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
如果我們在iOS9下直接進行HTTP請求是會收到如下錯誤提示椿疗,需要在Info.plist新增App Transport Security Settings
**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.**
Paste_Image.png
8. 現(xiàn)在編譯應該沒有問題
二漏峰、代碼部分
1. 第一步:在橋接文件中引入"WXApi.h"頭文件,然后在中AppDelegate.m寫入如下代碼:
import UIKit
@UIApplicationMain
// 在Appdelegate里面添加微信代理
class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//向微信注冊應用
// @param1 微信開發(fā)者ID
// @param2 應用附加信息届榄,長度不超過1024字節(jié)
WXApi.registerApp("wxed8b3e67969559b5", withDescription: "wechat")
return true
}
// 這個方法是用于從微信返回第三方App 處理微信通過URL啟動App時傳遞的數(shù)據(jù)
// @param url 微信啟動第三方應用時傳遞過來的URL
// @param delegate WXApiDelegate對象浅乔,用來接收微信觸發(fā)的消息。
func application(application: UIApplication, handleOpenURL url: NSURL) -> Bool {
if url.scheme == "wxed8b3e67969559b5" {
WXApi.handleOpenURL(url, delegate: self)
}
return true
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
if url.scheme == "wxed8b3e67969559b5" {
WXApi.handleOpenURL(url, delegate: self)
}
return true
}
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
Tools.logPrint("openURL:\(url.absoluteString)")
if url.scheme == "wxed8b3e67969559b5" {
return WXApi.handleOpenURL(url, delegate: self)
}
return true
}
}
2. 第二步:請求CODE
開發(fā)者需要配合使用微信開放平臺提供的SDK進行授權登錄請求接入。正確接入SDK后并擁有相關授權域(scope靖苇,什么是授權域席噩?)權限后,開發(fā)者移動應用會在終端本地拉起微信應用進行授權登錄贤壁,微信用戶確認后微信將拉起開發(fā)者移動應用悼枢,并帶上授權臨時票據(jù)(code)。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if WXApi.isWXAppInstalled() {
print("weixin ready")
} else {
// 把微信登錄的按鈕隱藏掉
}
}
// 請求CODE
@IBAction func wechatLoginClick(sender: UIButton) {
// 如果在這里判斷是否安裝了微信脾拆,會報-canOpenURL: failed for URL: "weixin://app/wx5efead4057f98bc0/" - error: "This app is not allowed to query for scheme weixin"錯誤
let req = SendAuthReq()
req.scope = "snsapi_userinfo"
req.state = "App"
//第三方向微信終端發(fā)送一個SendAuthReq消息結構
if !WXApi.sendReq(req) {
print("weixin sendreq failed")
}
}
}
執(zhí)行完上面那一步后馒索,如果客戶端安裝了微信,那么就會向微信請求相應的授權名船,圖如下:
Paste_Image.png
返回說明
用戶點擊授權后绰上,微信客戶端會被拉起,跳轉至授權界面渠驼,用戶在該界面點擊允許或取消蜈块,SDK通過SendAuth的Resp返回數(shù)據(jù)給調用方。
Paste_Image.png
3. 第三步:通過code獲取access_token
獲取code后迷扇,請求以下鏈接獲取access_token:
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&gr
ant_type=authorization_code
Paste_Image.png
// 授權后回調
// AppDelegate.m
func onReq(req: BaseReq!) {
//onReq是微信終端向第三方程序發(fā)起請求百揭,要求第三方程序響應。第三方程序響應完后必須調用sendRsp返回谋梭。在調用sendRsp返回時信峻,會切回到微信終端程序界面。
print(req.type)
}
func onResp(resp: BaseResp!) {
//如果第三方程序向微信發(fā)送了sendReq的請求瓮床,那么onResp會被回調盹舞。sendReq請求調用后,會切到微信終端程序界面隘庄。
if resp.isKindOfClass(SendAuthResp) {
let authResp = resp as! SendAuthResp
print("ErrCode : \(authResp.errCode)") // 0
print("EodeStr : \(authResp.errStr)") // nil
print("Code : \(authResp.code)") // 0017Avci0BJ0Rj1hIqai0jEsci07AvcI
print("State : \(authResp.state)") // State : App
print("Lang : \(authResp.lang)") // nil
print("Country : \(authResp.country)") // nil
if authResp.errCode == 0 {
let code = authResp.code
let AFN = AFHTTPSessionManager()
let params = ["appid": WX_APPID, "secret": WX_APPSECRET_TEST, "code": code, "grant_type": "authorization_code"]
AFN.GET("https://api.weixin.qq.com/sns/oauth2/access_token", parameters: params, success: { (_, response) in
let accessToken = response!["access_token"] as! String
let refreshToken = response!["refresh_token"] as! String
let openID = response!["openid"] as! String
// 本地持久化踢步,以便access_token的使用、刷新或者持續(xù)
if (accessToken.isEmpty == false && openID.isEmpty == false) {
NSUserDefaults.standardUserDefaults().setObject(accessToken, forKey: "access_token")
NSUserDefaults.standardUserDefaults().setObject(refreshToken, forKey: "refresh_token")
NSUserDefaults.standardUserDefaults().setObject(openID, forKey: "openid")
NSUserDefaults.standardUserDefaults().synchronize() // 命令直接同步到文件里丑掺,來避免數(shù)據(jù)的丟失
}
self.wechatLoginByRequestForUserInfo()
}, failure: { (_, error) in
print(error)
})
}
}
}
Paste_Image.png
// 獲取用戶個人信息(UnionID機制)
func wechatLoginByRequestForUserInfo() {
let accessToken = NSUserDefaults.standardUserDefaults().objectForKey("access_token")
let openID = NSUserDefaults.standardUserDefaults().objectForKey("openid")
// 獲取用戶信息
let params = ["access_token": accessToken! as! String, "openid": openID! as! String] as Dictionary<String, String>
let AFN = AFHTTPSessionManager()
AFN.GET("https://api.weixin.qq.com/sns/userinfo", parameters: params, progress: nil, success: { (_, response) in
// 這里可以實現(xiàn)公司的要求获印,比如我司是微信登錄成功后,通過segue跳轉到主界面
print(response)
}, failure: { (_, error) in
print(error)
})
}