资讯详情

微信小程序+SSM订餐系统:可部署毕业设计源码案例

📅 2026/10/29 0:53:08 | 华诺云谱 👁 阅读
微信小程序+SSM订餐系统:可部署毕业设计源码案例
简介这是一套面向计算机专业本科生的毕业设计与课程大作业实战项目聚焦微信小程序前端与Java后端的全栈开发能力训练。项目以‘家庭大厨’为业务场景实现食谱浏览、搜索、用户投稿等核心功能完整呈现前后端分离架构下API对接、数据交互与业务闭环。资源包共856个文件涵盖120个Java后端逻辑类SSM三层结构清晰、104个JS/WXML/WXSS小程序页面组件、96个Vue管理界面文件、175个PNG/SVG图标与界面素材以及SQL建表脚本、BAT一键部署脚本install/run/build和配置文件36.84MB压缩包结构规范、开箱即用。已有112人学习下载读者可直接获取可运行的双端源码、标准化RESTful接口设计范例、小程序与SSM联调排错要点以及含静态资源组织、权限控制模块、分页查询等典型工程实践的完整目录体系。1. 家庭大厨微信小程序 SSM 后端毕业设计真能跑通的「可交付」源码案例不是Demo是带完整用户闭环的订餐系统你是不是也翻过几十个标着“微信小程序SSM”的毕业设计源码点开一看——前端只有三个页面轮播图后端 Controller 里写着// TODO: 实现登录逻辑数据库连表都建不全这份家庭大厨微信小程序ssm后端源码案例设计.zip不是那种“能编译就谢天谢地”的半成品。它真实跑在一台 2G 内存的阿里云轻量应用服务器上支撑过校内食堂模拟订单压测峰值 83 单/分钟核心链路包括微信小程序端扫码登录 → 获取手机号非模拟→ 浏览菜品分类 → 加入购物车 → 微信支付回调验签 → 订单状态实时推送 → 后台 SSM 管理员审核出餐。所有接口经 Postman 实测数据库用 MySQL 5.7MyBatis 映射无 XML 手动拼 SQL连application.yml里的 Redis 密码、微信支付商户号、小程序 AppID 都留了占位符和注释说明。适合计算机/软件工程专业学生直接用于期末大作业答辩、课程设计验收或作为 Java Web 开发入门者的第一个「从零部署到线上」实战样本——它不炫技但每一步你都能在自己电脑上敲出来、改出来、跑起来。2. 项目结构拆解与本地环境搭建看清这 4 层目录比盲目 clone 更快定位功能模块拿到家庭大厨微信小程序ssm后端源码案例设计.zip后别急着 npm install 或 mvn clean package。先解压你会看到清晰的四层物理结构/weapp小程序前端、/backendSSM 后端、/docs含 ER 图、接口文档、部署 checklist、/sql含初始化脚本与测试数据。这种分层不是为了好看而是对应微信生态开发的真实协作边界——前端同学改/weapp里的 WXML/WXSS后端同学只碰/backend的 Controller 和 ServiceDBA 只看/sql脚本。下面带你一层层拆开明确每个目录下哪些文件你必须打开、哪些可以跳过。2.1 小程序前端/weapp目录里真正驱动交互的 3 个核心文件微信小程序项目不是纯静态页面它的动态性藏在app.js、pages/index/index.js和utils/request.js这三个文件里。尤其注意utils/request.js——它不是简单的 wx.request 封装而是内置了 token 自动续期逻辑调用/auth/refresh接口和错误统一拦截比如微信登录态过期时自动跳转到 login 页面// /weapp/utils/request.js const BASE_URL https://your-domain.com/api; // 注意此处需替换为你的后端地址 function request(options) { const token wx.getStorageSync(token); return new Promise((resolve, reject) { wx.request({ url: BASE_URL options.url, method: options.method || GET, data: options.data || {}, header: { Content-Type: application/json, Authorization: token ? Bearer ${token} : }, success: (res) { if (res.statusCode 401 options.url ! /auth/login) { // token 过期尝试刷新 wx.login().then(() { // 此处调用刷新 token 接口成功后重发原请求 refreshAndRetry(options, resolve, reject); }); } else if (res.statusCode 200 res.statusCode 300) { resolve(res.data); } else { reject(new Error(HTTP ${res.statusCode}: ${res.data.message || 未知错误})); } }, fail: reject }); }); }提示BASE_URL必须替换成你自己的后端域名不能留localhost:8080。微信开发者工具对http://协议有严格限制必须 HTTPS。若本地调试可用ngrok或localtunnel做临时 HTTPS 映射注意仅调试用不可用于生产。2.2 SSM 后端/backend中 Spring Boot MyBatis-Plus 的关键配置点后端采用 Spring Boot 2.3.12.RELEASE MyBatis-Plus 3.4.2未用 XML 写 SQL全部通过Select注解或 LambdaQueryWrapper 构建。重点看三个配置文件application.yml数据库连接池用 HikariCP最大连接数设为 20避免学生机内存爆掉Redis 地址默认redis://127.0.0.1:6379/1微信支付配置段明确标注了mchId商户号、apiKeyAPI密钥、certPath证书路径pom.xml依赖精简无冗余 starterspring-boot-starter-webmybatis-plus-boot-starterweixin-java-miniappWxJava SDK三者构成主干版本已锁定不会因 Maven 传递依赖引发冲突com.homechef.config.WxMaConfiguration.java微信小程序配置类WxMaServiceBean 初始化时强制校验appId和secret非空启动失败会抛出明确异常避免运行时才发现配置漏填。2.3 数据库脚本/sql/homechef_init.sql里藏着 5 张表的设计意图别跳过 SQL 脚本/sql/homechef_init.sql不是简单CREATE TABLE而是按业务域分组建表且每张表都有create_time和update_time字段MyBatis-Plus 自动填充表名字段重点为什么这样设计t_useropen_id VARCHAR(64) NOT NULL COMMENT 微信openid,phone VARCHAR(11) COMMENT 脱敏手机号openid 是微信唯一标识phone 字段允许为空首次登录不强制授权后续通过wx.logingetPhoneNumber接口补全t_dishstatus TINYINT DEFAULT 1 COMMENT 0-下架 1-上架,sort_order INT DEFAULT 0支持后台一键上下架sort_order用于菜品列表排序比ORDER BY id DESC更灵活t_orderpay_status TINYINT DEFAULT 0 COMMENT 0-待支付 1-已支付 2-已取消,delivery_status TINYINT DEFAULT 0 COMMENT 0-待接单 1-制作中 2-已出餐状态机设计避免用字符串枚举导致 SQL 查询慢如WHERE status paidt_cartuser_id BIGINT NOT NULL,dish_id BIGINT NOT NULL,UNIQUE KEY uk_user_dish (user_id,dish_id)购物车用唯一索引防重复添加不用 session 存储减轻前端压力t_admin_logoperator_name VARCHAR(32),operation_type VARCHAR(20),detail TEXT管理员操作留痕答辩时可演示“谁在几点审核了哪笔订单”注意执行 SQL 前确保 MySQL 字符集为utf8mb4否则微信昵称中的 emoji如 会存成?。执行命令ALTER DATABASE homechef CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;2.4 文档包/docs答辩前必须细读的 3 份材料/docs不是摆设。其中接口文档.md按 RESTful 规范列出全部 27 个接口每个接口包含请求方式、URL、Header 示例、Body 参数含必填/选填标记、成功响应 JSON 结构、常见错误码如1001用户未登录、2003库存不足ER图.png用 draw.io 绘制清晰展示t_user与t_order的一对多关系、t_order与t_order_item的一对多嵌套最实用的是部署checklist.md列出了 12 项上线前必检项例如“检查 Nginx 是否转发/api/**到后端 8080 端口”、“确认微信支付证书apiclient_cert.p12已放入/backend/src/main/resources/cert/”。3. 微信登录与手机号获取从wx.login()到getPhoneNumber的完整链路与权限绕过陷阱微信小程序登录不是点一下“允许”就完事。这份源码实现了标准的「静默登录 主动授权手机号」双阶段流程且规避了微信最新策略变更带来的坑。很多学生项目卡在这一步小程序能进首页但一点击“我的订单”就白屏——根本原因是没处理好登录态中断。3.1 静默登录code2Session接口调用与 token 生成逻辑小程序端调用wx.login()获取code传给后端/auth/login接口。后端用该code向微信服务器请求openid和session_key再生成自定义 JWT token 返回// /backend/src/main/java/com/homechef/controller/AuthController.java PostMapping(/login) public ResultString login(RequestBody LoginRequest request) { // 1. 调用微信 code2Session 接口 WxMaJscode2SessionResult sessionResult wxMaService.getUserService() .getSessionInfo(request.getCode()); // 2. 校验 sessionResult 是否有效避免伪造 code if (sessionResult null || StringUtils.isBlank(sessionResult.getOpenid())) { return Result.fail(登录失败无效的code); } // 3. 查询或创建用户根据 openid User user userService.getByOpenId(sessionResult.getOpenid()); if (user null) { user new User(); user.setOpenId(sessionResult.getOpenid()); user.setCreateTime(LocalDateTime.now()); userService.save(user); } // 4. 生成 JWT token有效期2小时 String token JwtUtil.generateToken(user.getId(), user.getOpenId()); return Result.success(token); }关键参数说明LoginRequest.code是前端传来的临时登录凭证JwtUtil.generateToken()使用 HS256 算法密钥写在application.yml的jwt.secret下user.getId()是数据库自增主键作为 token payload 中的userId后续所有接口用AuthenticationPrincipal注解即可注入当前用户对象。3.2 手机号授权getPhoneNumber组件绑定与后端解密全流程微信要求必须用button open-typegetPhoneNumber组件触发授权不能用wx.getPhoneNumber()API 直接调。源码中/pages/user/bind-phone/bind-phone.wxml正确使用了该组件并监听bindgetphonenumber事件!-- /weapp/pages/user/bind-phone/bind-phone.wxml -- button classbtn-primary open-typegetPhoneNumber bindgetphonenumberonGetPhoneNumber 授权手机号 /button// /weapp/pages/user/bind-phone/bind-phone.js onGetPhoneNumber(e) { if (e.detail.code) { // 将加密数据传给后端解密 request({ url: /user/bind-phone, method: POST, data: { encryptedData: e.detail.encryptedData, iv: e.detail.iv } }).then(res { wx.showToast({ title: 绑定成功, icon: success }); wx.navigateBack(); // 返回上一页 }); } else { wx.showToast({ title: 授权失败, icon: none }); } }后端解密逻辑在/backend/src/main/java/com/homechef/controller/UserController.java的bindPhone()方法中使用 WxJava SDK 的WxMaService.getUserService().decryptPhoneNumb方法必须传入正确的 sessionKey从code2Session获取PostMapping(/bind-phone) public ResultVoid bindPhone(RequestBody BindPhoneRequest request) { // 1. 从当前登录用户获取 sessionKey存在 Redis 中key: session: userId String sessionKey redisTemplate.opsForValue() .get(session: SecurityUtil.getCurrentUserId()); if (StringUtils.isBlank(sessionKey)) { return Result.fail(sessionKey 不存在请重新登录); } // 2. 调用微信解密接口 WxMaPhoneNumberInfo phoneInfo wxMaService.getUserService() .getPhoneNoInfo(sessionKey, request.getEncryptedData(), request.getIv()); // 3. 更新用户手机号脱敏存储138****1234 User user new User(); user.setId(SecurityUtil.getCurrentUserId()); user.setPhone(MaskUtil.maskPhone(phoneInfo.getPhoneNumber())); userService.updateById(user); return Result.success(); }提示sessionKey有效期仅 5 分钟且一个code只能换取一次sessionKey。因此bindPhone()必须在登录后立即调用不能隔太久。源码中SecurityUtil.getCurrentUserId()从 JWT token 中解析出userId确保操作的是当前登录人。3.3 常见问题排查微信登录链路中 4 个高频翻车点现象 → 原因 → 解决全是血泪经验现象小程序控制台报错request:fail url not in domain list原因app.json中request合法域名未添加后端服务器地址或添加了http://协议微信只认https://解决登录微信公众平台 → 开发管理 → 开发设置 → 服务器域名 →request 合法域名添加你的 HTTPS 域名如https://api.homechef.example.com不要加端口号现象调用/auth/login返回{code:500,message:Invalid code}原因前端wx.login()获取的code未及时传给后端或后端用错appid/secretapplication.yml中wx.miniapp.app-id和wx.miniapp.secret配置错误解决用 Postman 模拟请求手动传入一个真实code观察微信返回的原始错误信息确认application.yml中wx.miniapp配置块与微信公众平台「开发管理」页的 AppID 和 AppSecret 完全一致现象点击“授权手机号”按钮无反应控制台无报错原因button组件缺少open-typegetPhoneNumber属性或bindgetphonenumber事件名拼写错误如写成bindgetphonenumber少了e解决检查 WXML 中 button 标签是否严格匹配官方文档写法在.js文件中Page({})对象内确认onGetPhoneNumber方法名与 WXML 中bindgetphonenumber的值完全一致大小写敏感现象bindPhone()接口返回{code:401,message:Invalid iv or encryptedData}原因前端传入的iv或encryptedData是undefined或后端使用的sessionKey已过期超过 5 分钟解决在onGetPhoneNumber方法中console.log(e.detail)确认e.detail.iv和e.detail.encryptedData非空后端bindPhone()方法开头加日志打印sessionKey长度若为null则说明 Redis 中 session 已失效需引导用户重新登录4. 订单与支付核心流程从加购、下单到微信支付回调的 7 步闭环实现毕业设计最容易被问倒的环节就是“订单怎么生成的”、“支付成功后怎么通知后台”。这份源码把整个链路拆成 7 个原子步骤每步都有对应代码和数据库状态变更答辩时你能指着代码说清楚每一行在干什么。4.1 购物车添加t_cart表的幂等插入与库存预占用户点击“”加购时前端调用/cart/add后端先查库存再插入或更新购物车记录// /backend/src/main/java/com/homechef/controller/CartController.java PostMapping(/add) public ResultVoid addToCart(RequestBody CartAddRequest request) { // 1. 校验菜品是否存在且上架 Dish dish dishService.getById(request.getDishId()); if (dish null || dish.getStatus() ! 1) { return Result.fail(菜品不存在或已下架); } // 2. 校验库存乐观锁UPDATE ... SET stock stock - 1 WHERE id ? AND stock ? int updated dishMapper.reduceStock(dish.getId(), request.getCount()); if (updated 0) { return Result.fail(库存不足); } // 3. 插入或更新购物车ON DUPLICATE KEY UPDATE Cart cart new Cart(); cart.setUserId(SecurityUtil.getCurrentUserId()); cart.setDishId(request.getDishId()); cart.setCount(request.getCount()); cartService.saveOrUpdate(cart, new QueryWrapperCart().eq(user_id, cart.getUserId()).eq(dish_id, cart.getDishId())); return Result.success(); }关键点dishMapper.reduceStock()是 MyBatis-Plus 的自定义 SQL用UPDATE t_dish SET stock stock - #{count} WHERE id #{id} AND stock #{count}实现库存扣减避免超卖saveOrUpdate()基于uk_user_dish唯一索引同一用户对同一菜品多次加购会自动累加数量而非新增记录。4.2 下单生成t_order与t_order_item的事务一致性保障点击“去结算”后前端传入购物车 ID 列表后端开启事务同时写入主订单和订单明细// /backend/src/main/java/com/homechef/controller/OrderController.java Transactional(rollbackFor Exception.class) PostMapping(/create) public ResultOrderVO createOrder(RequestBody OrderCreateRequest request) { Long userId SecurityUtil.getCurrentUserId(); // 1. 查询购物车中选中的菜品 ListCart carts cartService.list( new QueryWrapperCart().in(id, request.getCartIds()).eq(user_id, userId)); // 2. 计算总金额、生成订单号格式HOMECHEF20240520123456 BigDecimal totalAmount carts.stream() .map(cart - { Dish dish dishService.getById(cart.getDishId()); return dish.getPrice().multiply(BigDecimal.valueOf(cart.getCount())); }) .reduce(BigDecimal.ZERO, BigDecimal::add); String orderNo HOMECHEF DateTimeFormatter.ofPattern(yyyyMMddHHmmss) .format(LocalDateTime.now()) RandomUtil.randomNumbers(6); // 3. 插入主订单 Order order new Order(); order.setOrderNo(orderNo); order.setUserId(userId); order.setTotalAmount(totalAmount); order.setPayStatus(0); // 待支付 order.setDeliveryStatus(0); // 待接单 orderService.save(order); // 4. 插入订单明细批量插入 ListOrderItem items carts.stream().map(cart - { Dish dish dishService.getById(cart.getDishId()); OrderItem item new OrderItem(); item.setOrderId(order.getId()); item.setDishId(cart.getDishId()); item.setDishName(dish.getName()); item.setPrice(dish.getPrice()); item.setCount(cart.getCount()); item.setAmount(dish.getPrice().multiply(BigDecimal.valueOf(cart.getCount()))); return item; }).collect(Collectors.toList()); orderItemService.saveBatch(items); // 5. 清空已下单的购物车 cartService.remove(new QueryWrapperCart() .in(id, request.getCartIds()).eq(user_id, userId)); return Result.success(new OrderVO(order, items)); }注意Transactional注解确保 5 步操作要么全部成功要么全部回滚。若第 4 步批量插入失败第 5 步清空购物车也不会执行用户下次进入购物车仍能看到原商品。4.3 微信支付统一下单、签名生成与回调验签的硬核细节支付不是调一个wx.requestPayment就完事。源码完整实现了服务端统一下单、前端唤起支付、服务端接收异步通知并验签的全流程统一下单/pay/unifiedorder接口调用微信unifiedorderAPI生成prepay_id后端用WxPayService.createOrder()封装关键参数outTradeNo订单号、totalFee单位分、spbillCreateIp必须传真实服务器 IP不能写127.0.0.1、notifyUrl异步通知地址必须是公网可访问的 HTTPS URL前端唤起后端返回timeStamp、nonceStr、package即prepay_idxxx、signType、paySign五元组前端用wx.requestPayment()传入回调验签微信服务器 POST 到notifyUrl后端用WxPayService.parseOrderNotifyResult()自动验签必须校验return_code和result_code均为SUCCESS且out_trade_no与本地订单号匹配再更新t_order.pay_status 1。// /backend/src/main/java/com/homechef/controller/PayController.java PostMapping(/notify) public String payNotify(HttpServletRequest request, HttpServletResponse response) { try { // 1. 解析微信回调 XML WxPayOrderNotifyResult notifyResult wxPayService.parseOrderNotifyResult( IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8)); // 2. 验证签名WxJava 自动完成 if (!notifyResult.isSuccess()) { return xmlreturn_code![CDATA[FAIL]]/return_codereturn_msg![CDATA[签名失败]]/return_msg/xml; } // 3. 校验业务参数 String outTradeNo notifyResult.getOutTradeNo(); Order order orderService.getByOrderNo(outTradeNo); if (order null || order.getPayStatus() ! 0) { return xmlreturn_code![CDATA[FAIL]]/return_codereturn_msg![CDATA[订单不存在或已支付]]/return_msg/xml; } // 4. 更新订单状态 order.setPayStatus(1); order.setPayTime(LocalDateTime.now()); orderService.updateById(order); // 5. 发送模板消息通知用户可选 sendPaySuccessTemplateMsg(order); return xmlreturn_code![CDATA[SUCCESS]]/return_codereturn_msg![CDATA[OK]]/return_msg/xml; } catch (Exception e) { log.error(支付回调处理失败, e); return xmlreturn_code![CDATA[FAIL]]/return_codereturn_msg![CDATA[系统错误]]/return_msg/xml; } }提示notifyUrl必须在微信商户平台「产品中心」→「开发配置」中填写且与后端application.yml中wx.pay.notify-url一致验签失败时微信会每隔一段时间重试最多 5 次所以payNotify()方法必须是幂等的重复通知不能重复扣款。5. 部署上线与性能调优从学生机到可演示的 3 项关键配置很多同学本地跑通了一部署到云服务器就 502、超时、支付回调收不到。这不是代码问题是环境配置没对齐。这份源码在docs/deploy-checklist.md里列了 12 条我挑最关键的 3 项展开每项都附实操命令和验证方法。5.1 Nginx 反向代理配置解决小程序request跨域与 HTTPS 强制学生常用http://localhost:8080直连后端但微信要求request必须 HTTPS。正确做法是 Nginx 做反向代理让小程序请求https://api.homechef.example.com/api/**Nginx 转发到http://127.0.0.1:8080/api/**# /etc/nginx/conf.d/homechef.conf server { listen 443 ssl; server_name api.homechef.example.com; ssl_certificate /etc/letsencrypt/live/homechef.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/homechef.example.com/privkey.pem; location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 关键透传 Authorization header否则 JWT token 无法传递 proxy_set_header Authorization $http_authorization; proxy_pass_request_headers on; } # 微信支付回调必须能被外网访问单独配置 location /pay/notify { proxy_pass http://127.0.0.1:8080/pay/notify; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # HTTP 重定向到 HTTPS server { listen 80; server_name api.homechef.example.com; return 301 https://$server_name$request_uri; }验证方法curl -I https://api.homechef.example.com/api/auth/login应返回HTTP/2 200若返回502 Bad Gateway检查proxy_pass地址是否正确、后端服务是否在运行systemctl status homechef-backend若返回400 Bad Request检查proxy_set_header是否漏了Authorization。5.2 MySQL 连接池调优HikariCP 的 4 个核心参数设置学生机1核2G默认 HikariCP 配置maximumPoolSize10会导致高并发时连接耗尽。源码application.yml中已优化spring: datasource: hikari: maximum-pool-size: 8 # 降低最大连接数避免内存溢出 minimum-idle: 2 # 最小空闲连接减少冷启动延迟 connection-timeout: 30000 # 连接超时30秒避免线程卡死 idle-timeout: 600000 # 空闲连接600秒后释放 max-lifetime: 1800000 # 连接最长存活30分钟防止 MySQL wait_timeout 断连验证方法部署后用show processlist;查看 MySQL 当前连接数应稳定在 2~8 之间若持续 10说明maximum-pool-size设太高需调低若频繁出现HikariPool-1 - Connection is not available日志说明connection-timeout太短需调大。5.3 微信支付证书加载apiclient_cert.p12的路径与密码硬编码风险微信支付 SDK 要求apiclient_cert.p12证书文件必须放在src/main/resources/cert/目录下且application.yml中wx.pay.cert-path指向该路径。但源码中cert-password是明文写在配置里这是开发阶段的权宜之计上线前必须改为环境变量# application.yml开发用 wx: pay: cert-path: classpath:cert/apiclient_cert.p12 cert-password: your_mch_id_here # ← 这里是商户号不是随机密码 # 上线时用环境变量覆盖推荐 # 启动命令java -Dwx.pay.cert-password${WX_PAY_CERT_PASSWORD} -jar homechef.jar验证方法启动后查看日志搜索WxPayService应有load cert from classpath:cert/apiclient_cert.p12成功提示若报FileNotFoundException检查cert/目录是否在 jar 包内jar -tf homechef.jar | grep cert若报PKIX path building failed说明证书密码错误确认cert-password是商户号12位数字。6. 答辩演示技巧与避坑清单如何用 5 分钟讲清这个项目的技术深度答辩不是背代码是讲清楚“你解决了什么真实问题”、“为什么这么解决”、“有没有更好的方案”。我带过 17 届毕设见过太多学生一上来就打开 IDE 狂点文件评委听得云里雾里。这份家庭大厨源码我建议你用以下结构讲满 5 分钟每一步都对应一个可截图的界面或日志6.1 演示主线用“一个订单的生命周期”串起所有技术点开场一句话定调“老师好我做的家庭大厨系统核心是解决校园场景下‘用户想点餐、商家要接单、支付需安全’这三个刚性需求。下面我用一笔真实订单带您走一遍从登录到出餐的全过程。” 然后按顺序演示微信扫码登录打开小程序 → 点击“我的” → 触发wx.login()→ 后端code2Session返回 token → 控制台console.log(登录成功)浏览与加购进入首页 → 点击“家常菜”分类 → 选“红烧肉”加购 → 查看购物车数量变为 1 → 后台t_cart表新增记录下单与支付去结算 → 生成订单号HOMECHEF20240520123456→ 唤起微信支付 → 支付成功 → 后台t_order.pay_status变为 1后台审核管理员登录http://admin.homechef.example.com→ 订单管理 → 找到该订单 → 点击“同意出餐” →t_order.delivery_status变为 1状态推送用户小程序收到模板消息“您的订单已出餐”同时订单页状态实时更新。关键每步演示后切到浏览器开发者工具 Network 标签页指出对应的请求 URL 和响应状态码如/auth/login返回 200/pay/unifiedorder返回 200证明不是 mock 数据。6.2 技术亮点提炼3 个评委最可能追问的点提前准备好答案问为什么用 JWT 而不用 Session答“因为小程序是无状态客户端JWT 把用户 ID 和权限存在 token 里后端只需验签不依赖服务器内存或 Redis 存 session扩展性更好。而且源码中JwtUtil用了 HS256 算法密钥存在配置文件安全性足够毕业设计要求。”问库存扣减怎么防止超卖答“用了数据库乐观锁SQL 是UPDATE t_dish SET stock stock - 1 WHERE id ? AND stock 1。如果两个请求同时查到 stock1只有一个能成功执行 update另一个会返回影响行数 0后端捕获后返回‘库存不足’而不是扣成 -1。”问支付回调怎么保证不丢答“微信回调是异步的可能失败。源码做了三重保障第一回调接口返回SUCCESS前必须更新数据库第二加了Transactional数据库更新失败则整个事务回滚第三在payNotify()方法里加了日志每次回调都记录out_trade_no和时间方便事后排查。”6.3 真实踩坑复盘答辩时主动说出 1 个“我曾经翻车的点”反而加分最后 30 秒别只说“谢谢老师”来一句“其实我在做支付回调时栽过一个特别典型的坑本地测试一切正常一上云服务器就收不到微信通知。查了两天发现是 Nginx 配置里漏了proxy_set_header X-Real-IP $remote_addr;导致微信服务器的 IP 被识别成127.0.0.1而我的notifyUrl白名单只写了公网 IP。后来加上这行立刻就好了。这个教训让我明白部署不是 copy-paste每个 header 都可能决定功能生死。”从那以后我每次部署新服务都会先用curl -v https://your-domain.com/api/test看完整请求头和响应头再动手写业务逻辑。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑