#!/usr/bin/env python3 """ 积分实时通知机制验证测试脚本 测试完整的积分获得流程和通知推送 """ import requests import json import time import threading from datetime import datetime # 配置 BASE_URL = "http://localhost:5511" ADMIN_TOKEN = "admin-token" # 假设的管理员token MEMBER_ID = "019c4c9d-13d9-70e8-a275-a0b941d91fae" # 测试会员ID def log(message): """打印带时间戳的日志""" timestamp = datetime.now().strftime("%H:%M:%S") print(f"[{timestamp}] {message}") def test_member_login(): """测试会员登录获取token""" log("=== 测试会员登录 ===") try: response = requests.get(f"{BASE_URL}/api/members/current") if response.status_code == 200: member_data = response.json() log(f"✅ 会员登录成功: {member_data.get('nickname', 'Unknown')}") log(f" 当前积分: {member_data.get('availablePoints', 0)}") return True else: log(f"❌ 会员登录失败: {response.status_code}") return False except Exception as e: log(f"❌ 会员登录异常: {str(e)}") return False def test_get_member_points(): """获取会员当前积分""" log("=== 查询会员积分 ===") try: response = requests.get(f"{BASE_URL}/api/members/current") if response.status_code == 200: member_data = response.json() points = member_data.get('availablePoints', 0) log(f"✅ 当前可用积分: {points}") return points else: log(f"❌ 查询积分失败: {response.status_code}") return None except Exception as e: log(f"❌ 查询积分异常: {str(e)}") return None def test_scan_marketing_code(code="TEST123"): """测试扫描营销码获得积分""" log("=== 测试扫描营销码 ===") try: payload = { "code": code, "scanTime": datetime.now().isoformat() } response = requests.post( f"{BASE_URL}/api/marketing-codes/scan", json=payload, headers={"Content-Type": "application/json"} ) log(f"请求URL: {BASE_URL}/api/marketing-codes/scan") log(f"请求体: {json.dumps(payload, indent=2, ensure_ascii=False)}") log(f"响应状态: {response.status_code}") log(f"响应内容: {response.text}") if response.status_code == 200: result = response.json() log(f"✅ 扫码成功: {result}") return True, result else: log(f"❌ 扫码失败: {response.status_code} - {response.text}") return False, response.text except Exception as e: log(f"❌ 扫码异常: {str(e)}") return False, str(e) def test_sse_connection(): """测试SSE连接""" log("=== 测试SSE实时通知连接 ===") try: url = f"{BASE_URL}/api/notifications/stream?memberId={MEMBER_ID}" log(f"连接SSE: {url}") def sse_listener(): try: with requests.get(url, stream=True) as response: log(f"SSE连接状态: {response.status_code}") if response.status_code == 200: log("✅ SSE连接建立成功") for line in response.iter_lines(): if line: decoded_line = line.decode('utf-8') if decoded_line.startswith('data:'): data = decoded_line[5:].strip() if data: try: notification = json.loads(data) log(f"🔔 收到通知: {notification}") except json.JSONDecodeError: log(f"🔔 原始数据: {data}") else: log(f"❌ SSE连接失败: {response.status_code}") except Exception as e: log(f"❌ SSE监听异常: {str(e)}") # 启动SSE监听线程 sse_thread = threading.Thread(target=sse_listener, daemon=True) sse_thread.start() time.sleep(2) # 等待连接建立 return sse_thread except Exception as e: log(f"❌ SSE连接异常: {str(e)}") return None def test_create_test_marketing_code(): """创建测试用的营销码""" log("=== 创建测试营销码 ===") try: # 先查询现有批次 response = requests.get(f"{BASE_URL}/api/admin/marketing-codes/batches") if response.status_code == 200: batches = response.json() if batches and len(batches) > 0: batch_no = batches[0]['batchNo'] log(f"使用现有批次: {batch_no}") # 创建单个测试码 payload = { "batchNo": batch_no, "count": 1, "prefix": "TEST" } create_response = requests.post( f"{BASE_URL}/api/admin/marketing-codes/generate", json=payload, headers={"Content-Type": "application/json"} ) if create_response.status_code == 200: codes = create_response.json() if codes and len(codes) > 0: test_code = codes[0] log(f"✅ 创建测试码成功: {test_code}") return test_code else: log(f"❌ 创建测试码失败: {create_response.status_code}") log(f"响应内容: {create_response.text}") else: log("❌ 没有可用的营销码批次") else: log(f"❌ 查询批次失败: {response.status_code}") return None except Exception as e: log(f"❌ 创建测试码异常: {str(e)}") return None def main(): """主测试流程""" log("🚀 开始积分实时通知机制验证测试") log("=" * 50) # 1. 测试基础连接 if not test_member_login(): log("❌ 基础连接测试失败,退出测试") return # 2. 获取初始积分 initial_points = test_get_member_points() if initial_points is None: log("❌ 无法获取初始积分,退出测试") return # 3. 建立SSE连接监听通知 sse_thread = test_sse_connection() if not sse_thread: log("❌ SSE连接失败,继续其他测试") # 4. 等待一段时间让SSE连接稳定 log("⏳ 等待SSE连接稳定...") time.sleep(3) # 5. 测试扫码获得积分 log("\n" + "=" * 30) log("开始积分获得测试") log("=" * 30) success, result = test_scan_marketing_code("TEST123") # 6. 等待通知处理 log("⏳ 等待通知处理...") time.sleep(5) # 7. 验证积分是否更新 log("\n" + "=" * 30) log("验证积分更新") log("=" * 30) final_points = test_get_member_points() if final_points is not None and initial_points is not None: points_diff = final_points - initial_points log(f"📊 积分变化: {initial_points} -> {final_points} (变化: {points_diff})") if points_diff > 0: log("✅ 积分成功增加") elif points_diff == 0: log("⚠️ 积分无变化") else: log("❌ 积分减少") # 8. 总结 log("\n" + "=" * 50) log("🎯 测试总结") log("=" * 50) log(f"初始积分: {initial_points}") log(f"最终积分: {final_points}") log(f"扫码结果: {'成功' if success else '失败'}") log("测试完成!") if __name__ == "__main__": main()