Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with international phone #s and improper contact book formatting

I've been holding off on posting this question for awhile, as there's several scenarios I have to deal with. Basically, our app uses Twilio to send an SMS with a verification code to a user's phone to confirm they actually own that device. We are glad Twilio as a whole can accept international phone numbers. However there are several huge issues on the local device which currently has us thinking we should only support/guarantee United States phone #s for now. But this is why I'm asking this question, to see if you can perhaps point me in a better direction.

So the problems are the following scenarios: Most users don't input the + and the country code for when they add contacts; aka proper formatting, which Twilio expects in the request body as: +15555555555. Our 'solution' was to strip all the garbage characters from the phone #s in the iOS contact book such as ()#+*- and whitespace. We then add a +1 to the front of the cleaned NSString, which makes the phone # now a U.S. phone #, which is incorrect for other users of other countries. Most of our users will be U.S. citizens, but that's not an excuse for us to not fix this properly. Even if a user is a 'good' user and correctly formats their contacts with a + and the country code, we have to ignore it because the majority will not be correctly formatted unfortunately.

I don't believe getting the device's locale is an optimal solution either. Surely there must be a simpler and better way of doing this and not making ANY assumptions of where the user is? If so, could you please post some recommendations?

Edit: I took the rewarded bounties suggestion and this is what I ultimately came up with:

NSDictionary *dictCodes = [NSDictionary dictionaryWithObjectsAndKeys:@"972", @"IL",
                                       @"93", @"AF", @"355", @"AL", @"213", @"DZ", @"1", @"AS",
                                       @"376", @"AD", @"244", @"AO", @"1", @"AI", @"1", @"AG",
                                       @"54", @"AR", @"374", @"AM", @"297", @"AW", @"61", @"AU",
                                       @"43", @"AT", @"994", @"AZ", @"1", @"BS", @"973", @"BH",
                                       @"880", @"BD", @"1", @"BB", @"375", @"BY", @"32", @"BE",
                                       @"501", @"BZ", @"229", @"BJ", @"1", @"BM", @"975", @"BT",
                                       @"387", @"BA", @"267", @"BW", @"55", @"BR", @"246", @"IO",
                                       @"359", @"BG", @"226", @"BF", @"257", @"BI", @"855", @"KH",
                                       @"237", @"CM", @"1", @"CA", @"238", @"CV", @"345", @"KY",
                                       @"236", @"CF", @"235", @"TD", @"56", @"CL", @"86", @"CN",
                                       @"61", @"CX", @"57", @"CO", @"269", @"KM", @"242", @"CG",
                                       @"682", @"CK", @"506", @"CR", @"385", @"HR", @"53", @"CU",
                                       @"537", @"CY", @"420", @"CZ", @"45", @"DK", @"253", @"DJ",
                                       @"1", @"DM", @"1", @"DO", @"593", @"EC", @"20", @"EG",
                                       @"503", @"SV", @"240", @"GQ", @"291", @"ER", @"372", @"EE",
                                       @"251", @"ET", @"298", @"FO", @"679", @"FJ", @"358", @"FI",
                                       @"33", @"FR", @"594", @"GF", @"689", @"PF", @"241", @"GA",
                                       @"220", @"GM", @"995", @"GE", @"49", @"DE", @"233", @"GH",
                                       @"350", @"GI", @"30", @"GR", @"299", @"GL", @"1", @"GD",
                                       @"590", @"GP", @"1", @"GU", @"502", @"GT", @"224", @"GN",
                                       @"245", @"GW", @"595", @"GY", @"509", @"HT", @"504", @"HN",
                                       @"36", @"HU", @"354", @"IS", @"91", @"IN", @"62", @"ID",
                                       @"964", @"IQ", @"353", @"IE", @"972", @"IL", @"39", @"IT",
                                       @"1", @"JM", @"81", @"JP", @"962", @"JO", @"77", @"KZ",
                                       @"254", @"KE", @"686", @"KI", @"965", @"KW", @"996", @"KG",
                                       @"371", @"LV", @"961", @"LB", @"266", @"LS", @"231", @"LR",
                                       @"423", @"LI", @"370", @"LT", @"352", @"LU", @"261", @"MG",
                                       @"265", @"MW", @"60", @"MY", @"960", @"MV", @"223", @"ML",
                                       @"356", @"MT", @"692", @"MH", @"596", @"MQ", @"222", @"MR",
                                       @"230", @"MU", @"262", @"YT", @"52", @"MX", @"377", @"MC",
                                       @"976", @"MN", @"382", @"ME", @"1", @"MS", @"212", @"MA",
                                       @"95", @"MM", @"264", @"NA", @"674", @"NR", @"977", @"NP",
                                       @"31", @"NL", @"599", @"AN", @"687", @"NC", @"64", @"NZ",
                                       @"505", @"NI", @"227", @"NE", @"234", @"NG", @"683", @"NU",
                                       @"672", @"NF", @"1", @"MP", @"47", @"NO", @"968", @"OM",
                                       @"92", @"PK", @"680", @"PW", @"507", @"PA", @"675", @"PG",
                                       @"595", @"PY", @"51", @"PE", @"63", @"PH", @"48", @"PL",
                                       @"351", @"PT", @"1", @"PR", @"974", @"QA", @"40", @"RO",
                                       @"250", @"RW", @"685", @"WS", @"378", @"SM", @"966", @"SA",
                                       @"221", @"SN", @"381", @"RS", @"248", @"SC", @"232", @"SL",
                                       @"65", @"SG", @"421", @"SK", @"386", @"SI", @"677", @"SB",
                                       @"27", @"ZA", @"500", @"GS", @"34", @"ES", @"94", @"LK",
                                       @"249", @"SD", @"597", @"SR", @"268", @"SZ", @"46", @"SE",
                                       @"41", @"CH", @"992", @"TJ", @"66", @"TH", @"228", @"TG",
                                       @"690", @"TK", @"676", @"TO", @"1", @"TT", @"216", @"TN",
                                       @"90", @"TR", @"993", @"TM", @"1", @"TC", @"688", @"TV",
                                       @"256", @"UG", @"380", @"UA", @"971", @"AE", @"44", @"GB",
                                       @"1", @"US", @"598", @"UY", @"998", @"UZ", @"678", @"VU",
                                       @"681", @"WF", @"967", @"YE", @"260", @"ZM", @"263", @"ZW",
                                       @"591", @"BO", @"673", @"BN", @"61", @"CC", @"243", @"CD",
                                       @"225", @"CI", @"500", @"FK", @"44", @"GG", @"379", @"VA",
                                       @"852", @"HK", @"98", @"IR", @"44", @"IM", @"44", @"JE",
                                       @"850", @"KP", @"82", @"KR", @"856", @"LA", @"218", @"LY",
                                       @"853", @"MO", @"389", @"MK", @"691", @"FM", @"373", @"MD",
                                       @"258", @"MZ", @"970", @"PS", @"872", @"PN", @"262", @"RE",
                                       @"7", @"RU", @"590", @"BL", @"290", @"SH", @"1", @"KN",
                                       @"1", @"LC", @"590", @"MF", @"508", @"PM", @"1", @"VC",
                                       @"239", @"ST", @"252", @"SO", @"47", @"SJ", @"963", @"SY",
                                       @"886", @"TW", @"255", @"TZ", @"670", @"TL", @"58", @"VE",
                                       @"84", @"VN", @"1", @"VG", @"1", @"VI", nil];

NSLocale *locale = [NSLocale currentLocale];
NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
NSString *callingCode = [dictCodes objectForKey:countryCode];

NSCharacterSet *validCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]invertedSet];

for (NSString *sub in mutablePhonesArray)
{
    NSString *newString = [[sub componentsSeparatedByCharactersInSet:validCharacters]componentsJoinedByString:@""];

    NSString *newString2 = newString;

    if (![newString hasPrefix:@"+"])
    {
        newString2 = [NSString stringWithFormat:@"+%@%@",callingCode,newString];
    }

    NSString *substring = [newString2 substringFromIndex:1];
    NSString *removeExtraPlusSigns = [substring stringByReplacingOccurrencesOfString:@"+" withString:@""];
    NSString *finalPhone = [NSString stringWithFormat:@"+%@",removeExtraPlusSigns];

    [newPhoneArray addObject:finalPhone];
}
like image 634
klcjr89 Avatar asked Jul 15 '14 23:07

klcjr89


2 Answers

To find the calling prefix, first access the users current locale through the NSLocale class. Note that this does not require any additional permissions or private APIs.

NSLocale *locale = [NSLocale currentLocale];
NSString *countryCode = [locale objectForKey: NSLocaleCountryCode];
NSString *callingCode = [dictCodes objectForKey:countryCode];    

The use the country code to retrieve the pertinent calling code from a hard coded NSDictionary of all the ISO country codes and the corresponding calling codes which I have included below.

NSDictionary *dictCodes = [NSDictionary dictionaryWithObjectsAndKeys:@"972", @"IL",
                                  @"93", @"AF", @"355", @"AL", @"213", @"DZ", @"1", @"AS",
                                  @"376", @"AD", @"244", @"AO", @"1", @"AI", @"1", @"AG",
                                  @"54", @"AR", @"374", @"AM", @"297", @"AW", @"61", @"AU",
                                  @"43", @"AT", @"994", @"AZ", @"1", @"BS", @"973", @"BH",
                                  @"880", @"BD", @"1", @"BB", @"375", @"BY", @"32", @"BE",
                                  @"501", @"BZ", @"229", @"BJ", @"1", @"BM", @"975", @"BT",
                                  @"387", @"BA", @"267", @"BW", @"55", @"BR", @"246", @"IO",
                                  @"359", @"BG", @"226", @"BF", @"257", @"BI", @"855", @"KH",
                                  @"237", @"CM", @"1", @"CA", @"238", @"CV", @"345", @"KY",
                                  @"236", @"CF", @"235", @"TD", @"56", @"CL", @"86", @"CN",
                                  @"61", @"CX", @"57", @"CO", @"269", @"KM", @"242", @"CG",
                                  @"682", @"CK", @"506", @"CR", @"385", @"HR", @"53", @"CU",
                                  @"537", @"CY", @"420", @"CZ", @"45", @"DK", @"253", @"DJ",
                                  @"1", @"DM", @"1", @"DO", @"593", @"EC", @"20", @"EG",
                                  @"503", @"SV", @"240", @"GQ", @"291", @"ER", @"372", @"EE",
                                  @"251", @"ET", @"298", @"FO", @"679", @"FJ", @"358", @"FI",
                                  @"33", @"FR", @"594", @"GF", @"689", @"PF", @"241", @"GA",
                                  @"220", @"GM", @"995", @"GE", @"49", @"DE", @"233", @"GH",
                                  @"350", @"GI", @"30", @"GR", @"299", @"GL", @"1", @"GD",
                                  @"590", @"GP", @"1", @"GU", @"502", @"GT", @"224", @"GN",
                                  @"245", @"GW", @"595", @"GY", @"509", @"HT", @"504", @"HN",
                                  @"36", @"HU", @"354", @"IS", @"91", @"IN", @"62", @"ID",
                                  @"964", @"IQ", @"353", @"IE", @"972", @"IL", @"39", @"IT",
                                  @"1", @"JM", @"81", @"JP", @"962", @"JO", @"77", @"KZ",
                                  @"254", @"KE", @"686", @"KI", @"965", @"KW", @"996", @"KG",
                                  @"371", @"LV", @"961", @"LB", @"266", @"LS", @"231", @"LR",
                                  @"423", @"LI", @"370", @"LT", @"352", @"LU", @"261", @"MG",
                                  @"265", @"MW", @"60", @"MY", @"960", @"MV", @"223", @"ML",
                                  @"356", @"MT", @"692", @"MH", @"596", @"MQ", @"222", @"MR",
                                  @"230", @"MU", @"262", @"YT", @"52", @"MX", @"377", @"MC",
                                  @"976", @"MN", @"382", @"ME", @"1", @"MS", @"212", @"MA",
                                  @"95", @"MM", @"264", @"NA", @"674", @"NR", @"977", @"NP",
                                  @"31", @"NL", @"599", @"AN", @"687", @"NC", @"64", @"NZ",
                                  @"505", @"NI", @"227", @"NE", @"234", @"NG", @"683", @"NU",
                                  @"672", @"NF", @"1", @"MP", @"47", @"NO", @"968", @"OM",
                                  @"92", @"PK", @"680", @"PW", @"507", @"PA", @"675", @"PG",
                                  @"595", @"PY", @"51", @"PE", @"63", @"PH", @"48", @"PL",
                                  @"351", @"PT", @"1", @"PR", @"974", @"QA", @"40", @"RO",
                                  @"250", @"RW", @"685", @"WS", @"378", @"SM", @"966", @"SA",
                                  @"221", @"SN", @"381", @"RS", @"248", @"SC", @"232", @"SL",
                                  @"65", @"SG", @"421", @"SK", @"386", @"SI", @"677", @"SB",
                                  @"27", @"ZA", @"500", @"GS", @"34", @"ES", @"94", @"LK",
                                  @"249", @"SD", @"597", @"SR", @"268", @"SZ", @"46", @"SE",
                                  @"41", @"CH", @"992", @"TJ", @"66", @"TH", @"228", @"TG",
                                  @"690", @"TK", @"676", @"TO", @"1", @"TT", @"216", @"TN",
                                  @"90", @"TR", @"993", @"TM", @"1", @"TC", @"688", @"TV",
                                  @"256", @"UG", @"380", @"UA", @"971", @"AE", @"44", @"GB",
                                  @"1", @"US", @"598", @"UY", @"998", @"UZ", @"678", @"VU",
                                  @"681", @"WF", @"967", @"YE", @"260", @"ZM", @"263", @"ZW",
                                  @"591", @"BO", @"673", @"BN", @"61", @"CC", @"243", @"CD",
                                  @"225", @"CI", @"500", @"FK", @"44", @"GG", @"379", @"VA",
                                  @"852", @"HK", @"98", @"IR", @"44", @"IM", @"44", @"JE",
                                  @"850", @"KP", @"82", @"KR", @"856", @"LA", @"218", @"LY",
                                  @"853", @"MO", @"389", @"MK", @"691", @"FM", @"373", @"MD",
                                  @"258", @"MZ", @"970", @"PS", @"872", @"PN", @"262", @"RE",
                                  @"7", @"RU", @"590", @"BL", @"290", @"SH", @"1", @"KN",
                                  @"1", @"LC", @"590", @"MF", @"508", @"PM", @"1", @"VC",
                                  @"239", @"ST", @"252", @"SO", @"47", @"SJ", @"963", @"SY",
                                  @"886", @"TW", @"255", @"TZ", @"670", @"TL", @"58", @"VE",
                                  @"84", @"VN", @"1", @"VG", @"1", @"VI", nil];
like image 161
Matt Avatar answered Nov 15 '22 05:11

Matt


Twilio evangelist here.

You might look at using libphonenumber. Its got a pretty good phone number parser in it that will let you get E164 formatted numbers back out.

Hope that helps.

like image 45
Devin Rader Avatar answered Nov 15 '22 04:11

Devin Rader