
简介本资源是一套完整的微信小程序酒水商城实战项目源码面向前端初学者及小程序开发入门者旨在通过真实电商场景帮助掌握小程序核心开发技能。压缩包共58个文件包含9个JavaScript逻辑文件、8个WXML页面结构文件、8个WXSS样式文件、8个JSON配置文件及24张图片资源整体大小1.83MB结构清晰覆盖首页、商品列表、详情、购物车、订单、用户中心等典型模块。已有229人学习下载体现了较强的实践参考价值。读者可直接运行调试深入理解WXML/WXSS组件化开发、setData数据驱动、wx.request网络请求、事件绑定与购物车状态管理、微信支付对接流程等关键环节并借鉴其页面路由设计与模块化组织方式为后续电商类小程序开发提供可复用的代码范式与工程结构参考。 做了这么多年小程序开发微信小程序商城的活儿接了不下二十个这次整理的一份酒水商城案例源码算是把这类项目的常规套路完整沉淀下来了。从登录授权、商品展示、购物车到支付订单再到管理员后台的商品上下架和订单处理一整套流程都是能直接跑的。如果你正打算做电商类小程序或者想找一份结构清晰、能二次开发的源码做参考这篇文章值得你花几分钟看完。我会把项目里最核心的设计思路、关键代码实现、以及开发微信小程序商城时容易踩的坑全部拆开来讲。1. 项目概述一套能跑通全流程的酒水商城到底包含什么1.1 从需求场景看这套源码的价值先说说市面上小程序商城的现状。很多初学者在小程序开发者工具里导入一个源码包发现页面能打开但登录联不通、支付调不起、后台数据写不进原因多半是前后端没有完整贯通。这套酒水商城案例源码之所以适合拿来学习和二次开发就是因为它不是单纯的前端壳子而是把前端小程序、后端服务、数据库和管理后台打通了形成了一个可演示、可上线、可扩展的闭环。所谓可演示是指你导入工具后修改少量配置就能用测试账号跑通从浏览商品到提交订单的完整路径。可上线意味着接口权限、支付参数、域名白名单这些都已经按微信生态的规范预留了位置缺的只是你自己的商户号和证书密钥。可扩展则体现在代码分层清楚加一个促销模块、加一个优惠券功能不需要推翻重来。这套源码适合三类人一是刚学完小程序基础、想做项目练手的开发者二是产品经理或运营想快速理解商城类小程序的功能边界三是有定制需求、想在现成项目上快速改版的创业者。不管你是哪种角色先花十分钟把目录结构看懂后面就顺手多了。1.2 为什么酒水品类能代表一类典型电商项目有人可能会问为什么偏偏是酒水商城而不是通用的XX商城。这里的门道在于酒水商品在电商系统里是最难做好的品类之一比卖衣服、卖数码产品更考验系统的细节处理能力。酒水有典型的规格属性同一款酒可能有单瓶、双瓶礼盒、整箱装不同规格价格不同库存独立甚至条形码都不同。这就是电商领域常说的SKUStock Keeping Unit库存量单位管理。普通商品只需要把一张图、一个价格、一个库存丢上去而酒水必须走规格组合前端选择规格时价格、库存、图片、条码要联动变化。这套源码里的SKU选择器就是专门为一个商品挂多个规格设计的。还有保质期和批次问题。酒类虽然是越陈越香但啤酒、果酒、低度数预调酒都有明确保质期仓储端需要按批次入库、按先进先出原则发货。后台如果不记录批次过期酒水照样被当成正常库存卖出去迟早出问题。源码里的库存表保留了批次字段就是为这个场景设计的。另外酒水是高客单价商品用户的支付信任门槛较高。小程序的支付流程、订单状态流转、售后处理都比普通商品要求更严谨。一套源码如果能把酒水这类复杂商品管理好换成熟食、零食、美妆等品类基本就是改改字段的事。2. 技术选型与项目架构拆解2.1 原生小程序 vs uni-app/Taro我为什么这么选市面上做小程序商城主流技术方案有三类微信原生小程序、uni-app、Taro。这套源码选用的是微信原生小程序加后端API的模式并不是说其他方案不好而是原生方案在商城这类复杂交互场景里有它独特的优势。原生小程序的开发语言是WXML、WXSS和JavaScript微信开发者工具提供的调试体验最直接编译速度快API 调用的兼容性也最好。你写一句wx.request工具就能直接帮你补全参数真机调试的报错信息也最完整。相比之下uni-app 虽然能一套代码多端复用但在处理微信特有能力时经常需要条件编译绕来绕去遇到问题排查成本会高一些。Taro 更适合团队中有 React 背景的开发语法是类 React 的但对于没有 React 经验的人来说学习曲线也够陡的。当然这不代表原生方案没有短板。原生小程序不支持直接使用现代前端框架的组件化开发思维但通过官方自定义组件机制照样能把页面拆得足够细。这套源码里商品卡片、数量选择器、订单状态标签都封装成了独立组件结构上并不输给 Vue 或 React 方案。如果你是个人开发者或者小团队我建议优先选择原生方案。原因很简单市面上能百度到的周边生态、踩坑文章90%都是原生小程序的。你遇到问题搜解决方案的速度直接决定开发效率。2.2 目录结构与模块划分的心法一个清晰的小程序目录结构应该做到见名知意。这套源码的目录划分值得抄作业├── app.js # 全局逻辑会话管理全局配置 ├── app.json # 页面路由、窗口样式、分包配置 ├── app.wxss # 全局样式变量 ├── project.config.json # 项目配置包含appid等 ├── pages/ │ ├── index/ # 首页轮播、金刚区、推荐商品 │ ├── category/ # 分类页左右联动布局 │ ├── goods/ # 商品详情页SKU弹窗、加入购物车 │ ├── cart/ # 购物车勾选、改数量、结算 │ ├── order/ # 订单列表与详情 │ ├── pay/ # 支付结果页 │ └── mine/ # 个人中心地址、优惠券、设置 ├── components/ # 公用组件 │ ├── sku-popup/ # SKU选择弹窗 │ ├── number-stepper/ # 数量增减组件 │ └── empty/ # 空态占位组件 ├── utils/ │ ├── request.js # 请求封装拦截器token注入 │ ├── auth.js # 登录态管理 │ └── util.js # 金额格式化、时间格式化 └── api/ ├── goods.js # 商品相关接口 ├── cart.js # 购物车接口 ├── order.js # 订单接口 └── user.js # 用户接口pages 目录下的页面全部通过app.json注册分包策略也在这里配置。components 目录是所有可复用组件的家这样首页和商品详情页想用同一个 SKU 弹窗直接引用组件路径即可不重复写逻辑。api 目录单独放接口函数是很多新手容易忽略的好习惯。不要在每个页面里直接写wx.request而是把请求 URL、方法、参数统一封装在 api 模块里。这样一旦后端接口地址变了你只需要改一个文件而不是满项目搜索。utils/request.js 是整小程序请求的中枢。它统一处理wx.request的封装自动注入 token收到 401 时自动跳转登录页还能在请求头里加上版本号方便后期接口治理。2.3 前后端接口设计与数据表建模后端接口遵循 RESTful 风格资源用名词复数动作用请求方法区分。比如GET /api/goods获取商品列表POST /api/cart添加购物车PUT /api/order/{id}更新订单状态。这种风格的好处是接口语义清晰前端调用时基本不用看后端代码猜都能猜出用途。数据表设计上关键几张表要单独拿出来讲product 商品表id, name, main_image, detail_images, status, sort, created_at sku 规格表id, product_id, name(如500ml单瓶), price, stock, barcode, image cart 购物车表id, user_id, sku_id, quantity, checked, created_at order 订单表id, order_no, user_id, total_amount, pay_status, ship_status, created_at order_item 订单明细表id, order_id, sku_id, product_name, price, quantity user 用户表id, openid, nickname, avatar, phone address 地址表id, user_id, name, phone, province, city, detailproduct 和 sku 是典型的一对多关系一个酒水商品挂多个规格。order 和 order_item 也是一对多一个订单里包含多种商品。之所以要拆出 order_item是因为下单那一刻的商品名称、价格、图片需要固定下来。如果只记录商品ID将来商品改名或下架历史订单的展示就全乱套了。库存扣减这块源码里用的是预扣库存方案。用户提交订单时不是立即减库存而是先把库存锁定支付成功后再真正扣减订单超时未支付则释放锁定。这样做的好处是避免高并发下用户拍下商品后无法支付的尴尬同时也是所有正规电商平台都在采用的做法。3. 核心功能模块与关键实现3.1 微信登录与静默授权微信小程序的登录流程是很多新手第一次接触时容易懵的地方。先说结论小程序的登录不是为了让你登录而是为了把微信的 openid 和你自己后端的用户体系绑定起来。登录时序分三步小程序端调用wx.login获取一个临时凭证 code这个 code 有效期只有五分钟而且只能用一次。小程序把 code 发给自己的后端服务器后端拿着 code 加上小程序的 appid 和 secret调用微信的jscode2session接口换取 openid 和 session_key。后端查一下 user 表里有没有这个 openid没有就自动注册一个新用户然后用自己的加密算法签发一个业务 token 返回给小程序端。// 小程序端登录核心代码 wx.login({ success: async (res) { const { code } res; // 将code发送到自己的后端 const loginRes await request.post(/api/user/login, { code }); // 拿到自己后端的token wx.setStorageSync(token, loginRes.data.token); } });这里有个细节值得提醒不要把 appid 和 secret 写在小程序前端代码里。secret 是后端密钥泄露了别人就能冒充你的小程序调用微信接口。正确做法是 secret 只保存在后端配置里前端只传 code。另外wx.getUserProfile这个获取用户头像昵称的接口在最新的微信基础库版本里已经做过调整真实场景是用户点击授权按钮后触发。源码里已经处理了未授权时用默认头像昵称的降级逻辑毕竟用户完全有权拒绝授权你不能因为这个卡住不让下单。3.2 商品列表与搜索排序首页的商品列表不是简单地把数据库所有商品查出来丢给前端。源码里做了三层处理分页、排序、筛选。分页是必须的酒水商城动辄上百个SKU全量一次性返回会拖垮首屏渲染。代码里采用传统的page和pageSize参数后端返回total总数前端据此判断还有没有下一页。// 请求商品列表 export function getGoodsList(data) { return request.get(/api/goods, { params: { page: data.page || 1, pageSize: data.pageSize || 10, categoryId: data.categoryId, keyword: data.keyword, sort: data.sort || default } }); }排序策略在酒水场景下值得细说。默认排序通常按sort字段倒序也就是后台手动控制推荐位。销量排序按sales_count价格排序按price。后端在编写查询语句时要注意 sort 参数做白名单校验不能直接把前端传来的字段拼进 SQL 的 ORDER BY 里否则容易产生排序注入风险。这一点虽然不在小程序端代码里但在接口设计中一定要遵守规则。搜索功能走的是后端的模糊查询前端在搜索页监听输入框的bindinput事件加一个 300 毫秒的防抖处理。不要用户敲一个字就发一次请求否则后端瞬间会被打满这也是实战中非常容易犯的错误。3.3 商品详情页与SKU选择器商品详情页是商城转化率的核心酒水类商品的详情页尤其讲究。大图轮播要展示包装、酒体、背标信息图文详情要展示酒精度、产地、原料、生产日期。源码里用swiper组件实现顶部轮播图下方用 rich-text 渲染后端返回的富文本详情。SKU选择器是整个商城里逻辑最绕的组件。用户选择一个商品看到不同规格不同价格不同库存本质上是前端在维护一个 SKU 组合矩阵。举例来说一款金色年华葡萄酒有 750ml 单瓶、750ml 双瓶礼盒、整箱 6 瓶三个规格。每个规格的价格分别是 129、258、699库存分别是 50、20、10。用户点开规格弹窗时组件默认选中第一个有库存的规格同时联动显示价格区间。// SKU组件核心方法根据选中规格更新展示信息 selectSku(skuIndex) { const sku this.data.skuList[skuIndex]; if (sku.stock 0) { wx.showToast({ title: 该规格已售罄, icon: none }); return; } this.setData({ currentSku: sku, price: sku.price, stock: sku.stock, selectedSkuText: sku.name }); }这里要注意空库存规格的置灰逻辑如果某规格库存为0按钮要变成灰色不可点而不是用户点击后才弹提示。这是提升用户操作效率的细节也是源码里已经处理好的部分。3.4 购物车与结算流程购物车的核心逻辑不复杂但细节多。勾选状态、数量增减、价格汇总、失效商品提示每一项都要处理干净。购物车页面的数据结构经过后端汇总返回给前端的格式大概是{ list: [ { id: 1, skuId: 101, productName: 金色年华葡萄酒, skuName: 750ml单瓶, price: 129.00, quantity: 2, checked: true, stock: 50, image: https://cdn.example.com/goods/101.jpg } ], totalPrice: 258.00, selectedCount: 2 }结算按钮点击后前端做三件事校验勾选商品是否为空、校验商品库存是否充足、拿选中的商品生成订单确认页。确认页展示商品明细、收货地址、配送方式和支付金额。酒水商城经常有满减活动比如满299减30这部分逻辑是前端根据总价计算出来的因为后端在下单接口里也会做同样校验双重保险。提交订单时后端接口参数至少要包含地址ID、商品明细列表、备注和配送时间。接口返回订单ID后前端立即发起支付。3.5 微信支付的对接细节微信支付是小程序商城最敏感的一环也是很多源码跑不通的主要原因。其实微信支付对接本身不复杂前后端配合好一个流程就行。流程是这样的小程序端点击去支付把订单号发给后端。后端收到请求确认订单属于当前用户且未支付然后调用微信支付统一下单接口拿到prepay_id。后端用prepay_id生成支付参数timeStamp、nonceStr、package、signType、paySign返回给前端。前端拿到参数调用wx.requestPayment拉起微信支付控件。wx.requestPayment({ timeStamp: res.data.timeStamp, nonceStr: res.data.nonceStr, package: res.data.package, signType: RSA, paySign: res.data.paySign, success: () { // 跳转支付成功页 wx.redirectTo({ url: /pages/pay/result?statussuccess }); } });这里面最容易踩的坑是签名算法不一致。微信支付签名现在推荐使用 RSA 方式和以前常用的 MD5 不同。用 MD5 做签名在 2023 年以后的新商户号上会直接报错。所以源码里的签名实现是按照 RSA 来写的这个细节如果你后期要接入自己的支付逻辑一定要先确认自己用的签名类型是什么。另外支付回调是后端接收微信服务器发送的通知用来更新订单状态。这个回调接口必须是公网可访问的 HTTPS 地址并且要做签名验证不能随便让陌生人伪造回调把订单改成已支付。4. 实操过程从零跑通这套源码4.1 环境配置与工程导入拿到源码包后第一步不是急着看代码而是把环境准备好。你需要一个注册好的微信小程序账号拿到 appid微信开发者工具稳定版建议用最新版后端环境源码使用的是 Node.js 服务需要本地安装 Node.js 16 以上版本MySQL 数据库用于存储业务数据导入工程时在微信开发者工具中点击导入项目把源码目录选进来填好 appid。如果没有 appid也可以先用测试号但支付相关功能测试不了因为测试号没有微信支付权限。后端部署相对简单源码里包含数据库初始化 SQL 文件。本地新建一个数据库执行 SQL 文件再把后端配置文件的数据库连接信息改成你自己的最后启动后端服务即可。4.2 需要修改的关键配置项把源码跑起来之前有几个配置项必须改否则一定报错配置位置配置项说明project.config.jsonappid你的小程序 appidutils/config.jsbaseUrl后端接口地址本地调试填 http://127.0.0.1:3000/api后端 .env 文件DB_HOST / DB_USER / DB_PASSWORD数据库连接信息后端 .env 文件WX_APPID / WX_SECRET小程序 appid 和密钥后端 .env 文件PAY_MCH_ID / PAY_API_KEY微信支付商户号与密钥值得强调的是微信开发者工具默认不允许请求 http 明文接口本地调试时需要在工具右上角详情-本地设置里勾选不校验合法域名。这个选项只在开发阶段开上线前必须关闭并且把后端接口域名配置到小程序后台的 request 合法域名里。4.3 从商品上架到支付下单的完整演示弄好配置后我建议你按这条路径完整走一遍确认系统真的通了启动后端服务确认数据库表已自动初始化。打开小程序管理后台手动录入一个测试商品挂主图和详情图添加两个SKU比如500ml单瓶和整箱装分别填价格和库存。小程序端进入首页下拉刷新确认商品出现在列表里。点击商品进入详情页切换SKU确认价格和库存联动变化。加入购物车进入购物车页面修改数量点击结算。选择或新增收货地址提交订单。到支付环节如果是测试环境后端可以配置一个免支付开关跳过真实支付直接模拟支付成功回调。走到第七步你就把一套商城的核心链路走通了。后面想接真实支付只需要把你的微信商户号相关密钥填进后端配置里就行。5. 实战踩坑与常见问题排查5.1 小程序白屏问题与前端页面渲染很多人在开发阶段会遇到小程序页面白屏的问题尤其是在模拟器上编译正常、真机上却一片空白。这个问题的原因通常有两类第一类是 JS 报错中断了渲染。小程序页面渲染依赖 WXML 里的数据绑定如果 JS 里某个对象为空访问了不存在的属性渲染就直接停了。排查方法很简单打开调试器的 Console 面板看有没有红色的报错信息有就顺着堆栈找到具体代码。第二类是分包或组件路径写错。如果引用了不存在的组件路径编译阶段不会报错但页面渲染时组件加载失败整个页面就白屏了。我在源码调试时遇到过usingComponents里路径大小写写错导致组件加载失败的情况排查了很久。这里建议所有组件路径统一用小写字母加中划线的方式命名。另外一个很常见的场景是用 uni-app 开发小程序后模拟器正常、微信开发者工具打开是白屏。这个问题通常出在编译模式或基础库版本不兼容上。解决思路是检查微信开发者工具的基础库版本是否过旧以及 uni-app 编译出的分包配置是否正确。5.2 顶部导航栏高度与安全区适配小程序顶部导航栏高度是另一个反复出现的坑。因为 iPhone X 以后的机型都有刘海状态栏高度和导航栏高度在不同机型上完全不同。静态写死padding-top: 64px的做法在 iPhone 12 上可能还好在 iPhone SE 上就会显得顶部空一截在小屏安卓机上又会被刘海挡住。正确的做法是动态获取系统信息const systemInfo wx.getSystemInfoSync(); // 状态栏高度 const statusBarHeight systemInfo.statusBarHeight; // 导航栏高度胶囊按钮位置等信息 const menuButtonInfo wx.getMenuButtonBoundingClientRect();拿到statusBarHeight后给页面的自定义导航栏设置padding-top同时用safe-area-inset-top做兜底。这套源码里封装了一个navbar组件所有页面统一使用就是为了避免每个页面各写一套适配逻辑。还有底部 TabBar 和 iPhone 底部 home indicator 的适配采用env(safe-area-inset-bottom)解决底部按钮的间距一定要加上这个值否则 iPhone 用户会感觉按钮贴到了屏幕底部点起来非常难受。5.3 分包异步化与主包体积控制微信小程序有主包不得超过 1.5MB 的限制超过后上传代码直接失败。商城项目商品图片多、页面复杂一不小心就会触碰这个红线。解决方案是分包。把商品详情页、订单列表、用户中心这些二级页面全部放到分包里主包只保留首页和公共组件。源码里的分包配置{ pages: [ pages/index/index, pages/category/category, pages/cart/cart, pages/mine/mine ], subpackages: [ { root: packageGoods, pages: [ pages/goods/detail, pages/goods/search ] }, { root: packageOrder, pages: [ pages/order/list, pages/order/detail, pages/pay/result ] } ] }分包之后还有一个优化点分包异步化。默认情况下主包访问分包页面时需要跳转前加载分包会有短暂的白屏等待。通过分包异步化配置可以在主包代码中直接用require引用分包里的公共模块减少等待时间。使用require.async加载分包资源时注意不要让页面跳转和分包加载产生竞争条件。我遇到过一种情况用户快速点击两次跳转按钮分包还没有加载完成页面就启动跳转导致导航失败。解决办法是跳转前加一个 loading 状态并且防止按钮重复点击。5.4 常见问题速查表把开发中高频出现的问题整理成表方便你直接对照排查问题现象可能原因解决方案请求返回 403token 过期或未携带检查 request.js 是否在请求头注入 Authorization登录一直失败appid 与 secret 不匹配检查后端配置的 appid/secret 是否与小程序后台一致支付调起报错签名类型不对确认后端使用 RSA 签名并且时间戳和随机串合法图片加载不出来图片域名未配置白名单小程序后台配置 downloadFile 合法域名开发阶段勾选不校验域名发布审核被拒类目与资质不匹配酒水类目需要食品经营许可证提前在后台提交资质真机调试蓝牙/扫码不可用权限未声明检查 app.json 里 permission 字段是否有相应权限说明用户拒绝授权后无法使用授权逻辑没有降级提供手动填写手机号/地址的入口代替强制wx.getUserProfile这个表里的每一条都是真实项目里见过多次的问题。尤其是酒水类目资质审核很多开发者把功能都做完了提交审核才发现自己没有食品经营许可证导致小程序被驳回。这类事情要提前确认清楚。6. 源码的二次开发与扩展方向6.1 管理后台与权限控制源码配套的管理后台覆盖了商品、订单、用户、营销四大模块的基本功能。商品模块支持上下架、编辑、设置库存订单模块支持发货、退款操作用户模块可以查看用户列表和订单记录。如果要在后台加一个运营角色比如运营专员只能管商品、不能管订单那么后端接口需要做权限控制。常见做法是在后端用一个中间件检查角色字段把角色码和接口权限建立对应关系。代码里已经预留了 user 表的 role 字段在此基础上扩展并不困难。我建议优先给后台加上操作日志功能。电商后台多人操作是常态商品改价、订单改状态、退款操作最好都能留痕。将来出了问题追溯起来会省很多事。6.2 营销组件与同城配送的扩展思路商城跑通基础交易后下一步就是做增长和效率。这套源码预留了优惠券表结构但没有把完整的领券、核销链路做完。扩展时可以基于现有订单金额计算逻辑先在结算接口增加coupon_id参数后端校验优惠券的有效期、使用门槛和使用状态再把优惠金额从订单总价中扣减。配送这块酒水商城的同城配送需求很强。如果要做同城配送通常有两种路线自建配送员派单系统或者接入第三方配送平台。自建的成本高适合订单密度大的区域接入第三方需要在用户下单后调用第三方创建订单接口把取货地址、收货地址、重量等信息传过去然后在小程序端实时展示骑手位置。路线图建议按照基础交易 - 会员与营销 - 配送与售后 - 数据报表这个顺序推进。每增加一个模块都会对现有代码结构提出新的要求但源码底子打得清楚往上加东西不会伤筋动骨。源码的价值从来不是让你直接拿去上线而是让你知道一套正经的商城小程序是怎么组织的。我见过太多人拿到源码后第一件事是改标题、换图、传代码结果第二天就问为什么首页加载不出来。老老实实把目录结构和数据表关系搞清楚再动手改才是省时间的做法。最后再分享一个我做商城项目的习惯永远保留一个最小可运行的版本不动所有的修改都在副本上进行。这样即使改出问题随时能回到那个能跑的版本上对照排查。这套酒水商城源码我也建议你这么用先原封不动跑起来再开始你的表演。本文还有配套的精品资源点击获取