Blog

Integrating UPS Online Tools with PHP/mySQL e-commerce

by Bobby Whitman

close  

Today, I was faced with a brand new challenge. A client had contracted us to create an online store complete with custom shopping cart and payment gateway interaction. After carefully considering business logistics, the client decided to do all of the shipping of online sales using UPS. So, in order to accurately calculate shipping costs to pass along to the customer we were asked to integrate UPS Online Tools into the checkout process we were designing. The goal was to have the client select their preferred method of shipping, display the cost for UPS to ship to their zip code, and have that cost added to the total so it could be charged to the customer’s credit card.

“No problem,” I thought. Surely, UPS has a great API with tons of resources and sample scripts, right? Well, not so much. All I really got out of them was a 63 page PDF filled mostly with XML 101 and an error code reference. The only sample code I could find was written Java and Visual Basic. After all, who needs samples in popular web languages like ASP, ColdFusion, Perl, and PHP?

Ok, so let’s turn to Google, surely someone has done this before and is willing to share their source with the community, right? Again, no luck. I googled for the better part of an hour finding nothing more than some software piece for sale claiming to do it and a bunch of unanswered forum posts from about 4 years ago.

Looks like I am on my own. So, I rolled up my sleeves and started poking around the UPS service and I have what I think is a good solution. Now, I am writing this resource paper so I can share this solution with all, so the next person looking need go no farther.

Goal: Given a destination city/zip/country, an approximate weight of the package, and the type of shipping service I want to order from UPS (e.g. 2nd day air, ground, etc.) be able to calculate shipping rates on the fly and store that data in my database so I can record it as part of the order.

To achieve this end I will want to use the UPS Rates and Service Selection XML Tool. In order to use this, I will need an account at UPS.com and what is called a Developer’s Key that you can use to generate an XML Access Key.

This tool works as follows:
1. You format a request using XML and the format specified by UPS. This format is explained in the Developer’s Guide provided by UPS.
2. Send this request to the UPS service via HTTP POST.
3. The UPS service will then output a response in XML.

When we get this response from UPS we can parse the resultant XML using PHP and retrieve the data we desire.

Step 1: Create the XML using the correct format for UPS.

Essentially there is two things we must do here. First, we have to gain access to the UPS service. We do this by sending an AccessRequest through XML. In this exmaple, your ‘UserId’ and ‘Password’ make up your UPS.com login and ‘AccessKey’ is the XML Access Key generated through UPS.com.

<?xml version=”1.0″?>
<AccessRequest xml:lang=”en-US”>
<AccessLicenseNumber>AccessKey</AccessLicenseNumber>
<UserId>UserId</UserId>
<Password>Password</Password>
</AccessRequest>

Second, we send data regarding the shipment for which we want costs calculated. We take these two XML files, concatenate them, and send them both in our request.

<?xml version=”1.0″?>
<RatingServiceSelectionRequest xml:lang=”en-US”>
<Request>
<RequestAction>Rate</RequestAction>

<RequestOption>Rate</RequestOption>
</Request>
<Shipment>
<Shipper>
<ShipperNumber>ShipperNumber</ShipperNumber>
<Address>
<City>Columbus</City>

<PostalCode>43220</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Shipper>
<ShipTo>
<Address>
<City>Cincinnati</City>

<PostalCode>45207</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</ShipTo>
<ShipFrom>
<Address>
<City>Columbus</City>

<PostalCode>43220</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</ShipFrom>
<Service>
<Code>03</Code>
</Service>

<Package>
<PackagingType>
<Code>02</Code>
<Description>Customer Supplied</Description>
</PackagingType>
<Description>Rate</Description>
<PackageWeight>

<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>10</Weight>
</PackageWeight>
</Package>
</Shipment>
</RatingServiceSelectionRequest>

You can pretty much see what is going on here. But to clarify, we send details about the Request and the Shipment, which involves the following information:

Shipper – UPS assigned ShipperNumber and general info about the shipper.
ShipTo – Critical information (city, zip code, and country) on the shipment destination.
ShipFrom – Critical information (city, zip code, and country) on the shipment source.
Package – Information about the package including packaging type and weight of package.
Service – A code for the UPS service to use. See Below.

<?

$ups_service = array(
’01′ => ‘UPS Next Day Air ’,
’02′ => ‘UPS Second Day Air ’,
’03′ => ‘UPS Ground’,
’12′ => ‘UPS Three-Day Select ’,
’13′ => ‘UPS Next Day Air Saver ’,
’14′ => ‘UPS Next Day Air Early A.M. SM’,
’59′ => ‘UPS Second Day Air A.M. ’,
’65′ => ‘UPS Saver’,
);

?>

Note that you may choose receive information on the costs of all UPS products for this shipment. In this case we change the RequestOption to ‘Shop’ and omit the ‘Service’ node.

This is the basic structure of the XML, there are a number of additional fields you may specify regarding the Shipment, for more information here, please refer to the Developer’s Guide provided by UPS.

Next, I am going to use some PHP so we can parameterize the critical information:

<?

$destCity = $_POST['x_ship_to_city'];
$destZip = $_POST['x_ship_to_zip'];
$destCountry = ‘US’;

$shipWeight = $_POST['ship_weight'];
$shipType = $_POST['ship_method'];

$shipperNumber = ‘ENTER SHIP NUMBER’;

$myCity = ‘Columbus’;
$myZip = ’43220′;
$myCountry = ‘US’;

$accessLicense = ‘ENTER ACCESS KEY’;
$userId = ‘ENTER USER ID’;
$password = ‘ENTER PASSWORD’;

$XML = ‘<?xml version=”1.0″?>
<AccessRequest xml:lang=”en-US”>
<AccessLicenseNumber>’ . $accessLicense . ‘</AccessLicenseNumber>
<UserId>’ . $userId . ‘</UserId>
<Password>’ . $password . ‘</Password>
</AccessRequest>
<?xml version=”1.0″?>
<RatingServiceSelectionRequest xml:lang=”en-US”>
<Request>
<RequestAction>Rate</RequestAction>
<RequestOption>Rate</RequestOption>
</Request>
<Shipment>
<Shipper>
<ShipperNumber>’ . $shipperNumber . ‘</ShipperNumber>
<Address>
<City>’ . $myCity . ‘</City>
<PostalCode>’ . $myZip . ‘</PostalCode>
<CountryCode>’ . $myCountry . ‘</CountryCode>
</Address>
</Shipper>
<ShipTo>
<Address>
<City>’ . $destCity . ‘</City>
<PostalCode>’ . $destZip . ‘</PostalCode>
<CountryCode>’ . $destCountry . ‘</CountryCode>
</Address>
</ShipTo>
<ShipFrom>
<Address>
<City>’ . $myCity . ‘</City>
<PostalCode>’ . $myZip . ‘</PostalCode>
<CountryCode>’ . $myCountry . ‘</CountryCode>
</Address>
</ShipFrom>
<Service>
<Code>’ . $shipType . ‘</Code>
</Service>
<Package>
<PackagingType>
<Code>02</Code>
<Description>Customer Supplied</Description>
</PackagingType>
<Description>Rate</Description>
<PackageWeight>
<UnitOfMeasurement>
<Code>LBS</Code>
</UnitOfMeasurement>
<Weight>’ . $shipWeight . ‘</Weight>
</PackageWeight>
</Package>
</Shipment>
</RatingServiceSelectionRequest>’;

?>

Step 2: Post the XML to UPS.

Now that we have generated a properly formatted request we need to send this to the UPS service for real-time processing. To do so, we will uses PHP built-in CURL functions. If you are not familiar with CURL, get more here: http://curl.haxx.se/, or here: http://us2.php.net/manual/en/ref.curl.php. The following code connects to the UPS server, POSTS the XML data, and returns the HTTP output to the $resp variable. As a result, $resp is now a string containing the XML that UPS has sent back. If you request was successful, this XML contains the shipping cost data that we want.

<?

$ch = curl_init(“https://wwwcie.ups.com/ups.app/xml/Rate”);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $XML);

$resp = curl_exec($ch);

curl_close ($ch);

?>

Step 3: Parsing the response XML with PHP.

Finally, we have the correct response from the UPS server. We need to parse this XML data to get what we want into our database or at the very least a PHP variable so we can add it to the total of the shipment. For this I will use the SimpleXML class that is built into PHP 5+.

<?

$data = new SimpleXMLElement($resp);

?>

This will load all the XML data conveniently into a PHP object. Drop in a and you will see exactly what we have to work with. We can then hack through the XML structure fairly easily to get what we want, or use XPath to essentially query our XML.

<?

$cost = (double)$data->RatedShipment->TotalCharges->MonetaryValue;

?>

The variable $cost now has the shipping price that we need to charge our online customer. You can now use this data in your existing e-commerce application.

Lastly, suppose you wish to display all UPS shipping services with their associated prices so that your customer could make a choice based on price. As I mentioned above you can change the RequestOption node in your request XML to have a value of ‘Shop’. If this modification is made, the UPS XML response includes multiple RatedShipment nodes, one for each service. If this is the case, we can use the snippet below to build an array where our keys are the UPS shipping service codes and the values are the associated costs.

<?

$shipping = array();
foreach($data->RatedShipment as $rate) {

$service = (string)$rate->Service->Code;
$cost = (double)$rate->TotalCharges->MonetaryValue;

$shipping[$service] = $cost;

}

?>

    Post Comment

    Twitter

    Fact vs. Fiction: What Usability is Not, http://t.co/aDAdJLa4

    Posted on Tue, Feb 7
    by phil_franks

    Twitter

    an oldie, but a goodie // Death to design by committee // via @Boagworld http://t.co/6Mo1Vxyl

    Posted on Mon, Feb 6
    by pomajp

    Twitter

    The Myth Of The Sophisticated User http://t.co/Mlr7M20r (via Instapaper)

    Posted on Mon, Feb 6
    by pomajp

    Blog

    Web/Graphic Designer Position Available

    by Gary Moneysmith

    close  

    Dynamit was honored as one of the “Best Places to Work” in 2010 & 2011 by Columbus Business First newspaper and Interactive Agency of the Year. Times are even better in 2012 and we’re hiring a Web/Graphic Designer for our aggressively growing team.

    This is an exciting opportunity to work on cutting edge projects for well-known brands in a dynamic, entrepreneurial and highly creative environment. Please email resumes/cover letters and portfolio information (documents or links to online examples) to Gary Moneysmith via gmoney@dynamit.us.

    A web/graphic designer on the Dynamit team will:

    • Be well versed with Adobe Creative Suite: Strong knowledge of Photoshop, experience with Illustrator and InDesign.
    • Have a strong understanding of Usability & Web Trends: Experience with user interface design, knowledge of best practices & examples of this in a portfolio or live site/application design. They will also be up-to-date on web trends and design tactics with examples.
    • Have experience in user experience design (UXD) designing application and system interfaces. This experience is crucial for this position.
    • Have Basic Programming Knowledge: We’re not looking for a developer here, but the designer should have the ability to design for web with a knowledge of the boundaries and how to design for execution by a programmer.
    • Have a Strong Portfolio: We’d like to see much more web work than print.
    • Be eager to learn, with a passion for design & the web. The designer should have a strong internal drive for industry knowledge and be committed to furthering the craft.

    Experience is important, but personality is key. Our culture is what drives us, and we’re looking to build our team with someone who both fits and contributes to it.

    The position is full time at our office in the Arena District in Columbus, Ohio. We offer a competitive salary and benefits package as well as a fun, high-energy, intellectually-stimulating work environment.

    Benefits Include

    • Competitive salary (compensation will be based on skills and experience)
    • Fully paid medical/dental insurance for employees
    • Paid parking
    • Unlimited vacation time (within reason)
    • Office bar + climbing wall — not recommended together

    Don’t sit back. If you want to work in a fast paced work environment with great people who love what they do, apply today.

    About Dynamit
    Dynamit is a digital agency based in the Arena District in Columbus, Ohio. We work with clients and brands on digital initiatives that include strategy, design, user experience and development. We influence communication and commerce. Client work includes Hilton Worldwide, Charley's Grilled Subs, McGraw-Hill, British Broadcasting Corporation (BBC), E-Z-GO, American Electric Power (AEP), Columbus College of Art & Design and the Ohio State Medical Center (OSUMC) to name but a few.

      Post Comment

      Twitter

      The Biggest Opportunity For Disruption Today: Health Care Products That Work, http://t.co/ndynGRKD

      Posted on Mon, Feb 6
      by phil_franks