Skip to content

Instantly share code, notes, and snippets.

@klaus01
Last active January 16, 2019 03:55
Show Gist options
  • Save klaus01/c4159cae21fc3f43918d0e9b1f99f88a to your computer and use it in GitHub Desktop.
Save klaus01/c4159cae21fc3f43918d0e9b1f99f88a to your computer and use it in GitHub Desktop.
不集成微信 SDK 实现登录权限和分享内容
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let vc = SLAppStartUpVideoVC()
WeChatServices.appID = "xxxxx"
WeChatServices.appSecret = "xxxxx"
// 还需要配置 Info.plst 的 CFBundleURLTypes 和 LSApplicationQueriesSchemes
// 分享链接给好友
let content = WeChatServices.ShareContent.link(title: "标题",
description: "说明",
thumbnail: 缩略图 UIImage,
like: "链接")
WeChatServices.share(content: content, to: .friend, success: { (resultDic) in
log.info(resultDic)
}, fail: { (resultDic, error) in
log.error(resultDic)
log.error(error)
})
// 授权登录
WeChatServices.auth(success: { (dic) in
log.info(["登录成功", dic])
}, fail: { (dic, error) in
log.error(["微信登录失败", error])
})
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
if WeChatServices.handleOpenURL(url) { return true }
return false
}
}
//
// WeChatServices.swift
// SuperLine
//
// Created by 柯磊 on 2018/12/3.
// Copyright © 2018 AMonster. All rights reserved.
//
import UIKit
/// 微信业务
struct WeChatServices {
/// 分享到
///
/// - friend: 好友
/// - timeline: 朋友圈
public enum ShareTo: Int {
case friend, timeline
}
/// 分享的内容
///
/// - link: 分享链接(标题,摘要,缩略图,链接)
public enum ShareContent {
case link(title: String, description: String?, thumbnail: UIImage?, like: String)
}
typealias WeChatServicesSuccess = ([String: Any]) -> Void
typealias WeChatServicesFail = ([String: Any]?, NSError) -> Void
static private let kErrorDomain = "WeChatServices"
static private let kAuthState = "MyWAuth"
static private var _successBlock: WeChatServicesSuccess?
static private var _failBlock: WeChatServicesFail?
/// 微信应用ID
static var appID: String!
/// 微信应用Secret
static var appSecret: String!
/// 是否安装了微信
static var isInstalled: Bool {
if let url = URL(string: "weixin://"), UIApplication.shared.canOpenURL(url) {
return true
}
if let url = URL(string: "wechat://"), UIApplication.shared.canOpenURL(url) {
return true
}
return false
}
/// 调用授权
///
/// - Parameters:
/// - success: 成功回调
/// - fail: 失败回调
static func auth(success: WeChatServicesSuccess?, fail: WeChatServicesFail?) {
if !checkEnvironment() { return }
let urlString = String(format: "weixin://app/%@/auth/?scope=snsapi_userinfo&state=%@", appID!, kAuthState)
if let url = URL(string: urlString) {
_successBlock = success
_failBlock = fail
UIApplication.shared.openURL(url)
} else {
log.error("openURL 链接错误:" + urlString)
}
}
/// 分享内容
///
/// - Parameters:
/// - content: 分享内容及类型
/// - to: 分享到哪儿
static func share(content: ShareContent, to: ShareTo, success: WeChatServicesSuccess?, fail: WeChatServicesFail?) {
if !checkEnvironment() { return }
var shareDic = [String: Any]()
shareDic["result"] = "1"
shareDic["returnFromApp"] = "1"
shareDic["scene"] = to.rawValue.toString
shareDic["sdkver"] = "1.5"
shareDic["command"] = "1010"
switch content {
case .link(let title, let description, let thumbnail, let like):
shareDic["objectType"] = "5"
shareDic["title"] = title
shareDic["description"] = description ?? title
shareDic["mediaUrl"] = like
if let image = thumbnail {
shareDic["thumbData"] = image.jpegData(compressionQuality: 0.8)
}
}
do {
let data = try PropertyListSerialization.data(fromPropertyList: [appID: shareDic], format: .binary, options: 0)
UIPasteboard.general.setData(data, forPasteboardType: "content")
} catch let error as NSError {
log.error(error)
return
}
let urlString = String(format: "weixin://app/%@/sendreq/?", appID)
if let url = URL(string: urlString) {
_successBlock = success
_failBlock = fail
UIApplication.shared.openURL(url)
} else {
log.error("openURL 链接错误:" + urlString)
}
}
static func handleOpenURL(_ url: URL) -> Bool {
guard let scheme = url.scheme, scheme.hasPrefix("wx") else {
return false
}
if url.absoluteString.contains("://oauth"), let dic = url.queryParameters {
// 登录成功
guard let code = dic["code"] else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "授权返回信息缺少 code"])
_failBlock?(nil, error)
return true
}
log.info(["获取授权成功", dic])
getAccessToken(code: code)
} else if let contentData = UIPasteboard.general.data(forPasteboardType: "content"),
let contentDic = try! PropertyListSerialization.propertyList(from: contentData, options: [], format: nil) as? [String: Any],
let appID = appID,
let resultDic = contentDic[appID] as? [String: Any],
let resultStr = resultDic["result"] as? String,
let result = resultStr.toInt() {
if let state = resultDic["state"] as? String, state == kAuthState, result != 0 {
// 登录失败
let error = NSError(domain: kErrorDomain, code: result, userInfo: resultDic)
_failBlock?(resultDic, error)
return true
} else if result == 0 {
// 分享成功
_successBlock?(resultDic)
} else {
// 分享失败
let error = NSError(domain: kErrorDomain, code: result, userInfo: resultDic)
_failBlock?(resultDic, error)
}
}
return true
}
// MARK: - private methods
private static func checkEnvironment() -> Bool {
if appID == nil {
log.error("未设置微信 AppID")
return false
}
return true
}
private static func getAccessToken(code: String) {
let str = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%@&secret=%@&code=%@&grant_type=authorization_code"
let urlString = String(format: str, appID!, appSecret!, code)
guard let url = URL(string: urlString) else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "生成获取授权信息链接失败"])
_failBlock?(nil, error)
return
}
let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, _, error) in
if let err = error {
DispatchQueue.main.async {
_failBlock?(nil, err as NSError)
}
return
}
guard let resultData = data else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "获取授权信息未返回数据"])
DispatchQueue.main.async {
_failBlock?(nil, error)
}
return
}
do {
if let dic = try JSONSerialization.jsonObject(with: resultData, options: []) as? [String: Any] {
if let access_token = dic["access_token"] as? String,
let openid = dic["openid"] as? String {
getUserInfo(access_token: access_token, openid: openid)
} else {
let errorCode = dic["errcode"] as? Int ?? -1
let errorMessage = (dic["errmsg"] as? String) ?? "返回数据缺少 access_token 和 openid"
var newDic = dic
newDic[NSLocalizedDescriptionKey] = errorMessage
let error = NSError(domain: kErrorDomain, code: errorCode, userInfo: newDic)
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
} else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "解析授权信息 JSON 失败"])
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
} catch let error as NSError {
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
})
task.resume()
}
private static func getUserInfo(access_token: String, openid: String) {
let str = "https://api.weixin.qq.com/sns/userinfo?access_token=%@&openid=%@"
let urlString = String(format: str, access_token, openid)
guard let url = URL(string: urlString) else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "生成获取用户信息链接失败"])
_failBlock?(nil, error)
return
}
let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, _, error) in
if let err = error {
DispatchQueue.main.async {
_failBlock?(nil, err as NSError)
}
return
}
guard let resultData = data else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "获取用户信息未返回数据"])
DispatchQueue.main.async {
_failBlock?(nil, error)
}
return
}
do {
if let dic = try JSONSerialization.jsonObject(with: resultData, options: []) as? [String: Any] {
if dic["openid"] != nil {
DispatchQueue.main.async {
_successBlock?(dic)
}
} else {
let errorCode = dic["errcode"] as? Int ?? -1
let errorMessage = (dic["errmsg"] as? String) ?? "返回数据缺少 access_token、openid 和 unionid"
var newDic = dic
newDic[NSLocalizedDescriptionKey] = errorMessage
let error = NSError(domain: kErrorDomain, code: errorCode, userInfo: newDic)
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
} else {
let error = NSError(domain: kErrorDomain, code: -1, userInfo: [NSLocalizedDescriptionKey: "解析用户信息 JSON 失败"])
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
} catch let error as NSError {
DispatchQueue.main.async {
_failBlock?(nil, error)
}
}
})
task.resume()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment