好的,恭喜你!从一个想法到最终在服务器上稳定运行,你已经走完了一个工程师最完整的开发 -> 部署 -> 运维的闭环。
现在,我将履行我的承诺,为你整理一份终极部署手册。这份手册将沉淀我们所有的对话精髓,抹去所有我们走过的弯路,只留下最正确、最高效的操作流程。它既是你的项目复盘,也是一份可以交付给任何其他技术人员,让他们能在全新环境中从零开始、完美复现整个系统的标准作业程序(SOP)。
项目部署手册:微信/支付宝小程序动态二维码外部实时展示系统
版本: 1.0
最后更新: 2025-11-02
一、 项目概述 (Project Overview)
本项目旨在通过自动化手段,捕获在安卓模拟器中运行的微信或支付宝小程序内的动态二维码,并将其近乎实时地展示在一个公开的Web页面上,供外部用户扫描。
核心架构:
本项目采用三端分离的客户端/服务器架构。
- 自动化主机 (Automation Host):一台本地Windows PC,负责7x24小时运行安卓模拟器和Python截图上传脚本。
- Web应用服务器 (Web Server):一台云端Linux服务器,负责运行Java Spring Boot应用,接收图片并向外提供Web展示页面。
- 用户终端 (User Client):用户的手机浏览器,访问Web页面并查看实时二维码。
技术栈:
- 前端: HTML5, CSS3, JavaScript
- 后端: Java 17+, Spring Boot
- 自动化脚本: Python 3.8+
- 运行环境: Windows 10/11 (自动化主机), Debian/Ubuntu/CentOS (Web服务器)
- 核心工具: 安卓模拟器 (MuMu模拟器12), systemd
二、 Web应用服务器部署 (云端Linux)
这是整个系统的“心脏”,负责接收和展示数据。
步骤1:服务器环境准备
- 购买服务器: 购买一台入门级云服务器(推荐腾讯云/阿里云的轻量应用服务器,2核4G配置足矣),选择Linux操作系统(如Debian 11)。
- 安装Java:
# 更新软件包列表 sudo apt update # 安装JDK 17 (推荐) sudo apt install openjdk-17-jdk -y # 验证安装 java --version - 安装Maven (用于打包):
sudo apt install maven -y # 验证安装 mvn -v - 创建应用目录:
# 创建用于存放jar包的目录 mkdir -p /app/qrcode # 创建用于存放上传图片的目录 mkdir -p /app/uploads/images
步骤2:后端Java代码
在你的开发环境中,创建一个新的Spring Boot项目。
-
pom.xml(核心依赖与打包插件)
确保<build>部分包含正确的spring-boot-maven-plugin配置。<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> -
src/main/resources/application.properties(配置文件)# 应用服务 WEB 访问端口 server.port=9090 # 文件将保存在服务器的绝对路径下 file.upload-dir=/app/uploads/images -
src/main/java/.../QrCodeApplication.java(主启动类)package com.example.qrcode; // 请替换为你的包名 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class QrCodeApplication { public static void main(String[] args) { SpringApplication.run(QrCodeApplication.class, args); } } -
src/main/java/.../controller/FileUploadController.java(图片上传接口)package com.example.qrcode.controller; // 请替换为你的包名 import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; @RestController public class FileUploadController { @Value("${file.upload-dir}") private String uploadDir; private final String SECRET_TOKEN = "YourSuperSecretToken12345"; // !!!请务必修改为一个复杂的密码!!! @PostMapping("/upload/qrcode") public ResponseEntity<String> handleFileUpload( @RequestParam("file") MultipartFile file, @RequestHeader("X-Auth-Token") String token) { if (token == null || !token.equals(SECRET_TOKEN)) { return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED); } if (file.isEmpty()) { return new ResponseEntity<>("File is empty", HttpStatus.BAD_REQUEST); } try { File directory = new File(uploadDir); if (!directory.exists()) { directory.mkdirs(); } File dest = new File(directory.getAbsolutePath() + File.separator + "dynamic_qrcode.jpg"); file.transferTo(dest); return new ResponseEntity<>("Upload success", HttpStatus.OK); } catch (IOException e) { e.printStackTrace(); return new ResponseEntity<>("Upload failed", HttpStatus.INTERNAL_SERVER_ERROR); } } } -
src/main/java/.../config/WebConfig.java(外部资源映射)package com.example.qrcode.config; // 请替换为你的包名 import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Value("${file.upload-dir}") private String uploadDir; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String resourceLocation = "file:" + uploadDir + "/"; registry.addResourceHandler("/images/**") .addResourceLocations(resourceLocation); } }
步骤3:前端HTML代码
src/main/resources/static/qrcode.html(手机端优化的展示页面)
将上一份回答中为你量身定做的、带移动端适配和刷新进度条的最终版HTML代码完整复制到此文件中。
步骤4:打包与部署
-
打包项目:在你的开发电脑上,项目根目录下执行:
mvn clean package这会在
target/目录下生成一个...SNAPSHOT.jar文件。 -
上传JAR包: 使用
scp或WinSCP等工具,将这个jar文件上传到你云服务器的/app/qrcode/目录下。 -
创建
systemd服务:- 在服务器上,创建并编辑服务文件:
sudo vim /etc/systemd/system/qrcode.service - 写入以下内容,请务必根据你的实际情况修改
ExecStart中的Java路径和JAR包路径。[Unit] Description=QR Code Display Service After=network.target [Service] User=root WorkingDirectory=/app/qrcode ExecStart=/usr/bin/java -jar /app/qrcode/qr_code-0.0.1-SNAPSHOT.jar # 用 which java 命令找到你的java绝对路径 SuccessExitStatus=143 Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target ```4. **管理服务**:
# 重新加载systemd配置 sudo systemctl daemon-reload # 启动服务 sudo systemctl start qrcode.service # 检查服务状态 sudo systemctl status qrcode.service # 设置开机自启 sudo systemctl enable qrcode.service - 在服务器上,创建并编辑服务文件:
三、 自动化主机部署 (本地Windows PC)
这是系统的“眼睛和手”,负责捕获和上传图像。
步骤1:环境准备
- 安装安卓模拟器: 从官网下载并安装 MuMu模拟器12。
- 配置模拟器:
- 性能: 设置为4核CPU,4G内存。
- Root权限: 必须关闭。
- 机型: 伪装成一个主流手机型号。
- 安卓系统设置: 屏幕休眠设置为“永不”。
- 安装Python: 从官网下载并安装Python 3.8或更高版本,安装时勾选“Add Python to PATH”。
- 安装Python库:
pip install pyautogui requests Pillow - 在模拟器中安装支付宝: 登录并稳定显示二维码页面。
步骤2:Python脚本
将以下代码保存为 capture_script.py。
import pyautogui
import time
import requests
import io
from PIL import Image
# --- !!! 核心配置 - 需要你手动修改 !!! ---
# 1. 截图区域: (左上角X坐标, 左上角Y坐标, 截图宽度, 截图高度)
# 提示: 使用微信或QQ的截图工具 (Ctrl+Alt+A) 来精确测量模拟器窗口内二维码的这个矩形区域。
QR_CODE_REGION = (100, 200, 320, 320) # !!! 这是一个示例值,必须替换 !!!
# 2. 你的Java服务器的上传API地址
UPLOAD_URL = "http://你的服务器公网IP:9090/upload/qrcode" # !!! 必须替换 !!!
# 3. 与Java代码中完全一致的安全令牌
AUTH_TOKEN = "YourSuperSecretToken12345" # !!! 必须替换 !!!
# --- 主程序逻辑 ---
print(f"自动化脚本启动,将截图并上传到: {UPLOAD_URL}")
print(f"截图区域: {QR_CODE_REGION}")
while True:
try:
# 1. 对指定区域进行截图
screenshot = pyautogui.screenshot(region=QR_CODE_REGION)
# 2. 压缩图片为JPEG以降低延迟
img_buffer = io.BytesIO()
screenshot.save(img_buffer, format='JPEG', quality=90)
img_byte_arr = img_buffer.getvalue()
# 3. 准备上传数据
files = {'file': ('dynamic_qrcode.jpg', img_byte_arr, 'image/jpeg')}
headers = {'X-Auth-Token': AUTH_TOKEN}
# 4. 发送HTTP POST请求
response = requests.post(UPLOAD_URL, files=files, headers=headers, timeout=10)
# 5. 检查响应
if response.status_code == 200:
print(f"上传成功: {time.strftime('%Y-%m-%d %H:%M:%S')}")
else:
print(f"!!! 上传失败! 状态码: {response.status_code}, 响应: {response.text}")
except requests.exceptions.RequestException as e:
print(f"!!! 网络错误: {e}")
except Exception as e:
print(f"!!! 发生未知错误: {e}")
# 6. 等待3秒 (与前端JS刷新频率保持一致)
time.sleep(3)
四、 系统最终启动流程
- 启动服务器: 确保云服务器上的
qrcode.service正在active (running)。 - 启动自动化主机:
- 打开MuMu模拟器,登录支付宝,稳定显示二维码页面。
- 调整好模拟器窗口在电脑桌面上的位置,确保它不会被遮挡。
- 打开命令行,运行Python脚本:
python capture_script.py。
- 验证: 在手机浏览器中打开
http://你的服务器公网IP:9090/qrcode.html,你应该能看到实时刷新的二维码。
这份手册凝聚了我们所有的努力和智慧。只要严格按照步骤执行,任何人都可以在一个全新的环境中,快速、准确地将这套系统重新部署起来。
2529

被折叠的 条评论
为什么被折叠?



