Files
flux-web/src/js/services/auth-flow.service.js

221 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 授权流程服务
* 处理多个 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<Object>} - 状态信息 { 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<Object>} - { 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<void>}
*/
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 };