一个包子店的下单系统,是怎么搭起来的

坡晓馒 poxiaoman.com 全栈架构拆解:一个 Worker + 一个数据库,撑起顾客下单、收银 POS、老板后台

坡晓馒 PO XIAO MAN · 系统架构笔记

2026-06-14

一句话:整套系统没有传统服务器,就是一段跑在 Cloudflare 上的程序 + 一个小数据库,对外是三个网址(顾客下单、老板后台、收银 POS),对内共用同一套数据。所以老板看到的营收 = 线上单 + 线下单,自动合并;同一份订单,顾客看是「套餐」,后厨看是「要做几个包子」。

说明:本文讲的是真实上线的系统(poxiaoman.com),重点在「为什么这样设计」,技术名词第一次出现都会用大白话解释。


0. 先看全貌:一套数据,三个入口

系统总览:一个 Cloudflare Worker + 一个 D1 数据库,对外是顾客站、老板后台、收银 POS 三个入口

整套系统的骨架其实很简单:

三个网址背后是同一段程序、同一个数据库。这一点是整个系统的灵魂:数据只有一份,谁写的单都进同一张订单表,所以营收、对账、备货全都自动合并,老板不用对两本账。

serverless(无服务器,不是真没服务器,而是你不用管服务器——平台帮你按请求自动跑、自动扩容、不用时不收钱)」。对一个包子店来说,这意味着没有运维、平时几乎零成本。


1. 三个前端,其实是三套「看同一份数据的眼镜」

顾客、老板、店员看到的界面完全不同,但底下读写的是同一批数据:

入口 谁用 它其实在做什么
顾客站 顾客 往订单表一条待付款单;查自己的会员数据
收银 POS 店员 往订单表一条已付的「线下单」,标记是哪个收银员
老板后台 老板 订单表,算营收、画备货图、对账

这就是「一份数据、多种视图」:不复制数据、不同步、不对账,而是让不同的人用不同的「眼镜」去看同一张表。

一个最能说明问题的例子是「生产计划」——

同一份订单数据的两种视图:顾客看到「套餐」,后厨看到「每种包子要做几个」

顾客下的是「科学平衡盒」「高蛋白组合」这些套餐;但后厨需要知道的是「鲜肉包做几个、青菜包做几个」。系统里存了一张「BOM(物料清单,bill of materials,就是「一个套餐由哪些单品、各几个」组成的配方表)」,把当天所有订单按 BOM 展开求和,就得到一张「今天每种包子要做多少」的柱状图。同一份订单,换个视图,就从「卖了什么」变成「要做什么」。


2. 钱的部分:一台「不会算错」的状态机

涉及钱的地方,系统用一台状态机来管——每张订单的付款状态只能按固定规则走,绝不乱跳:

支付状态机:未付款→已付款→退款,三道防线保证不重复入账、不被改价
未付款 ──付款成功──▶ 已付款(自动加积分、通知老板)
未付款 ──失败/超时──▶ 失败 / 过期
已付款 ──退款──▶ 已退款(自动扣回积分)

光有流程还不够,钱要算得对,靠三道「防线」:

这三道防线是用伪造的付款事件逐条压测过的:正常付款、重复通知、金额不符、退款、坏签名——结果全部符合预期。钱的事,不靠「应该没问题」,靠「测过」。


3. 会员系统:从「记个手机号」到「真账户」

最早会员只是「按手机号记积分」。但一旦加了「储值余额」(顾客可以充钱进账户,比如充 500 送 80),「只凭手机号」就成了漏洞——别人知道你手机号就能花你的钱。于是会员升级成了真账户

这里有个通用的教训:加了新功能,常常会让旧的「方便」变成新的「风险」。系统里一放「钱」,原来「凭手机号查会员」的便利设计立刻得收紧。


4. 自动化:定时任务 + 主动通知

系统会在没人盯着的时候自己干活,靠两样东西:

这些通知都做成了「接好但默认关着」——代码就绪,等接上 WhatsApp 的官方凭证就自动开启,不用改一行逻辑。


5. 几个「省」出来的设计选择

这套系统在很多地方选了「更省、更简单」的做法,值得说一下为什么:

选择 为什么
无状态令牌(不建会话表) 服务器不用存任何登录态,验证时重算签名即可——零数据库读、天然能扩容
商品/订单/会员都进一个 D1 数据一份,营收/对账/备货自动合并,不用同步两套
支付二维码、状态机都「手写」不引库 边缘函数冷启动快、部署小、依赖少、不容易出意外
中英文用一个小词典切换 不引翻译库,商品名直接取数据库里已有的中英双名
配色/品牌写成一组变量 改主题只改一处

核心思路是:一个小店的系统,不需要大公司那套重型架构。一段边缘程序 + 一个小数据库,把「一份数据、多种视图 + 钱的事严谨」这两件事做扎实,就够撑起顾客下单、收银、对账、会员、备货一整套。


6. 一句话收尾

复杂的不是技术堆叠,而是想清楚同一份数据要被谁、以什么方式看。把这件事想透,剩下的就是一段不长的程序——但每一处碰到钱的地方,都得当真。