吉达将于2026年9月23日至10月6日举办第27届阿拉伯海湾杯,八支国家队分为两个小组,在阿卜杜拉国王体育城球场和阿卜杜拉·费萨尔亲王球场进行比赛。这是一条体育新闻,对大多数人来说,故事到此为止。

但其中还藏着一个运营层面的故事,关系到吉达及周边的每一家餐厅、酒店、商店、交通公司和诊所。在整整两周内,站在你收银台前的客户构成会发生变化。参赛球队来自伊拉克、阿曼、科威特、阿联酋、卡塔尔、巴林和也门,每支球队都会带来一批手机号码以 964、968、965、971、974、973 和 967 开头的球迷。这是你的系统赖以构建的那个区号之外的七个国家区号。

大多数沙特系统背后那个无声的假设

根据王国的国家编号计划,本地手机号码以 05 开头,共十位数字。这是一个明确的监管事实,问题并不在这里。问题在于这个事实是如何作为一条僵硬的校验规则进入代码的:一个字段会拒绝任何不符合“以零五开头的十位数字”的输入。

这条规则看起来是正确的,因为它全年对 99% 的客户都有效。然后,像这样的两周到来了,这条规则就不再是保护,而变成了一扇锁住的门。区别很重要:保护拒绝的是错误输入,而这条规则拒绝的是一位正想给你付款的真实客户。

更糟的是,这种模式不只存在于电话字段。凡是开发人员假定客户是沙特居民的地方,它都会反复出现:

  • 手机号码字段。锁定 05 开头,或锁定固定十位长度的校验,会在海湾国家号码到达你的服务器之前就将其拒绝。
  • 验证码。即使字段接受了号码,你的短信服务商也可能没有为你的账户开通国际发送,于是客户输入号码后,等待一条永远不会到达的消息。
  • 支付页面。支付网关只配置了 Mada。访客持有的是海湾国家银行发行、属于国际卡组织的银行卡,看到的是一个他无法理解的拒绝。
  • 证件字段。必填的十位国民身份证号或居留证号,以一或二开头。访客持有的是护照,而表单没有提供第三种选项。
  • 地址。一个只包含沙特城市的封闭列表,加上本地格式的必填邮编,而这个表单其实根本不需要地址,因为订单是到门店自取的。
  • 语言。在预订或支付等关键路径上只有阿拉伯语界面。海湾访客读得懂阿拉伯语,但随行的球迷和陪同人员中有一部分读不懂。

为什么这些都不会出现在你的报表里

真正的危险就在这里。当你的表单拒绝一位访客的号码时,不会发生任何可以衡量的事情。仪表板上没有失败订单,日志里没有错误,也没有客服工单。客户试了两次,关掉标签页,转身去了表单接受这个号码的竞争对手那里。你看到的结果是:在繁忙的一周里,销售额比预期略低,然后你用别的任何理由来解释它。

系统会极其详细地记录成功,却对那些还没开始就失败的事情保持沉默。一笔完成的订单从第一次点击到发票都留有完整轨迹,而在浏览器中被校验拦下的访客根本没有到达服务器,自然也不会留下任何痕迹。因此,这里的第一个修复不在表单,而在度量:把校验失败作为单独的事件记录下来,记录字段名称和拒绝原因,但不保存输入内容本身。这样记录一周,就能准确告诉你是哪个字段在拒绝客户,这与我们在你在架构中看不见的单点故障一文中讨论的是同一种可见性。

在9月23日之前真正能修复什么

五天不足以重建一个系统,但足以消除上面提到的六个障碍,因为其中大多数属于配置而不是开发。下面的顺序按影响从高到低排列:

  • 让手机号码字段支持国际格式。提供默认选中沙特阿拉伯的国家区号选择器,并以统一的、以加号开头的标准国际格式存储号码。这是只涉及一个层面的改动,它为所有国家而不只是七个国家解决问题。
  • 在赛事开始前,用真实的海湾国家号码测试验证码送达。不要想当然地认为已经开通。向某个参赛国家的真实号码发送验证码,确认它在几秒内送达。这个测试只需几分钟,却能暴露一个可能让你损失两周的故障。
  • 开通国际银行卡和移动钱包。向你的支付服务商确认你的账户上实际启用了哪些卡组织,而不是你的套餐理论上支持哪些。如果还没有钱包支付选项,就加上它,因为对于不愿在从未用过的网站上输入卡号的访客来说,这是最快的路径。
  • 把证件字段改为选填,或增加护照选项。如果这个字段是出于法定原因而存在,就在旁边说明,并接受护照格式。如果只是出于习惯而存在,本周就删掉它。
  • 让地址摆脱封闭列表。把城市改为自由文本字段,把邮编改为选填,尤其是在不涉及配送的订单中。
  • 只翻译关键路径。菜单或商品列表、预订步骤、支付页面和路线页面。你不需要在周二之前翻译完整个网站。你需要的是访客能够完成购买。

修复之后紧接着是容量问题。这个高峰不是分散在一天之中,而是集中在每场比赛前后的两个短时间窗口里,其表现与我们在发薪日:一个你早已知道日期的高峰一文中描述的模式非常相似,只有一个区别:这群人还会在地理上移动,朝着同一个方向,在同一时间。

这两周你将收集的数据

来自王国境外的访客在你的系统中注册,就意味着产生了受《个人数据保护法》(PDPL)约束的个人数据,与本地客户的数据完全一样。实际要点很简单:不要收集你不会使用的字段。在仓促搭建的表单中每增加一个额外字段,都是一项在赛事结束后数月内仍伴随你的义务。

在你的隐私页面上说明你收集什么、为什么收集以及保存多长时间,要用访客能看懂的语言,而不是照抄的法律套话。在两周内只在你这里注册一次的人不会去读十段文字,但如果你为了订一张桌子而要求他提供国民身份证号,他一定会注意到。

Origami 的看法

我们在审查现有系统时经常遇到这种模式:一条三年前为当时成立的情况而写的校验规则,之后作为一个永久决定留在代码里,再也没有人重新审视过。问题不在于某个开发人员写错了,而在于这个假设从未被写在任何可供审查的地方,于是它成了结构的一部分,而不是一项设置。

因此,我们在构建系统时会把校验规则与代码分离,把它们当作配置来处理,并且即使今天所有客户都是本地客户,我们也始终以国际格式存储手机号码。构建时的成本几乎为零。而两年后,当你在达曼开设一家服务巴林访客的分店,或者当一项赛事来到你所在的城市时,成本就是一小时的配置与一个以周计算的变更项目之间的差别。我们在服务范围内构建的一切都遵循同样的原则:今天成立的假设,应写成一项设置,而不是一行代码中的条件。

10月6日之后留下的东西

赛事在十月六日结束,而你修复的部分不会随之结束。王国持续举办大型活动,各种季节活动、会议和赛事如今已是日程表上的常态,而不是例外。一个今天能接纳境外访客的系统,在下一次活动中也能接纳他们,无需任何额外工作。

本周就从最小的可执行步骤开始:打开你的网站或应用,尝试用一个真实的海湾国家手机号码和一张非沙特银行卡完成一次完整购买。如果顺利完成,你就准备好了。如果你卡在了某个字段上,那么你刚刚找到了两周销售额本来会从哪里流失。

资料来源