Google Apps Script USPS Address Validation API

1.4k views Asked by At

I am trying to call the USPS Address Validation API from within Google Apps Script. It requires XML, which I am inexperienced with compared to JSON. Here is another stackoverflow question that is similar (How do I get domestic shipping rates via the USPS API using Google Apps Script?), and I have followed it to a "t", but it is different enough and when adapted for the USPS Address Validation API, it is not working for me. I have signed up for a userid and received a confirmation from USPS.

Here is the USPS Address Validation API documentation: https://www.usps.com/business/web-tools-apis/address-information-api.htm#_Toc34052588.

Here is my Apps Script Code (with the USPS userid changed for confidentiality):

      var site = 'https://secure.shippingapis.com/ShippingAPI.dll';

      var userid = "999ABCDE9999";

      var payload = {
        "API": "Verify",
        "XML" : "<AddressValidateRequest USERID=\"" + userid + "\"> \
                 <Revision>0</Revision> \
                 <Address ID=\"0\"> \
                 <Address2>" + address1 + "</Address2> \
                 <City>" + city1 + "</City> \
                 <State>" + state1 + "</State> \
                 <Zip5>" + zip1 + "</Zip5> \
                 </Address> \
                 </AddressValidationRequest>"
      };

      var options = {
        method: "POST",
        payload: payload
      }

      Logger.log('payload = ' + JSON.stringify(payload));

      var response = UrlFetchApp.fetch(site, options);

      var xmlreturn = response.getContentText();

      Logger.log('return xml = ' + xmlreturn);

Here are my logs (with the street address changed for confidentiality as well:

payload = {"API":"Verify","XML":"<AddressValidateRequest USERID=\"999ABCDE9999\">                  <Revision>0</Revision>                  <Address ID=\"0\">                  <Address2>123 AnyStreet Dr</Address2>                  <City>Forney</City>                  <State>TX</State>                  <Zip5>75126</Zip5>                  </Address>                  </AddressValidationRequest>"}

return xml = <?xml version="1.0" encoding="UTF-8"?>
<Error><Number>80040B19</Number><Description>XML Syntax Error: Please check the XML request to see if it can be parsed.(B)</Description><Source>USPSCOM::DoAuth</Source></Error>

This is the return/result I get regardless of what I try to do. I think, perhaps, a problem could be that payload.XML includes USERID=\"999ABCDE9999\" instead of what the documentation says it should - USERID="999ABCDE9999" (without the backslash), but I don't know how to get rid of those (and have tried).

Thank you for your help!

1

There are 1 answers

0
Chris On BEST ANSWER

I figured out what the problem was. My only real problem was that I had my closing XML tag incorrect. It should be < /AddressValidateRequest > instead of < /AddressValidationRequest >. You ALSO need to include a self-closing < Address1/ > tag before < Address2 > and < Zip4/ > after < /Zip5 >. It will throw an error if you don't.

However, I'm glad I had the problem and posted it here, so that hopefully this will help others in the future to have the code pretty much the way you'll need it for a USPS Validation request from Google Apps Script. I had not found this anywhere else. Here is the final code, then I'll talk about how I worked with the result below as well.

      var userid = 'Enter the ID USPS Gave you when you signed up here';

      var url = 'https://secure.shippingapis.com/ShippingAPI.dll';

      var payload = {
        "API": "Verify",
        "XML" : "<AddressValidateRequest USERID=\"" + userid + "\"> \
                 <Revision>1</Revision> \
                 <Address ID=\"0\"> \
                 <Address1/> \
                 <Address2>" + address1 + "</Address2> \
                 <City>" + city1 + "</City> \
                 <State>" + state1 + "</State> \
                 <Zip5>" + zip1 + "</Zip5> \
                 <Zip4/> \
                 </Address> \
                 </AddressValidateRequest>"
      };

      var options = {
        "method": "POST",
        "payload": payload,
        muteHttpExceptions: true
      }

      // Use a try & catch routine to catch any major errors.
      try {
        var response = UrlFetchApp.fetch(url, options);
      }
      catch (e) {
        Logger.log(e);
        continue;         // If there is an error (i.e. the API service is not available), then skip the rest of the logic for this row.
      }

      var xmlReturn = response.getContentText();

Once you have the "xmlreturn" (as I called it above) from the fetch, you'll need to parse the XML response to get each piece of the address returned from USPS. Here is how I did it using regex for Address Line 2. You do the same pretty much for the other pieces, just changing your regex slightly.

        // *********************************
        // Get Address Line 2
        // *********************************

        var uspsAddress2Reg = /(?<=<Address2>)[^]+(?=<\/Address2>)/g;
        var uspsAddress2Arr =xmlReturn.match(uspsAddress2Reg);

        // If we found the Address Line 2 in the following format: <Address2>1234 ANYSTREET DRIVE</Address2>

        if (uspsAddress2Arr != null) {

          var uspsAddress2 = uspsAddress2Arr[0];

        } else {

          var uspsAddress2 = '';           // If not found, set it to blank.

        }  // End If (uspsAddress2Arr != null)