电话区号与城市的关系,是很多人在做用户数据校验时忍不住想用、用了又后悔的一条规则:固定电话的区号确实对应某个地区,于是顺手写一条「区号必须与城市匹配」的校验,上线之后开始拦截合法用户。这篇讲清国际区号与国内区号的分工、为什么按号码推断所在地越来越不可靠,以及测试数据里该怎么处理这条规则。
国际区号、国内区号与地区分别管什么
国际编号的层次很简单:国家代码在前,国内号码在后。国家代码长度在一到三位之间,写出来时通常带一个国际前缀符号,表示这是从境外拨入的号码。国内号码的划分规则由各国自己定,这才是区号出现的地方。
国内的区号通常用于固定电话:一段号码段对应一个地理区域或者一个本地交换局。移动号码的划分逻辑完全不同,它按运营商和号段分配,与城市没有对应关系。所以「区号对应城市」这条说法,严格讲只对固定电话成立。
手机号能反映所在地吗?
不能,而且这条结论比过去更确定了。手机号在分配时不绑定使用地点,用户带着号码跨城市甚至跨国漫游都很正常。携号转网进一步削弱了号码段与运营商之间的对应关系:号码不变、运营商更换,按号段推断运营商的准确率就会下降。
对校验设计来说,这意味着手机号只应该被检查格式:长度是否合理、国家代码与所选国家是否一致、是否只包含数字与允许的分隔符。把它和城市绑起来,等于把一条本来就不成立的假设写成硬规则。
为什么按号码推断地区越来越不可靠
原因可以归结为三点:号码的归属地在登记之后不再更新,用户迁移不改变号码;转网让号段与运营商的对应发生漂移;虚拟运营商与融合业务让号段的实际用途更复杂。这三条叠在一起,使得基于号段的地区推断只是一种概率猜测。
因此,如果业务确实需要用户所在地区,正确做法是直接询问或者从可信来源获取,而不是从电话号码里推断。把推断结果当作事实写进用户档案,后续所有基于它的决策都会带上这个误差。
在数据层面还有一层问题:推断出来的地区和用户自报的地区放在同一个字段里,就再也分不清哪个是猜的。分析人员会把它当成用户提供的信息使用,风控系统也会据此判断,而实际上它的准确率可能连一半都没有。把两者分开存放,是让这条推断保持可评估状态的前提。
测试数据里要不要做号码与城市的一致性检查?
要做,但要分清强度。强制的检查会拦截合法数据,因此只适合用在确实存在约束的地方,例如固定电话与其登记地区。手机号的一致性检查应当降级为提示或者只用于生成测试数据的便利,而不是作为拒绝输入的依据。
下表把几种常见规则按建议的强度排开:
| 检查 | 建议强度 | 原因 |
|---|---|---|
| 国家代码与所选国家一致 | 强制 | 这与用户填写的国家直接矛盾 |
| 号码长度落在该国允许范围内 | 强制 | 长度错误几乎一定是输入问题 |
| 字符集只含数字与分隔符 | 强制 | 归类清晰,误判极少 |
| 固定电话区号与城市匹配 | 建议 | 存在合理例外 |
| 手机号与城市匹配 | 不建议 | 前提不成立 |
| 号段推断运营商 | 仅作参考 | 携号转网导致漂移 |
把这张表定下来,比事后再讨论某条规则该不该拦要省事。
号码该以什么形式存储
建议统一按一种形式存,展示时再按国家排版。常见的选择是只保留国家代码与国内号码的数字,去掉空格、连字符和括号,同时把用户原始输入另存一份作为参考。这样做的好处是比较、去重和导入导出都不会因为书写差异而失败。
要注意把号码的存储类型设为字符串。开头可能是零,位数也可能很长,用整数存会遇到前导零丢失与数值溢出的双重问题,与邮编是同一类坑,具体的邮编讨论见各国邮编格式。
另外要决定国际前缀怎么处理。用户可能写成带国际前缀的形式,也可能在本国号码前加一个本地长途前缀,两者在键盘输入时看起来很像。存储时把这两类归一,并且在展示时按用户所在国家决定要不要显示国家代码,能避免同一个人被存成两条记录。校验信息里区分手机与固定电话也有用:它们允许的格式规则不同,混在一起校验就只能取最宽松的那一档。
给开发者:生成测试号码时要保证什么
第一,国家代码与国内号码的结构要来自同一国家,长度符合当地规则,移动号段与前缀应当是当地确实启用的。分组方式也应当符合当地习惯,而不是一律按三位一组。
第二,不要生成看起来像在用号码的号码。测试数据里出现一个真实的在用号码,可能给别人带来骚扰,这也是号码属于个人数据的直接后果,相关讨论见地址数据与隐私。
第三,如果测试场景需要号码与地址成套出现,那就把两者放进同一条记录里一起生成,并注明这条记录里的城市是登记地区而非使用地区。想对照具体国家的号码格式与地址层级,可以看本站英国的国家页,各国的国内号码分段方式差别比较明显。
第四,把按号段推断所在地这条逻辑明确标注为启发式,并在数据模型里与用户自报的地区分开存放。合并在一起之后,没有人能再分辨哪个值是用户说的、哪个是系统猜的。国家层面的代码该怎么统一存储,见ISO 国家代码与行政区代码。用来做比对的样本号码与地址只用于测试,不能投递。
下一步
检查你的校验规则里有没有「手机号必须与城市匹配」这一条,如果有,把它降级为提示,并观察一段时间里被它拦下的数据量。需要成套的地址与电话号码测试数据时,用随机地址生成器选国家生成,号码会按当地的分段习惯给出,且不是任何在用号码。