import { IOS } from "cc/env"; import { native } from 'cc'; export interface IOSAuthResult { status: 'connected' | 'cancelled' | 'error'; isCancel: boolean; identityToken?: string; authorizationCode?: string; userId?: string; name?: string; email?: string; nonce?: string; reason?: string; } class IOSAuth { private listening = false; private seed = 0; private pending: { id: string; resolve: (result: IOSAuthResult) => void; timer: ReturnType } | null = null; init(): void { if (this.listening) return; native.jsbBridgeWrapper.addNativeEventListener('appleauth.response', payload => { let response: { requestId: string; data: IOSAuthResult }; try { response = JSON.parse(payload); } catch { return; } const pending = this.pending; if (!pending || response.requestId !== pending.id) return; clearTimeout(pending.timer); this.pending = null; pending.resolve(response.data); }); this.listening = true; } /** nonce 原样传给 Apple;生产环境建议使用后端预先生成并绑定本次登录的随机挑战。 */ async login(nonce?: string): Promise { const failure = (reason: string): IOSAuthResult => ({ status: 'error', isCancel: false, reason }); if (this.pending) return failure('Apple 登录正在进行中。'); if (nonce !== undefined && (!nonce.trim() || nonce.length > 512)) return failure('nonce 无效。'); try { this.init(); } catch (error) { return failure(String(error)); } const id = `${Date.now()}-${++this.seed}`; return new Promise(resolve => { const timer = setTimeout(() => { this.pending = null; resolve(failure('Apple 授权等待超时,请关闭系统授权窗口后重试。')); }, 180000); this.pending = { id, resolve, timer }; try { native.jsbBridgeWrapper.dispatchEventToNative('appleauth.request', JSON.stringify({ requestId: id, nonce })); } catch (error) { clearTimeout(timer); this.pending = null; resolve(failure(String(error))); } }); } } const iosAuth = IOS ? new IOSAuth : null; export default iosAuth;