diff --git a/ylgamehall/Source/SDK/WeChat/WeChatManager.swift b/ylgamehall/Source/SDK/WeChat/WeChatManager.swift index c2fdc4a..34cf52b 100644 --- a/ylgamehall/Source/SDK/WeChat/WeChatManager.swift +++ b/ylgamehall/Source/SDK/WeChat/WeChatManager.swift @@ -34,8 +34,12 @@ public final class WeChatManager: NSObject { // MARK: - Authorize - /// 拉起微信授权(msext 行为:state = "wechat_sdk" + scope = 4 项) - /// 返回的 code 可用 WeChatAuth.exchangeForUser 拿 7 字段用户信息。 + /// 拉起微信授权(msext NewRootVC.m → WXApiRequestHandler.m 同款路径)。 + /// 必须用新版 SDK 2.x 的 `sendAuthReq:viewController:delegate:completion:`: + /// - viewController = SDK 拉起微信回来时的 present 上下文(缺失则 SDK 无法弹起) + /// - delegate = SDK 弱引用,授权完成由 WXApiDelegate.onResp 回调(与 SceneDelegate + /// openURL 路径解耦,授权回包独立由 SDK 直接派给 delegate) + /// 旧版 1.x 的 `WXApi.send(req)` 已 deprecated,不传 vc/delegate 会导致 H5 调了无反应。 public func authorize() async throws -> WXAuthCodePayload { #if canImport(WechatOpenSDK) let state = UUID().uuidString @@ -44,13 +48,51 @@ public final class WeChatManager: NSObject { let req = SendAuthReq() req.scope = Self.authScope req.state = state - WXApi.send(req) + + guard let vc = Self.topmostViewController() else { + authPending.removeValue(forKey: state) + cont.resume(throwing: WeChatError.authFailed(-3)) + return + } + WXApi.sendAuthReq(req, viewController: vc, delegate: self) { [weak self] success in + // success = SDK 是否成功拉起微信 app;失败立刻 fail(如微信未安装、 + // URL Scheme 未配置等)。成功后真实回包由 onResp 路径处理。 + guard !success else { return } + Task { @MainActor in + guard let self else { return } + if let pending = self.authPending.removeValue(forKey: state) { + pending.resume(throwing: WeChatError.authFailed(-3)) + } + } + } } #else throw WeChatError.sdkNotLinked #endif } + /// 取当前最顶层 ViewController(含 presented / nav.visible),供微信 SDK 作为 + /// modal present 的上下文。msext 直接 self(gameController/NewRootVC),新外壳 + /// AccreditLoginHandler 是 stateless enum,由本方法 resolve。 + private static func topmostViewController() -> UIViewController? { + let windowScene = UIApplication.shared.connectedScenes + .compactMap { $0 as? UIWindowScene } + .first(where: { $0.activationState == .foregroundActive }) + ?? UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first + guard let root = windowScene?.windows.first(where: \.isKeyWindow)?.rootViewController + ?? windowScene?.windows.first?.rootViewController else { + return nil + } + var top: UIViewController = root + while let presented = top.presentedViewController { + top = presented + } + if let nav = top as? UINavigationController, let visible = nav.visibleViewController { + return visible + } + return top + } + // MARK: - Share public enum ShareScene { @@ -103,7 +145,12 @@ public final class WeChatManager: NSObject { case .session: req.scene = Int32(WXSceneSession.rawValue) case .timeline: req.scene = Int32(WXSceneTimeline.rawValue) } - WXApi.send(req) + // 分享回包路径:用户在微信操作后由 SceneDelegate.openURLContexts → + // WXApi.handleOpen(url:delegate:WeChatManager.shared) → onResp 到达, + // 故 sendReq 这里不需要再传 delegate;completion=nil 让拉起失败时 + // 不打扰 sharePending 队列(队列由 onResp 的 FIFO 消费)。 + // 新版 SDK 2.x `sendReq:completion:` 替代旧 `send:`(后者 deprecated)。 + WXApi.send(req, completion: nil) } #else throw WeChatError.sdkNotLinked @@ -132,7 +179,12 @@ public final class WeChatManager: NSObject { case .session: req.scene = Int32(WXSceneSession.rawValue) case .timeline: req.scene = Int32(WXSceneTimeline.rawValue) } - WXApi.send(req) + // 分享回包路径:用户在微信操作后由 SceneDelegate.openURLContexts → + // WXApi.handleOpen(url:delegate:WeChatManager.shared) → onResp 到达, + // 故 sendReq 这里不需要再传 delegate;completion=nil 让拉起失败时 + // 不打扰 sharePending 队列(队列由 onResp 的 FIFO 消费)。 + // 新版 SDK 2.x `sendReq:completion:` 替代旧 `send:`(后者 deprecated)。 + WXApi.send(req, completion: nil) } #else throw WeChatError.sdkNotLinked