diff --git a/lib/channel/weixin.js b/lib/channel/weixin.js index cc36e97..786d4f0 100644 --- a/lib/channel/weixin.js +++ b/lib/channel/weixin.js @@ -7,18 +7,14 @@ * Requires Node.js >= 18 (global fetch). * * method: login - * params : { callId, timeout, emit, onReplyRef } - * returns: { abort, onReply } + * params : { callId, timeout, emit } + * returns: { abort } * * emit(payload) sends a sys-call reply upstream: - * { action:'event', event:'qrcode', data:{ url, expire:30, index } } - * { action:'event', event:'need_verifycode', data:{ retry } } - * { action:'progress', event:'scanned', data:{ status:'waiting_confirm' } } - * { action:'finish', event:'success', data:{ accountId } } - * { action:'finish', event:'failed', code, message } - * - * To provide a verify code after 'need_verifycode', the upstream dispatcher - * should call the returned onReply({ data: { code: '1234' } }). + * { action:'event', event:'qrcode', data:{ url, expire:30, index } } + * { action:'progress', event:'scanned', data:{ status:'waiting_confirm' } } + * { action:'finish', event:'success', data:{ accountId } } + * { action:'finish', event:'failed', code, message } */ const crypto = require('crypto'); @@ -227,10 +223,9 @@ async function _fetchQRCode(botType) { return data; } -async function _pollQRStatus(apiBaseUrl, qrcode, verifyCode) { +async function _pollQRStatus(apiBaseUrl, qrcode) { try { - let endpoint = `ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`; - if (verifyCode) endpoint += `&verify_code=${encodeURIComponent(verifyCode)}`; + const endpoint = `ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`; const data = await _getJson(apiBaseUrl, endpoint, QR_LONG_POLL_TIMEOUT_MS); if (data.ret !== undefined && data.ret !== 0) { throw new Error(`get_qrcode_status ret=${data.ret} errmsg=${data.errmsg || ''}`); @@ -279,47 +274,15 @@ function login({ callId, timeout = 180, botType = DEFAULT_BOT_TYPE, emit }) { let aborted = false; let finished = false; - // Pending verify-code: resolve/reject - let _pendingVerifyResolve = null; - let _pendingVerifyReject = null; - - function _waitForVerifyCode() { - return new Promise((resolve, reject) => { - _pendingVerifyResolve = resolve; - _pendingVerifyReject = reject; - }); - } - - function onReply(msg) { - const event = (msg.event || '').toString(); - const code = (msg.data && msg.data.code) ? String(msg.data.code).trim() : ''; - if (event === 'verify_code' && _pendingVerifyResolve) { - log.info('weixin', `callId=${callId} verify_code received`); - const resolve = _pendingVerifyResolve; - _pendingVerifyResolve = null; - _pendingVerifyReject = null; - resolve(code); - } - } - function abort() { aborted = true; - if (_pendingVerifyReject) { - const reject = _pendingVerifyReject; - _pendingVerifyResolve = null; - _pendingVerifyReject = null; - reject(new Error('aborted')); - } log.info('weixin', `callId=${callId} aborted`); } const timeoutMs = Math.max(timeout * 1000, 30_000); // Run async without blocking caller - _runLogin({ callId, timeoutMs, botType, emit, - isAborted: () => aborted, - waitForVerifyCode: _waitForVerifyCode, - }) + _runLogin({ callId, timeoutMs, botType, emit, isAborted: () => aborted }) .then(() => { finished = true; }) .catch((err) => { if (finished) return; @@ -328,10 +291,10 @@ function login({ callId, timeout = 180, botType = DEFAULT_BOT_TYPE, emit }) { emit({ action: 'finish', event: 'failed', code: 500, message: err.message }); }); - return { abort, onReply }; + return { abort }; } -async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForVerifyCode }) { +async function _runLogin({ callId, timeoutMs, botType, emit, isAborted }) { let qrRefreshCount = 1; let scannedEmitted = false; let activeLogin = null; @@ -344,8 +307,7 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV qrcode: qrData.qrcode, qrcodeUrl: qrData.qrcode_img_content, startedAt: Date.now(), - apiBaseUrl: FIXED_BASE_URL, - pendingVerify: null, + apiBaseUrl: FIXED_BASE_URL, }; emit({ action: 'event', @@ -366,18 +328,12 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV emit({ action: 'finish', event: 'failed', code: 1003, message: 'QR expired too many times' }); return; } - await startOrRefreshQr(); - scannedEmitted = false; - activeLogin.pendingVerify = null; - continue; + await startOrRefreshQr(); + scannedEmitted = false; + continue; } - const status = await _pollQRStatus( - activeLogin.apiBaseUrl, - activeLogin.qrcode, - activeLogin.pendingVerify - ); - activeLogin.pendingVerify = null; // consumed + const status = await _pollQRStatus(activeLogin.apiBaseUrl, activeLogin.qrcode); if (isAborted()) return; @@ -399,18 +355,10 @@ async function _runLogin({ callId, timeoutMs, botType, emit, isAborted, waitForV } case 'need_verifycode': { - const retry = !!activeLogin.pendingVerify; - emit({ action: 'event', event: 'need_verifycode', data: { retry } }); - log.info('weixin', `callId=${callId} need_verifycode (retry=${retry})`); - try { - const code = await waitForVerifyCode(); - if (isAborted()) return; - activeLogin.pendingVerify = code; - } catch (_) { - // aborted while waiting - return; - } - break; + // Verify code entry not supported; treat as failure + log.warn('weixin', `callId=${callId} need_verifycode not supported`); + emit({ action: 'finish', event: 'failed', code: 1005, message: 'verify code required (not supported)' }); + return; } case 'expired': { diff --git a/lib/sys-call.js b/lib/sys-call.js index 45d208d..d2db635 100644 --- a/lib/sys-call.js +++ b/lib/sys-call.js @@ -8,12 +8,10 @@ * Supported actions (incoming from VPS): * request — start a new task * cancel — abort a running task - * reply — forward input to a running task (e.g. verify code) * * Handler interface: - * handler[method](params) → { abort, onReply? } - * abort() — called on cancel - * onReply(msg) — called on reply (optional) + * handler[method](params) → { abort } | function + * abort() — called on cancel */ const log = require('./logger'); @@ -54,18 +52,6 @@ function handle(msg, send) { return; } - // ── reply (e.g. verify code from frontend) ──────────────────────────────── - if (action === 'reply') { - const task = running.get(callId); - if (task && typeof task.onReply === 'function') { - log.info('sys-call', `reply callId=${callId} event=${msg.event || ''}`); - try { task.onReply(msg); } catch (e) { log.warn('sys-call', `onReply error: ${e.message}`); } - } else { - log.debug('sys-call', `reply for unknown/no-onReply callId=${callId}`); - } - return; - } - // ── request ─────────────────────────────────────────────────────────────── if (action !== 'request') { log.warn('sys-call', `unexpected action=${action} callId=${callId}`); @@ -107,7 +93,7 @@ function handle(msg, send) { return; } - // Normalise: handler may return a function (abort only) or { abort, onReply } + // Normalise: handler may return a function (abort only) or { abort } if (typeof task === 'function') { task = { abort: task }; }