
做茶叶商城小程序千万别一上来就聊代码。我去年帮朋友做“潇湘知茶”茶叶购物网上商城系统时第一件事是花了两个晚上蹲在他店里看他怎么卖茶。你得知道你面向的是什么样的用户买茶的人在乎什么然后才谈得上 Spring Boot 后端怎么搭、小程序端怎么调。很多人觉得电商系统不就是商品加购物车加订单嘛照着模板套一套就行但真把茶叶这个品类放进去你会发现从商品建模到库存扣减都有不少需要仔细斟酌的地方。这篇博文我就以“潇湘知茶”这个实际项目为线索把从零搭建一个基于 Spring Boot 框架的微信小程序茶叶商城的完整思路写出来。内容会覆盖项目定位、后端数据结构、小程序登录鉴权、订单状态机、茶叶品类的特殊玩法以及上线前必须处理的部署和审核问题。适合正在做 Spring Boot 毕设、想入门微信小程序电商开发、或者准备把线下茶叶生意搬到线上的朋友参考。1. 潇湘知茶到底解决什么问题项目定位与功能边界做项目之前先想清楚一个问题这个商城小程序的核心消费者是谁茶叶不是标准品同样的龙井明前和雨前价格能差出几倍。如果只是简单照搬普通商品电商的逻辑用户进来根本不知道买什么转化率会非常难看。潇湘知茶的定位是做一个“有品类心智”的 B2C 茶叶商城。目标用户分两类一类是 30 到 50 岁、对茶叶品质有要求但不想跑线下茶城的中年用户另一类是习惯线上购买、喜欢尝试新茶、看重包装和内容故事性的年轻用户。这两类人在小程序里的行为模式完全不一样前者喜欢搜“普洱”“红茶”直接找熟茶后者更容易被首页的“茶山日记”“冲泡攻略”等内容吸引。基于这个定位功能边界就很清楚了。用户端我保留了最小可用的电商闭环微信登录、首页商品推荐、分类浏览、商品详情、加入购物车、下单支付、订单查询、售后申请。管理端则是典型的后台操作商品管理、库存管理、订单处理、发货管理、用户管理。这里我不建议一上来就加拼团、秒杀、分销这类复杂功能先把基础闭环跑通后续作为业务增强再迭代是更稳妥的做法。整个项目的前端我们用的微信小程序原生框架后端是 Spring Boot数据库选了 MySQL中间层用 Redis 做缓存和分布式会话。技术选型上没有追求新奇原则是“团队熟悉、部署方便、社区资料多”。尤其是 Spring Boot打包成 jar 之后扔到服务器上一条命令就能跑起来对有毕设演示或者小规模商业化需求来说性价比非常高。2. 后端骨架搭建Spring Boot核心配置与数据模型设计框架搭起来很快Spring Initializr 把依赖选好项目结构生成之后就算开始了。但我想重点说说数据模型这才是支撑整个业务的地基。很多新手做电商系统喜欢把商品、订单、库存揉在一张表里后面查数据、做统计、扩展逻辑的时候会非常痛苦。2.1 用户表和登录信息表用户表tb_user的主要字段包括id、openid、nickname、avatar、phone、gender、status、create_time。这里要特别提醒一点openid是微信侧的用户唯一标识但不要把它当作业务主键来用。业务主键用自增的idopenid只作为登录态关联字段。因为后续你可能会接入公众号、H5 或者第三方 App如果用户表主键直接用 openid跨平台打通的时候会非常被动。如果是想要记录用户的收货地址建议单独建一张tb_user_address表字段有id、user_id、receiver、phone、province、city、district、detail、is_default。把地址拆出来而不是直接塞到用户表里是因为一个用户可能有好几个收货地址而且地址字段通常比较长混在一起会让用户表变得很臃肿。2.2 商品表和 SKU 设计茶叶商品有个特点规格多。同样一款安化黑茶可能有 250 克袋装、500 克礼盒装、1 公斤收藏装等不同规格。所以我设计了tb_product和tb_sku两张表。tb_product存商品公共信息tb_category_id、name、subtitle、main_image、detail_images、description、status。tb_sku存具体规格信息product_id、spec_name、price、stock、sales、image。这样设计的好处是详情页展示的是商品维度但加购物车和下单时锁定的是 SKU 维度。价格和库存挂在 SKU 上而不是挂在商品上否则同一个商品有不同规格时库存根本对不上。还有一个非常容易被忽略的细节价格字段必须用DECIMAL(10, 2)绝对不要用float或者double。电商里涉及大量加减乘除浮点数的精度问题会造成莫名其妙的金额误差。我见过有人用 double 存储价格订单算下来差了 0.01 元排查半天最后发现是浮点精度在作怪。这种问题在财务对账时就是灾难。2.3 订单表和订单明细表订单相关我拆了两张表。主表tb_order存订单整体信息order_no、user_id、total_price、freight、address_snapshot、status、pay_type、pay_time、delivery_time、finish_time、create_time。明细表tb_order_item存订单里的商品快照order_id、product_id、sku_id、product_name、sku_spec、price、quantity。这里有一个经验订单明细里一定要保存商品名称和规格快照而不是只存 sku_id。因为商品信息是会变的过个半年商家改了商品标题你再去翻历史订单会看到旧的订单里商品名称也跟着变了这显然不合理。快照就是“历史事实”下单时是什么样永远保留什么样。数据库建完之后Spring Boot 这边我用的是 MyBatis-Plus主要用它的BaseMapper来减少简单 CRUD 代码。复杂的连表查询、动态条件筛选还是走 XML 手写 SQL。这里有个原则要守住数据校验尽量在 Service 层做Controller 只负责参数接收和结果封装千万别把业务逻辑写在 Controller 里否则后面项目膨胀起来你会想剁手。3. 小程序登录与Token鉴权从wx.login到拦截器的完整链路微信小程序的登录机制是前后端分离项目里最容易踩坑的地方。很多新手直接把wx.login拿到的 code 传给后端后端把这个 code 当作身份凭证就完事了。这是错的。code 是一次性的有效期只有五分钟而且用完之后就作废它只能用来换取 openid 和 session_key不能作为会话标识。3.1 登录流程拆解整个登录流程应该是这样小程序端调用wx.login()拿到一个临时 code。然后通过wx.request把 code 发到后端接口比如/api/auth/login。后端拿到 code 之后调用微信官方接口jscode2session带上appid和secret换取用户的openid和session_key。后端拿着 openid 去查tb_user如果没查到就说明是新用户自动注册。查到就更新一下最后的登录时间。接下来后端生成一个 JWT Token把userId放进去返回给小程序端。小程序端把 Token 存到wx.setStorageSync里之后的每次请求在 Header 里带上Authorization: Bearer token。这里有个关键点jscode2session接口应该由后端调用绝对不要把appid和secret写在小程序前端代码里。secret 在客户端暴露等于把你的后端完全暴露给攻击者任何人都可以用你的 secret 去换取用户信息。3.2 拦截器和 Token 校验后端我直接写了一个拦截器注册到 WebMvcConfigurer 中拦截除/api/auth/login、/api/product/**、/api/category/**之外的路径。拦截器里的逻辑很简单拿到 Header 中的 token解析 JWT如果 token 不存在或者校验失败直接返回 401。如果解析成功把userId放进请求的 Attribute 里方便 Controller 层取用。JWT 的密钥我用的是 HMAC-SHA256 对称算法生成密钥沉淀在配置文件中通过环境变量注入不写死在代码里。Token 的有效期设置在 7 天左右比较合理。用户不活跃之后需要重新登录虽然体验上会稍微繁琐一点但对后台的安全性和服务的可管理性来说是必要的。实测下来这种 Token 机制在微信小程序里非常稳定配合wx.request的统一封装后期加个响应拦截器还能顺手处理 401 跳转重新登录。4. 购物车与订单模块状态流转和库存防超卖的实现策略购物车和订单是电商系统里事故高发区技术难点不在 CRUD而在数据一致性和状态管理。4.1 购物车是临时的还是持久的购物车我选择了持久化到 Redis。为什么不用数据库表因为购物车的数据特点是读多写少、不需要事务、也不需要跨表查询放在 Redis 里用 Hash 结构存效率最高。Redis 的 key 可以设计成cart:userIdfield 可以设计成skuIdvalue 就是quantity。当然这个方案在用户清空浏览器缓存或者退出登录后会丢失数据但是对不是强依赖购物车营销的场景来说Redis 的方案完全够用。如果你做的是深度电商需要用户在网页端和 App 端购物车同步那就得改用 MySQL 表来持久化。4.2 库存防超卖的核心逻辑重点说说库存防超卖。比如一个 SKU 初始库存是 10同时有 10 个用户下单每个买 1 件。如果下单逻辑是先查库存如果库存充足就执行 update 扣减在并发场景下会发生超卖因为多个线程可能同时读到库存为 10。解决方案我用的是乐观锁。在tb_sku表增加一个version字段每次扣库存时执行这样一段 SQLUPDATE tb_sku SET stock stock - 1, sales sales 1, version version 1 WHERE sku_id #{skuId} AND version #{oldVersion};执行完之后检查影响行数如果返回 0 说明这个版本的库存已经被别人更新过了当前操作失败需要重试或者直接提示用户库存不足。这样可以从底层保证不会出现卖超的情况。如果用 Redis 做扣减也可以借助 Lua 脚本来保证原子性核心思路是一样的。4.3 订单状态流转设计订单状态我定义在tb_order.status字段中用的是整数状态码维护起来更清晰。订单创建之后是 0待付款用户付款之后变成 1待发货商家发货之后变成 2待收货用户确认收货之后变成 3已完成。如果用户下单之后没有付款系统提供一个取消订单功能状态变成 4已取消。如果发货之后用户不满意可以提交售后申请订单状态变成 5售后中。这里有个细节状态的流转必须通过接口来做不要允许前端直接修改后端数据。用户点击“确认收货”之后后端接口要判断当前订单状态是不是 2只有状态为 2 的订单才能流转到 3。这个校验一旦疏忽就会出现订单状态乱跳的 bug。我在给系统写状态更新的时候用了简单的状态机校验而不是直接信任前端传过来的目标状态。5. 茶叶电商的差异点会员运营、营销工具与内容化改造基础版商城跑通之后潇湘知茶马上面临一个问题和淘宝、京东上的茶叶品牌店比小程序凭什么留住用户如果还是靠价格战那做小程序的意义就不大了。茶叶消费的决策周期长、复购逻辑强、内容属性重所以我们在系统里做了几个改进。5.1 轻量级会员积分系统茶叶是典型的“长期复购”型商品用户一旦认可了一款茶会持续购买。所以我加了积分模块。用户在商城消费后按比例获得积分积分可以抵扣下单金额。比如满 100 元积 5 分100 分抵 2 元。这个模块初期实现起来不复杂tb_user_points表记录积分流水tb_point_rule表配置规则下单时检查用户积分余额计算抵现金额。不过要小心比例控制比例太高容易变成恶性促销商家利润直接被积分吃掉。建议初期控制在 1% 到 2% 的积分抵扣比例后续根据毛利用户数据再调整。5.2 内容化商品详情页传统的商品详情页是图片加文字干巴巴的。茶叶不是标品用户更想知道“这款茶产自哪里、工艺有什么特殊、口感如何、该怎么泡”。所以潇湘知茶的详情页做成了“图文长文 冲泡视频 产品属性表格”的混排模式。在 Spring Boot 后端我设计了一个tb_content_block表来存储详情页的内容模块每个模块有类型字段可以是图片、标题、段落、视频渲染时按 sort 字段输出到小程序端。这样改动的好处是运营可以像写文章一样去维护商品详情而不是每次改详情都要改动整个页面代码。内容化改造对茶叶转化率的提升非常明显用户能通过内容建立信任感下单决策周期也会缩短。5.3 分销裂变的实现方案小程序本身有天然的社交传播基因。我在后台加了一个简单的分销接口用户分享商品给好友好友通过分享链接进入小程序并下单后分享者可以获得一笔佣金。技术实现上用的是tb_distribution_record表记录分享者、购买者、商品、佣金比例。分享时前端在 URL 里带上share_user_id小程序启动时拿到这个参数通过接口上报给后端。下单时系统会检查是否存在有效的分享关系如果有就在记录表里插入一条待结算佣金。在合规层面这个功能要注意别做成多级分销维持在《电商法》允许的推荐返利范畴不要碰金字塔式的层级计酬这也是我实际开发中反复提醒自己的点。6. 上线部署避坑清单HTTPS、小程序类目与常见审核驳回项目开发完之后部署和上线又是一道坎。我这个系统在本地跑得好好的一上生产环境就遇到各种奇葩问题这里把我踩过的坑集中列一下。6.1 服务器和域名配置小程序要求所有请求域名必须配置在微信公众平台后台的服务器域名白名单里而且必须是 HTTPS。所以我买一台云服务器装完 Docker 之后用 Nginx 做反向代理把后端 Spring Boot 的 8080 端口代理到 443 端口同时配置 SSL 证书。Docker 部署 Spring Boot 的 com.sourecode 配置大概是这样FROM openjdk:8-jre-alpine COPY target/xiaoxiangzhicha.jar /app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, /app.jar]然后在服务器上用docker build -t xiaoxiangzhicha:latest .构建镜像再通过docker run -d -p 8080:8080 --name xiaoxiangzhicha xiaoxiangzhicha:latest启动容器。Nginx 里配置 SSL 证书然后把location /api/反代到http://localhost:8080。注意在微信开发者工具里调试时可以勾选“不校验合法域名”但真机预览和线上版本绝对不能勾这个选项。6.2 小程序审核的典型驳回理由小程序审核是我见过最容易让人心态爆炸的环节。茶馆电商的小程序审核通常会因为类目不符被驳。茶叶属于食品类目需要提供食品经营许可证资质文件要提前上传。如果你的小程序涉及茶叶分销、佣金提现审核还会特别关注是否存在传销风险所以在小程序页面上要避免出现明显的“三级返佣”“无限代提成”等字眼积分和平价返利也要注意表述。还有就是用户隐私协议。小程序里如果收集了用户的手机号、收货地址必须在小程序后台配置用户隐私保护指引否则提交审核会以“隐私不合规”被驳回。这个坑几乎人人都会踩建议动工之前就把隐私政策文档准备好。6.3 数据备份与线上监控上线之后最怕数据库出问题。我配置了每天凌晨的自动备份使用mysqldump把整个xiaoxiangzhicha库备份到远程存储保留最近 7 天的备份文件。同时业务日志和异常日志都会写入到文件里方便出现问题时排查。小程序端也加了wx.reportMonitor之类的基础上报配合服务端日志定位问题。实际跑下来我觉得做商城系统切忌“毕设思维”为了做出来而做。把业务想透、把数据表设计清楚、把状态流转校验好、把运营内容充实起来这套基于 Spring Boot 的茶叶商城才真正能从小程序商店的列表里被人挑中。微信生态每年都在变主题设计也好、支付接口也罢那些都是工具层面的东西对用户价值的理解才是不容易被替代的。希望这篇复盘能帮正准备做同类项目的朋友少走点弯路。