Search code examples
xmlgoogle-apps-scriptusps

Google Apps Script USPS Address Validation API


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!


Solution

  • 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)