PQThirdPlatformUtil.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //
  2. // PQThirdPlatformUtil.swift
  3. // PQSpeed
  4. //
  5. // Created by SanW on 2020/5/30.
  6. // Copyright © 2020 BytesFlow. All rights reserved.
  7. //
  8. import Kingfisher
  9. import UIKit
  10. import UserNotifications
  11. import WechatOpenSDK
  12. // MARK: - 微信相关工具类
  13. /// 微信相关工具类
  14. // 初始化微信要使用的参数 e.g.
  15. /*
  16. let state: String = "com.piaoquan.pqspeed"
  17. let appid: String = "wxfc2fc07ab379e4bf"
  18. let secret: String = "06f696424accb17b7234dce32e4821b4"
  19. let universalLink: String = "https://speed.piaoquantv.com/"
  20. let scope = "snsapi_userinfo"
  21. */
  22. public class WXApiInfo: NSObject {
  23. public var state: String = ""
  24. public var appid: String = ""
  25. public var secret: String = ""
  26. public var universalLink: String = ""
  27. public var scope = ""
  28. }
  29. public class PQSingletoWXApiUtil: NSObject {
  30. public static let shared = PQSingletoWXApiUtil()
  31. var openId: String? // openID
  32. // 回调
  33. public var wxApiUtilHander: ((_ userData: [String: Any]?, _ errorMsg: String?) -> Void)?
  34. var mAppInfo: WXApiInfo = WXApiInfo()
  35. public func registerApp(appInfo: WXApiInfo?) {
  36. if appInfo == nil {
  37. return
  38. }
  39. mAppInfo = appInfo!
  40. #if DEBUG
  41. WXApi.startLog(by: .detail) { msg in
  42. BFLog(message: "微信回调Log--\(msg)")
  43. }
  44. #endif
  45. WXApi.registerApp(mAppInfo.appid, universalLink: mAppInfo.universalLink)
  46. // #if DEBUG
  47. // WXApi.checkUniversalLinkReady { step, result in
  48. // BFLog(message: "微信回调自检--\(step),result = \(result)")
  49. // }
  50. // #endif
  51. }
  52. public func handleOpen(url: URL) -> Bool {
  53. return WXApi.handleOpen(url, delegate: self)
  54. }
  55. public func handleOpenUniversalLink(userActivity: NSUserActivity) -> Bool {
  56. return WXApi.handleOpenUniversalLink(userActivity, delegate: self)
  57. }
  58. public func authorize() -> PQSingletoWXApiUtil {
  59. if !isInstallWX() {
  60. if wxApiUtilHander != nil {
  61. wxApiUtilHander!(nil, "您还未安装微信客户端!")
  62. }
  63. return .shared
  64. }
  65. let req = SendAuthReq()
  66. req.scope = mAppInfo.scope
  67. req.state = mAppInfo.state
  68. WXApi.send(req) { [weak self] isSuccess in
  69. if !isSuccess {
  70. self?.wxApiUtilHander!(nil, "您还未安装微信客户端!")
  71. }
  72. }
  73. return .shared
  74. }
  75. /// 分享
  76. /// - Parameters:
  77. /// - type: 类型 1- 分享视频 2-分享活动 3-分享卡点视频
  78. /// - scene: 场景
  79. /// - title: 标题
  80. /// - description:描述
  81. /// - imageUrl: 图片url
  82. /// - path: 网页地址
  83. /// - videoId: 视频ID type == 1时不为空
  84. /// - pageSource: 页面pageSource type == 1时不为空
  85. /// - Returns: <#description#>
  86. public func share(type: Int = 1, scene: Int32, shareWeappRawId: String? = nil, title: String?, description: String?, imageUrl: String?, path: String?, videoId: String, pageSource: PAGESOURCE, shareId: String) -> PQSingletoWXApiUtil {
  87. if !isInstallWX() {
  88. if wxApiUtilHander != nil {
  89. wxApiUtilHander!(nil, "您还未安装微信客户端!")
  90. }
  91. return .shared
  92. }
  93. let message = WXMediaMessage()
  94. message.title = title ?? ""
  95. message.description = description ?? ""
  96. ImageDownloader.default.downloadImage(with: URL(string: imageUrl ?? "")!, options: nil) { result in
  97. switch result {
  98. case let .success(imageResult):
  99. message.thumbData = zipImage(image: imageResult.image, size: 64)
  100. if type == 1 || type == 3, scene == Int32(WXSceneSession.rawValue) {
  101. let wxMiniObject = WXMiniProgramObject()
  102. wxMiniObject.miniProgramType = PQENVUtil.shared.envMode == .ENVModeOnline ? .release : .test
  103. wxMiniObject.userName = shareWeappRawId ?? cShareWeappRawId
  104. var preParams: String = ""
  105. var page: String = ""
  106. var isRhythmVideo = 0
  107. if type == 3 {
  108. preParams = "package-point/show/show"
  109. page = "pages/post/post"
  110. isRhythmVideo = 1
  111. } else {
  112. preParams = "user-videos"
  113. page = "pages/category"
  114. isRhythmVideo = 0
  115. }
  116. var params = (preParams + "?id=\(videoId)&tp=share&rootPageSource=\(pageSource.rawValue)&shareDepth=1&rootLaunchShareId=\(shareId)&parentShareId=\(shareId)&shareId=\(shareId)&shareAppType=13&mid=\(getMachineCode())&su=\(BFLoginUserInfo.shared.uid)&isRhythmVideo=\(isRhythmVideo)").addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
  117. ["/", "=", "?", "&"].forEach { char in
  118. let custom = CharacterSet(charactersIn: char).inverted
  119. params = params?.addingPercentEncoding(withAllowedCharacters: custom) ?? ""
  120. }
  121. wxMiniObject.path = "\(page)?jumpPage=" + (params ?? "")
  122. wxMiniObject.webpageUrl = "https://piaoquan.yishihui.com/"
  123. wxMiniObject.hdImageData = message.thumbData
  124. message.mediaObject = wxMiniObject
  125. } else {
  126. let webpageObject = WXWebpageObject()
  127. webpageObject.webpageUrl = path ?? ""
  128. message.mediaObject = webpageObject
  129. }
  130. let req = SendMessageToWXReq()
  131. req.message = message
  132. req.scene = scene
  133. WXApi.send(req) { [weak self] isSuccess in
  134. if self?.wxApiUtilHander != nil {
  135. self?.wxApiUtilHander!(nil, isSuccess ? "分享成功~" : "分享失败了~")
  136. }
  137. }
  138. case let .failure(error):
  139. BFLog(message: "下载图片失败:\(error.localizedDescription)")
  140. }
  141. }
  142. return .shared
  143. return .shared
  144. }
  145. /// 处理发起数据
  146. /// - Parameter response: <#response description#>
  147. /// - Returns: <#description#>
  148. public func dealWithPayParams(response: [String: Any]) -> PQSingletoWXApiUtil {
  149. var partnerid: String = ""
  150. var prepayId: String = ""
  151. var nonceStr: String = ""
  152. var timeStamp: UInt32 = 0
  153. var package: String = "Sign=WXPay"
  154. var sign: String = ""
  155. if response.keys.contains("partnerid") {
  156. partnerid = response["partnerid"] as! String
  157. }
  158. if response.keys.contains("prepayid") {
  159. prepayId = response["prepayid"] as! String
  160. }
  161. if response.keys.contains("noncestr") {
  162. nonceStr = response["noncestr"] as! String
  163. }
  164. if response.keys.contains("timestamp") {
  165. timeStamp = UInt32(Int("\(response["timestamp"] ?? "0")") ?? 0)
  166. }
  167. if response.keys.contains("package") {
  168. package = response["package"] as! String
  169. }
  170. if response.keys.contains("sign") {
  171. sign = response["sign"] as! String
  172. }
  173. requestPayReq(partnerid: partnerid, prepayId: prepayId, nonceStr: nonceStr, timeStamp: timeStamp, package: package, sign: sign)
  174. return .shared
  175. }
  176. /// 发起
  177. /// - Parameters:
  178. /// - partnerid: 商家向财付通申请的商家id
  179. /// - prepayId: 预
  180. /// - nonceStr: 随机串,防重发
  181. /// - timeStamp: 时间戳,防重发
  182. /// - package: 商家根据财付通文档填写的数据和签名
  183. /// - sign: 商家根据微信开放平台文档对数据做的签名
  184. /// - Returns: <#description#>
  185. public func requestPayReq(partnerid: String, prepayId: String, nonceStr: String, timeStamp: UInt32, package: String, sign: String) {
  186. // 调起微信
  187. let payReq: PayReq = PayReq()
  188. payReq.partnerId = partnerid
  189. payReq.prepayId = prepayId
  190. payReq.nonceStr = nonceStr
  191. payReq.timeStamp = timeStamp
  192. payReq.package = package
  193. payReq.sign = sign
  194. WXApi.send(payReq) { _ in
  195. }
  196. }
  197. /// 是否安装了微信
  198. /// - Returns: <#description#>
  199. public func isInstallWX() -> Bool {
  200. return UIApplication.shared.canOpenURL(URL(string: "weixin://")!)
  201. }
  202. override private init() {
  203. super.init()
  204. }
  205. override public func copy() -> Any {
  206. return self
  207. }
  208. override public func mutableCopy() -> Any {
  209. return self
  210. }
  211. }
  212. extension PQSingletoWXApiUtil: WXApiDelegate {
  213. public func onReq(_ req: BaseReq) {
  214. BFLog(message: "微信回调拉起 -- \(req)")
  215. if req.isKind(of: LaunchFromWXReq.self) && ((req as! LaunchFromWXReq).message.messageExt?.count ?? 0) > 0 {
  216. BFLog(message: "小程序回调数据--\(String(describing: (req as! LaunchFromWXReq).message.messageExt))")
  217. // PQBoardCommandUtil.dealWithPasteboardData(messageExt: (req as! LaunchFromWXReq).message.messageExt)
  218. }
  219. }
  220. public func onResp(_ resp: BaseResp) {
  221. BFLog(message: "微信回调返回 -- \(resp)")
  222. if resp.isKind(of: SendAuthResp.self) {
  223. if (resp as! SendAuthResp).state == mAppInfo.state {
  224. accessToken(code: (resp as! SendAuthResp).code!)
  225. } else {
  226. if wxApiUtilHander != nil {
  227. wxApiUtilHander!(nil, "网络不可用")
  228. }
  229. }
  230. } else if resp.isKind(of: PayResp.self) {
  231. if wxApiUtilHander != nil {
  232. wxApiUtilHander!(["returnKey": (resp as! PayResp).returnKey, "code": resp.errCode], resp.errStr)
  233. }
  234. }
  235. }
  236. public func accessToken(code: String) {
  237. let url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=\(mAppInfo.appid)&secret=\(mAppInfo.secret)&code=\(code)&grant_type=authorization_code"
  238. DispatchQueue.global(qos: .userInitiated).async { [weak self] in
  239. let zoneStr = try? String(contentsOf: URL(string: url)!, encoding: .utf8)
  240. if zoneStr == nil {
  241. if self?.wxApiUtilHander != nil {
  242. self?.wxApiUtilHander!(nil, "授权失败了~")
  243. }
  244. return
  245. }
  246. let data = zoneStr!.data(using: .utf8)
  247. let dict: [String: Any] = try! JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: Any]
  248. self?.openId = "\(dict["openid"] ?? "")"
  249. BFLoginUserInfo.shared.openId = self?.openId ?? ""
  250. let access_token: String = "\(dict["access_token"] ?? "")"
  251. let userUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=\(access_token)&openid=\(self?.openId ?? "")"
  252. DispatchQueue.global(qos: .userInitiated).async {
  253. let userInfoStr = try? String(contentsOf: URL(string: userUrl)!, encoding: .utf8)
  254. let userInfoData = userInfoStr!.data(using: .utf8)
  255. let userDict: [String: Any] = try! JSONSerialization.jsonObject(with: userInfoData!, options: .mutableContainers) as! [String: Any]
  256. DispatchQueue.main.async { [weak self] in
  257. if userDict.count > 0 {
  258. if self?.wxApiUtilHander != nil {
  259. self?.wxApiUtilHander!(userDict, nil)
  260. }
  261. } else {
  262. if self?.wxApiUtilHander != nil {
  263. self?.wxApiUtilHander!(nil, "授权失败了~")
  264. }
  265. }
  266. }
  267. }
  268. }
  269. }
  270. }