完善:多步 H5 授权流程
This commit is contained in:
220
src/js/services/auth-flow.service.js
Normal file
220
src/js/services/auth-flow.service.js
Normal 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 };
|
||||
Reference in New Issue
Block a user