Solución:
Utilice la API de codificación geográfica
Por ejemplo, para buscar zip 77379 use una solicitud como esta:
https://maps.googleapis.com/maps/api/geocode/json?address=77379&sensor=true&key=YOUR_GOOGLE_PLATFORM_API_KEY
Encontré un par de formas de hacer esto con API basadas en web. Creo que el Servicio Postal de EE. UU. Sería el más preciso, ya que los códigos postales son lo suyo, pero Ziptastic parece mucho más fácil.
Uso de la API HTTP / XML del servicio postal de EE. UU.
De acuerdo con esta página en el sitio web del Servicio Postal de EE. UU. Que documenta su API web basada en XML, específicamente la Sección 4.0 (página 22) de este documento PDF, tienen una URL donde puede enviar una solicitud XML que contiene un código postal de 5 dígitos y lo harán responda con un documento XML que contenga la ciudad y el estado correspondientes.
Según su documentación, esto es lo que enviaría:
http://SERVERNAME/ShippingAPITest.dll?API=CityStateLookup&XML=<CityStateLookupRequest%20USERID="xxxxxxx"><ZipCode ID= "0"><Zip5>90210</Zip5></ZipCode></CityStateLookupRequest>
Y esto es lo que recibirías de vuelta:
<?xml version="1.0"?>
<CityStateLookupResponse>
<ZipCode ID="0">
<Zip5>90210</Zip5>
<City>BEVERLY HILLS</City>
<State>CA</State>
</ZipCode>
</CityStateLookupResponse>
USPS lo hace requieren que se registre con ellos antes de poder usar la API, pero, por lo que yo sé, no hay ningún cargo por el acceso. Por cierto, su API tiene algunas otras características: puede realizar la estandarización de direcciones y la búsqueda de códigos postales, así como todo el conjunto de seguimiento, envío, etiquetas, etc.
Usando la API Ziptastic HTTP / JSON (ya no es compatible)
Actualización: a partir del 13 de agosto de 2017, Ziptastic ahora es una API paga y se puede encontrar aquí
Este es un servicio bastante nuevo, pero de acuerdo con su documentación, parece que todo lo que necesita hacer es enviar una solicitud GET a http://ziptasticapi.com, así:
GET http://ziptasticapi.com/48867
Y devolverán un objeto JSON a lo largo de las líneas de:
{"country": "US", "state": "MI", "city": "OWOSSO"}
De hecho, funciona. Puede probar esto desde una línea de comando haciendo algo como:
curl http://ziptasticapi.com/48867
function getCityState($zip, $blnUSA = true) {
$url = "http://maps.googleapis.com/maps/api/geocode/json?address=" . $zip . "&sensor=true";
$address_info = file_get_contents($url);
$json = json_decode($address_info);
$city = "";
$state = "";
$country = "";
if (count($json->results) > 0) {
//break up the components
$arrComponents = $json->results[0]->address_components;
foreach($arrComponents as $index=>$component) {
$type = $component->types[0];
if ($city == "" && ($type == "sublocality_level_1" || $type == "locality") ) {
$city = trim($component->short_name);
}
if ($state == "" && $type=="administrative_area_level_1") {
$state = trim($component->short_name);
}
if ($country == "" && $type=="country") {
$country = trim($component->short_name);
if ($blnUSA && $country!="US") {
$city = "";
$state = "";
break;
}
}
if ($city != "" && $state != "" && $country != "") {
//we're done
break;
}
}
}
$arrReturn = array("city"=>$city, "state"=>$state, "country"=>$country);
die(json_encode($arrReturn));
}