1. 客户情况
客户是甲米府的跳岛游运营商,经营 12 年,船队中有快艇与长尾船,每艘可坐 30 人,每天 2 班,覆盖 Phi Phi、Hong Islands、James Bond、4 Islands 和私人包船路线。
启动项目前,预订系统是 manual + digital 的半成品 — 实体店前的纸质订单、外籍客户用 WhatsApp、泰国客户用 LINE,加上 WordPress + WooCommerce 的旧站。最大的问题是直接预订的 checkout 流失率高达 78%,因为唯一的支付方式是 bank transfer,而外籍客户几乎没人愿意使用。
客户结构:中国 45%、东欧 (主要俄罗斯) 25%、泰国 15%、其他 15% — 旧站只支持英文,翻译还是自己用 Google Translate 做的,导致用户经常误解套餐含什么。
目前 70% 营收来自 OTA 平台 (Klook、GetYourGuide、Viator),被抽 18-25% 佣金,利润越来越薄。项目目标是 6 个月内直接预订增长 400%+,把 OTA 依赖降到营收的 40% 以下。
2. 为什么通用方案不奏效
我们先评估了现成方案,因为客户希望能买 SaaS 就不愿意定制开发。
WooCommerce + 多语言插件 (WPML、Polylang) — 实际使用中插件经常路由错语言,会话内切币时 checkout flow 会崩。即便企业版也不能解决 WooCommerce 核心架构为零售设计、不适合预订的问题。
FareHarbor、Rezdy、Bokun — 支持跳岛游预订,多币种也 OK,但没有一个支持 PromptPay QR,而这是泰国客户的主要渠道 → 泰国客户必须转账后发凭证,非即时。
Multi-boat scheduling SaaS — 没有方案支持客户常用的 “boat shuffle” 业务逻辑:当 B 船故障,需要自动将客户转到 A 船,并同时通知船长和所有客户。
因此结论是必须定制开发。
3. 我们的方案
技术栈: Next.js 14 (App Router) + Stripe + PromptPay QR generator (自研) + next-intl (i18n) + Prisma + PostgreSQL + Vercel Edge 用于区域级 tour catalog 缓存。
多币种: 用 Stripe 原生处理 THB/USD/EUR/CNY/RUB,在 checkout 开始时锁定汇率 (避免客户选 add-ons 期间的汇率波动)。
Custom vs SaaS — 客户选择 custom 的原因:
| 项目 | SaaS (Bokun) | Custom |
|---|---|---|
| 第 1 年 | $24,000 | $14,000 一次性 |
| 5 年 TCO | $120,000 | ~$20,000 |
| PromptPay | 无 | 有 |
| Boat shuffle 逻辑 | 无 | 有 |
| OTA webhook 自定义 | 不可以 | 可以 |
定制的 5 年 TCO 比 SaaS 低 60%+ (定制 = $14K 一次性 + $1.2K/年 hosting × 5 = ~$20K)
架构的 4 大支柱:
- i18n 做对 — 4 语言 (TH/EN/CN/RU) 按路由 + 用户 locale 懒加载,每行文案通过母语译者 (不是 Google Translate)
- 实时船队同步 — Postgres triggers + websocket 订阅,使可用性在所有 client 上 <500ms 更新
- 多支付 — Stripe (国际卡 + Apple/Google Pay)、PromptPay QR (即时 THB)、bank transfer (兜底)
- 船长手机 PWA — 离线优先,适用于海上无信号场景,回岸后同步
4. 周计划
第 1-2 周:Discovery
- 访谈 owner、GM、2 位船长、1 位行政,梳理真实流程
- 数据库 schema 设计 22 张表,涵盖船期、船长班次、产品包、客户、支付、退款、OTA 同步日志
第 3-5 周:后端 API
- 预订流程 API 含座位锁机制 (checkout 期间 hold 5 分钟)
- 船队可用性引擎:跨船队实时查冲突,支持 boat shuffle
- 支付处理:Stripe 集成 + 自研 PromptPay QR generator + 银行转账对账 worker
第 6-8 周:客户前端
- 移动优先预订 UI (70% 流量来自手机)
- 4 语言懒加载 — 单语初始 bundle = 38KB
- Checkout 流程:选 tour → 日期 → 人数 → add-ons → 支付 → 确认
- 货币换算小部件实时显示,checkout 时锁定汇率
第 9-10 周:行政控制台
- 泰语 reservations 控制台 UI (行政全是泰国人)
- 退款流程支持部分退款、天气取消
- OTA 合作伙伴 webhooks:Klook、GetYourGuide、Viator — 双向库存同步
第 11-12 周:船长手机 PWA
- 通过 Service Worker + IndexedDB 队列实现离线优先
- QR 扫码 check-in (客户在码头出示预订 QR)
- 基于天气的取消流程:船长报取消 → 行政批准 → 系统自动退款 + 4 语言通知客户
第 13 周:打磨
- 母语 CN + RU 译者审阅每行文案
- 可访问性审核 (WCAG AA)
- 安全审查 (OWASP Top 10 + PCI 范围审查)
第 14 周:软上线
- 渐进式 rollout:10% → 50% → 100%,持续 5 天
- 培训:行政 2 次,船长 1 次
- 上线后 2 周完整监控
5. 遇到的问题
Thailand 的 Stripe: 最初规划时 Stripe 还未对 TH 注册主体直接开放 → 客户选择 Stripe Atlas 在 Delaware 开公司收国际付款 + 用 PromptPay 处理 THB → 税务设置比预期复杂,需协调泰国会计 + 美国 CPA 处理 form 5472,合规审查多了 2 周。
俄语翻译术语表: 俄罗斯客户熟悉海事专用术语如 “Skiff” (小船)、“Catamaran” — Google Translate 翻译成业内没人用的词 → 解决:建立 80+ 词条术语表,母语译者审阅后再翻全文。
船长 app 在海上卡死: 软上线第一周有报告说船长 app 在海上无信号时卡死 → 解决:用 service worker + 离线优先同步队列,在网络恢复后工作,并在船离港时预缓存当天所有预订数据。
6. 上线后效果 + 持续
第 3 个月:
- 直接预订 +420% vs 基线
- OTA 依赖从 70% 降至 35% 营收占比
- 客单价 +25%,因为多人预订更容易、add-ons (lunch upgrade、photographer) 拉升客单
第 6 个月:
- 回头客率 18% (此前 4%) — 来自一手 booking data 的邮件二次营销
- 上线后用户请求,扩展上线了私人包船预订流程
经验总结:
- i18n 必须投入母语译者,没有捷径 — Google Translate 会让付高价的中国和俄罗斯客户彻底失去信任。
- Boat shuffle 逻辑是 SaaS 无法覆盖的 — 泰国 tour operator 的运营现实比西方 tour ops 标准复杂得多。
持续:
- 季度维护服务模式下,负责系统维护 + 每季度新功能发布
- Roadmap:AI 动态定价、面向企业客户的团体预订小部件、多产业扩展 (客户有开度假村的计划)