如果你正在为毕业设计发愁,或者想从零跑通一套基于微信小程序的外卖管理系统,这篇内容应该能帮你省下不少时间。我前后花了大约一个半月,独立完成了一个可运行的完整项目,包括小程序用户端、商家管理后台、平台管理后台,以及配套的毕业设计论文。这个项目我内部代号就叫“模拟外卖平台X”,下文统一用WaimaiPro指代。现在的源码已经整理成了可以直接导入运行的模板,论文部分也形成了完整结构。接下来我会从系统整体设计说起,一步一步拆前端、后端、数据库、订单支付流程,最后把复现步骤、论文写法和踩过的坑全部摊出来。整篇不会端着讲理论,都是我做项目时的真实思考过程。
1. 先看清项目全貌:这套外卖系统由谁在用、包含哪些模块
1.1 三端角色拆解:用户、商家、平台管理员
一套完整的外卖管理系统,至少有三类角色在同时使用,这一点很多初学者容易漏掉。
用户端就是我们平时在微信里打开的那个小程序,核心操作是浏览商家、点餐、支付、查订单、管理地址。这部分面向C端,界面要简单直接,功能链路要短,最好三步以内就能下完一单,不然用户很容易流失。我在设计页面时尽量把常用操作控制在两次点击以内,比如加购之后购物车入口常驻底部,点开直接去结算。
商家端我做成的是一个Web管理页面,商家登录后可以维护菜品分类、上下架菜品、调整价格、修改库存、接单和发货。商家不需要在手机上装App,用浏览器打开就能操作,开发量也相对可控。订单提醒我用了简单的轮询方式,商家的新订单页面每5秒刷新一次数据,比即时通信方案简单很多,实际演示效果也不错。
平台管理员是第三个角色,主要做商家入驻审核、订单监控、数据统计。毕业设计里,这一端可以适当简化,但至少要有商家列表和审核状态管理,否则业务闭环不完整。
这三个角色的关系一句话讲清楚:管理员审核商家,商家在后台维护菜品,用户在小程序下单,订单流按状态在用户端和商家端之间流转。整个系统就围绕这条主线展开。
1.2 功能模块梳理:每个端具体有哪些功能点
先说用户端(微信小程序)。登录授权用的是微信静默登录,不强制用户绑定手机号,但地址填写会引导授权。首页包含轮播图、快捷入口、推荐商家列表,支持按距离和销量排序。商家主页是左边分类、右边菜品列表的经典布局,菜品卡片显示图片、名称、月售、价格。购物车按商家隔离,支持加购、改数量、清空。订单模块覆盖提交订单、微信支付、订单列表、订单详情、取消订单、确认收货。地址管理支持新增、编辑、删除、设为默认。
再说商家端(Web后台)。登录用账号密码,账号由管理员在后台创建。菜品管理是核心,包括分类维护、菜品上下架、价格和库存修改。订单处理模块做新订单列表、接单、发货、查看详情。统计模块展示近7日订单量、销售额、热门菜品排行。这个统计不需要复杂的报表工具,后端按日期分组统计,前端用简单的柱状图组件渲染就行。
最后是管理后台(简化版)。商家管理主要看商家列表、入驻审核状态、营业状态。订单监控支持全部订单查询和按状态筛选。基础配置就两块:公告和首页轮播图。整个项目一共有三个登录角色、三个前端工程和一套后端服务,这个规模对课程设计和毕业设计来说恰到好处。
1.3 用一条完整流程串起整个系统
一条外卖订单的完整生命周期大概是这样的:用户打开小程序,wx.login静默登录拿到用户标识;在首页选一个商家,进入菜单页面加购;点击去结算,填写或选择地址,前端计算出金额;点击提交订单,后端创建订单,状态为待支付;调用wx.requestPayment拉起微信支付,支付成功后后端收到回调,订单状态改为已支付待接单;商家在Web后台看到新订单,接单开始制作,状态改为已接单制作中;出餐后点发货,状态改为配送中;用户收到餐后确认收货,状态改为已完成。如果用户一直不确认,我设计了超时自动完成机制,配送后2小时自动变已完成。
这条主流程串起来之后,后续后端接口、前端页面的开发顺序也就清晰了。凡是跟主链路相关的模块先做,统计、评价、审核这些旁支功能后做,整个项目推进会顺畅很多。
2. 技术选型的纠结:原生小程序、跨端框架还是云开发
2.1 三条主流路线的横向对比
做小程序外卖,前端路线其实有三种选择,我当时专门花了一天整理对比表。
| 对比维度 | 原生小程序 | 跨端框架(如uni-app) | 微信云开发/云托管 |
|---|---|---|---|
| 开发语言 | WXML/WXSS/JS | Vue/React语法 | JS/云函数 |
| 学习成本 | 低,直接看官方文档 | 中,需要熟悉框架封装 | 低,但有平台概念 |
| 调试体验 | 直观,直接面对微信API | 多一层编译,偶发兼容问题 | 调试方便,但依赖云端 |
| 与微信生态贴合度 | 最高 | 中 | 最高 |
| 后端可控性 | 完全可控 | 完全可控 | 受限于云服务 |
| 论文技术展示 | 前端+后端都有素材 | 前端展示单一 | 后端展示偏弱 |
对于准备做毕业设计的同学,我个人的看法是:如果目标是快速出demo,云开发最省事;如果目标是展示完整的前后端技能,原生小程序加自建后端更合适;如果以后想跨平台运营,跨端框架值得考虑。技术上没有绝对的最优解,只有跟当前目标匹配的解法。
2.2 我为什么选原生小程序加自建后端
我做这个项目的目的一是掌握微信小程序开发,二是搭建一个前后端分离的完整业务系统,三是给论文提供充足的技术素材。前两个目的指向原生加自建后端,所以我最后选了原生小程序。
后端具体技术栈是Spring Boot 2.x + MyBatis Plus + MySQL 8.0,Redis作为可选组件,用来缓存首页轮播数据和存储自定义登录token。为什么是Spring Boot?因为在毕业设计这个阶段,Java后端生态的资料量最丰富,遇到问题基本都能搜到解法。MyBatis Plus比纯MyBatis省了CRUD的样板代码,也能保留SQL的可控性,比如复杂的统计查询我还是手写XML里的动态SQL。
数据库用MySQL,关系型数据库在订单、菜品这种强关联业务里比文档型数据库更顺手。而且数据库设计本身就是论文的硬性章节,用MySQL设计的E-R图、表结构说明更容易被评审老师认可。
2.3 数据库设计:决定后面返工量的一步
数据表设计直接决定后面的开发量和论文篇幅。我的方案是8张核心表,这里重点说字段设计思路:
user表:id、openid、nickname、avatar、phone、create_time。openid必须设唯一索引,一个微信用户对应一条记录,第二次登录直接查出来更新昵称头像就行。
merchant表:id、name、logo、description、start_price(起送价)、delivery_fee(配送费)、status(营业状态:0停业、1营业)、audit_status(审核状态)。注意这里为什么独立一个audit_status?因为商家入驻要管理员审核,审核通过后才能在小程序端展示。
category表:id、merchant_id、name、sort。菜品分类挂在商家下面,不是全局共享的,每家店有自己的分类。
dish表:id、merchant_id、category_id、name、image、price、stock、sales、status。菜品表要冗余merchant_id,这样所有菜品查询都能直接按商家过滤,不用先查分类再查菜品,避免一次多表join。
address表:id、user_id、receiver_name、receiver_phone、province、city、district、detail、is_default。
cart表:id、user_id、merchant_id、dish_id、quantity。注意按商家隔离,不同商家的菜品不能同时结算。这个约束在加购接口就要算好,如果购物车里已经有A商家的菜,再加B商家的菜时要么清空A,要么把B单独开一组。我实际做的是切换商家时直接清空之前的购物车,理由很简单,外卖场景本来就是单店下单。
orders表:id、order_no(业务订单号)、user_id、merchant_id、address_snapshot(地址快照)、total_amount、delivery_fee、pay_amount、remark、status、create_time、pay_time、deliver_time、finish_time。
order_detail表:id、order_id、dish_id、dish_name(菜品名快照)、price、quantity。
这里有一个我已经吃过的教训:订单表里要有地址快照、订单明细表里要有菜品名快照。原因很简单,用户地址可以改,商家菜品也可以改,但订单一旦生成,下单那一刻的地址和菜品名必须固定下来,否则之后查历史订单,信息可能对不上。这个设计细节建议直接抄进论文的数据库设计章节。
3. 小程序端实现细节:登录态、页面组织与购物车设计
3.1 微信登录态的处理流程
小程序端登录逻辑是不少同学第一个卡住的地方,这里把流程完整拆开。
关键流程:wx.login()拿到临时code,有效期5分钟,只能使用一次;把code发给后端,后端调用微信登录凭证校验接口换取openid和session_key;用openid在user表里查用户,不存在则自动注册;生成自定义token,我用UUID生成后存到Redis,key设为token:xxxx,value存userId,有效期7天;把token返回小程序端,前端存到Storage,后续请求在header里带Authorization字段。
我当时的简化处理是:后端生成自定义token直接返回,不依赖微信自带的sessionKey。自己生成token的好处是后端完全掌控登录态,方便在论文里描述“自定义会话管理机制”。要注意的是,session_key涉及微信敏感数据,后端拿到后不应该返回给前端。
小程序端代码封装大概是这样的:
// utils/login.js function wxLogin() { return new Promise((resolve, reject) => { wx.login({ success: async (res) => { try { const result = await request({ url: '/wx/login', method: 'POST', data: { code: res.code } }); if (result.code === 200) { wx.setStorageSync('token', result.data.token); wx.setStorageSync('userInfo', result.data.userInfo); resolve(result.data); } else { reject(new Error('登录失败')); } } catch (e) { reject(e); } }, fail: (err) => reject(err) }); }); }后端Spring Boot的登录接口伪代码:
@PostMapping("/wx/login") public Result login(@RequestBody Map<String, String> params) { String code = params.get("code"); // 调用微信接口,用code换openid String openid = wechatService.code2Session(code); User user = userMapper.selectByOpenid(openid); if (user == null) { user = new User(); user.setOpenid(openid); user.setNickname("微信用户"); userMapper.insert(user); } String token = UUID.randomUUID().toString().replace("-", ""); redisTemplate.opsForValue().set("token:" + token, user.getId().toString(), 7, TimeUnit.DAYS); return Result.ok().put("token", token).put("userInfo", user); }注意:这里的请求地址是相对路径,实际开发中baseUrl会统一配置。如果后端部署在云服务器,域名必须在微信公众平台配置为request合法域名,否则小程序真机访问会被拦截。
3.2 首页、商家菜单、购物车的实现思路
首页布局我是这样做的:顶部搜索框、轮播图、分类快捷入口(全部、美食、甜点、饮品)、推荐商家列表。商家列表用分页插件做滚动加载,每页10条,后端用LIMIT实现。排序有两个维度,距离优先和销量优先。距离在demo里是手动模拟的,每个商家存一个latitude和longitude,用Haversine公式计算距离,销量直接取dish表的sales汇总。
商家菜单页是外卖App的标准布局:左侧一级分类栏,右侧菜品列表。菜品卡片包含图片、名称、月售、价格,价格下面放加号按钮。加号按钮同时做两件事:更新购物车数据,在菜品卡片当前位置弹出数量控制框。这一块的交互很容易被忽略,实际做的时候要处理好数量为0时,数量控制框的隐藏和恢复。
购物车我选了本地缓存优先策略,加购时直接写入Storage,不请求后端。这样做的好处是购物车操作高频,每次加减都发请求会造成明显卡顿。但本地缓存有个前提:结算时必须以服务端数据为准,我在后端创建订单接口里重新计算了所有金额。
切换商家时清空购物车的校验一定要做。我实测的时候遇到过这种场景:用户先在A店加购了2份菜品,然后进入B店继续加购,如果不做清空,结算时就会把A店的菜带到B店的订单里。虽然后端校验会拦截,但前端体验已经出了问题,用户会认为系统莫名其妙。
3.3 地址管理与订单确认页的交互细节
地址管理页面我做了列表、新增、编辑、删除四组操作,默认地址用radio标识。用户从地址列表选地址后,需要把选中地址对象带回上一页。回传的方式是用事件通道,就是通过页面栈给上一页传参,这比存全局变量更干净。
订单确认页包含商家名、菜品清单、数量、配送费、起送价,下方是地址卡片和支付金额。提交按钮在两种状态下要禁用:金额没到起送价、地址未选择。这里有个细节,起送价校验要提前在前端做提示,不要等到用户点提交了才弹错。
前端金额只做展示,真正的金额计算和校验放在后端。具体做法是:提交订单时,前端把dishId和quantity的列表传给后端,后端重新查数据库计算总价,再对库存做一次扣减。这样前端就算篡改了金额,接口层也会挡住。论文里可以写“服务端负责价格可信校验”,这句话是有技术含量的。
如果后端扣了库存但支付超时未完成,需要定时任务回滚库存;如果订单被取消,也要回滚库存。这个逻辑我在下面支付兜底部分会一起说清。
4. 订单状态机与微信支付:全项目最容易翻车的一段
4.1 订单状态机的设计
订单状态是整个系统的核心,状态设计得清晰,前后端开发和论文都不会乱。我定义的枚举如下:
- 0:待支付
- 1:已支付待接单
- 2:已接单制作中
- 3:配送中
- 4:已完成
- 5:已取消
- 6:已退款
状态流转约束用文字描述就是:待支付状态下只有两个出口,用户取消或支付成功;取消是终态;已支付待接单可以接单变成制作中,也可以申请退款变成已退款;制作中发货变成配送中;配送中用户确认收货或系统超时自动完成后变成已完成;已完成和已退款都是终态。
这个状态机在后端要做一个统一的枚举类和校验方法。每个状态变更接口都要先判断当前状态是否允许流转到目标状态,不允许就直接抛异常。例如用户不能把已支付订单直接改成已完成,只能确认收货。我当时在每个状态变更方法里都做了前置状态校验,防止绕过正常流程。论文里把这个状态机画成一张表,会很加分。
前端不同页面根据订单状态渲染不同按钮:待支付显示“去支付”,已接单显示“等待商家出餐”,配送中显示“确认收货”,已完成显示“再来一单”。按钮事件要绑定到状态对应的接口,不要出现用户点了配送中的订单却调了支付接口的情况。
4.2 微信支付的接入全过程:从申请到回调验签
微信支付是这类商城项目的硬骨头。我按步骤说,每一步都很关键。
第一步,注册微信支付商户号。要求企业主体或个体工商户资质,个人无法开通。商户号开通后,需要在商户平台关联小程序AppID,完成AppID授权。这一步不做,后面拉支付必报“商户号与AppID不匹配”。
第二步,后端配置。需要的参数:appId、mchId(商户号)、APIv3密钥、商户证书序列号、商户私钥。这些配置写在application.yml,但证书文件和密钥绝不能提交到公共代码仓库,这一点要养成习惯。我当时把配置文件单独拆出一个application-prod.yml,只在服务器上保留。
第三步,统一下单。后端调用微信支付的“JSAPI下单”接口,传入openid、订单号、金额(单位分)、商品描述、notify_url回调地址。成功返回prepay_id。金额单位是分,这个很容易踩坑,前端显示的是元,下单选参数传的时候必须乘以100。
第四步,组装前端拉起支付的参数。后端把prepay_id转成小程序端wx.requestPayment需要的5个参数:timeStamp、nonceStr、package(值为prepay_id=xxx)、signType、paySign。paySign必须后端按微信规范计算签名,不能用前端自己造。
第五步,前端拉起支付:
wx.requestPayment({ timeStamp: res.timeStamp, nonceStr: res.nonceStr, package: res.package, signType: 'RSA', paySign: res.paySign, success: () => { // 支付成功,跳转到订单详情页,等待后端回调结果 wx.redirectTo({ url: '/pages/order/detail?id=' + orderId }); }, fail: (err) => { // 用户取消支付或支付失败 console.log('支付失败', err); } });这一步容易踩坑的是:signType可能是RSA也可能是MD5(旧版商户),要看商户平台配置的API版本;参数名必须是驼峰;timeStamp必须是字符串,不能是数字;package值一定要带prepay_id=前缀。
第六步,编写支付回调接口。用户支付成功后,微信服务器会异步请求你在统一下单时填写的notify_url。后端必须做到:先验签,对回调报文做签名验证,确认消息来自微信;再查单,确认这笔订单真实存在且金额一致;更新订单状态为已支付,把回调里的交易单号记录下来;最后返回字符串success给微信,否则微信会按规则重试回调。
验签流程是硬性要求。不做验签就信任回调内容,安全风险非常大。支付回调报文有的字段是加密的,需要用商户私钥解密,拿到订单号、交易状态等信息。论文的安全设计部分提到“对支付回调进行验签与解密”,这句话能给系统设计加分。
4.3 支付掉单的兜底处理
回调是不可控的,网络抖动、服务重启都可能丢回调。掉单了用户付了钱但订单还是待支付,这个时候必须给用户一个出路。
我做了两层兜底。第一层是前端轮询:用户在订单详情页停留时,每3秒查一次订单状态,支付成功或掉单后的状态变化很快能反映到页面。第二层是后端主动查单:用户点击“刷新状态”按钮时,后端调用微信支付查单接口,按订单号查询微信侧真实支付状态。如果微信侧已支付但本地订单还是待支付,就补更新订单状态,这个动作就是“对账”。
开发阶段微信支付还没配好之前,我加了一个模拟支付开关。打开之后,用户点“确认支付”直接调接口把订单置为已支付,整个流程就能先跑通。演示的时候也更顺畅,不用真的付钱。但论文里要写明生产环境必须走真实支付流程,模拟开关只用于开发和演示。
库存回滚的逻辑也在订单模块里。创建订单时扣库存,如果用户在待支付状态主动取消订单,后端要立即回滚库存;如果超时未支付,定时任务扫描超过30分钟的待支付订单,自动取消并回滚库存。这块逻辑虽然小,但直接关系到库存准确性,不做就会出现用户体验问题和数据不一致。
5. 照着复现:从环境准备到小程序提交审核的完整步骤
5.1 环境清单与项目初始化
前端环境:微信开发者工具稳定版,一个小程序账号(个人主体可以注册,但外卖类目需要企业主体资质才能正式发布;做演示可以先用测试号或体验版),HTTPS服务器域名(开发阶段可在工具里勾选“不校验合法域名”)。
后端环境:JDK 8+、Maven 3.x、IDEA或任意IDE、MySQL 8.0、Redis 5.0+(可选,用来存token)。
项目初始化步骤:新建Spring Boot工程,引入web、mysql、mybatis-plus、lombok、redis依赖;创建数据库waimai_db,按第二章的表结构建表并导入初始商家和菜品数据;修改application.yml中的数据库连接和微信参数;启动后端,确认端口正常监听。
5.2 后端接口开发顺序与自测方法
一个建议的开发顺序,按业务依赖走:
- 用户模块:登录接口、用户信息查询和更新
- 商家模块:商家列表(含分页)、商家详情
- 菜品模块:分类列表、菜品列表(带分页和搜索)
- 地址模块:增删改查、设置默认地址
- 购物车模块:加购、改数量、清空、列表查询
- 订单模块:创建订单、订单列表、订单详情、取消订单、确认收货、商家接单和发货
- 支付模块:统一下单、支付回调、查单
每写完一组接口就用API调试工具自测。我用的Apifox,重点测试参数校验和异常分支,比如菜品不存在、库存不足、订单不属于当前用户、状态不允许流转。这些边界情况在代码里必须处理,在论文测试章节也正好用来写测试用例。调试工具里的历史记录保存好,做论文截图时直接就能用。
5.3 小程序端配置与联调
小程序端的配置要点:在微信公众平台的开发设置里配好request合法域名、uploadFile合法域名;开发者工具中填入小程序AppID;配置project.config.json里的appid和miniprogramRoot;网络请求封装一个request.js,统一带token、统一错误提示、统一401处理。
联调时先在开发者工具里跑通全流程,再切真机预览。真机预览要特别注意:本地开发时如果后端在电脑上,小程序真机无法访问你电脑的局域网IP,要么后端部署到云服务器,要么使用内网穿透工具把本地服务暴露出去。很多同学在这里卡住,我一开始也是,后来把后端放到了云服务器才解决。如果没有服务器,本地开发阶段可以用开发者工具的真机调试模式配合内网映射。
代码把基础的不安全偏好先说清楚,正式演示时再切换为云服务器域名,这样效率最高。
5.4 提交审核前必查清单
上传代码前要做的检查项我列一下:
- 隐私协议弹窗:项目里如果用用户手机号、地址,必须在隐私协议里声明,小程序管理后台也要填写用户隐私保护指引;
- 选择合适的服务类目:外卖相关通常需要“餐饮服务/食品经营”类资质,没有资质可以先选择“工具-生活服务”或“商业服务-其他”类目做演示版本,或者只给体验成员访问;
- 开通备案:新发布小程序需要小程序备案,时间要预留,一般建议提前一周开始;
- 图片资源压缩:菜品图和轮播图压缩后总包体积尽量控制在2M以内,必要时用分包加载。
审核被拒是常态,不要慌。被拒后看审核原因,大多数是类目资质不匹配,要么补齐资质,要么降级为内部体验版本。论文里注明这是演示系统,不影响答辩。
6. 毕业论文怎么组织:从目录到测试章节的写作参考
6.1 论文目录与整体逻辑
做毕业设计不只是写代码,论文往往占一半精力。我的论文目录如下,供参考:
摘要、关键词、Abstract
第一章 绪论:背景、意义、国内外研究现状、研究内容
第二章 相关技术介绍:微信小程序、Spring Boot、MySQL、Redis
第三章 需求分析:业务描述、功能性需求、非功能性需求、用例模型
第四章 系统设计:总体架构、功能模块设计、数据库设计
第五章 系统实现:按模块的实现说明加核心代码
第六章 系统测试:测试环境、测试用例、结果分析
结束语、参考文献、致谢
论文不是写给自己看的,评审老师最先看逻辑主线。主线一般是“背景—技术—需求—设计—实现—测试”这条链路,每一章要跟下一章有衔接。比如第二章技术选型是为第四章设计做铺垫,第三章需求分析承接第一章背景。写的时候不要东一块西一块,把开发时序直接当作论文的推进逻辑。
6.2 需求分析与数据库设计章节的写法
需求分析不是抄模板。我当时做了三个用例图:用户、商家、管理员,每个用例配一个用例描述表。表格字段包括:用例编号、用例名称、参与者、前置条件、主流程、异常流。这个写法评审老师认可,工作量也相对可控,只要你在实际开发时确实理清了业务逻辑。
主流程和异常流的写法有个技巧:主流程写正常操作路径,异常流写失败或边界情况。比如“提交订单”这个用例,主流程是用户选择地址、点击提交、系统创建订单;异常流是地址未填写、菜品库存不足、起送价未达到。每一个异常流都对应我在后端写的参数校验逻辑,论文和代码是对得上的。
数据库设计章节放E-R图加数据表结构说明。评审最关注三样东西:表间关系是否清晰,主外键是否合理;关键字段是否明确,比如订单状态用什么类型和值;有没有体现业务约束,比如购物车按商家隔离、订单地址冗余快照。把第四章里讲到的快照设计写进去,这条会让论文内容显得有思考深度,不是泛泛的建表说明。
6.3 实现与测试章节的组织技巧
实现章节按功能模块写,每个模块给三样东西:功能概述、页面效果截图、核心代码片段。核心代码不用贴全部,重点是接口方法、业务判断逻辑、状态流转逻辑。文字部分要解释代码的作用,而不是把代码一摆就完事。比如状态机校验那段,我可以写“为保证订单不可乱序流转,每个变更接口都调用了checkStatusIsLegal方法,前置状态不匹配时统一抛出业务异常”,比直接贴一长串代码更能体现理解。
测试章节我写了三类内容:功能测试用例表,包含模块、用例名称、步骤、输入数据、预期结果、实际结果、是否通过;接口测试,登录、下单、支付的请求响应结果截图;兼容性测试,不同微信版本、不同手机型号下的页面表现说明。
测试用例表要尽量覆盖异常分支,比如未登录下单、库存不足、支付金额不一致,这比只写正常流程更能拿分。我当时把测试用例数量做到了60条以上,答辩时评审老师翻到测试章节基本就没有再追问功能细节了。
7. 实测踩坑记录:支付和审核的几个大坑,我帮你提前排掉
7.1 支付拉起失败:商户号、AppID和signType的方向排查
第一次调支付,前端wx.requestPayment返回失败,我折腾了一整天才定位到问题根源。这个问题的坑点很典型,值得单独说。
第一个问题是商户号和小程序AppID的绑定关系。在商户平台里,不是拿一个mchId填进配置就能用的,必须先在商户平台完成AppID授权,把小程序绑定到商户号下面。我当时就是漏了这一步,后端参数都填对了,实际请求微信接口时一直报“商户号与AppID不匹配”。排查链路建议:先从商户平台的绑定关系查起,再逐个核对后端配置参数,不要一上来就改代码。
第二个问题是signType。新商户默认用的是APIv3密钥,签名算法为RSA,参数里的signType要传RSA。如果后端用旧版MD5方式签名,而前端传RSA,支付一定起不来。我之前在网上找的示例代码大多是旧版,照抄之后被坑了一晚上。排查方式是用微信官方支付工具导出校验签名是否一致,不一致就说明签名串拼接顺序或编码有问题。
如果遇到支付回调验签失败,同样不要急着看代码逻辑,先确认商户私钥、证书序列号是否配置正确,再确认回调报文的解密逻辑。微信支付的官方对接文档其实写得很清楚,只是示例代码比较分散,耐心读一遍比在网上搜零散博客靠谱得多。
7.2 外卖类目的资质限制:个人开发者做不了正式版
外卖系统涉及餐饮交易,正式发布要求企业或个体工商户主体,还要上传食品经营许可证之类的资质。个人主体注册的小程序,基本只能做demo和内部体验版。
我的做法是:先把完整功能在体验版中演示,体验成员可以正常下单和查看订单流。论文里标注“系统基于演示环境运行,可扩展接入真实支付与配送服务”,既合规,又不影响项目完整度。
如果你做的是课程设计,也不一定要正式发布。答辩现场用开发者工具或体验版演示,完全可以证明系统的完整度。重点是整个业务闭环能跑通,而不是在微信里搜到你的小程序。
7.3 本地购物车与服务端数据不一致的兜底
因为购物车我选了本地缓存优先,遇到过一个很实际的场景:用户在小程序端加购了10份菜,但后端库存只剩3份。提交订单时后端校验发现库存不足,直接报错,前端购物车还显示10份。体验很割裂,用户会以为系统有问题。
我的解决办法是:提交订单接口返回结构化的失败原因,比如“某菜品仅剩X份,请调整数量”。前端捕获到这个失败信息后,用返回里的最新库存刷新本地购物车,把超过库存的数量自动修正。这个兜底逻辑不复杂,但能显著提升订单流程的完成率,也可以写成论文里的项目亮点。
另外,同一用户在不同设备上会有两份不同的本地购物车。如果强调数据一致性,可以在登录后拉取一次服务端购物车并合并本地数据。我在生产思路上有考虑,实际演示版本直接以本地为准。论文的讨论部分可以提到这个优化方向,评审老师会认为你思考过数据一致性问题。
写到这里,WaimaiPro从设计到落地的主要过程就讲得差不多了。如果让我给正在做类似系统的你一条最实用的建议,我会说:先把订单状态机画清楚,再去写代码。状态机一旦明确,后端接口、前端按钮、论文表格都能顺着长出来。支付和审核的问题也早点调研,别等代码写完了才发现资质不具备。项目源码现在是可以直接导入运行的,配合论文模板,你只需要把自己学校的校名、指导老师信息替换进去,再把测试截图换成你自己的运行结果就行。这个后续如果要做成真正的商用系统,可以加上GPS定位、骑手端App、优惠券系统,但骨架已经在了,往上长东西不难。