Address Standardization & Verification with USPS web tools and PHP

Before using this code you will need to sign up for an account with USPS webtools here.

Class, save as ‘usps_address_class.php’

class usps {
		public $account = 'xxxxxxx'; //you need to register for this
		public $url = '';
		public $address1, $address2, $city, $state, $zip;
		public $ship_address1, $ship_address2, $ship_city, $ship_state, $ship_zip;
	function toXML() {
		$xml = ' <AddressValidateRequest USERID="' . $this->account . '"><Address ID="1">';
		$xml .= '<Address1>' . $this->address1 . '</Address1>';
		$xml .= '<Address2>' . $this->address2 . '</Address2>';
		$xml .= '<City>' . $this->city . '</City>';
		$xml .= '<State>' . $this->state . '</State>';
		$xml .= '<Zip5>' . $this->zip . '</Zip5>';
		$xml .= '<Zip4></Zip4></Address>';
		if ($this->ship_address2 <> ''){
			//shipping address
			$xml .= '<Address ID="2">';
			$xml .= '<Address1>' . $this->ship_address1 . '</Address1>';
			$xml .= '<Address2>' . $this->ship_address2 . '</Address2>';
			$xml .= '<City>' . $this->ship_city . '</City>';
			$xml .= '<State>' . $this->ship_state . '</State>';
			$xml .= '<Zip5>' . $this->ship_zip . '</Zip5>';
			$xml .= '<Zip4></Zip4></Address>';
		$xml .= '</AddressValidateRequest>';
     return $xml;
	function submit_request() {
		$ch = curl_init($this->url);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, "API=Verify&XML=" . $this->toXML());
		curl_setopt($ch, CURLOPT_TIMEOUT, 60);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
		$result = curl_exec($ch);
		$error = curl_error($ch);
		if(empty($error)) {
			return $result;

And a sample page accessing it:

$uspsRequest = new usps(); //class instantiation
$uspsRequest->address1 = 'suite 321';
$uspsRequest->address2 = '1600 Pennsylvania Ave NW';
$uspsRequest->city = 'Washington';
$uspsRequest->state = 'DC';
$uspsRequest->zip = '20500';
//optional second address
$uspsRequest->ship_address1 = '';
$uspsRequest->ship_address2 = '';
$uspsRequest->ship_city = '';
$uspsRequest->ship_state = '';
$uspsRequest->ship_zip = '';
$result = $uspsRequest->submit_request();
if (!empty($result)){
		$xml = new SimpleXMLElement($result);
if(isset($xml->Address[0]->Error)) { echo ' Error Address 1';}
if(isset($xml->Address[1]->Error)) { echo ' Error Address 2';}
echo $xml->Address[0]->Address2 . ' ' . $xml->Address[0]->Address1 ;
echo '<br />';
echo $xml->Address[0]->City. ' ' . $xml->Address[0]->State  . ' ' . $xml->Address[0]->Zip5;
echo '<br />';
echo $xml->Address[1]->Address2 . ' ' . $xml->Address[1]->Address1 ;
echo '<br />';
echo $xml->Address[1]->City. ' ' . $xml->Address[1]->State  . ' ' . $xml->Address[1]->Zip5;
?> Code to Programatically Populate Address Fields in UPS Worldship

This code represents a full 8 hour day of coding. I’m posting it here as a debt of gratitude to all those on the forums who have donated their time helping out people like me. If this code helps you please let me know in the comments.

Option Explicit On
Imports System.Runtime.InteropServices
Imports System.text
Public Module upscode
Dim sShipInt As IntPtr
Dim bExit As Boolean = False
Dim bSub As Boolean = False
Dim ipName, ipAddr1, ipZip, ipCity, ipState, ipState2, ipCountry, ipPhone, ipEmail As IntPtr
Dim bName, bAddr1, bZip, bCity, bState, bCountry, bPhone, bEmail As Boolean
Dim iCountryCbo As Integer
Dim iStateCbo As Integer
Private Const WM_SETTEXT As Long = &HC
Private Const CB_SETCURSEL As Long = &H14E
Private Const CB_FINDSTRING As Long = &H14C
Private Const WM_SETFOCUS As Long = &H7
Private Const SW_RESTORE As Long = 9
Private Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
Private Function FindWindowEx(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, _
ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
End Function
Private Sub GetClassName(ByVal hWnd As System.IntPtr, _
ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer)
End Sub
Private Function GetWindowTextLength(ByVal hWnd As IntPtr) As Integer
End Function
Private Function GetWindowText(ByVal hwnd As IntPtr, _
ByVal lpString As StringBuilder, _
ByVal cch As Integer) As Integer
End Function
Private Function SendMessageByString(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
ByVal lParam As String) As IntPtr
End Function
' _
'Private Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
'                             ByVal lParam As String) As IntPtr
'End Function
Private Function SetForegroundWindow(ByVal hwnd As IntPtr) As Boolean
End Function
'  _
'Private Function SetActiveWindow(ByVal hwnd As IntPtr) As Boolean
' End Function
Private Function ShowWindow(ByVal handle As IntPtr, ByVal nCmd As Int32) As Boolean
End Function
Public Function GetChildHandle(ByVal parent As IntPtr, ByVal className As String) As IntPtr
Dim child As IntPtr = FindWindowEx(parent, IntPtr.Zero, className, Nothing)
Return child
End Function
'use spy++ to locate window names and classes: start-&gt;all programs-&gt;visual staudio 2005-&gt;visual studio tools-&gt;spy++
'windows (labels/textboxes/forms) are nested so loop through them looking for the intptr assigned to textboxes we
'want to change - these are dynamic
Public Function InsertToWorldship(ByVal sFirstName As String, ByVal sLastName As String, ByVal sAddr1 As String, _
ByVal sAddr2 As String, ByVal sCity As String, ByVal sState As String, _
ByVal sZip As String, ByVal sCountry As String, ByVal sEmail As String) As Boolean
bExit = False
bSub = False
Dim parent As IntPtr = FindWindow("UOFUPSOnlineOffice32", "UPS WorldShip")
Dim child As IntPtr = GetChildHandle(parent, "MDIClient")
If CLng(child) = 0 Then
MessageBox.Show("Could not locate UPS Worldship Process", "Exit")
Exit Function
End If
'at this point the class name becomes dynamic, so loop until finding the next known static handle ' Ship To '
RecurseWindows(CLng(child), )
bExit = False
bSub = True
RecurseWindows(CLng(sShipInt), )
If sCountry.Substring(0, 3) = "USA" Then
sCountry = "United States"
End If
ShowWindow(parent, SW_RESTORE)
SendMessageByString(ipName, WM_SETTEXT, CInt(IntPtr.Zero), sFirstName & " " & sLastName)
SendMessageByString(ipAddr1, WM_SETTEXT, CInt(IntPtr.Zero), sAddr1 & " " & sAddr2)
iCountryCbo = CInt(SendMessageByString(ipCountry, CB_FINDSTRING, -1, sCountry))
'   SetForegroundWindow(ipCountry)
SendMessageByString(ipCountry, CB_SETCURSEL, iCountryCbo, "0")
'   SetForegroundWindow(ipZip)
'   Threading.Thread.Sleep(100)
'  Threading.Thread.Sleep(100)
'  SendMessageByString(ipZip, WM_SETTEXT, IntPtr.Zero, CInt(sZip) & "-   ")
' SetActiveWindow(ipZip)
SendMessageByString(ipCity, WM_SETTEXT, CInt(IntPtr.Zero), sCity)
' SendMessageByString(ipState2, WM_SETTEXT, IntPtr.Zero, "Blah")
iStateCbo = CInt(SendMessageByString(ipState, CB_FINDSTRING, -1, sState))
SendMessageByString(ipState, CB_SETCURSEL, iStateCbo, "0")
' SendMessageByString(ipPhone, WM_SETTEXT, IntPtr.Zero, "1234567890")
SendMessageByString(ipEmail, WM_SETTEXT, CInt(IntPtr.Zero), sEmail)
End Function
Public Sub RecurseWindows(Optional ByVal Parent_hWnd As Long = 0, Optional ByVal Level As Long = 0)
If bExit = True Then
Exit Sub
End If
If CBool(Parent_hWnd) Then
Dim tLen As Long, sbWindowText As New System.Text.StringBuilder
sbWindowText.Append(Space(260)) 'MAX_PATH
tLen = GetWindowTextLength(CType(Parent_hWnd, IntPtr))
GetWindowText(CType(Parent_hWnd, IntPtr), sbWindowText, sbWindowText.Length)
If bSub = True Then
AssignIntPtr(CType(Parent_hWnd, IntPtr), sbWindowText.ToString)
End If
If bSub = False Then
If sbWindowText.ToString = "  Ship To  " Then
sShipInt = CType(Parent_hWnd, IntPtr)
bExit = True
End If
End If
End If
Dim Child_hWnd As Long
Child_hWnd = CLng(FindWindowEx(CType(Parent_hWnd, IntPtr), CType(0, IntPtr), vbNullString, vbNullString))
Do While CBool(Child_hWnd)
RecurseWindows(Child_hWnd, Level + 1)
Child_hWnd = CLng(FindWindowEx(CType(Parent_hWnd, IntPtr), CType(Child_hWnd, IntPtr), vbNullString, vbNullString))
End Sub
Private Sub AssignIntPtr(ByVal Parent_hWnd As IntPtr, ByVal Text As String)
'the text we are actually looking for here is the label that precedes the text/combobox we want to change, so
'set a flag and next time through the loop assign the intptr
If bName = True Then
ipName = Parent_hWnd
bName = False
End If
If bAddr1 = True Then
ipAddr1 = Parent_hWnd
bAddr1 = False
End If
If bZip = True Then
ipZip = Parent_hWnd
bZip = False
End If
If bCity = True Then
ipCity = Parent_hWnd
bCity = False
End If
If ipState.ToInt64 &gt; 0 AndAlso ipState2 = IntPtr.Zero Then
ipState2 = Parent_hWnd
End If
'2nd stated text box - used if country&lt;&gt;USA
If bState = True Then
ipState = Parent_hWnd
bState = False
End If
If bCountry = True Then
ipCountry = Parent_hWnd
bCountry = False
End If
If bPhone = True Then
ipPhone = Parent_hWnd
bPhone = False
End If
If bEmail = True Then
ipEmail = Parent_hWnd
bEmail = False
End If
If Text.ToString = "Company or &Name:" Then
bName = True
End If
If Text.ToString = "Addre&ss 1:" Then
bAddr1 = True
End If
If Text.ToString = "Posta&l Code:" Then
bZip = True
End If
If Text.ToString = "&City or Town:" Then
bCity = True
End If
If Text.ToString = "State/Pr^&ovince/County:" Then
bState = True
End If
If Text.ToString = "Countr&y/Territory:" Then
bCountry = True
End If
If Text.ToString = "Tele&phone:" Then
bPhone = True
End If
If Text.ToString = "E-&mail Address:" Then
bEmail = True
End If
End Sub
End Module