/** * 授权流程服务 * 处理多个 H5 授权页面的逐个加载、轮询检测、超时控制和最终跳转 */ import { ApiClient } from '../core/api.js'; import { API_CONFIG } from '../config/index.js'; // 授权状态常量 const AUTH_STATUS = { WAITING: 1, // 等待授权 CALLBACK: 2, // 已回调 APPLY_OK: 3, // 进件成功 APPLY_FAIL: 4 // 进件失败 }; export class AuthFlowService { // 配置常量 static POLL_INTERVAL = 3000; // 轮询间隔:3秒 static POLL_TIMEOUT = 10 * 60 * 1000; // 超时时间:10分钟 static COUNTDOWN_SECONDS = 5; // 倒计时:5秒 /** * 检查单个 API 的授权状态 * @param {number} formdataid - 表单数据ID * @param {string} apicode - API编码 * @returns {Promise} - 状态信息 { apicode, apiname, status, h5url } */ static async checkAuthStatus(formdataid, apicode) { try { const response = await ApiClient.xpost(API_CONFIG.ENDPOINTS.CHECK_AUTH_STATUS, { formdataid, apicode }); if (response.retcode === 0 && response.result) { return response.result; } console.warn('[AuthFlowService] 检查授权状态失败:', response.retinfo); return null; } catch (error) { console.error('[AuthFlowService] 检查授权状态出错:', error); return null; } } /** * 等待授权完成(轮询) * @param {number} formdataid - 表单数据ID * @param {string} apicode - API编码 * @param {Function} onStatusChange - 状态变化回调 * @returns {Promise} - { success: boolean, status: number, timeout: boolean } */ static async waitForAuth(formdataid, apicode, onStatusChange) { const startTime = Date.now(); while (true) { // 检查超时 if (Date.now() - startTime > this.POLL_TIMEOUT) { console.log('[AuthFlowService] 轮询超时:', apicode); return { success: false, status: AUTH_STATUS.WAITING, timeout: true }; } // 查询状态 const result = await this.checkAuthStatus(formdataid, apicode); if (result) { // 通知状态变化 if (onStatusChange) { onStatusChange(result); } // 状态 >= 2 表示已回调/成功/失败,可以进入下一个 if (result.status >= AUTH_STATUS.CALLBACK) { return { success: result.status === AUTH_STATUS.CALLBACK || result.status === AUTH_STATUS.APPLY_OK, status: result.status, timeout: false }; } } // 等待下次轮询 await this.sleep(this.POLL_INTERVAL); } } /** * 执行授权流程 * @param {number} formdataid - 表单数据ID * @param {Array} h5Urls - H5 URL 列表 [{ apicode, apiname, h5url }] * @param {Object} callbacks - 回调函数集合 * - onStart(item, index) - 开始处理某个产品 * - onProgress(item, index, status) - 状态更新 * - onComplete(item, index, result) - 单个产品完成 * - onAllComplete() - 全部完成 * - onIframeChange(url) - iframe 需要切换 URL * @returns {Promise} */ static async startAuthFlow(formdataid, h5Urls, callbacks = {}) { const { onStart, onProgress, onComplete, onAllComplete, onIframeChange } = callbacks; console.log('[AuthFlowService] 开始授权流程, formdataid:', formdataid, 'h5Urls:', h5Urls); for (let i = 0; i < h5Urls.length; i++) { const item = h5Urls[i]; console.log('[AuthFlowService] 处理第', i + 1, '个产品:', item.apiname); // 通知开始处理 if (onStart) { onStart(item, i); } // 切换 iframe if (onIframeChange && item.h5url) { onIframeChange(item.h5url); } // 轮询等待授权完成 const result = await this.waitForAuth(formdataid, item.apicode, (status) => { if (onProgress) { onProgress(item, i, status); } }); console.log('[AuthFlowService] 产品授权结果:', item.apiname, result); // 通知单个完成 if (onComplete) { onComplete(item, i, result); } } // 全部完成 console.log('[AuthFlowService] 全部授权流程完成'); if (onAllComplete) { onAllComplete(); } } /** * 开始倒计时 * @param {number} seconds - 倒计时秒数 * @param {Function} onTick - 每秒回调,参数为剩余秒数 * @param {Function} onComplete - 倒计时完成回调 * @returns {Function} - 取消函数 */ static startCountdown(seconds, onTick, onComplete) { let remaining = seconds; let cancelled = false; const tick = () => { if (cancelled) return; if (onTick) { onTick(remaining); } if (remaining <= 0) { if (onComplete) { onComplete(); } return; } remaining--; setTimeout(tick, 1000); }; tick(); // 返回取消函数 return () => { cancelled = true; }; } /** * 跳转到目标页面 * @param {string} url - 目标 URL */ static redirect(url) { if (url) { window.location.href = url; } } /** * 辅助函数:延时 * @param {number} ms - 毫秒 * @returns {Promise} */ static sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * 获取状态文本 * @param {number} status - 状态码 * @returns {string} */ static getStatusText(status) { switch (status) { case AUTH_STATUS.WAITING: return '等待授权'; case AUTH_STATUS.CALLBACK: return '已完成'; case AUTH_STATUS.APPLY_OK: return '授权成功'; case AUTH_STATUS.APPLY_FAIL: return '授权失败'; default: return '未知状态'; } } } // 导出状态常量 export { AUTH_STATUS };