Sprint 1-3 Completed (Backend + Frontend): Backend (Sprint 1-2): - Implement 5-layer Agent framework (Query->Planner->Executor->Tools->Reflection) - Create agent_schema with 6 tables (agent_definitions, stages, prompts, sessions, traces, reflexion_rules) - Create protocol_schema with 2 tables (protocol_contexts, protocol_generations) - Implement Protocol Agent core services (Orchestrator, ContextService, PromptBuilder) - Integrate LLM service adapter (DeepSeek/Qwen/GPT-5/Claude) - 6 API endpoints with full authentication - 10/10 API tests passed Frontend (Sprint 3): - Add Protocol Agent entry in AgentHub (indigo theme card) - Implement ProtocolAgentPage with 3-column layout - Collapsible sidebar (Gemini style, 48px <-> 280px) - StatePanel with 5 stage cards (scientific_question, pico, study_design, sample_size, endpoints) - ChatArea with sync button and action cards integration - 100% prototype design restoration (608 lines CSS) - Detailed endpoints structure: baseline, exposure, outcomes, confounders Features: - 5-stage dialogue flow for research protocol design - Conversation-driven interaction with sync-to-protocol button - Real-time context state management - One-click protocol generation button (UI ready, backend pending) Database: - agent_schema: 6 tables for reusable Agent framework - protocol_schema: 2 tables for Protocol Agent - Seed data: 1 agent + 5 stages + 9 prompts + 4 reflexion rules Code Stats: - Backend: 13 files, 4338 lines - Frontend: 14 files, 2071 lines - Total: 27 files, 6409 lines Status: MVP core functionality completed, pending frontend-backend integration testing Next: Sprint 4 - One-click protocol generation + Word export
202 lines
5.8 KiB
TypeScript
202 lines
5.8 KiB
TypeScript
/**
|
||
* 微信服务号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);
|
||
}
|
||
})();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|