修复微信授权无响应:authorize 改用 sendAuthReq:viewController:delegate:
H5 调 accreditlogin 后无反应。对照 daoqi msext 找到根因: msext NewRootVC.m → WXApiRequestHandler.m:sendAuthRequestScope: 用的是 `[WXApi sendAuthReq:req viewController:vc delegate:[WXApiManager sharedManager]]` (新版 SDK 2.x 推荐路径,传 viewController + delegate)。 而 ylgamehall 之前用 `WXApi.send(req)`——旧版 1.x 方法,新版头里已无声明, 不传 viewController(SDK 无法弹起微信 modal context)+ 不传 delegate (SDK 不知道往哪发回包)= H5 调了无反应。 修复: - authorize:改用 `WXApi.sendAuthReq(_:viewController:delegate:completion:)`, 传当前最顶层 VC(新增 topmostViewController() helper:connectedScenes → foregroundActive windowScene → keyWindow.rootVC → 穿过 presented / nav.visible) + self(WXApiDelegate)。completion 处理拉起失败立即 fail continuation。 - shareLink / shareImage:从旧 send 改新 `WXApi.send(_:completion:)` (sendReq:completion: 的 Swift 桥名)。分享回包仍由 SceneDelegate openURL → WXApi.handleOpen(url:delegate:WeChatManager.shared) → onResp 路径接收,不需要在 send 时再传 delegate。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
be09e6e697
commit
624dd93c65
@@ -34,8 +34,12 @@ public final class WeChatManager: NSObject {
|
|||||||
|
|
||||||
// MARK: - Authorize
|
// MARK: - Authorize
|
||||||
|
|
||||||
/// 拉起微信授权(msext 行为:state = "wechat_sdk" + scope = 4 项)
|
/// 拉起微信授权(msext NewRootVC.m → WXApiRequestHandler.m 同款路径)。
|
||||||
/// 返回的 code 可用 WeChatAuth.exchangeForUser 拿 7 字段用户信息。
|
/// 必须用新版 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 {
|
public func authorize() async throws -> WXAuthCodePayload {
|
||||||
#if canImport(WechatOpenSDK)
|
#if canImport(WechatOpenSDK)
|
||||||
let state = UUID().uuidString
|
let state = UUID().uuidString
|
||||||
@@ -44,13 +48,51 @@ public final class WeChatManager: NSObject {
|
|||||||
let req = SendAuthReq()
|
let req = SendAuthReq()
|
||||||
req.scope = Self.authScope
|
req.scope = Self.authScope
|
||||||
req.state = state
|
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
|
#else
|
||||||
throw WeChatError.sdkNotLinked
|
throw WeChatError.sdkNotLinked
|
||||||
#endif
|
#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
|
// MARK: - Share
|
||||||
|
|
||||||
public enum ShareScene {
|
public enum ShareScene {
|
||||||
@@ -103,7 +145,12 @@ public final class WeChatManager: NSObject {
|
|||||||
case .session: req.scene = Int32(WXSceneSession.rawValue)
|
case .session: req.scene = Int32(WXSceneSession.rawValue)
|
||||||
case .timeline: req.scene = Int32(WXSceneTimeline.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
|
#else
|
||||||
throw WeChatError.sdkNotLinked
|
throw WeChatError.sdkNotLinked
|
||||||
@@ -132,7 +179,12 @@ public final class WeChatManager: NSObject {
|
|||||||
case .session: req.scene = Int32(WXSceneSession.rawValue)
|
case .session: req.scene = Int32(WXSceneSession.rawValue)
|
||||||
case .timeline: req.scene = Int32(WXSceneTimeline.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
|
#else
|
||||||
throw WeChatError.sdkNotLinked
|
throw WeChatError.sdkNotLinked
|
||||||
|
|||||||
Reference in New Issue
Block a user