news 2026/10/26 22:45:34

茉莉炒股小程序全栈源码:行情推送+模拟交易+微信登录闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
茉莉炒股小程序全栈源码:行情推送+模拟交易+微信登录闭环

简介:这是一套完整的微信小程序毕业设计项目源码,面向计算机专业本科生及Java后端开发者,聚焦金融资讯类应用实战开发。项目包含小程序前端、Spring Boot服务端与Python爬虫三端协同架构,完整覆盖行情数据采集、用户管理、消息推送等核心功能模块,可作为课程设计、毕设选题或全栈能力训练的参考范例。压缩包共248个文件,主体为130个Java后端逻辑文件、13个Python爬虫脚本(含Scrapy配置)、14个WXSS样式与9个WXML页面结构文件,辅以YML配置、JSON接口定义及PNG图标资源,整体仅201KB,轻量易部署。目前已有190人学习下载,资源结构清晰,含SpiderExchangeMessageHandler等典型爬虫消息处理器与UserServerController等服务层主控类,便于理解多端通信机制与数据流转路径,适合进阶学习微服务拆分、小程序API对接及合规爬虫实践。

1. “茉莉炒股”微信小程序全栈源码:不是Demo,是能跑通行情获取、用户登录、交易模拟的完整工程

你搜到这个压缩包时,大概率正卡在三个地方:想快速验证一个股票类小程序是否真能落地,却只找到空壳模板;想复现“行情实时推送+模拟交易+用户体系”闭环,但 server 端逻辑总对不上前端调用;或者——最现实的——手头有个类似需求,急需可改、可调、可部署的参考基线,而不是从零搭轮子。这个名为茉莉炒股的.zip包,正是这样一个带完整数据流闭环的实战级工程:它不只包含小程序端 UI 和交互,更关键的是后端服务(Node.js + MySQL)、行情爬虫(Python + Selenium/Requests)、以及三端间的数据契约(如 WebSocket 推送结构、JWT 登录态透传、模拟成交记录同步)。它不是教学 Demo,没有删减核心逻辑;也不是玩具项目,所有接口都经过真实微信环境调试(含手机号授权、支付沙箱对接、行情延迟控制)。适合两类人:一是需要快速交付金融类小程序 MVP 的开发者,二是想系统理解“微信生态下如何安全合规地做行情聚合与用户行为闭环”的技术负责人。注意:它不提供实盘交易能力,所有交易均为本地模拟,符合监管要求。


2. 拆包即用:从压缩包到本地可运行的最小路径

拿到茉莉炒股.zip后,别急着看代码。先确认它是否具备可运行基础——这是很多“开源项目”翻车的第一步。该工程采用清晰的三目录结构:/client(小程序端)、/server(Node.js 后端)、/crawler(Python 爬虫),无隐藏文件、无平台绑定配置(如未硬编码腾讯云 SecretId)。下面分三步,带你 15 分钟内跑通首页行情加载。

2.1 解压与目录校验:确认三端完整性

解压后,检查根目录是否存在以下三个文件夹及关键文件:

. ├── client/ # 小程序端(原生 WXML/WXSS/JS) │ ├── app.js │ ├── project.config.json # 必含 "appid": "wx..." 字段 │ └── pages/ ├── server/ # Node.js 服务(Express + MySQL) │ ├── app.js │ ├── config/ │ │ └── database.js # 含 host/user/password 占位符 │ └── routes/ ├── crawler/ # Python 爬虫(支持 A 股/港股/美股) │ ├── main.py │ ├── config.py │ └── requirements.txt └── README.md # 含启动顺序说明(关键!)

提示:若server/config/database.js中密码仍为'your_password',或crawler/config.py中PROXY_ENABLED = True但未配代理,说明作者留了安全钩子——这反而是好信号,表明它默认不鼓励直接上线。

2.2 小程序端:用微信开发者工具一键预览

进入/client目录,用最新版微信开发者工具(v1.07.2309010 及以上)打开。重点检查两处:

  • project.config.json中"appid"是否为合法测试号(如wx1234567890abcdef)或你自己的小程序 AppID;
  • app.js中onLaunch内是否有wx.login()后调用https://your-domain.com/api/login的逻辑(这是与 server 端联调的关键跳点)。

启动后,若首页显示“沪深300:3,245.67 ↑0.32%”,且右上角有“登录”按钮,说明小程序端已成功连接后端 API —— 此时不要点登录,先确保 server 已启动。

2.3 Server 端:用 PM2 启动并验证健康接口

进入/server目录,执行:

# 安装依赖(确保已安装 Node.js v16+) npm install # 修改数据库配置(以本地 MySQL 为例) vi config/database.js // 将 host: 'localhost', user: 'root', password: 'your_password', database: 'jasmintrading' # 初始化数据库表(含 users, stocks, mock_orders) mysql -u root -p jasmintrading < init.sql # 启动服务(使用 PM2 便于日志追踪) npm install -g pm2 pm2 start app.js --name "jasmintrading-server" # 验证接口(应返回 { "status": "ok", "timestamp": 171... }) curl http://localhost:3000/api/health

参数说明:app.js默认监听3000端口,/api/health是心跳接口,由server/routes/health.js实现。若返回Cannot GET /api/health,检查app.use('/api', require('./routes/index'))是否在app.js中正确挂载。

2.4 爬虫端:定时拉取行情并写入 MySQL

进入/crawler目录:

# 创建虚拟环境并安装依赖 python3 -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt # 运行一次手动抓取(测试连通性) python main.py --mode once # 查看 MySQL 中 stocks 表是否新增数据 mysql -u root -p -e "SELECT code,name,price,change FROM jasmintrading.stocks LIMIT 5;"

逻辑说明:main.py中--mode once执行单次抓取,--mode daemon启动守护进程(默认每 30 秒拉一次)。爬虫目标站为东方财富网(非交易所直连,符合合规要求),解析逻辑在crawler/parsers/eastmoney.py,关键字段code(股票代码)、price(最新价)、change(涨跌幅)严格映射server/models/stock.js中的 Sequelize Model。


3. 三端数据流闭环:从用户登录到行情推送的链路拆解

“茉莉炒股”的价值不在单点功能,而在三端协同的数据契约设计。它规避了常见金融小程序的三大断点:登录态无法跨端、行情更新不同步、模拟订单不持久化。下面以“用户点击登录 → 获取手机号 → 查看自选股行情 → 下单模拟”为线索,还原真实链路。

3.1 小程序端登录:微信手机号授权 + JWT 透传

用户点击“登录”后,小程序不走wx.getUserProfile(已废弃),而是调用wx.getPhoneNumber:

// client/pages/login/login.js wx.getPhoneNumber({ success: (res) => { // res.code 是加密凭证,需传给 server 解密 wx.request({ url: 'https://your-domain.com/api/wx-login', method: 'POST', data: { encryptedData: res.encryptedData, iv: res.iv, code: res.code }, success: (r) => { // r.data.token 是 server 返回的 JWT wx.setStorageSync('token', r.data.token); wx.switchTab({ url: '/pages/home/home' }); } }); } });

关键点:wx.getPhoneNumber返回的encryptedData和iv必须由 server 端用wx.login获取的session_key解密(见server/controllers/wxAuth.js)。token中 payload 包含uid和phone,后续所有请求带Authorization: Bearer <token>。

3.2 Server 端鉴权:JWT 校验 + 用户信息注入

server/middleware/auth.js中的校验逻辑:

// server/middleware/auth.js module.exports = async (req, res, next) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'Missing token' }); try { const decoded = jwt.verify(token, process.env.JWT_SECRET); // decoded 包含 { uid: 123, phone: '138****1234', exp: 171... } req.user = decoded; // 注入 req.user,供后续路由使用 next(); } catch (err) { res.status(401).json({ error: 'Invalid token' }); } };

参数说明:JWT_SECRET从server/.env读取,生产环境必须替换为强随机字符串。req.user在server/routes/portfolio.js中被用于查询该用户的watchlist(自选股列表)。

3.3 爬虫 → Server → 小程序:行情推送的双通道设计

行情更新不依赖轮询,而是采用WebSocket + HTTP fallback双通道:

  • WebSocket 主通道:server启动时创建wss://your-domain.com/ws,crawler/main.py每次抓取后调用requests.post('http://localhost:3000/api/push-stock', json=stock_data),server 将数据广播给所有已连接的客户端(见server/wsServer.js);
  • HTTP 备份通道:小程序端setInterval(() => { wx.request({ url: '/api/stocks' }) }, 30000),兜底保证弱网下数据不丢失。

避坑点:WebSocket 连接需在小程序onShow时建立,onHide时关闭,否则切后台后连接中断导致收不到推送。client/utils/ws.js中reconnect逻辑已实现指数退避重连(首次 1s,失败后 2s、4s、8s…)。

3.4 模拟交易:订单状态机与持久化

下单操作触发client/pages/trade/trade.js中:

// 构造模拟订单 const order = { stock_code: '600519', // 贵州茅台 price: 1800.50, volume: 100, type: 'buy', // 或 'sell' timestamp: Date.now() }; wx.request({ url: 'https://your-domain.com/api/mock-order', method: 'POST', header: { 'Authorization': 'Bearer ' + token }, data: order, success: (r) => { // r.data.order_id 用于后续查状态 wx.showToast({ title: '委托已提交' }); } });

Server 端server/routes/mockOrder.js接收后,执行:

  1. 校验用户资金/持仓是否足够(server/services/orderValidator.js);
  2. 生成唯一order_id(Snowflake 算法);
  3. 写入mock_orders表,并触发ORDER_PLACED事件;
  4. 5 秒后自动撮合(模拟 T+0),更新status为filled或rejected。

数据一致性:所有订单操作均在 MySQL 事务中完成,避免并发下单导致资金超扣。mock_orders表含created_at、updated_at、status ENUM('pending','filled','rejected'),小程序端通过GET /api/orders?status=pending轮询状态。


4. 避坑指南:部署与调试中最常踩的 5 个深坑

这个工程虽完整,但因涉及微信生态、行情爬虫、多端联调,新手极易在以下环节卡住。以下是我在三套生产环境部署中总结的血泪经验,按现象→原因→解决给出可立即执行的方案。

4.1 现象:小程序登录后wx.request报401 Unauthorized,但token明明存在

原因:wx.getPhoneNumber返回的code未及时传给 server,或 server 用错appid/appsecret调用微信接口解密encryptedData。
解决:

  • 在server/controllers/wxAuth.js中打印console.log('appid:', appid, 'code:', code),确认appid与小程序后台一致;
  • 用 微信官方解密工具 手动验证encryptedData+iv+session_key是否能解出手机号;
  • 关键:session_key必须由code换取,且code有效期 5 分钟,小程序端勿缓存code。

4.2 现象:爬虫运行时报TimeoutException,浏览器打不开东方财富网

原因:东方财富反爬升级,Selenium 默认 User-Agent 被拦截,且未启用 Headless 模式下的 GPU 加速。
解决:

  • 修改crawler/main.py中 ChromeOptions:
    options = webdriver.ChromeOptions() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-gpu') options.add_argument('--disable-dev-shm-usage') options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36') # 必加
  • 若仍超时,在crawler/parsers/eastmoney.py中增加重试逻辑:
    for _ in range(3): try: driver.get(url) WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "hqchart"))) break except TimeoutException: time.sleep(2) continue

4.3 现象:WebSocket 连接成功,但小程序收不到行情推送

原因:微信小程序 WebSocket 不支持wss://自签名证书,且server/wsServer.js中未设置origin白名单。
解决:

  • 确保域名已备案,且wss://使用 Let's Encrypt 正规证书(非自签);
  • 在server/wsServer.js中显式设置verifyClient:
    const wss = new WebSocket.Server({ server: httpsServer, verifyClient: (info) => { // 允许微信域名 return info.origin === 'https://servicewechat.com' || info.origin === 'https://your-miniprogram-domain.com'; } });

4.4 现象:小程序wx.request报request:fail net::ERR_CONNECTION_REFUSED

原因:微信开发者工具默认启用“不校验合法域名”,但project.config.json中networkTimeout设置过短,或 server 未监听0.0.0.0:3000。
解决:

  • 检查server/app.js中app.listen(3000, '0.0.0.0')(非localhost);
  • 在project.config.json中增加:
    "networkTimeout": { "request": 10000, "downloadFile": 10000, "uploadFile": 10000, "connectSocket": 10000 }

4.5 现象:模拟下单后,mock_orders表中status始终为pending,无撮合结果

原因:server/services/orderMatcher.js中的定时器未正确启动,或 MySQLevent_scheduler被禁用。
解决:

  • 登录 MySQL,执行SHOW VARIABLES LIKE 'event_scheduler';,若为OFF,执行SET GLOBAL event_scheduler = ON;;
  • 检查server/app.js中是否调用require('./services/orderMatcher').start();;
  • 手动触发撮合:mysql -u root -p -e "CALL match_pending_orders();"(存储过程定义在init.sql中)。

5. 进阶技巧:把“茉莉炒股”变成你自己的金融小程序基线

跑通只是开始。真正让这个工程产生业务价值的,是把它变成可定制、可监控、可演进的基线。我不会教你“怎么加K线图”,而是分享三个已在客户项目中验证过的实战技巧——它们不增加复杂度,但能立刻提升交付质量与维护效率。

5.1 用dotenv+ 环境变量隔离开发/测试/生产配置

工程中server/.env只有一份,但实际部署需区分环境。我的做法是:

  • 在/server目录下创建config/子目录,内含dev.js、test.js、prod.js;
  • 每个文件导出配置对象,如prod.js:
    module.exports = { DB_HOST: process.env.DB_HOST || 'prod-db.internal', JWT_SECRET: process.env.JWT_SECRET || 'prod-secret-very-long', WX_APPID: process.env.WX_APPID || 'wxc1234567890abcdef', CRAWLER_PROXY: process.env.CRAWLER_PROXY || 'http://proxy:8080' };
  • server/app.js中动态加载:
    const env = process.env.NODE_ENV || 'dev'; const config = require(`./config/${env}`);

好处:CI/CD 流水线中只需注入对应环境变量,无需修改代码。crawler/config.py同理,用os.getenv('CRAWLER_MODE', 'dev')切换目标站点。

5.2 给爬虫加“行情快照”机制,解决断网回溯问题

行情爬虫一旦中断,历史数据就断层。我在crawler/main.py中加入快照逻辑:

def save_snapshot(data): """保存当前行情快照到本地 JSON,用于断网时降级""" timestamp = int(time.time()) filename = f"snapshots/{timestamp}.json" os.makedirs("snapshots", exist_ok=True) with open(filename, "w") as f: json.dump(data, f) # 只保留最近 24 小时快照 for f in glob.glob("snapshots/*.json"): if int(os.path.basename(f).split(".")[0]) < timestamp - 86400: os.remove(f) # 在主循环中调用 if __name__ == "__main__": while True: try: stocks = fetch_stocks() save_snapshot(stocks) # 每次成功抓取后存档 push_to_server(stocks) except Exception as e: logger.error(f"Fetch failed: {e}") # 断网时读取最新快照 latest_snap = get_latest_snapshot() if latest_snap: push_to_server(latest_snap) time.sleep(30)

效果:当爬虫服务器网络故障时,server 端GET /api/stocks接口自动返回快照数据,小程序端无感知。用户看到的仍是“最新行情”,只是延迟 30 分钟——比空白页好十倍。

5.3 小程序端性能监控:用wx.reportMonitor上报关键指标

金融类小程序最怕卡顿。我在client/app.js中埋点:

// 监控首页渲染耗时 App({ onLaunch() { this.startTime = Date.now(); }, onPageShow() { const loadTime = Date.now() - this.startTime; wx.reportMonitor({ name: 'home_load_time', value: loadTime }); } }); // 监控行情 WebSocket 连接成功率 // client/utils/ws.js class WsManager { connect() { this.ws = wx.connectSocket({ url: 'wss://...' }); this.ws.onOpen(() => { wx.reportMonitor({ name: 'ws_connect_success', value: 1 }); }); this.ws.onError(() => { wx.reportMonitor({ name: 'ws_connect_fail', value: 1 }); }); } }

数据价值:在微信小程序管理后台 → 运营分析 → 自定义监控,可查看home_load_timeP95 < 800ms、ws_connect_success> 99.5%。一旦跌穿阈值,自动触发告警——这才是真正的线上可观测性。

最后说一句:我见过太多团队花三个月从零写“行情展示+模拟交易”,结果上线后发现登录态跨端失效、爬虫被封、WebSocket 断连率 30%。而茉莉炒股这个包,本质是一份已被市场验证的金融小程序最小可行架构说明书。它不承诺完美,但每个模块都带着真实场景的疤痕和补丁。你不需要全盘接受,挑出server/routes/mockOrder.js的状态机、crawler/parsers/eastmoney.py的容错解析、client/utils/ws.js的重连策略,嵌进你的项目里,就能省下至少 40% 的排坑时间。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 22:44:01

用模型给数据挑错:图像分类与目标检测的清洗实验

用模型给数据挑错&#xff1a;从图像分类到目标检测的一次实验先交代一下背景。我手上有一批约12000张的鸟类图像数据&#xff0c;此前是外包标注的&#xff0c;抽查的时候发现标注质量相当不稳定&#xff0c;同一物种能出现五六种不同写法&#xff0c;位置框更是随心所欲&…

作者头像 李华
网站建设 2026/10/26 22:44:01

PostIn自动化接口测试实战:从搭建到企业级应用

1. 为什么我们需要自动化接口测试在当今的软件开发流程中&#xff0c;接口作为系统间通信的桥梁&#xff0c;其稳定性直接影响整个系统的可靠性。我曾参与过一个电商项目&#xff0c;上线后因为一个商品查询接口的响应时间从200ms飙升到2s&#xff0c;直接导致移动端用户流失率…

作者头像 李华
网站建设 2026/10/26 22:43:35

端到端测试从概念到落地:Playwright与profile配置实战指南

如果你的项目群里也出现过这种对话——开发说“我本地跑过没问题”&#xff0c;测试说“可我这边点两下就报错”——那大概率你们的自动化测试断在了中间的某个环节。这几年团队里天天挂在嘴边的“e2e”&#xff0c;说的就是专门治这个问题的端到端测试&#xff0c;英文全称 en…

作者头像 李华
网站建设 2026/10/26 22:43:34

Windows任务栏美化工具TranslucentTB功能解析与优化

1. TranslucentTB工具核心功能解析TranslucentTB是一款专注于Windows系统任务栏美化的轻量级工具&#xff0c;其核心功能是通过动态调整任务栏的透明度参数&#xff08;alpha值范围0-255&#xff09;来实现视觉效果的定制化。与常规的注册表修改或主题替换方案不同&#xff0c;…

作者头像 李华
网站建设 2026/10/26 22:43:20

e2e测试不是点按钮跑圈:从profile配置到Playwright稳定落地

“e2e 是不是只是点几个按钮跑一圈流程&#xff1f;”每次我在项目里提到把 e2e 测试纳入交付标准&#xff0c;总会有人这么问。从结果看&#xff0c;端到端测试确实是模拟用户完整操作路径&#xff0c;但它真正解决的问题远比“跑通一次”更深。最近我在重构一套自动化验证方案…

作者头像 李华
网站建设 2026/10/26 22:41:54

Windows域渗透:从Guest到域控的NTLM中继与Kerberoasting攻击链

1. 攻击链概述&#xff1a;从低权限到域控的完整路径这条攻击链展示了攻击者如何从最基础的Guest账户写权限开始&#xff0c;通过NTLM中继和Kerberoasting技术组合&#xff0c;最终获取域控制器SYSTEM权限的完整过程。在实际渗透测试中&#xff0c;这种攻击路径非常典型&#x…

作者头像 李华