国际手机号归属地判断

由于项目对标国际,简单的正则表达式很难覆盖全面国际手机号,谷歌的libphonenumber可以很好地的很方便的很全面的实现国际收集归属地验证。

使用libphonenumber

libphonenumber是一个工具包,不增加其他第三方依赖,直接引入依赖使用即可。

  • 引入libphonenumber四个jar依赖
    <dependency>
      <groupId>com.googlecode.libphonenumber</groupId>
      <artifactId>libphonenumber</artifactId>
      <version>8.12.16</version>
    </dependency>

    <dependency>
      <groupId>com.googlecode.libphonenumber</groupId>
      <artifactId>geocoder</artifactId>
      <version>2.152</version>
    </dependency>

    <dependency>
      <groupId>com.googlecode.libphonenumber</groupId>
      <artifactId>carrier</artifactId>
      <version>1.142</version>
    </dependency>

    <dependency>
      <groupId>com.googlecode.libphonenumber</groupId>
      <artifactId>prefixmapper</artifactId>
      <version>2.152</version>
    </dependency>
  • 使用libphonenumber工具包进行手机号处理
import com.alibaba.fastjson.JSONObject;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
import java.util.Locale;

/**
 * @description:
 * @author: liangbo
 * @create 2021-01-20 15:38
 * @Version 1.0
 **/
public class PhoneUtil {
  private static PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();

  private static PhoneNumberToCarrierMapper carrierMapper = PhoneNumberToCarrierMapper.getInstance();

  private static PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();

  /**
   * check phone
   *
   * @param phoneNumber eg" 18012345678"
   * @param countryCode eg "86"
   * @return the result "true" or "false"
   */
  public static boolean checkPhoneNumber(Long phone, Integer countryCode) {


    Phonenumber.PhoneNumber pn = new Phonenumber.PhoneNumber();
    pn.setCountryCode(countryCode);
    pn.setNationalNumber(phone);

    return phoneNumberUtil.isValidNumber(pn);
  }

  /**
   * check phone that it brings country code
   *
   * @param phoneNumber eg" +8618012345678"
   * @return the result "true" or "false"
   * @throws NumberParseException handle phone that it can't resolve
   */
  public static boolean checkPhoneNumberBringCountryCode(String phoneNumber) throws NumberParseException {
    Phonenumber.PhoneNumber cn = phoneNumberUtil.parse(phoneNumber, "CN");
    return phoneNumberUtil.isValidNumber(cn);
  }

  public static JSONObject getPhoneNumberInfo(String phoneNumber) throws Exception {

    Phonenumber.PhoneNumber referencePhonenumber;
    try {
      String language = "US";
      referencePhonenumber = phoneNumberUtil.parse(phoneNumber, language);
    } catch (NumberParseException e) {
      throw new Exception(e.getMessage());
    }
    String regionCodeForNumber = phoneNumberUtil.getRegionCodeForNumber(referencePhonenumber);

    if (regionCodeForNumber == null) {
      throw new Exception("Missing region code by phone number " + phoneNumber);
    }

    boolean checkSuccess = PhoneUtil.checkPhoneNumber(referencePhonenumber.getNationalNumber(), referencePhonenumber.getCountryCode());
    if (!checkSuccess) {
      throw new Exception("Not an active number:" + phoneNumber);
    }

    String description = geocoder.getDescriptionForNumber(referencePhonenumber, Locale.CHINA);

    int countryCode = referencePhonenumber.getCountryCode();
    long nationalNumber = referencePhonenumber.getNationalNumber();
    JSONObject resultObject = new JSONObject();
    // 区域编码 Locale : HK, US, CN ...
    resultObject.put("regionCode", regionCodeForNumber);
    // 国号: 86, 1, 852 ... @link: https://blog.csdn.net/wzygis/article/details/45073327
    resultObject.put("countryCode", countryCode);
    // 去掉+号 和 国号/区号 后的实际号码
    resultObject.put("nationalNumber", nationalNumber);
    // 所在地区描述信息
    resultObject.put("description", description);
    // 去掉+号后的号码 (用于阿里云发送短信)
    resultObject.put("number", String.valueOf(countryCode) + nationalNumber);
    resultObject.put("fullNumber", phoneNumber);

    return resultObject;

  }

  public static void main(String[] args) {
    try {
      System.out.println(getPhoneNumberInfo("+1-2843418176)").toJSONString());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

使用效果

{"number":"12843418176","regionCode":"VG","nationalNumber":2843418176,"countryCode":1,"description":"英属维京群岛","fullNumber":"+1-2843418176)"}
  • ps 经验证的手机号格式应该满足 “+国际区号手机号”格式,才能正确获取到手机号信息

phonenumbers 更多用法欢迎大家探讨

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容