/** * 微信服务号URL验证测试脚本 * * 功能: * 1. 模拟微信服务器发送GET请求验证URL * 2. 测试签名生成和验证逻辑 * 3. 验证服务端是否正确返回echostr */ import axios from 'axios'; import crypto from 'crypto'; import dotenv from 'dotenv'; import path from 'path'; import { fileURLToPath } from 'url'; // 获取当前文件目录 const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // 加载.env文件 dotenv.config({ path: path.resolve(__dirname, '../../../.env') }); const BASE_URL = process.env.API_BASE_URL || 'http://localhost:3001'; const TOKEN = process.env.WECHAT_MP_TOKEN || ''; console.log('🧪 微信服务号URL验证测试'); console.log('='.repeat(60)); console.log(''); // ==================== 1. 检查配置 ==================== if (!TOKEN) { console.error('❌ 未配置 WECHAT_MP_TOKEN,请检查 .env 文件'); process.exit(1); } console.log('📋 测试环境:'); console.log(` BASE_URL: ${BASE_URL}`); console.log(` TOKEN: ${TOKEN.substring(0, 10)}... (长度: ${TOKEN.length})`); console.log(''); // ==================== 2. 生成测试参数 ==================== console.log('🔧 生成测试参数...\n'); const timestamp = Date.now().toString(); const nonce = Math.random().toString(36).substring(2, 12); const echostr = 'test_echo_' + Math.random().toString(36).substring(2); console.log(' timestamp: ' + timestamp); console.log(` nonce: ${nonce}`); console.log(` echostr: ${echostr}\n`); // ==================== 3. 生成签名 ==================== console.log('🔐 生成签名...\n'); const arr = [TOKEN, timestamp, nonce].sort(); const str = arr.join(''); const signature = crypto.createHash('sha1').update(str).digest('hex'); console.log(` 排序后拼接: ${str.substring(0, 50)}...`); console.log(` SHA1哈希: ${signature}\n`); // ==================== 4. 发送GET请求 ==================== async function testUrlVerification() { console.log('📤 发送URL验证请求...\n'); const url = `${BASE_URL}/api/v1/iit/patient-wechat/callback`; console.log(` 请求URL: ${url}`); console.log(` 请求方法: GET`); console.log(` 查询参数:`); console.log(` signature: ${signature}`); console.log(` timestamp: ${timestamp}`); console.log(` nonce: ${nonce}`); console.log(` echostr: ${echostr}\n`); try { const response = await axios.get(url, { params: { signature, timestamp, nonce, echostr, }, timeout: 5000, }); console.log('='.repeat(60)); console.log('\n✅ URL验证成功!\n'); console.log(`HTTP状态码: ${response.status}`); console.log(`返回内容类型: ${response.headers['content-type']}`); console.log(`返回内容: ${response.data}\n`); // 验证返回内容 if (response.data === echostr) { console.log('✅ 返回的echostr正确,验证通过!\n'); console.log('='.repeat(60)); console.log('\n🎉 测试成功!您的服务端配置正确\n'); console.log('📝 后续步骤:'); console.log(' 1. 登录微信公众平台:https://mp.weixin.qq.com/'); console.log(' 2. 进入:设置与开发 → 基本配置 → 服务器配置'); console.log(' 3. 填写以下信息:'); console.log(` URL: ${BASE_URL}/api/v1/iit/patient-wechat/callback`); console.log(` Token: ${TOKEN}`); console.log(` EncodingAESKey: ${process.env.WECHAT_MP_ENCODING_AES_KEY?.substring(0, 10)}...`); console.log(' 4. 选择"安全模式"'); console.log(' 5. 点击"提交"进行验证'); console.log(' 6. 验证成功后点击"启用"'); console.log(''); } else { console.error('❌ 返回的echostr不正确!'); console.error(` 期望: ${echostr}`); console.error(` 实际: ${response.data}\n`); process.exit(1); } } catch (error: any) { console.log('='.repeat(60)); console.error('\n❌ URL验证失败\n'); if (error.code === 'ECONNREFUSED') { console.error('连接被拒绝,可能的原因:'); console.error(' 1. 后端服务未启动'); console.error(' 2. 端口号不正确'); console.error('\n解决方法:'); console.error(' 1. 运行 npm run dev 启动后端服务'); console.error(' 2. 确认服务运行在正确的端口(默认3001)'); } else if (error.response) { console.error(`HTTP状态码: ${error.response.status}`); console.error(`错误信息: ${error.response.statusText}`); console.error(`响应内容: ${JSON.stringify(error.response.data, null, 2)}`); if (error.response.status === 403) { console.error('\n可能的原因:'); console.error(' 1. Token配置不一致'); console.error(' 2. 签名验证失败'); console.error('\n解决方法:'); console.error(' 1. 检查 .env 文件中的 WECHAT_MP_TOKEN'); console.error(' 2. 运行配置检查脚本:'); console.error(' npx tsx src/modules/iit-manager/test-patient-wechat-config.ts'); } else if (error.response.status === 404) { console.error('\n可能的原因:'); console.error(' 1. 路由未注册'); console.error(' 2. URL路径不正确'); console.error('\n解决方法:'); console.error(' 1. 确认路由已在 routes/index.ts 中注册'); console.error(' 2. 检查URL路径是否正确'); } } else { console.error(`错误信息: ${error.message}`); } console.error('\n'); process.exit(1); } } // ==================== 5. 执行测试 ==================== (async () => { try { await testUrlVerification(); } catch (error: any) { console.error('测试执行异常:', error.message); process.exit(1); } })();