简介:萤火商城 v2.0.8 是一套基于 PHP7.4、ThinkPHP6.0、Uni-APP 与 Ant Design Vue 的轻量级电商系统源码包,面向需要快速搭建微信小程序、H5、公众号及 APP 商城的开发者和中小企业。前后端分离、100% 开源,适合二次开发与学习电商系统设计。资源共 2000 个文件,核心以 1175 个 PHP 文件为主,覆盖后端接口、业务逻辑与权限控制;另有 155 个 JS、46 个 CSS、136 个 PNG 等前端资源,以及 SQL 数据库脚本、JSON 配置和 Markdown 说明文档,压缩包整体约 17.34MB,目录结构清晰,便于按模块定位代码。目前已有 267 人学习下载。借助这套源码,可掌握多端商城的技术选型、前后端交互方式、后台权限设计及 Uni-APP 跨端打包思路;描述中附有超管与商户后台演示地址及默认账号密码,方便快速跑通流程、对照源码理解业务逻辑,是进阶 ThinkPHP 与 Uni-APP 开发的实用参考资料。
1. 萤火商城 v2.0.8:一套能直接跑通微信小程序的商用商城底座
如果你正在给客户交付一个多端商城项目,大概率会搜到这个名字:萤火商城 v2.0.8。它不是那种静态展示页模板,而是一套 Java Spring Boot 多模块后端加 uni-app 多端前端组成的系统,v2.0 多端商业版把多商户、分销、拼团、积分这几条线都补齐了。适合两类人:一类是手头有商城需求的 Java 工程师,想直接复用商品、订单、购物车、支付这条完整链路;另一类是想低成本开多端店铺的运营者,把程序跑通后改配置就能上线。这套东西真正值钱的地方不是界面好看,而是它把微信小程序、H5、管理后台对接到同一套后端服务上,省掉了大量联调工作。下文按落地顺序讲:先拆架构,再本地跑通,最后给五个上线前必须避开的坑。
2. 拆架构:Spring Boot 多模块与 uni-app 多端的协作逻辑
2.1 后端模块划分:一次商品详情请求的完整调用链
后端代码继承了若依框架的权限管理逻辑,但应用层完全围绕着商城业务重构,模块拆得比较细:商品、订单、用户、营销、支付、售后各自独立成包。这种拆法在单体阶段看起来多了一层目录,但后续要拆微服务或做多商户隔离时,工作量会小很多——这也是商业版和随手改改的开源版最大的差别。
一次商品详情请求,大概走的是这条链路:
// GoodsController:对外暴露商品查询入口 @RestController @RequestMapping("/api/goods") public class GoodsController { @Autowired private GoodsService goodsService; // 前端小程序请求 /api/goods/detail/1001 @GetMapping("/detail/{goodsId}") public R detail(@PathVariable Long goodsId) { return R.ok(goodsService.getDetail(goodsId)); } }Controller 很薄,只做参数接收和统一返回封装R。真正干活的是 Service 层:先查 Redis 缓存,缓存没有命中再查数据库,然后把库存、价格、营销标签一并组装返回。这样设计的直接好处是微信小程序端首页多次滑动刷新时,不会每次都打穿 MySQL。
Service 层再往下就是 MyBatis 的 Mapper 接口和 XML 文件。GoodsMapper.xml里通常有一段超过 20 行的关联查询,把商品主表、SKU 表、商品分类和营销活动表 join 在一起。你看不懂这段 SQL 没关系,只需要记住:排查商品数据问题时,先去GoodsMapper.xml里看字段映射,而不是在前端页面里猜。实际调试里很多商品价格不显示的问题,最后都定位在 SQL 结果没有映射到goodsSkuList这个字段上。
2.2 两个前端分开维护:uni-app 的多端编译与 Vue 2 管理台
用户端和运营后台是两套独立前端工程。运营后台用的是 Vue 2 + Element UI,逻辑传统,路由里挂着权限指令,这部分跟若依管理端一脉相承,上过手的人不会有陌生感。用户端则用 uni-app 编写,一次编码编译成微信小程序、支付宝小程序、H5、App。
uni-app 的条件编译是这个项目的关键机制,也是前端改版时最容易踩坑的地方:
// #ifdef MP-WEIXIN import wxApi from '@/common/wx-api' // #endif // #ifdef H5 import h5Api from '@/common/h5-api' // #endif#ifdef和#endif是 uni-app 的编译预处理命令,打包成微信小程序时,MP-WEIXIN代码块被保留,H5代码块被裁剪;打包成 H5 时则完全反过来。项目里支付、登录、分享这类依赖平台 SDK 的方法都做了这种分层。你在这个文件里加新 API 时,务必两边都实现,否则就会出现微信端支付正常、H5 端点支付按钮没反应的诡异问题。这种问题不在编译期报错,只能靠真机逐端去试,所以一开始就要养成平台分层的习惯。
2.3 商业版的核心门槛:多商户与营销组件在表结构上的落点
免费版和商业版最本质的差距不在界面,而在数据库表设计。多商户能力不是加一个shop_id字段那么简单,而是整个商品、订单、结算、售后链路都要跟着商家维度走。
看一下商品表在商业版里的设计意图:
-- 多商户版商品表核心结构(简化) CREATE TABLE `shop_goods` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `shop_id` bigint(20) NOT NULL COMMENT '所属商户ID,单商户版没有此字段', `goods_name` varchar(255) NOT NULL COMMENT '商品名称', `goods_price` decimal(10,2) NOT NULL COMMENT '商品价格', `is_delete` tinyint(1) DEFAULT 0 COMMENT '软删除标记', PRIMARY KEY (`id`), KEY `idx_shop_goods_shop_id` (`shop_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;shop_id出现在商品表里,意味着订单表、购物车表、结算单表全都跟着带上了这个维度。你在做二次开发时,凡是新写的查询都必须带上shop_id过滤条件,否则管理员账号能看到全部商家数据,普通商家却能通过越权接口查到别人店铺的商品。这套系统里权限拦截依赖于一个@RequiresPermissions注解,但对多商户数据的行级隔离,主要靠 SQL 层手动控制,这是比注解更容易漏掉的地方。
营销组件在表结构上的落点更明显:分销、拼团、积分抵扣分别对应独立的分销关系表、拼团活动表、积分流水表。其中分销关系表记录了每个用户的上级链,退款时会反向扣减分销佣金,这部分逻辑写在订单取消的 Service 里。理解了这个结构,你才知道为什么订单状态机不是简简单单的“未支付”和“已支付”两个状态。
3. 本地跑通:从空 MySQL 到小程序首页显示商品
3.1 环境版本清单与检查命令
这步别凭感觉来,版本不对后面全是坑。我实际跑通 v2.0.8 用的环境是这样的组合:
| 组件 | 推荐版本 | 用途 | 注意点 |
|---|---|---|---|
| JDK | 1.8 | 后端运行 | 不要一上来升到 JDK 17,部分老依赖反射会报错 |
| MySQL | 5.7 或 8.0 | 数据存储 | 8.0 需要改 driver 配置,5.7 最稳 |
| Redis | 6.x | 缓存与验证码 | Windows 下装完先ping一下 |
| Maven | 3.6+ | 构建后端 | 首次构建耗时较长,建议配国内镜像 |
| Node.js | 14.x | 编译小程序前端 | uni-app 项目对 Node 18+ 可能有依赖告警 |
| 微信开发者工具 | 最新稳定版 | 预览小程序 | 需注册测试号或使用真实 AppID |
打开命令行,先把底摸清,避免装了个“看起来像”的环境:
java -version mvn -v redis-cli ping mysql --version node -vredis-cli ping返回PONG才说明 Redis 真能用,后面登录验证码、商品缓存的很多怪问题都跟 Redis 没起来有关。版本这里不啰嗦,但请把上面表格截个图,当 checklist 用。
3.2 建库与导入 SQL:字符集和导入顺序决定了成败
v2.0.8 的代码包解压后,/sql目录里通常按schema.sql、data.sql、升级脚本拆成多个文件。先建库,再按顺序导入,不要一条命令导入整个目录,容易因为表关联顺序报外键错误。
# 建库,字符集必须用 utf8mb4,否则商品里的 emoji 存不进去 mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS yshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 先建表,再导基础数据 mysql -uroot -p yshop < /解压路径/sql/schema.sql mysql -uroot -p yshop < /解压路径/sql/data.sqlschema.sql建表,data.sql塞基础数据——包括管理员账号、默认店铺、初始分类和演示商品。导入成功后,用mysql -uroot -p yshop -e "show tables;"看到几十张表左右才算正常,如果核心表缺失,后面后端一启动就报Table 'yshop.shop_order' doesn't exist。
还有个细节容易被忽略:如果本机 MySQL 是 8.0,注意数据源的 driver 要改成com.mysql.cj.jdbc.Driver。5.7 用老驱动没问题,8.0 下老驱动会被直接拒绝连接。
3.3 后端配置:数据源、Redis、支付参数在哪里改
后端配置集中在ruoyi-admin模块的src/main/resources/application.yml里。打开后优先改三块:数据源、Redis、文件访问路径。
spring: datasource: url: jdbc:mysql://localhost:3306/yshop?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 你的数据库密码 driver-class-name: com.mysql.jdbc.Driver # MySQL 8.0 改成 com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 database: 0 password: # 本机没设密码就留空serverTimezone=Asia/Shanghai一定要保留,否则订单时间比本地时间差 8 小时,你会误以为是时区 bug。useSSL=false是开发环境常规操作,生产环境走内网时也别开,性能损耗不值得。
文件存储默认是本地磁盘路径,配置项通常是yshop.filePath或file.local.path。不改这个也行,但你要能记住默认路径在哪,否则后面商品图片传上去找不到文件。很多人在这一步跳过,结果小程序上传商品图后,图片存在了服务器某个角落,页面显示的是绝对路径下的空图。建议一开始就规划好一个专门目录,比如/data/yshop/upload。
3.4 启动后端并运行小程序端:联调前的最后一公里
后端是标准的 Maven 多模块工程,启动入口在ruoyi-admin模块。命令行到项目根目录执行:
mvn spring-boot:run -pl ruoyi-admin首次启动会自动下载依赖,耗时看网速。启动成功的标志是日志里出现Started RuoYiApplication,并且控制台输出一个本地端口,通常是8080。验证后端活着,浏览器直接访问http://localhost:8080/api/goods/detail/1,能返回 JSON 就说明数据库连接、Redis、商品模块都正常。
接着打开小程序用户端工程,先改公共配置里的接口地址:
// common/config.js const BASE_URL = 'http://localhost:8080' // 开发联调阶段指向本机后端用 HBuilderX 导入用户端项目,点“运行到小程序模拟器”,微信开发者工具会自动打开编译产物。如果请求报url not in domain list,那是开发阶段的域名校验问题:微信开发者工具右上角详情里勾选“不校验合法域名”,就能正常请求本地接口,不需要为此配置正式域名。真机预览就反过来,必须用局域网 IP 或已备案的 HTTPS 域名,否则请求直接失败,这种翻车最容易出现在首次真机调试时——感觉不是你的问题,其实就是地址没换成局域网 IP。
4. 改成自己的店:系统配置、支付、运费与营销参数
4.1 商城参数配置:哪些开关动了会引发连锁问题
跑通默认程序后,接下来的工作全在运营后台完成。后台入口是http://localhost:8080,使用data.sql里初始化的管理员账号登录。首次登录先把“系统配置/商城设置”这个页面里的店铺名称、logo、客服电话改掉,这三个是最显眼的默认痕迹。
再往下看,有一个“商城模式”或“平台模式”的开关,对应单商户与多商户切换。v2.0.8 商业版这个开关一旦切到多商户,很多表查询就会强制校验shop_id。你如果当前只想做一个自营商城,就把开关留在单商户模式,否则后台会多出“商家入驻”菜单,处理起来繁琐。开关本身不复杂,麻烦的是对接口和数据的影响——切换后老数据没有分配的shop_id会被默认归到管理员店铺下,别在数据量大了之后再做切换,那时候补数据能让人崩溃。
4.2 微信支付与小程序登录:appid、商户号与回调的三方对账
微信支付和登录是全网商城源码里最容易反复折腾的部分,因为错误提示往往只有一句“系统繁忙”。这套系统里,用户端小程序登录走微信的code2Session,支付走 JSAPI 下单。
先理清三个主体的关系:小程序 AppID、微信商户号、APIv3 密钥。登录只依赖 AppID 和 AppSecret,两者必须来自同一个微信开放平台账号;支付则要把小程序 AppID 绑定到商户号,在商户平台里操作“AppID 授权绑定”,绑定之后后端配置里三个字段才能互认。
后端支付配置一般长这样:
wx: appid: wx你的小程序appid secret: 你的小程序secret mch-id: 你的微信商户号 api-v3-key: 商户平台设置的APIv3密钥 serial-no: 商户证书序列号 private-key-path: /opt/cert/apiclient_key.pemapi-v3-key是 32 字节,在商户平台手动设置;serial-no在商户平台“API安全”里查看,跟apiclient_key.pem证书文件一定要配套。常见的 401 报错,十有八九是serial-no填错或私钥文件路径读不到;签名错误则优先检查api-v3-key是否复制了空格。回调地址建议先配置为内网穿透工具提供的临时地址,用微信支付官方测试账号先把流程跑通,再替换成线上域名,别一上来就上正式域名,调试成本极高。
4.3 运费模板与快递查询:按件数、按金额还是按距离
运费模板在后台的“配送管理”里,创建模板时要选择计费方式。这套系统支持按件数和按金额两种模式,两种有本质区别:按件数适合卖标准小件,比如手机壳、数据线;按金额适合卖大件或高货值商品,满一定金额包邮。
建模板时要设置默认运费和指定地区运费两个层级,前者是所有未单独设置地区,后者是针对新疆、西藏等偏远地区单独加价。很多运营者第一次只设了默认运费,结果偏远地区也按同一个价发货,每单亏十几块钱。这类问题的根因不是代码 bug,而是模板规则没有落到具体地区。快递轨迹查询接的是快递鸟或快递 100 的 API,在后台填appid和appkey即可。注意这类服务商要求你在管理后台绑定 IP 白名单,本地调试时填本机出口 IP,上线后改成服务器公网 IP,否则请求会被服务商拒绝,返回401 鉴权失败。
4.4 v2.0.8 里值得提前改完的 12 项配置
以下配置清单按上线前的优先级排序,拿到资源后建议逐项过一遍:
| 配置项 | 位置 | 说明 |
|---|---|---|
| 小程序 AppID | manifest.json + 后台 | 两处必须一致,不一致登录必挂 |
| 后端接口域名 | common/config.js | 上线后改成 HTTPS 域名 |
| 数据库密码 | application.yml | 换掉默认密码 |
| Redis 密码 | application.yml | 公网环境必须设 |
| 文件上传路径 | application.yml | 规划好磁盘目录,避免塞系统盘 |
| 支付回调地址 | 商户平台 + yml | 两边填同一个地址 |
| 商家入驻开关 | 后台系统配置 | 自营商城关闭,多商户平台开启 |
| 分销层级数 | 后台营销配置 | 默认 1 级,常见 2 级,超过需合规评估 |
| 运费模板默认规则 | 后台配送管理 | 不设就吃默认规则,容易亏运费 |
| 快递查询白名单 | 快递服务商管理端 | 只填服务器出口 IP |
| 短信签名 | 短信服务商控制台 | 未备案签名禁止商用 |
| 管理后台登录密码 | 修改管理员账号 | 默认密码上线前必须改 |
这 12 项不全部改完不叫上线。其中前四项属于“不改就出事”,中间四项属于“上线后每天都可能被坑”,最后四项属于“等出问题再补成本更高”。我见过很多团队把商城搭起来后直接丢到公网,结果第三天 Redis 被扫、支付回调被人刷接口,这就是配置阶段偷懒的代价。
5. 上线前避坑:最容易翻车的五个位置与排查顺序
5.1 商品图片全部不显示:从 src 里的 localhost 查起
现象:后台传了商品图,小程序端商品列表、详情页图片全部裂开,H5 端正常或同样裂开。
原因:本地开发时文件存储路径默认配置了本机绝对路径,存入数据库的图片地址形如/127.0.0.1:8080/upload/xxx.jpg,微信小程序真机访问不到开发机,自然会裂。另一个隐藏原因是你用了本地图片压缩组件,生成的临时域名不在小程序 downloadFile 合法域名列表里。
解决:先把配置里的yshop.filePath指向一个固定的上传目录,并确认application.yml里的访问前缀已经改成服务器公网域名或 CDN 地址。验证方式是用 curl 请求一张图片的完整 URL,返回200再看小程序端。我一般会加一条基线:所有商品图片地址必须走同一个域名前缀,绝不允许数据库里混存localhost和线上域名,否则换环境时图片数据要写脚本批量修。
5.2 小程序登录失败拿不到 openid:appid 与 secret 的匹配关系
现象:点击授权登录后一直转圈,后端日志报errcode: 40013或invalid appid。
原因:manifest.json 里填的是真实 AppID,但后台系统配置里填的secret却是另一个公众号或测试号应用下的密钥。微信接口校验的是“AppID + AppSecret”组合,不是只看 AppID。
解决:登录微信公众平台,在小程序后台“开发管理/开发设置”里重新生成 AppSecret,复制到后端配置,并保证 manifest.json 的 AppID 和后台配置一致。改完一定要重启后端,因为 secret 通常被缓存到了内存或 Redis。还有一种情况是工具里选择了“测试号”,测试号 AppID 用的不是正式小程序,真机预览时登录同样拿不到 openid,所以排查第一步先确认工具右上角的选择是正确的。
5.3 支付回调报签名错误:APIv3 密钥与证书序列号的对应关系
现象:小程序拉起支付成功,但订单状态一直不变,后台支付日志提示sign verification failed。
原因:微信支付 V3 接口验签要求三个东西同时匹配:APIv3 密钥、商户证书私钥、商户证书序列号。只要有一个填错,回调验签就失败,而且失败后微信不会自动重试到天荒地老,订单会停在“已支付未通知”状态。
解决:用官方工具验证票据,命令是:
# 用商户证书私钥对随机字符串签名 openssl dgst -sha256 -sign apiclient_key.pem -out signature.bin 你的随机字符串.txt然后把签名内容上传到微信支付官方验签工具页面对比。这一步能快速判断是私钥问题还是序列号问题。我实际的落地顺序是:先确认api-v3-key没有空格,再确认serial-no和私钥文件来自同一商户号,最后确认回调地址在商户平台“支付回调配置”里备案。这三项全对,签名错误基本消失。
5.4 订单超时不自动关闭:定时任务被触发却执行不到
现象:下单后不支付,等了 30 分钟订单状态仍是“待付款”,自动取消逻辑像从未存在过。后台任务管理里看得到定时任务记录,但日志没有执行痕迹。
原因:这套系统里订单超时关闭依赖 Redis 延迟队列或 Quartz 定时任务,两种方案都可能失效。前者的问题通常是 Redis 内存淘汰策略把 key 清了,后者的问题则是服务器时区与数据库时区不一致,任务调度到了错误时间点。
解决:先看任务日志,确认调度是否有触发记录;有触发但没执行,查执行的方法是否抛了未捕获异常。我之前抓过一次,原因很简单:任务里调用了第三方快递查询接口,超时设置太短,整个任务在线程池里等待耗死了,后续任务全部积压。解决方法是把集成任务的可选调用包在try-catch里,并给任务方法加@Async注解。从那以后,我所有商城项目的定时任务都会在日志里打执行耗时,不求多精确,只看得出哪个任务卡住。
5.5 后台改配置前台不生效:Redis 缓存比你想的存得更久
现象:后台把“全场包邮”门槛从 99 元改成 199 元,小程序端看到的仍是 99 元;后台清了缓存,过一会儿又变回旧值。
原因:商城前台的系统参数大量做了 Redis 缓存,后台修改操作只更新了数据库,但缓存里的旧值没过期,TTL 可能长达数小时。更隐蔽的是,部分配置缓存是多级结构,修改其中一个字段会更新缓存版本号,但版本号本身也被缓存,导致前端拿到的是过期版本号。
解决:后台的配置保存逻辑通常会触发“清除系统缓存”按钮,但不是所有配置项都接了这个事件。手动清一次 Redis 相关 key 是最直接的验证手段:
# 查看当前业务缓存 key,确认前缀后定向删除 redis-cli keys "yshop:*" redis-cli del "yshop:system_config"清理后刷新小程序端,正常就能看到新值,那说明是缓存层问题。如果清完还是旧值,就要看小程序端本地是否有全局数据缓存——uni-app 端有时候把系统参数存到了本地 storage,这种问题只能改前端代码,把读取配置的逻辑改成每次进首页拉取。排查顺序建议是:先清 Redis,再查小程序 storage,最后才怀疑是后端配置读写路径有 bug,按这个顺序能少走很多弯路。
6. 二次开发验证:一个 curl 脚本确认你的改动真实生效
6.1 改完业务后,我用接口自证而不是肉眼对照页面
商城类项目最怕的就是“感觉改了但没生效”。后端改完一个营销逻辑,光靠刷新小程序页面肉眼对比,很容易忽略缓存和编译问题。我自己的习惯是:每次改完代码,先对着接口层做一次冒烟验证,确认后端输出与预期一致,再去看页面。
比如你改了“积分抵扣比例”的配置,核心逻辑在计算订单金额的服务里。验证步骤是:启动后端,请求购物车结算接口,带上一个拥有积分的测试用户 token,直接看返回的amount字段变化。
# 请求商品详情,确认商品接口正常 curl -s http://localhost:8080/api/goods/detail/1 | python3 -m json.tool # 请求结算预览接口,第二次调用时观察抵扣金额是否变化 curl -s -X POST http://localhost:8080/api/cart/checkout \ -H "Content-Type: application/json" \ -H "token: 你的测试用户token" \ -d '{"cartIds": [12, 13], "usePoint": 1}' | python3 -m json.tool注意看usePoint字段从 0 改成 1 时,返回的payAmount是否按配置比例减少。如果不变,说明积分抵扣的计算没走你改的那条链路,需要回头查调用点是否被缓存或者被另一个同名方法覆盖。这种“接口自证”方式比在小程序里反复下拉刷屏高效得多,也方便让团队其他成员按同一组参数复现验证。
还有一个验证技巧:在关键业务方法里临时加一条带业务标识的日志,比如log.info("calc point deduct, user={}, total={}, point={}", userId, totalAmount, usePoint)。修改后跑一次接口,再通过日志确认你改的方法确实被调用了,而不是被另一个重载方法截胡。这个习惯帮我在多人协作的二开项目里避开了至少三次“改错文件”的尴尬——那两个文件长得实在太像。
从那次以后,我每次拿到一个商城类源码包,第一件事就是把接口列出来,挑两三个核心接口写成 curl 脚本,先跑通再改业务,而不是直接扎进代码里。这种做法能快速判断环境是否健康,也能在交付给客户时拿出一份可复现的验证过程。希望帮到你。
本文还有配套的精品资源,点击获取