daddyz / phonelib

Ruby gem for phone validation and formatting using google libphonenumber library data
MIT License
1.04k stars 130 forks source link

Parsing phone numbers for some countries the internationalPrefix is not respected [title edited] #231

Closed tvandergeer closed 2 years ago

tvandergeer commented 3 years ago

See example below for a Jordan (JO) number being parsed for a German (DE) user:

irb(main):002:0> Phonelib.parse('00962796820700',"DE").international(false, nil)
=> "49962796820700"

Note that it's prefixing the number with the German international prefix which is not correct.

If I do the same for the Dutch (NL) or Belgian (BE) number plan it works correctly:

irb(main):003:0> Phonelib.parse('00962796820700',"BE").international(false, nil)
=> "962796820700"
irb(main):004:0> Phonelib.parse('00962796820700',"NL").international(false, nil)
=> "962796820700"

If we replace the 00 in the phone number with + it works as expected

irb(main):001:0> Phonelib.parse('+962796820700',"DE").international(false, nil)
=> "962796820700"

Looks like this is specific to the German number plan.

The issue seems not to be related to the Metadata, because the online demo on appspot parses the number with 00 as expected: https://libphonenumber.appspot.com/phonenumberparser?number=00962796820700&country=DE

tvandergeer commented 3 years ago

I suspect it has something to do with the following:

irb(main):026:0> Phonelib.valid_for_country? '00962796820700','NL'
=> false
irb(main):027:0> Phonelib.valid_for_country? '00962796820700','DE'
=> true
irb(main):028:0> Phonelib.valid_for_country? '00962796820700','BE'
=> false

For some reason Phonelib thinks that 00962796820700 is a valid number for DE.

Does this have anything to do with the excemption being made for double_prefix like is set here: https://github.com/daddyz/phonelib/blob/master/lib/phonelib/data_importer.rb#L21

tvandergeer commented 3 years ago

We just found out that it's not limited to the German number plan. It also happens when parsing numbers in the GB and US number plan. See this example:

irb(main):001:0> Phonelib.parse('003662268000','GB').international(false,nil)
=> "44003662268000"

while it should be 3662268000

Or this US number plan:

Phonelib.parse('0115926500000','US').international(false,nil)
=> "10115926500000"

where it should be 5926500000

Phonelib seems to disregard the fact that for GB 00 and for US 011 are the internationalPrefixes. My hypothesis is that Phonelib favors the fact that the phone number without the internationalPrefix could be a national phone number.

We've now overcome this issue by searching (regexp matching) the value for a countries internationalPrefix and replace that with the internationally (globally?) accepted + character. So effectively for the above examples this becomes:

irb(main):001:0> Phonelib.parse('+3662268000','GB').international(false,nil)
=> "3662268000"

and

Phonelib.parse('+5926500000','US').international(false,nil)
=> "5926500000"
daddyz commented 2 years ago

@tvandergeer You are right, gem thinks that national number was passed, and tries to add country prefix in case you specify the country. In case some of parsing results will be valid, it will be returned. Germany with it's complicated numbering plan is the most complicated issue I had ever met, it may be parsed as valid for various length and double country prefix makes it even more complicated. And in case you are specifying number with "+" in the beginning, gem will try to parse number as is without country prefixes and it can also ignore second param for Phonelib.parse method. For your checks try to see also valid_country and valid? methods. Anyway for your examples you can try to check if number was parsed as valid? before getting international format.