Click here to Skip to main content
15,881,882 members
Articles / Web Development / ASP.NET

United States Postal Service (USPS) Web Tools Wrapper

Rate me:
Please Sign up or sign in to vote.
4.81/5 (31 votes)
9 May 2008CPOL2 min read 336.3K   6.4K   91  
United States Postal Service (USPS) Web Tools Wrapper is a .NET library you can use for address validation, retrieving rates and YES even printing labels
//////////////////////////////////////////////////////////////////////////
///This software is provided to you as-is and with not warranties!!!
///Use this software at your own risk.
///This software is Copyright by Scott Smith 2006
///You are free to use this software as you see fit.
//////////////////////////////////////////////////////////////////////////


using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace MAX.USPS
{
    public class USPSManager
    {
        #region Private Members
        private const string ProductionUrl = "http://production.shippingapis.com/ShippingAPI.dll";
        private const string TestingUrl = "http://testing.shippingapis.com/ShippingAPITest.dll";
        private WebClient web;
        private string _userid;
        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new USPS Manager instance
        /// </summary>
        /// <param name="USPSWebtoolUserID">The UserID required by the USPS Web Tools</param>
        public USPSManager(string USPSWebtoolUserID)
        {
            web = new WebClient();
            _userid = USPSWebtoolUserID;
            _TestMode = false;
            
        }
        /// <summary>
        /// Creates a new USPS Manager instance
        /// </summary>
        /// <param name="USPSWebtoolUserID">The UserID required by the USPS Web Tools</param>
        /// <param name="testmode">If True, then the USPS Test URL will be used.</param>
        public USPSManager(string USPSWebtoolUserID, bool testmode)
        {
            _TestMode = testmode;
            web = new WebClient();
            _userid = USPSWebtoolUserID;
        }

        #endregion

        #region Properties
        private bool _TestMode;
        /// <summary>
        /// Determines if the Calls to the USPS server is made to the Test or Production server.
        /// </summary>
        public bool TestMode
        {
            get { return _TestMode; }
            set { _TestMode = value; }
        }

        #endregion

        #region Address Methods
        /// <summary>
        /// Validate a single address
        /// </summary>
        /// <param name="address">Address object to be validated</param>
        /// <returns>Validated Address</returns>
        public Address ValidateAddress(Address address)
        {
            try
            {
                string validateUrl = "?API=Verify&XML=<AddressValidateRequest USERID=\"{0}\"><Address ID=\"{1}\"><Address1>{2}</Address1><Address2>{3}</Address2><City>{4}</City><State>{5}</State><Zip5>{6}</Zip5><Zip4>{7}</Zip4></Address></AddressValidateRequest>";
                string url = GetURL() + validateUrl;
                url = String.Format(url, _userid, address.ID.ToString(), address.Address1, address.Address2, address.City, address.State, address.Zip, address.ZipPlus4);
                string addressxml = web.DownloadString(url);
                if (addressxml.Contains("<Error>"))
                {
                    int idx1 = addressxml.IndexOf("<Description>") + 13;
                    int idx2 = addressxml.IndexOf("</Description>");
                    int l = addressxml.Length;
                    string errDesc = addressxml.Substring(idx1, idx2 - idx1);
                    throw new USPSManagerException(errDesc);
                }
                
                return Address.FromXml(addressxml);
            }
            catch(WebException ex)
            {
                throw new USPSManagerException(ex);
            }
        }
        /// <summary>
        /// Get the zip code by providing an Address object with a city and state
        /// </summary>
        /// <param name="city">City</param>
        /// <param name="state">State</param>
        public Address GetZipcode(string city, string state)
        {
            Address a = new Address();
            a.City = city;
            a.State = state;
            return GetZipcode(a);
        }

        /// <summary>
        /// Get the zip code by providing an Address object with a city and state
        /// </summary>
        /// <param name="address">Address Object</param>
        /// <returns>Address Object</returns>
        public Address GetZipcode(Address address)
        {
            try
            {
                //The address must contain a city and state
                if (address.City == null || address.City.Length < 1 || address.State == null || address.State.Length < 1)
                    throw new USPSManagerException("You must supply a city and state for a zipcode lookup request.");

                string zipcodeurl = "?API=ZipCodeLookup&XML=<ZipCodeLookupRequest USERID=\"{0}\"><Address ID=\"{1}\"><Address1>{2}</Address1><Address2>{3}</Address2><City>{4}</City><State>{5}</State></Address></ZipCodeLookupRequest>";
                string url = GetURL() + zipcodeurl;
                url = String.Format(url, _userid, address.ID.ToString(), address.Address1, address.Address2, address.City, address.State, address.Zip, address.ZipPlus4);
                string addressxml = web.DownloadString(url);
                if (addressxml.Contains("<Error>"))
                {
                    int idx1 = addressxml.IndexOf("<Description>") + 13;
                    int idx2 = addressxml.IndexOf("</Description>");
                    int l = addressxml.Length;
                    string errDesc = addressxml.Substring(idx1, idx2 - idx1);
                    throw new USPSManagerException(errDesc);
                }

                return Address.FromXml(addressxml);
            }
            catch (WebException ex)
            {
                throw new USPSManagerException(ex);
            }
        }

        /// <summary>
        /// Get the city and state by proving the zip code.
        /// </summary>
        /// <param name="zipcode">Zipcode</param>
        public Address GetCityState(string zipcode)
        {
            Address a = new Address();
            a.Zip = zipcode;
            return GetCityState(a);
        }

        /// <summary>
        /// Get the city and state by proving the zip code.
        /// </summary>
        /// <param name="address">Address object</param>
        /// <returns>Address Object</returns>
        public Address GetCityState(Address address)
        {
            try
            {
                //The address must contain a city and state
                if (address.Zip == null || address.Zip.Length < 1)
                    throw new USPSManagerException("You must supply a zipcode for a city/state lookup request.");
                
                string citystateurl = "?API=CityStateLookup&XML=<CityStateLookupRequest USERID=\"{0}\"><ZipCode ID= \"{1}\"><Zip5>{2}</Zip5></ZipCode></CityStateLookupRequest>";
                string url = GetURL() + citystateurl;
                url = String.Format(url, _userid, address.ID.ToString(), address.Zip);
                string addressxml = web.DownloadString(url);
                if (addressxml.Contains("<Error>"))
                {
                    int idx1 = addressxml.IndexOf("<Description>") + 13;
                    int idx2 = addressxml.IndexOf("</Description>");
                    int l = addressxml.Length;
                    string errDesc = addressxml.Substring(idx1, idx2 - idx1);
                    throw new USPSManagerException(errDesc);
                }

                return Address.FromXml(addressxml);
            }
            catch (WebException ex)
            {
                throw new USPSManagerException(ex);
            }
        }

        #endregion

        #region Tracking Methods
        public TrackingInfo GetTrackingInfo(string TrackingNumber)
        {
            try
            {
                string trackurl = "?API=TrackV2&XML=<TrackRequest USERID=\"{0}\"><TrackID ID=\"{1}\"></TrackID></TrackRequest>";
                string url = GetURL() + trackurl;
                url = String.Format(url, _userid, TrackingNumber);
                string xml = web.DownloadString(url);
                if (xml.Contains("<Error>"))
                {
                    int idx1 = xml.IndexOf("<Description>") + 13;
                    int idx2 = xml.IndexOf("</Description>");
                    int l = xml.Length;
                    string errDesc = xml.Substring(idx1, idx2 - idx1);
                    throw new USPSManagerException(errDesc);
                }

                return TrackingInfo.FromXml(xml);
            }
            catch (WebException ex)
            {
                throw new USPSManagerException(ex);
            }
        }
        #endregion

        #region Label Methods
        /// <summary>
        /// Fills a package's ShippingLabel with a Byte{} containing the Image for the label
        /// </summary>
        /// <param name="package">Package with From and To addresses provided</param>
        /// <returns>The same package with the ShippingLabel</returns>
        public Package GetDeliveryConfirmationLabel(Package package)
        {
            string labeldate = package.ShipDate.ToShortDateString();
            if (package.ShipDate.ToShortDateString() == DateTime.Now.ToShortDateString())
                labeldate = "";
            string url = "?API=DeliveryConfirmationV3&XML=<DeliveryConfirmationV3.0Request USERID=\"{0}\"><Option>{1}</Option><ImageParameters></ImageParameters><FromName>{2}</FromName><FromFirm>{3}</FromFirm><FromAddress1>{4}</FromAddress1><FromAddress2>{5}</FromAddress2><FromCity>{6}</FromCity><FromState>{7}</FromState><FromZip5>{8}</FromZip5><FromZip4>{9}</FromZip4><ToName>{10}</ToName><ToFirm>{11}</ToFirm><ToAddress1>{12}</ToAddress1><ToAddress2>{13}</ToAddress2><ToCity>{14}</ToCity><ToState>{15}</ToState><ToZip5>{16}</ToZip5><ToZip4>{17}</ToZip4><WeightInOunces>{18}</WeightInOunces><ServiceType>{19}</ServiceType><POZipCode>{20}</POZipCode><ImageType>{21}</ImageType><LabelDate>{22}</LabelDate><CustomerRefNo>{23}</CustomerRefNo><AddressServiceRequested>{24}</AddressServiceRequested><SenderName>{25}</SenderName><SenderEMail>{26}</SenderEMail><RecipientName>{27}</RecipientName><RecipientEMail>{28}</RecipientEMail></DeliveryConfirmationV3.0Request>";
            url = GetURL() + url;
            //url = String.Format(url,this._userid, (int)package.LabelType, package.FromAddress.Contact, package.FromAddress.FirmName, package.FromAddress.Address1, package.FromAddress.Address2, package.FromAddress.City, package.FromAddress.State, package.FromAddress.Zip, package.FromAddress.ZipPlus4, package.ToAddress.Contact, package.ToAddress.FirmName, package.ToAddress.Address1, package.ToAddress.Address2, package.ToAddress.City, package.ToAddress.State, package.ToAddress.Zip, package.ToAddress.ZipPlus4, package.WeightInOunces.ToString(), package.ServiceType.ToString().Replace("_", " "), package.OriginZipcode, package.LabelImageType.ToString(), labeldate, package.ReferenceNumber, package.AddressServiceRequested.ToString(),  package.FromAddress.Contact, package.FromAddress.ContactEmail, package.ToAddress.Contact, package.ToAddress.ContactEmail);
            url = String.Format(url, this._userid, (int)package.LabelType, package.FromAddress.Contact, package.FromAddress.FirmName, package.FromAddress.Address1, package.FromAddress.Address2, package.FromAddress.City, package.FromAddress.State, package.FromAddress.Zip, package.FromAddress.ZipPlus4, package.ToAddress.Contact, package.ToAddress.FirmName, package.ToAddress.Address1, package.ToAddress.Address2, package.ToAddress.City, package.ToAddress.State, package.ToAddress.Zip, package.ToAddress.ZipPlus4, package.WeightInOunces.ToString(), package.ServiceType.ToString().Replace("_", " "), package.OriginZipcode, package.LabelImageType.ToString(), labeldate, package.ReferenceNumber, package.AddressServiceRequested.ToString(), "", "", "", "");
            string xml = web.DownloadString(url);
            if (xml.Contains("<Error>"))
            {
                int idx1 = xml.IndexOf("<Description>") + 13;
                int idx2 = xml.IndexOf("</Description>");
                int l = xml.Length;
                string errDesc = xml.Substring(idx1, idx2 - idx1);
                throw new USPSManagerException(errDesc);
            }
            int i1 = xml.IndexOf("<DeliveryConfirmationLabel>") + 27;
            int i2 = xml.IndexOf("</DeliveryConfirmationLabel>");
            package.ShippingLabel = StringToUTF8ByteArray(xml.Substring(i1, i2 - i1));
            return package;
        }

        /// <summary>
        /// Fills a package's ShippingLabel with a Byte{} containing the Image for the label
        /// </summary>
        /// <param name="package">Package with From and To addresses provided</param>
        /// <returns>The same package with the ShippingLabel</returns>
        public Package GetSignatureConfirmationLabel(Package package)
        {
            string url = "?API=SignatureConfirmationV3&XML=<SignatureConfirmationV3.0Request USERID=\"{0}\"><Option>{1}</Option><ImageParameters></ImageParameters><FromName>{2}</FromName><FromFirm>{3}</FromFirm><FromAddress1>{4}</FromAddress1><FromAddress2>{5}</FromAddress2><FromCity>{6}</FromCity><FromState>{7}</FromState><FromZip5>{8}</FromZip5><FromZip4>{9}</FromZip4><ToName>{10}</ToName><ToFirm>{11}</ToFirm><ToAddress1>{12}</ToAddress1><ToAddress2>{13}</ToAddress2><ToCity>{14}</ToCity><ToState>{15}</ToState><ToZip5>{16}</ToZip5><ToZip4>{17}</ToZip4><WeightInOunces>{18}</WeightInOunces><ServiceType>{19}</ServiceType><POZipCode>{20}</POZipCode><ImageType>{21}</ImageType><LabelDate>{22}</LabelDate><CustomerRefNo>{23}</CustomerRefNo><AddressServiceRequested>{24}</AddressServiceRequested></SignatureConfirmationV3.0Request>";
            url = GetURL() + url;
            url = String.Format(url, this._userid, (int)package.LabelType, package.FromAddress.Contact, package.FromAddress.FirmName, package.FromAddress.Address1, package.FromAddress.Address2, package.FromAddress.City, package.FromAddress.State, package.FromAddress.Zip, package.FromAddress.ZipPlus4, package.ToAddress.Contact, package.ToAddress.FirmName, package.ToAddress.Address1, package.ToAddress.Address2, package.ToAddress.City, package.ToAddress.State, package.ToAddress.Zip, package.ToAddress.ZipPlus4, package.WeightInOunces.ToString(), package.ServiceType.ToString().Replace("_", " "), package.OriginZipcode, package.LabelImageType.ToString(), package.ShipDate.ToShortDateString(), package.ReferenceNumber, package.AddressServiceRequested.ToString(), package.FromAddress.Contact, package.FromAddress.ContactEmail, package.ToAddress.Contact, package.ToAddress.ContactEmail);
            string xml = web.DownloadString(url);
            if (xml.Contains("<Error>"))
            {
                int idx1 = xml.IndexOf("<Description>") + 13;
                int idx2 = xml.IndexOf("</Description>");
                int l = xml.Length;
                string errDesc = xml.Substring(idx1, idx2 - idx1);
                throw new USPSManagerException(errDesc);
            }
            int i1 = xml.IndexOf("<SignatureConfirmationLabel>") + 28;
            int i2 = xml.IndexOf("</DeliveryConfirmationLabel>");
            package.ShippingLabel = StringToUTF8ByteArray(xml.Substring(i1, i2 - i1));
            return package;
        }

     
        #endregion

        #region Rates

        public RateResponse GetRate(Package package)
        {
            try
            {
                string url = "?API=RateV2&XML=<RateV2Request USERID=\"{0}\"><Package ID=\"0\"><Service>{1}</Service><ZipOrigination>{2}</ZipOrigination><ZipDestination>{3}</ZipDestination><Pounds>{4}</Pounds><Ounces>{5}</Ounces><Container>{6}</Container><Size>{7}</Size></Package></RateV2Request>";

                int lb = package.WeightInOunces / 16;
                int oz = package.WeightInOunces % 16;
                string container = package.PackageType.ToString().Replace("_", " ");
                if (container == "None")
                    url = url.Replace("<Container>{6}</Container>", "");
                string fromZip = package.FromAddress.Zip;
                if (package.OriginZipcode != null && package.OriginZipcode.Length > 0)
                    fromZip = package.OriginZipcode;

                
                url = GetURL() + url;
                url = String.Format(url, _userid, package.ServiceType.ToString(), fromZip, package.ToAddress.Zip, lb.ToString(), oz.ToString(), container, package.PackageSize.ToString().Replace("_", " "));
                string xml = web.DownloadString(url);
                if (xml.Contains("<Error>"))
                {
                    int idx1 = xml.IndexOf("<Description>") + 13;
                    int idx2 = xml.IndexOf("</Description>");
                    int l = xml.Length;
                    string errDesc = xml.Substring(idx1, idx2 - idx1);
                    throw new USPSManagerException(errDesc);
                }

                return RateResponse.FromXml(xml);
            }
            catch (WebException ex)
            {
                throw new USPSManagerException(ex);
            }
        }
        #endregion

        #region TextConversions
        /// <summary>
        /// To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
        /// </summary>
        /// <param name="characters">Unicode Byte Array to be converted to String</param>
        /// <returns>String converted from Unicode Byte Array</returns>
        private String UTF8ByteArrayToString(Byte[] characters)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            String constructedString = encoding.GetString(characters);
            return (constructedString);
        }

        /// <summary>
        /// Converts the String to UTF8 Byte array and is used in De serialization
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        private Byte[] StringToUTF8ByteArray(String pXmlString)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            Byte[] byteArray = encoding.GetBytes(pXmlString);
            return byteArray;
        }
        #endregion

        #region Private methods
        private string GetURL()
        {
            string url = ProductionUrl;
            if (TestMode)
                url = TestingUrl;
            return url;
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Gologic Tech LLC.
United States United States
I work as an independent software architect and senior developer. I have worked on many large enterprise projects as well as small single user applications.

Comments and Discussions