微信小程序商城源码实战:Spring Boot+微信支付v3完整解析

发布时间:2026/9/8 6:02:49

微信小程序商城源码实战:Spring Boot+微信支付v3完整解析
简介微信小程序商城完整源码是一套可直接运行的电商小程序项目面向需要搭建微信商城或学习小程序开发的读者覆盖商品展示、购物车、订单管理、支付等核心流程适合从入门到进阶的小程序开发者参考使用。资源共60个文件压缩包仅412KB以WXML页面结构、WXSS样式、JS业务逻辑、JSON配置和PNG图片素材为主并附带一份docx源码说明文档目录包含pages、components、utils、models等模块页面结构清晰方便按模块查阅。目前已有7720人学习下载。通过该源码既能快速搭建可用的商城基础框架也能深入理解全局配置、页面生命周期、网络请求与支付对接等实现细节帮助开发者在实际项目中少走弯路。 我做小程序开发这些年商城类项目是接得最多的一种需求。而“微信小程序商城完整源码”这类搜索词的热度一直居高不下说明大家都在找一个能直接跑起来、结构清晰的参照系而不是那些下载下来就报错、缺配置、前后端对不上的半成品。这篇文章就围绕我从零搭建的一套小程序商城项目来拆解。整套源码包含用户登录、商品浏览、购物车、下单、微信支付v3、订单管理和售后流程后端用的是Spring Boot小程序端是原生框架数据库走MySQL。目的是给正在做毕设、面试项目或刚入职需要接手商城开发的读者提供一个可以直接借鉴的完整方案。1. 整体架构与模块划分1.1 为什么选前后端分离小程序商城和传统网页商城最大的区别在于运行环境。小程序有自己的生命周期、网络请求白名单和登录态体系天然适合前后端分离的结构。前端只负责页面渲染和交互所有业务逻辑、权限判断都收敛到后端接口这样小程序包体积小、加载速度快也方便后续如果要出App端、H5端接口可以直接复用。我在这套源码里把后端拆成了五个核心模块认证模块登录态、Token签发、商品模块SPU/SKU管理、分类、搜索、交易模块购物车、订单、支付、退款、营销模块优惠券、限时折扣、用户模块收货地址、个人资料、积分。模块之间通过统一的API层通信互相不直接调用对方的Mapper这样后期要扩展分销、秒杀之类的功能时不会牵一发动全身。1.2 数据库表设计的几个关键点商城最核心的几张表是商品表spu、规格表sku、购物车表cart、订单表orders、订单明细表order_item、支付流水表pay_log。我的设计原则有两个第一是SKU独立成表不把规格塞进商品表的JSON字段里因为后面要做库存扣减和价格计算JSON字段查起来非常痛苦第二是金额字段统一用分存储用int类型而不是decimal的元这样可以避免浮点运算的精度问题也符合微信支付对接时的单位要求。订单状态我用的是状态机字段名叫order_status取值范围是待支付(0)、已支付待发货(1)、已发货待收货(2)、已完成(3)、已关闭(4)、退款中(5)、已退款(6)。每次状态流转都必须通过订单服务层的方法来操作不允许在Controller里直接改状态这个约束能避免很多因为状态跳变导致的资损问题。1.3 源码目录结构与关键文件说明拿到源码之后可以先按这个结构快速找到对应功能的实现位置后端结构src/main/java/com/mall/ ├── controller/ // 接口层只做参数接收和数据返回 ├── service/ // 业务逻辑层核心代码都在这 ├── mapper/ // MyBatis数据访问层 ├── config/ // 微信配置、拦截器、线程池配置 ├── common/ // 统一返回体、异常处理、工具类 └── model/ // 实体类和DTO/VO小程序端结构pages/ ├── index/ // 首页 ├── category/ // 分类页 ├── cart/ // 购物车 ├── goods/ // 商品详情 ├── order/ // 订单确认和列表 ├── pay/ // 支付结果 ├── user/ // 个人中心 └── address/ // 收货地址管理小程序的网络请求我统一封装在utils/request.js里所有请求都会自动带上Token并且做了HTTP状态码和业务码的双重判断。这套封装逻辑在一开始就写好的话后面调试支付、订单这些核心流程会省非常多的时间。2. 商品浏览与购物车的核心逻辑2.1 商品列表的加载方式首页和分类页的商品列表我一开始是用传统的分页方式做的page和size两个参数传给后端。后来发现小程序的用户习惯是不断往下滑所以改成了游标分页用lastId来定位位置这样即使用户在短时间内快速翻页也不会出现重复数据的问题。商品详情页比较麻烦的地方在于SKU的选择。用户需要先选规格比如颜色、尺码然后前端展示对应的价格和库存。我这里的实现是后端一次性返回商品下所有SKU的完整数据前端在内存里做规格匹配不需要每次切换规格都请求一次接口。这个方案在处理几十个SKU的商品时性能足够小型商城不需要上SKU树结构那些复杂算法。2.2 购物车的计算链路购物车有个所有人都会踩的坑前端自己计算合计金额。小程序端改一下商品数量前端就本地算一个总价传到后端去下单这种情况下如果后端不重新校验用户完全可以通过篡改请求参数来减价。我的处理方式是购物车接口返回的每一项里都带上最新单价前端展示用下单时后端必须根据购物车ID重新从数据库查询价格和库存以服务端计算结果为准。还有一条经验是购物车要区分“选中”和“全选”的状态存储。我一开始把选中状态只存在前端storage里后来发现用户换设备后购物车还在选中项却丢了。调整方案是把选中状态同步到后端购物车表里加一个checked字段这样多端同步就不会有问题。2.3 订单确认页的价格组成订单确认页的价格组成看起来简单实际上容易乱商品金额、运费、优惠券抵扣。运费的计算规则我是单独抽了一个FreightCalculator类来处理规则是满99元包邮不满则收8元特殊商品比如大件家电在商品表里单独用freight_type字段标识为不参与包邮。优惠券的设计稍微复杂一点。优惠券需要区分满减券、折扣券和免邮券每一种的使用条件判断逻辑都不一样而且一张券只能用一次必须保证并发下单时不会被重复使用。实现时我在数据库里给优惠券表的used_status字段加了乐观锁更新时带上当前状态值更新影响行数为0就说明已经被用了。3. 微信支付v3对接全流程记录3.1 商户平台配置准备微信支付v3和v2最直观的区别就是v3的API是RESTful风格数据格式全部用JSON而且API密钥体系升级成了证书 私钥双重验证。对接之前需要准备的配置有商户号、商户API证书p12或pem格式、商户私钥、微信支付平台证书以及APIv3密钥。其中APIv3密钥是在商户平台手动设置的32位密钥用来解密回调数据。这一步最容易出错的地方是证书序列号。v3签名时Header里需要带Wechatpay-Serial很多新手会把API证书序列号和这个混在一起。记住一个规律请求时带的是商户API证书的序列号验签时用的平台证书只是用来解密和验签不需要在请求头里带它。相关配置我放在后端的application.yml里只引用路径不写死绝对路径方便不同环境切换wechat: pay: merchant-id: 你的商户号 api-v3-key: 你的APIv3密钥 private-key-path: /cert/apiclient_key.pem merchant-serial-number: 商户证书序列号 notify-url: https://你的域名/api/pay/callback3.2 服务端下单与小程序拉起收银台支付的下单流程实际上有两步第一步是后端调用微信支付的“小程序下单”接口拿到prepay_id第二步是后端用自己的私钥生成二次签名参数返回给小程序的wx.requestPayment拉起收银台。很多人在第一步成功后就直接把prepay_id丢给前端这是不对的小程序端必须要第五个参数paySign而这个签名必须由后端生成不能由前端自己算。后端下单核心代码的大致思路是// 构建请求参数金额单位必须为分 MapString, Object body new HashMap(); body.put(appid, appid); body.put(mchid, merchantId); body.put(description, 商城商品购买); body.put(out_trade_no, orderNo); body.put(notify_url, notifyUrl); MapString, Integer amount new HashMap(); amount.put(total, totalFee); // 单位是分不是元 amount.put(currency, CNY); body.put(amount, amount); body.put(payer, Collections.singletonMap(openid, openid)); // 统一下单 String response wxPayClient.post(/v3/pay/transactions/jsapi, body);拿到响应里的prepay_id之后后端需要生成小程序端拉起支付所需的签名参数appId、timeStamp、nonceStr、package值为prepay_idxxx然后用商户私钥做SHA256签名一并返回给前端。小程序端拉起支付的代码就是标准的wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: RSA, paySign: res.data.paySign, success: () { /* 支付成功跳转 */ }, fail: () { /* 用户取消或支付失败 */ } });3.3 支付回调这一步千万不能掉以轻心支付回调是后端最核心的接口。这里有一个很关键的原则回调接口不能把微信发过来的数据直接当信任数据用。必须做两件事第一用微信支付平台证书验证签名确认这条通知确实是微信官方发来的第二使用APIv3密钥解密resource节点中的数据获取真实的订单号和支付金额再用这个解出来的金额和本地订单表的金额做一致性对比金额对不上必须直接报错。回调的处理逻辑我放在一个独立的服务里面避免和Controller写在一起。处理完后必须给微信返回一个应答格式固定为{code:SUCCESS,message:成功}如果业务处理失败要返回非SUCCESS的状态微信才会按照间隔策略继续重试。这里有一个很隐蔽的问题如果回调处理耗时太长超过5秒微信就会判定超时并重试所以回调里不能做太多耗时操作比如发短信通知用户之类的应该丢到消息队列里异步处理。3.4 支付返错排查我在对接过程中遇到最多的错误码是SIGN_ERROR基本上都是私钥加载不正确或者签名算法用错了。还有INVALID_REQUEST这种一般是必填参数缺失要重点检查openid是不是当前小程序下的金额单位是不是传成了元。另外注意v3接口的错误信息是藏在响应体里的很多人在拦截器里直接把整个异常包装成了业务异常根本看不到原始报错调试阶段一定要把微信返回的完整错误信息打出来。4. 接口安全与性能优化细节4.1 Token机制的落地方式小程序的登录态有一个特点就是wx.login获取的code只能用一次用于跟微信服务器换openid和session_key。我这套源码里每次登录都会用code交换openid后端生成一个随机token并缓存到Redis里有效期是2小时token过期后前端会拦截401响应自动用wx.login重新走一遍静默登录流程。用户手机号解密这里也要提一句。小程序端获取手机号时的加密数据需要后端来解密解密需要用会话密钥session_key而且这个session_key不会长期有效所以不要想存下来反复用。我的做法是不持久化session_key每次需要解密时临时重新获取确保拿到的session_key和当前code是对应的。4.2 参数校验与敏感操作幂等商城的接口有很多是敏感操作比如下单、提交订单这类接口必须做幂等处理。我采用了TokenIdempotent注解的方式前端在提交订单时先在OrderTokenController里申请一个临时幂等令牌后端把令牌存入Redis过期时间5分钟提交订单时校验并删除令牌。如果用户连点两次提交第二次就会被拦截从源头上解决了重复下单问题。另外后端参数校验不要自己在Controller里if-else写一堆用Spring的Validation注解配合全局异常处理器能把大量重复代码收敛掉。所有金额类的参数前端传上来之后后端都要重新判断一遍不能信任前端的计算结果。4.3 缓存与数据库优化商品详情页是全站流量最高的接口每次都查数据库肯定扛不住。我把首页Banner、分类导航、热门商品列表都加了一层Redis缓存过期时间设置成10分钟后端更新商品时通过CacheEvict主动清缓存。这样做的效果非常明显商品详情接口的响应时间从平均300ms降到了40ms左右。数据库层面主要做了两件事第一是给订单表的out_trade_no加了唯一索引防止重复支付回调导致订单状态被覆盖第二是给订单明细表冗余了商品名和商品快照图这样订单历史记录就不会因为商品下架或改名而显示异常。5. 上线阶段碰到的实际问题与排查记录5.1 支付正常但订单状态不更新上线第一天就遇到了一个典型的回调问题用户能正常付款微信支付后台也能看到交易记录但小程序里的订单状态一直没有变成已支付。排查流程是先查看后端日志发现回调接口根本没有收到微信的请求。继续排查之后发现问题出在服务器安全组没有放行HTTPS端口微信服务器连不上回调地址自然就一直重试。配置回调地址还有一个容易踩的坑回调地址必须是外网能直接访问的HTTPS地址不能用IP地址而且域名需要ICP备案。如果只是本地调试可以用内网穿透工具把自己的本机服务映射出去但上线之前一定要换成正式域名否则微信支付会在几次重试后直接关掉这笔订单的后续通知。5.2 小程序端swiper与video组件的全屏冲突商品详情的轮播图区域我用了swiper后来运营说要在详情页里再嵌一个商品视频结果出现了iOS端点击视频全屏后关闭全屏时页面错位的情况。这个问题的根源是swiper组件和video组件在全屏切换时的层级计算有冲突属于原生组件在WebView渲染时的历史遗留问题。当时我试过两种方案。第一种是把video改成在弹层里播放全屏时用cover-view覆盖效果可以但交互上多了一步。第二种方案更省事不在swiper里嵌套video把视频移到详情页独立模块同时给video设置了enable-progress-gesture和show-center-play-btn再配合page-orientation设置全屏退出后的错位问题就消失了。如果你必须把视频放进swiper至少要在bindfullscreenchange里手动处理一下当前页面的滚动高度。5.3 软键盘遮挡底部查询按钮商品搜索页里因为商标的筛选区在页面底部iOS端唤起软键盘时经常会出现键盘区域刚好压住查询按钮的问题。小程序里给输入框都加了adjust-positiontrue但文本输入框聚焦时页面只是整体往上推底部区域还是会被遮住。一个比较稳的处理是在输入框聚焦和失焦事件里手动调整底部按钮的位置。具体做法是用wx.onKeyboardHeightChange监听键盘高度然后把按钮的bottom值动态设置成键盘高度加10像素。Android端键盘行为有时候不触发这个事件所以还要在失焦事件里把bottom重置回初始值。这个补丁很小但直接影响用户能不能顺利点到按钮属于上线前必须处理的那类问题。5.4 微信支付v3的常见报错速查表现象原因解决方案下单报SIGN_ERROR商户私钥加载错误或签名串格式不对检查私钥文件格式确认签名串拼接顺序回调验签失败平台证书版本过期或证书序列号取错下载最新平台证书并更新证书序列号拉起收银台报invalid signature前端paySign生成算法错误确认后端签名字段拼接方式与官方规则一致用户支付成功但订单未更新回调地址不可达或业务逻辑异常查后端日志确认是否收到回调检查接口幂等金额单位错误导致报错把元当分传给了微信所有金额统一转换为分再传输退款时报PARAM_ERROR证书加密数据解密失败确认使用APIv3密钥解商户证书私钥加密数据写在最后踩坑踩得多了之后我自己最大的体会是商城项目的核心不在于页面多好看、功能多丰富而是在订单和支付这条主链路上不能有任何逻辑漏洞。支付回调、幂等控制、金额校验这些模块无论项目多小都要认真对待因为一旦出了资金安全问题代价不是改几行代码能弥补的。最后再分享一个小技巧做支付联调的时候微信支付后台有沙箱环境可以模拟支付成功、支付失败、退款成功等各种情况不要直接拿生产环境反复测试先把沙箱链路跑通再切正式参数会省掉非常多的麻烦。本文还有配套的精品资源点击获取

相关新闻

CRM系统选型与落地:从免费SaaS到开源二次开发实战指南

CRM系统选型与落地:从免费SaaS到开源二次开发实战指南

2026/9/8 5:52:48

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

基于SpringBoot的社区居民服务系统:从需求拆解到代码实现全攻略

基于SpringBoot的社区居民服务系统:从需求拆解到代码实现全攻略

2026/9/8 5:52:48

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

STM32L151RCT6低功耗MCU全解析:原理、实操与选型对比

STM32L151RCT6低功耗MCU全解析:原理、实操与选型对比

2026/9/8 5:52:48

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

轻量级AVI播放器开发:MCIWnd控件实战与避坑指南

轻量级AVI播放器开发:MCIWnd控件实战与避坑指南

2026/9/8 7:02:51

简介:基于MCIWnd控件的AVI视频播放器是一份适合Windows平台初学者的多媒体编程工程资源。它围绕MCIWnd控件,实现了通过菜单选择视频文件并在客户区左上角动态创建播放窗口的功能,帮助开发者理解视频播放器窗口生成、文件关联及播放控制条调用…

VSCode+OpenOCD+ST-Link搭建STM32调试环境全攻略

VSCode+OpenOCD+ST-Link搭建STM32调试环境全攻略

2026/9/8 7:02:51

这些年用VSCode写STM32的人肉眼可见地多起来了。我之前一直用厂家自带的IDE干活,直到有次同时维护三个板卡工程,每个工程代码量都不小,Eclipse内核的编辑器索引卡到怀疑人生,才下定决心迁到VSCode CubeIDE OpenOCD ST-Link这套…

SSM医疗健康管理项目实战:从环境搭建到部署论文全流程解析

SSM医疗健康管理项目实战:从环境搭建到部署论文全流程解析

2026/9/8 7:02:51

你拿到“SSM医疗健康管理808lk”这个项目包的时候,大概率已经被目录里面一堆源码、数据库脚本、开发环境说明、还有那篇上万字的论文文档给淹没了。我最早接触这类项目是在帮学生做课程设计和毕业设计辅导那阵子,自己也动手跑通过好几个类似结构的管理系…

基于MFC的表达式解析计算器:中缀转后缀与界面交互实战

基于MFC的表达式解析计算器:中缀转后缀与界面交互实战

2026/9/8 7:02:51

简介:一款基于MFC的简易计算器项目源码,面向希望学习Windows界面编程与表达式解析的C开发者。项目从词法分析、语法分析到后缀表达式求值,完整覆盖数字、四则运算符与括号的识别,并实现了运算符优先级校验与配对检查;在…

DeepSeek Harness:空城计式轻量编排,从概念到工具调用实战

DeepSeek Harness:空城计式轻量编排,从概念到工具调用实战

2026/9/8 7:02:51

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

从Demo到生产:腾讯云上构建全能AI Agent的完整实践

从Demo到生产:腾讯云上构建全能AI Agent的完整实践

2026/9/8 6:52:51

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/7 20:21:46

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/8 4:55:53

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/7 8:03:37

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

芯片良率波动可视化:动画拆解工艺因果,重建客户信任

2026/9/8 0:02:30

芯片这个行业有个不太被人摆到台面上、但几乎每天都在发生的场景:客户拿着一条良率曲线截图问你,这批货的良率怎么掉了三个点,是不是工艺出问题了,产生的不良会不会流到他们产线上去。你解释了半天,客户似懂非懂&#…

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

PyTorch DataLoader参数冲突:sampler与shuffle互斥的根源与正确写法

2026/9/8 0:02:30

ValueError: sampler option is mutually exclusive with shuffle,这个报错我在 PyTorch 的 DataLoader 上至少见过几十次了,而且很有意思的是,它经常不是新手专属——很多写了好几年模型的老手,在从单机改成自定义采样器&#xf…

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

中国车企再破谣言,GAC吉利零跑获欧盟安全五星

2026/9/8 0:02:30

有人可能在网上开着皮卡拍视频,声称中国电动车不仅性能不如美国大排量车型,安全性也堪忧。然而事实恰恰相反,GAC、吉利和零跑最新推出的电动车型在极为严苛的欧盟新车安全评鉴(Euro NCAP)测试中全部斩获满分。就在特斯…

远程协作的工作台整理

远程协作的工作台整理

2026/9/8 4:23:39

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…