随着餐饮行业数字化经营的发展,扫码点餐小程序已经成为餐厅、奶茶店、快餐店、火锅店等餐饮场景中常见的应用工具。顾客通过手机进入点餐页面,选择商品、提交订单并完成支付,商家则通过管理后台处理订单、维护商品和查看经营数据。
对于想自己开发扫码点餐小程序的技术人员、软件开发团队以及准备搭建餐饮点餐系统的创业者来说,如何实现前端点餐页面、后端业务接口和商家管理后台之间的数据交互,是整个项目开发的关键。
一套完整的扫码点餐小程序,不仅需要实现商品展示和购物车功能,还需要处理桌台识别、订单创建、微信支付、订单状态更新以及商家实时接单等业务。
本文将以微信小程序、Vue 3、Node.js 和 MySQL 为例,从实际开发角度介绍扫码点餐系统的主要功能、关键技术及代码实现思路,帮助开发者了解一套扫码点餐小程序从开发到上线的基本过程。
一、扫码点餐小程序前端如何开发?
扫码点餐小程序的前端主要面向顾客,核心功能包括桌台识别、商品分类展示、商品详情、购物车、订单确认、微信支付和订单查询。
对于主要运行在微信生态内的扫码点餐系统,可以使用微信原生小程序开发。如果需要兼容多个平台,也可以选择 uni-app。
在实际开发中,建议优先完成商品列表、购物车和订单提交三个基础功能,再逐步接入桌台识别及微信支付。
1. 商品列表页面开发
商品列表是顾客进入扫码点餐小程序后最先接触的页面之一。
通常需要展示商品分类、商品图片、名称、价格和购买按钮。用户点击不同分类时,页面展示对应分类下的商品。
小程序可以通过 wx.request 调用服务端商品接口:
Page({
data: {
products: [],
loading: false
},
onLoad() {
this.loadProducts();
},
loadProducts() {
this.setData({
loading: true });
wx.request({
url: 'https://api.example.com/api/products',
method: 'GET',
data: {
storeId: 1001
},
success: (res) => {
if (res.statusCode === 200) {
this.setData({
products: res.data.data || []
});
}
},
fail: (error) => {
console.error('商品加载失败', error);
},
complete: () => {
this.setData({
loading: false });
}
});
}
});
这里的 storeId 代表当前门店编号。正式开发时,门店信息通常由桌台扫码结果获取,而不是固定写在页面中。
商品接口还需要根据门店营业状态、商品上下架状态以及库存情况返回对应数据,避免顾客选择无法购买的商品。
2. 购物车功能开发
购物车主要负责保存顾客选择的商品、购买数量和规格,并计算订单金额。
例如,顾客选择两份18元的炒饭和一份12元的饮料,购物车需要自动计算商品总金额。
可以使用 JavaScript 实现基本的购物车计算:
const cart = [
{
productId: 101,
name: '招牌炒饭',
price: 1800,
quantity: 2
},
{
productId: 102,
name: '鲜榨果汁',
price: 1200,
quantity: 1
}
];
function calculateTotal(items) {
return items.reduce((total, item) => {
return total + item.price * item.quantity;
}, 0);
}
const totalAmount = calculateTotal(cart);
console.log('订单金额:¥' + totalAmount / 100);
这里将商品价格统一使用整数分表示,可以避免 JavaScript 浮点数计算带来的金额精度问题。
需要注意,前端购物车金额仅用于页面展示。顾客提交订单时,服务端必须重新查询商品价格并计算订单金额,不能直接使用前端提交的总价。
如果系统支持商品规格,例如大杯、小杯、加料等,还需要根据商品规格编号区分购物车中的不同商品组合。
3. 桌台扫码识别功能
对于堂食扫码点餐系统,每张桌台通常需要对应一个独立的小程序码。
顾客扫码后,系统自动识别当前门店及桌台,避免用户手动输入桌号。
微信小程序可以通过页面参数获取扫码信息:
Page({
data: {
storeId: null,
tableId: null,
tableName: ''
},
onLoad(options) {
const scene = decodeURIComponent(
options.scene || ''
);
if (!scene) {
wx.showToast({
title: '桌台信息无效',
icon: 'none'
});
return;
}
wx.request({
url: 'https://api.example.com/api/tables/resolve',
method: 'GET',
data: {
scene },
success: (res) => {
if (res.data.code === 200) {
this.setData(res.data.data);
}
}
});
}
});
实际开发中,可以通过微信小程序码接口生成桌台专属小程序码,并将桌台短标识写入 scene 参数。
服务端根据该标识查询对应门店和桌台信息,同时验证桌台是否存在、是否启用,确保订单能够正确关联到对应门店。
二、Node.js 后端接口如何实现?
扫码点餐小程序的后端主要负责商品查询、订单创建、库存处理、支付接口、订单状态更新以及商家权限验证等业务。
以 Node.js 和 Express 为例,可以快速搭建一套基础的接口服务。
首先安装相关依赖:
npm install express mysql2 dotenv
然后创建服务端入口文件:
const express = require('express');
const app = express();
app.use(express.json());
app.get('/api/health', (req, res) => {
res.json({
code: 200,
message: '扫码点餐服务运行正常'
});
});
app.listen(3000, () => {
console.log('服务已启动,端口:3000');
});
通过这种方式,可以先完成基础接口服务,再逐步添加商品、订单和支付等业务接口。
1. 商品查询接口
商品查询接口主要根据门店编号返回对应的商品列表。
数据库可以使用 MySQL 保存商品信息,包含商品编号、门店编号、商品名称、价格、库存和上下架状态等字段。
例如:
CREATE TABLE products (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
store_id BIGINT NOT NULL,
product_name VARCHAR(100) NOT NULL,
price INT NOT NULL,
stock INT NOT NULL DEFAULT 0,
status TINYINT NOT NULL DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_store_status (store_id, status)
);
使用 Node.js 查询数据库中的商品:
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
connectionLimit: 10
});
app.get('/api/products', async (req, res) => {
const storeId = Number(req.query.storeId);
if (!Number.isSafeInteger(storeId) || storeId <= 0) {
return res.status(400).json({
message: '门店参数错误'
});
}
try {
const [rows] = await pool.execute(
`SELECT id, product_name, price, stock
FROM products
WHERE store_id = ? AND status = 1`,
[storeId]
);
res.json({
code: 200,
data: rows
});
} catch (error) {
res.status(500).json({
message: '商品查询失败'
});
}
});
这里使用参数化查询,避免直接拼接用户输入的 SQL 条件。
如果系统支持多个门店,商品查询必须根据当前门店进行过滤,确保顾客看到的是对应门店的商品及价格。
2. 订单创建接口
顾客在小程序中点击提交订单后,前端会将商品编号、规格、购买数量以及桌台信息发送到服务端。
服务端收到请求后,需要完成商品校验、价格计算、库存检查和订单创建。
例如,前端提交的数据可以是:
{
"storeId": 1001,
"tableId": 108,
"items": [
{
"productId": 101,
"quantity": 2
},
{
"productId": 102,
"quantity": 1
}
]
}
服务端不能直接信任前端提交的商品金额,而是需要重新查询数据库中的商品价格。
下面是订单金额计算的简化示例:
async function calculateOrderAmount(items, storeId) {
let totalAmount = 0;
for (const item of items) {
if (!Number.isSafeInteger(item.quantity) ||
item.quantity <= 0) {
throw new Error('商品数量无效');
}
const [rows] = await pool.execute(
`SELECT price, stock
FROM products
WHERE id = ?
AND store_id = ?
AND status = 1`,
[item.productId, storeId]
);
if (rows.length === 0) {
throw new Error('商品不存在或已下架');
}
const product = rows[0];
if (product.stock < item.quantity) {
throw new Error('商品库存不足');
}
totalAmount += product.price * item.quantity;
}
return totalAmount;
}
上述代码主要用于说明服务端金额计算逻辑。正式创建订单时,还需要使用数据库事务处理库存预占、订单主表写入和订单明细写入,避免并发下单造成库存超卖。
同时,建议为订单创建接口增加幂等控制,避免用户重复点击提交按钮产生重复订单。
三、微信支付与订单状态如何处理?
微信支付是扫码点餐小程序中的重要功能。
顾客提交订单后,服务端需要创建微信支付预支付订单,再将支付参数返回小程序。
小程序调用 wx.requestPayment 发起支付:
function requestPayment(payParams) {
wx.requestPayment({
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: 'RSA',
paySign: payParams.paySign,
success() {
wx.showToast({
title: '正在确认支付',
icon: 'none'
});
},
fail(error) {
console.error('支付未完成', error);
}
});
}
需要注意,微信小程序的支付成功回调并不能直接作为订单已支付的最终依据。
服务端需要按照微信支付 API v3 的要求验证支付通知签名、解密通知内容,并核对订单编号、商户号和支付金额。
只有确认支付成功后,才能将数据库中的订单支付状态更新为已支付。
在订单管理方面,建议将支付状态和业务订单状态分开管理。
例如:
const OrderStatus = {
PENDING_PAYMENT: 'pending_payment',
PAID: 'paid',
ACCEPTED: 'accepted',
PREPARING: 'preparing',
COMPLETED: 'completed',
CANCELLED: 'cancelled'
};
const PayStatus = {
UNPAID: 'unpaid',
PAID: 'paid',
REFUNDED: 'refunded'
};
当顾客支付成功后,订单进入待商家处理状态。商家接单后,可以进一步更新为制作中,完成制作后再将订单标记为已完成。
如果出现顾客取消、支付超时或退款等情况,则需要根据实际业务规则进入对应状态,不能简单地将所有订单都按照正常流程处理。
四、Vue 3 商家管理后台如何开发?
商家管理后台是扫码点餐系统的重要组成部分,主要面向餐厅负责人、收银人员和后厨工作人员。
后台一般需要实现商品管理、商品分类管理、桌台管理、订单管理、经营统计以及员工账号管理等功能。
对于前端技术选型,可以使用 Vue 3 配合 Element Plus 开发管理界面。
1. 商品管理功能
商品管理页面需要支持商品列表查询、商品新增、编辑、上下架以及库存管理。
下面是使用 Vue 3 获取商品列表的示例:
import {
ref, onMounted } from 'vue';
import axios from 'axios';
const products = ref([]);
const loading = ref(false);
async function loadProducts() {
loading.value = true;
try {
const response = await axios.get(
'/api/products',
{
params: {
storeId: 1001
}
}
);
products.value = response.data.data;
} catch (error) {
console.error('加载商品失败', error);
} finally {
loading.value = false;
}
}
onMounted(() => {
loadProducts();
});
正式项目中,后台门店编号应当来自已登录账号的门店选择结果,并由服务端再次校验权限。
如果系统支持多门店,还需要允许具备权限的管理人员切换门店,分别维护对应门店的商品信息。
2. 订单管理功能
订单管理页面需要展示订单编号、桌台名称、商品明细、订单金额、下单时间以及订单状态。
商家可以根据订单状态进行筛选,并执行接单、开始制作和完成订单等操作。
例如,使用 Axios 调用订单状态更新接口:
async function acceptOrder(orderId) {
try {
await axios.patch(
`/api/orders/${
orderId}/accept`
);
console.log('接单成功');
await loadOrders();
} catch (error) {
console.error('接单失败', error);
}
}
这里的订单接单接口必须由服务端验证当前账号的门店权限,并确认订单已经支付且处于允许接单的状态。
如果订单已经被其他工作人员接单,服务端应当阻止重复接单,避免订单状态出现异常。
3. 新订单实时提醒
对于餐饮门店来说,订单提醒的及时性直接影响出餐效率。
如果商家后台需要实时接收新订单,可以使用 WebSocket 建立消息连接。
例如:
const socket = new WebSocket(
'wss://api.example.com/ws/orders'
);
socket.onmessage = (event) => {
const message = JSON.parse(event.data);
if (message.type === 'NEW_ORDER') {
console.log('收到新订单:', message.orderNo);
loadOrders();
}
};
socket.onclose = () => {
console.log('订单连接已断开');
};
正式项目中,需要增加 WebSocket 身份认证、门店权限校验、断线重连和消息去重等机制。
对于需要后厨打印的餐厅,还可以通过云打印接口将订单信息发送到指定打印机,实现商家接单后自动打印小票。
五、多门店扫码点餐系统需要注意什么?
如果准备将扫码点餐小程序开发成可以销售给多个餐饮商家的系统,就需要提前考虑多商户和多门店管理。
例如,一个餐饮品牌可能拥有多家门店,不同门店需要独立管理商品、桌台、订单和员工。
在数据库设计时,可以通过 merchant_id 和 store_id 标识数据归属。
商家登录后台后,服务端根据账号所属商户及门店权限查询对应数据,避免不同商家之间出现数据混淆。
例如,查询当前商户某门店的订单:
app.get('/api/orders', requireAuth, async (req, res) => {
const merchantId = req.auth.merchantId;
const storeId = Number(req.query.storeId);
if (!Number.isSafeInteger(storeId) || storeId <= 0) {
return res.status(400).json({
message: '门店参数错误'
});
}
const allowed = await canAccessStore(
req.auth.userId,
merchantId,
storeId
);
if (!allowed) {
return res.status(403).json({
message: '无权访问该门店'
});
}
const [rows] = await pool.execute(
`SELECT * FROM orders
WHERE merchant_id = ?
AND store_id = ?
ORDER BY created_at DESC
LIMIT 100`,
[merchantId, storeId]
);
res.json({
code: 200,
data: rows
});
});
其中,requireAuth 和 canAccessStore 代表实际项目中需要实现的身份认证和门店权限验证逻辑。
对于多商户系统,还需要明确不同商家的微信支付收款配置,避免不同经营主体之间的订单资金归属不清晰。
如果计划提供独立部署或者二次开发服务,建议在开发初期就将商户管理、门店管理和订单业务进行合理拆分,方便后续功能扩展。
六、扫码点餐小程序如何部署上线?
当小程序前端、后端接口和商家管理后台开发完成后,就可以进入测试和部署阶段。
服务端通常可以部署在 Linux 服务器上,使用 Nginx 处理 HTTPS 请求及反向代理,Node.js 负责运行后端接口服务,MySQL 用于存储业务数据。
正式上线前,需要准备服务器、域名、HTTPS 证书、微信小程序主体以及对应的微信支付商户资质。
在测试阶段,建议重点检查以下内容:
- 顾客扫码后能否准确识别门店和桌台。
- 商品价格、规格和库存是否正确。
- 购物车金额与服务端订单金额是否一致。
- 微信支付成功后订单状态能否正确更新。
- 顾客重复提交订单时是否会产生重复数据。
- 商家后台能否及时收到新订单。
- 不同门店之间的商品和订单数据是否正确隔离。
- 网络异常、支付超时和打印失败时能否正常处理。
对于实际商用的扫码点餐系统,还需要建立数据库备份、日志记录、异常告警和服务器监控机制。
如果后续用户数量增加,可以根据访问量逐步优化数据库查询、缓存策略和服务器资源配置。
七、总结
开发一套扫码点餐小程序,主要需要完成三个部分的工作:顾客端实现商品浏览、购物车、扫码识别和在线支付;服务端负责商品查询、订单创建、金额计算、库存处理和支付状态管理;商家管理后台负责商品维护、订单处理、桌台管理和经营数据查询。
从技术选型来看,微信原生小程序、Vue 3、Node.js 和 MySQL 是一种比较常见的开发组合,能够满足中小型扫码点餐系统的基础需求。
对于想自己搭建扫码点餐系统的开发者,可以先实现单门店的完整点餐流程,确保商品、订单和支付功能稳定运行,再逐步扩展多门店管理、员工权限和经营统计等功能。
如果计划将扫码点餐小程序作为商业产品推广,或者为其他餐饮商家提供系统定制开发、独立部署和二次开发服务,则需要更加重视商户数据隔离、支付配置、系统稳定性和后续扩展能力。
扫码点餐小程序的开发难点,并不只是前端页面的展示效果,而是如何让顾客下单、微信支付、商家接单、后厨制作和订单管理之间形成稳定可靠的业务闭环。
对于准备进入餐饮软件开发领域的团队来说,从一套功能完整、流程清晰的扫码点餐系统开始,逐步完善多门店和多商户能力,是比较务实的开发方向。