将扫码页提升到列表层弹出并补齐 AppDelegate.window,避免扫码时 UIKit 取主窗口崩溃;Toast 改用独立 UIWindow 显示在 sheet 之上;合作获客员支持短信验证修改分成比例,同时优化冷启动根视图创建时机并补充相关测试。 Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
3.5 KiB
Swift
120 lines
3.5 KiB
Swift
//
|
||
// WeChatManager.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
import WechatOpenSDK
|
||
|
||
/// 微信 SDK 生命周期与回调管理,负责注册、URL/Universal Link 回跳及分享结果分发。
|
||
@MainActor
|
||
final class WeChatManager: NSObject {
|
||
static let shared = WeChatManager()
|
||
|
||
/// 最近一次分享结果,供 UI 监听。
|
||
private(set) var lastShareResult: WeChatShareResult?
|
||
|
||
private var shareCompletion: ((WeChatShareResult) -> Void)?
|
||
private var isRegistered = false
|
||
|
||
private override init() {
|
||
super.init()
|
||
}
|
||
|
||
/// 向微信注册 AppID 与 Universal Link,应用启动时调用。
|
||
func registerIfNeeded() {
|
||
guard !isRegistered else { return }
|
||
guard WeChatConfig.validateUniversalLink(WeChatConfig.universalLink) else {
|
||
assertionFailure("WeChat Universal Link 必须以 https 开头并以 / 结尾")
|
||
return
|
||
}
|
||
|
||
// #if DEBUG
|
||
// WXApi.startLog(by: WXLogLevel.detail) { log in
|
||
// print("WeChatSDK: \(log)")
|
||
// }
|
||
// #endif
|
||
|
||
let success = WXApi.registerApp(WeChatConfig.appID, universalLink: WeChatConfig.universalLink)
|
||
isRegistered = success
|
||
|
||
// #if DEBUG
|
||
// if success {
|
||
// checkUniversalLinkReady()
|
||
// }
|
||
// #endif
|
||
}
|
||
|
||
/// 处理 URL Scheme 回调。
|
||
@discardableResult
|
||
func handleOpenURL(_ url: URL) -> Bool {
|
||
WXApi.handleOpen(url, delegate: self)
|
||
}
|
||
|
||
/// 处理 Universal Link 回调。
|
||
@discardableResult
|
||
func handleContinueUserActivity(_ userActivity: NSUserActivity) -> Bool {
|
||
WXApi.handleOpenUniversalLink(userActivity, delegate: self)
|
||
}
|
||
|
||
/// 注册单次分享完成回调。
|
||
func setShareCompletion(_ completion: ((WeChatShareResult) -> Void)?) {
|
||
shareCompletion = completion
|
||
}
|
||
|
||
/// 发送分享请求到微信。
|
||
func sendShareRequest(_ request: SendMessageToWXReq, completion: ((WeChatShareResult) -> Void)? = nil) {
|
||
guard WXApi.isWXAppInstalled() else {
|
||
let result = WeChatShareResult.notInstalled
|
||
completion?(result)
|
||
return
|
||
}
|
||
guard WXApi.isWXAppSupport() else {
|
||
let result = WeChatShareResult.unsupported
|
||
completion?(result)
|
||
return
|
||
}
|
||
|
||
if let completion {
|
||
shareCompletion = completion
|
||
}
|
||
|
||
WXApi.send(request) { success in
|
||
if !success {
|
||
Task { @MainActor in
|
||
self.finishShare(with: .sendFailed(-1))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#if DEBUG
|
||
/// 调试 Universal Link 配置,仅 DEBUG 环境调用。
|
||
private func checkUniversalLinkReady() {
|
||
WXApi.checkUniversalLinkReady { step, result in
|
||
print("WeChat UL check step=\(step.rawValue) success=\(result.success) info=\(result.errorInfo ?? "") suggestion=\(result.suggestion ?? "")")
|
||
}
|
||
}
|
||
#endif
|
||
|
||
private func finishShare(with result: WeChatShareResult) {
|
||
lastShareResult = result
|
||
shareCompletion?(result)
|
||
shareCompletion = nil
|
||
}
|
||
}
|
||
|
||
extension WeChatManager: WXApiDelegate {
|
||
nonisolated func onReq(_ req: BaseReq) {
|
||
// 分享模块暂不处理来自微信的主动请求。
|
||
}
|
||
|
||
nonisolated func onResp(_ resp: BaseResp) {
|
||
guard let shareResp = resp as? SendMessageToWXResp else { return }
|
||
let result = WeChatShareResult.fromWXErrorCode(shareResp.errCode)
|
||
Task { @MainActor in
|
||
self.finishShare(with: result)
|
||
}
|
||
}
|
||
}
|