/** * Mock API 服务器 — 模拟"余额不足"响应 * 用于测试 OpenClaw 是否能正确识别 errorHandling 条件并弹出充值网址 * * 启动: node scripts/mock-balance-server.js * 端点: POST http://localhost:3899/api/mock/skill * - 默认返回 { code: -2, msg: "余额不足,请充值后重试" } * - 加 ?mode=ok 返回 { code: 200, data: { workId: "mock123" } } * - 加 ?mode=unauth 返回 { code: 401, msg: "unauthorized token" } */ const http = require('http'); const PORT = 3899; const RESPONSES = { insufficient: { code: -2, msg: '余额不足,请充值后重试', message: '余额不足,请充值后重试' }, ok: { code: 200, data: { workId: 'mock_' + Date.now() } }, unauth: { code: 401, msg: 'unauthorized token invalid' } }; const server = http.createServer((req, res) => { // CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Parse-Application-Id'); if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; } const url = new URL(req.url, `http://localhost:${PORT}`); const mode = url.searchParams.get('mode') || 'insufficient'; const body = RESPONSES[mode] || RESPONSES.insufficient; console.log(`[${new Date().toISOString()}] ${req.method} ${req.url} => mode=${mode}`); console.log(` Response: ${JSON.stringify(body)}`); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(body)); }); server.listen(PORT, () => { console.log(`\n╔══════════════════════════════════════════════════════╗`); console.log(`║ Mock Balance Server 已启动 ║`); console.log(`╚══════════════════════════════════════════════════════╝`); console.log(`\n 余额不足: POST http://localhost:${PORT}/api/mock/skill`); console.log(` 正常响应: POST http://localhost:${PORT}/api/mock/skill?mode=ok`); console.log(` 未授权: POST http://localhost:${PORT}/api/mock/skill?mode=unauth`); console.log(`\n等待请求...\n`); });