我最近为一位独立经营按摩诊所的按摩师搭建了一个网站。这属于那种需求虽然简单明了,但如果试图独自解决所有问题,却很容易出错的项目:一个外观得体的首页、一个真正能正常运行的在线预约系统,以及一种让店主无需每次有变动都给我打电话,就能自行管理日程和疗程的方式。
这就是我们选择使用Hapio的方式,以及它之所以能取得良好效果的原因。
起点
我的客户原本就有一个Facebook主页,并通过Messenger接受预约。这种方式原本还行——直到出现问题。比如重复预约、客户忘记预约,以及需要手动回答关于价格和空位情况的重复问题。她希望拥有自己的网站,让客户可以直接预约,同时她也能自行关闭营业日、调整营业时间并添加新的护理项目。
关键在于:她是一名按摩师,而不是系统管理员。我们构建的每一项内容,都必须让那些不以数据库和API为思维方式的人能够理解。
为什么不自己开发预订系统呢?
I 可能 已经开发了一个定制的预订系统。Laravel,一个 bookings 表格、可用时段的相关逻辑、冲突处理、两次治疗之间的间隔时间、休息日的处理、暑假安排……
但这恰恰是那种在白板上看起来很简单,实际操作时却要花六个月时间处理各种边界情况的代码。一个资源(一名治疗师)、带有例外情况的固定营业时间、每次治疗前后预留的缓冲时间、不同的治疗时长——这虽然不算什么高深的技术,但需要编写大量代码,而这些代码并不能为这个具体项目带来独特的价值。
Hapio 负责处理这些。我们有一个现成的 API,用于管理空房情况、预订、服务和日程安排。这样我就能专注于项目的核心:打造一个美观的网站和流畅的预订流程,让用户感觉这是专属于他们的系统,而不是千篇一律的通用预订系统。
我们最终确定的架构
我们开发了一个轻量级的 Laravel 应用程序,作为 Hapio 的封装层。请将其理解为“前端 + 集成层”,而非“完整的预订系统”。
Hapio 负责:
- 预订(创建、查询、取消)
- 服务/护理项目(名称、时长、价格、缓冲时间)
- 固定营业时间(周一至周日)
- 个别休息日(节假日、病假等)
- 根据上述所有条件计算可用时段
Laravel 负责:
- 登录页面和预订界面(Livewire)
- 用于查看日程安排、服务及预订概览的管理面板
- 电子邮件(确认、提醒、取消——同时发送给客户和业主)
- 安全的取消链接(采用 HMAC 签名,因此客户无法通过猜测进入他人的预订)
- 缓存可用插槽(Redis)
- Hapio 数据发生变化时的 Webhook 处理
Laravel 数据库基本上只存储管理员用户、会话和队列任务。本地不存储任何预订数据。Hapio 是数据源头。
对于这样规模的企业来说,这似乎很合适。一个小型本地数据库,一个 Redis 实例,除了必需的之外,无需维护任何其他内容。
预订流程
客户只需完成四个步骤:选择护理项目 → 选择时间 → 填写详细信息 → 完成。
页面加载时会从 Hapio 获取护理项目。时间数据按周获取——由于这是访问量最大的数据,我们会将其大量缓存到 Redis 中。周视图中,客户可以浏览未来最多十二周的内容。
预订确认后:
- 该预订已在Hapio中创建
- 客户信息(姓名、电话、电子邮箱、可选留言)将作为元数据保存在预订记录中
- 生成一个取消链接(使用我们控制的密钥进行 HMAC 签名)
- 已向客户和业主发送电子邮件
取消操作需通过带签名链接进行——无需登录。我们实行24小时规则:提前通知时间少于24小时时,您无法进行预订或取消。该规则在读取时由代码执行,而非在缓存中执行,因此即使缓存尚未失效,该规则也能始终如一地生效。
管理面板
所有者登录后,会看到四个标签页:
- 预订——即将进行的和已完成的预订,并支持取消
- 日程表——点击日历中的某一天即可收起或展开该天
- 营业时间——每周固定安排,按日列出
- 服务——添加、编辑、停用疗程
所有操作都通过 Hapio API 进行。管理面板本质上是基于其数据模型构建的一个美观的前端界面。当她更改营业时间或设置某天休息时,Hapio 会发送一个 webhook,我们会清空缓存,并在后台重新生成时间段。
要让 Webhook 流程变得健壮,花了一番功夫——包括签名验证、幂等性,以及在出现问题时回退到完全清空缓存——但一旦落实到位,这一切都是值得的。可用时段会快速更新,而我们无需轮询 API。
哪些方面做得很好
关注点分离。我们无需维护预订逻辑。Hapio 负责处理冲突、缓冲时间以及排程。我们负责用户体验以及该网站特有的功能。
Webhooks + 缓存。可用时段会缓存24小时。当Hapio中发生变化(新预订、日程变更、新增服务)并触发事件时,我们会使相关缓存失效并重新加载。这样,客户就能看到更新后的时间,而我们无需在每次页面加载时都从API获取所有数据。
预订的元数据。客户详细信息作为元数据存储在 Hapio 预订中。我们不需要单独的客户表。对于个人经营的企业来说,这样就足够了。
取消链接。确认邮件和提醒邮件中包含经 HMAC 签名的链接。客户无需登录或记住预订号。在允许取消之前,我们会先在服务器端验证令牌。
无需技术支持的行政管理。店主可以自行管理日程和项目。无论她想暂停营业一天还是新增一项护理项目,都不需要我介入。
我们不得不考虑的事情
SDK 与错误处理。我们使用 Hapio 的 PHP SDK 作为路径依赖。该 SDK 有时会抛出 PHP 警告,导致真正的错误信息被淹没——我们对调用进行了封装并抑制了警告,从而确保 API 错误能够真正显示出来。
24小时规则。业务规则“预订/取消前至少24小时”是在读取时由我们的代码执行的,而非在Hapio中执行。这意味着缓存中可能包含不会显示给客户的时段——我们在返回数据时会将其过滤掉。简单且可预测。
一个资源,一个地点。该配置指向一个地点和一个资源(治疗师)。如果业务扩展到多名治疗师或多个地点,我们就需要重新考虑,但对于目前的设置来说,这已经非常完美了。
摘要
对于一家由店主独自打理一切的小型按摩诊所来说,Hapio 无疑是最佳选择。我们并没有开发一个预约系统——而是构建了一个网站和一个集成层,使 Hapio 能够以符合该业务需求的方式被使用。
Laravel + Livewire 用于用户界面和电子邮件。Hapio 用于所有预订逻辑。Redis 用于缓存。通过 Webhooks 保持缓存同步。
多亏了Hapio——以及过程中人工智能的协助——她仅用了一个周末左右的时间,就将整个网站从零开始搭建起来,并使其达到可以实际用于开展业务的程度。
这虽然不是我建过的最复杂的建筑,但却是与该项目比例最协调的建筑之一。而这正是你所期望的。
草稿。文中涉及的具体地点、位置或人物均已故意省略。