export const initialBindingState = () => ({ ready: false, enabled: false, bound: false, subscribed: false, busy: false, sessionId: '', sessionStatus: '', sessionSubscribed: false, verificationCode: '', error: '' }) export function createWechatBindingFlow({ state, api, getSessionKey, isActive, openAuthorization }) { let owner = '', revision = 0 const cancel = () => { revision++; state.busy = false } const clearSession = () => { state.sessionId = ''; state.sessionStatus = ''; state.sessionSubscribed = false; state.verificationCode = '' } const run = async (operation) => { const key = getSessionKey() if (owner !== key) { cancel() Object.assign(state, initialBindingState()) owner = key } if (!key || !isActive() || state.busy) return const version = ++revision const current = () => version === revision && isActive() && getSessionKey() === key state.busy = true state.error = '' try { await operation(current) } catch (error) { if (current()) state.error = error?.message || '绑定操作失败,请重试' } finally { if (current()) state.busy = false } } const refresh = () => run(async (current) => { state.ready = false const status = await api.status() if (!current()) return Object.assign(state, status, { ready: true }) if (!status.enabled || status.bound) { clearSession(); return } if (!state.sessionId) return const session = await api.session(state.sessionId) if (!current()) return if (session.status === 'expired') { clearSession() state.error = '授权会话已过期,请重新绑定' return } state.sessionStatus = session.status state.sessionSubscribed = session.subscribed state.verificationCode = session.verificationCode || '' if (session.status !== 'scanned') return if (!session.subscribed) { state.error = '请先关注服务号,再重新授权绑定' return } // 仅确认本页面由当前登录用户主动发起的会话;回调网页不持有登录令牌。 const result = await api.confirm(state.sessionId) if (!current()) return if (!result.bound || !result.subscribed) throw new Error('绑定未完成,请刷新状态后重试') Object.assign(state, result) clearSession() }) const start = () => run(async (current) => { if (!state.ready || !state.enabled || state.bound) return clearSession() const session = await api.start() if (!current()) return state.sessionId = session.sessionId state.sessionStatus = 'waiting' await openAuthorization(session.authorizeUrl) }) return { refresh, start, cancel } }