完善:多步 H5 授权流程

This commit is contained in:
2026-01-25 19:01:17 +08:00
parent 0f90faa595
commit d1b2388616
6 changed files with 689 additions and 90 deletions

View File

@@ -0,0 +1,220 @@
/**
* 授权流程服务
* 处理多个 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 };