Jump to content
torinwalker

New UPS XML Shipping Module available

Recommended Posts

It's not done on the payment page, but in the "action=process" code of the shipping page when you submit the page. It reloads all the shipping modules, asks for quotes again, and then redirects to the payment page. You can see this more clearly if you enable the feature of storing boxes used - you'll find double entries for each order.

 

One of these days I'll study the process code to see why it is doing the re-quote. I think that if the submit passed a bit more information, this would not be required.

I couldn't believe it, but you are right :blush:

 

After so many years this was still news to me. What an inefficiency, unbelievable. Perhaps it was done as a security feature (never trust POST's from a user) but it would have made more sense to store the received quotes in a session variable, look that up and if the action is not process delete the session variable first (clients going back to the catalog etc.).

 

My time for going to checkout_shipping is indeed in the area of 2-3 seconds. Certainly not longer.

Share this post


Link to post
Share on other sites
it would have made more sense to store the received quotes in a session variable, look that up and if the action is not process delete the session variable first (clients going back to the catalog etc.).

This seems to work fine to avoid the quote being called if the action = process. I changed this piece of code in checkout_shipping.php (110-115):

		  if ($shipping == 'free_free') {
		$quote[0]['methods'][0]['title'] = FREE_SHIPPING_TITLE;
		$quote[0]['methods'][0]['cost'] = '0';
	  } else {
		$quote = $shipping_modules->quote($method, $module);
	  }

To:

		  if ($shipping == 'free_free') {
		$quote[0]['methods'][0]['title'] = FREE_SHIPPING_TITLE;
		$quote[0]['methods'][0]['cost'] = '0';
	  } else { // not free shipping
		// check if the cart and send to address haven't changed in the mean time
		 if (isset($_SESSION['shipping_quotes']) && $_SESSION['shipping_quotes']['cartID'] == $cartID && $_SESSION['shipping_quotes']['sendto'] == $sendto) {
		  foreach ($_SESSION['shipping_quotes']['quotes'] as $array_key => $shipping_quote) {
			if ($shipping_quote['id'] == $module) {
			  foreach ($shipping_quote['methods'] as $subarray_key => $method_array) {
				if ($method_array['id'] == $method) {
				   $quote[] = array('id' => $module, 'module' => $shipping_quote['module'], 'methods' => array($method_array));
				   break;
				} // end if ($method_array['id'] == $method)
			  } // end foreach ($shipping_quote['methods'] as $subarray_key => $method_array)
			  break; // found shipping quote in session
			} // end if ($shipping_quote['id'] == $module)
		  } // end foreach ($_SESSION['shipping_quotes']['quotes']...
// if for some reason the quote is not found in the session so $quote is not set here we get our quotes again
		  if (!isset($quote)) {
			$quote = $shipping_modules->quote($method, $module);
		  } // end if (!isset($quote))
		} else { 
		$quote = $shipping_modules->quote($method, $module);
		 }
	  }

And additionally (line 138-139) from:

// get all available shipping quotes
 $quotes = $shipping_modules->quote();

To:

// get all available shipping quotes
 $quotes = $shipping_modules->quote();
 if (!tep_session_is_registered('shipping_quotes')) tep_session_register('shipping_quotes');
 $shipping_quotes = array('cartID' => $cartID, 'sendto' => $sendto, 'quotes' => $quotes);

Share this post


Link to post
Share on other sites

Interesting, but I wonder why one couldn't just have POST parameters with the selected option? The value of the button would contain the shipping type and cost. Ah well, there's always another day.

 

I'll have to try your change - thanks.

Share this post


Link to post
Share on other sites
Interesting, but I wonder why one couldn't just have POST parameters with the selected option? The value of the button would contain the shipping type and cost.

You can't trust the customer hasn't save the page on his/her computer, edited the cost value with a text editor, saves the new file, views it in his/her browser and presses continue.... Then he/she gave him/herself a shipping discount.

Can't do that with keeping it in the session (server side).

Share this post


Link to post
Share on other sites

Yes, you're right.

 

I tried my delay problem on a couple of different servers using a simple PHP script that just did the CURL stuff. I get a consistent 13-seconds on two 1&1 servers, and an amazing 57 seconds using dreamhost.com! UPS has washed their hands of it. I am completely perplexed. Using curl_getinfo I see that all the time is taken in establishing the initial connection. I removed everything from the XML request except the outer headers, and got an error returned in 12 seconds. I don't know what else to do.

Share this post


Link to post
Share on other sites

Great contrib... Just one question.

 

Looking to add 2nd day saver and 2nd day am.

 

Just how do I go about this??

 

Thanks!

Share this post


Link to post
Share on other sites
I tried my delay problem on a couple of different servers using a simple PHP script that just did the CURL stuff. I get a consistent 13-seconds on two 1&1 servers, and an amazing 57 seconds using dreamhost.com! UPS has washed their hands of it. I am completely perplexed. Using curl_getinfo I see that all the time is taken in establishing the initial connection. I removed everything from the XML request except the outer headers, and got an error returned in 12 seconds. I don't know what else to do.

Sorry Steve, I don't know either. I have tried Google to come up with an answer but the only thing that came close on the curl mailing list was pointing to DNS being slow or network problems. But since your payment module which uses curl has no problems apparently, this doesn't make sense.

I don't know if it would help debugging that if you use an IP-address instead of www.ups.com on the line in the top with $this->host.

 

This works at least with me using 88.221.41.243 as the IP-address instead of www.ups.com for the production server and uncommenting the verify stuff (otherwise curl will complain with error 51: Error [51]: SSL: certificate subject name 'www.ups.com' does not match target host name '88.221.41.243'):

} else { // default behavior: cURL is assumed to be compiled in PHP
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		// uncomment the next line if you get curl error 60: error setting certificate verify locations
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
		// uncommenting the next line is most likely not necessary in case of error 60
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

Share this post


Link to post
Share on other sites

Well, Hallelujah! I had tried the IP address and disabling the verification but not both together. That does the trick! I wonder why the DNS resolution is so slow? I notice that www.ups.com is a CNAME for another CNAME, but CURL is supposed to cache DNS for two minutes or so.

 

Thanks! Your session variable idea works great too!

Share this post


Link to post
Share on other sites

hey everyone, i am getting this error when trying to using the xml mod

 

110206: Missing/Illegal ShipTo/Address/StateProvinceCode

 

If you prefer to use ups as your shipping method, please contact

 

i have tried every address under the sun, but cant get it to work...i have tried copying the american address that the store owner uses in the admin, but even that doesnt get me anywhere

Share this post


Link to post
Share on other sites

Hello Everyone,

 

After installing and testing the UPS XML files, I ran into one little problem.

 

The weight of the product shows in the UPS module is always 100 lbs heavier.

 

Meaning:

- if I order an Item at 20 lbs, the UPS module shows (1 pkg x 120 lbs total)**

- if I order an Item at 0 lbs, the UPS module shows (1 pkg x 100 lbs total)**

 

** United Parcel Service (XML) (1 pkg x 120 lbs total)

 

Is there a way for me to fix this?

 

Thank you very-very-very much for your help.

Share this post


Link to post
Share on other sites
hey everyone, i am getting this error when trying to using the xml mod

Something in the address of the owner of the store or the recipient is not in order according to UPS. Try the logging feature (see the shipping module itself for instructions) and catch what is sent out. That should give you a clue.

Share this post


Link to post
Share on other sites

Hi,

 

I´m new to osCommerce.

 

I have a Mexican osCommerce website using this nice UPS XML Shipping Module.

 

But I have this problem:

 

If I make tests using a shipping address in the USA the quotation is nice, but if the shipping address is in Mexico then it is not.

 

This is: my products origin place is Mexico, and the module access UPS services nice to other countries, but UPS services within Mexico are different from international services.

 

How can I add these UPS services (National within Mexico) in order to get accurate results?

 

Thanks a lot for your help and time.

 

Benito Estrada

Share this post


Link to post
Share on other sites
If I make tests using a shipping address in the USA the quotation is nice, but if the shipping address is in Mexico then it is not.

 

This is: my products origin place is Mexico, and the module access UPS services nice to other countries, but UPS services within Mexico are different from international services.

 

How can I add these UPS services (National within Mexico) in order to get accurate results?

You can't really, UPS is giving you these quotes. Shouldn't be a problem though. What do you mean with quotations not being nice?

Share this post


Link to post
Share on other sites

I found a partial solution to the problem of garbage rates when UPS does not return negotiated rates.

 

In two places in upsxml.php, replace:

 

if (!($serviceCode && $totalCharge)) {

 

with

 

if (!($serviceCode && is_numeric($totalCharge))) {

 

The problem is that you'll sometimes get a string back and this won't properly fail the test. In the case where rates are not available, the customer will now get an error saying so rather than garbage rates.

 

An alternative would be to return the list rates instead, but so far I have not managed to make that work.

 

I agree that the xmldocument code is very fragile. Perhaps it could be replaced by the use of the domxml PHP module.

Share this post


Link to post
Share on other sites

what does this error mean?

 

UPSXML TimeInTransit Error: 250050: License system not available experienced by customer with id 103 on 2007-11-03 23:15:52

 

also is there going to be a fix to figure out what item was being looked at when i get ups errors like this?

 

UPSXML Rates Error: 111050: Package exceeds the maximum size total constraints of 165 inches (length + girth, where girth is 2 x width plus 2 x height). experienced by customer with id 106 on 2007-11-03 21:04:40

 

or do i just have to go through my catalog and look at all the dimensions and calculate it myself?

Edited by jasyn

Share this post


Link to post
Share on other sites
what does this error mean?

You would need to ask UPS what exactly that means. My guess it is some server that looks up the user id's or developers id's could not be reached.

 

You can avoid errors in the TimeInTransit part taking down the rest (will be in the next version) by changing one line of code in the function quote (arond line 332):

Change (some more lines shown for reference):

		// debug only:
	/*  echo '<pre>Packages and variables:<br />';
	 print_r($this);
	 echo '<br />';
	 exit; */
	$this->servicesTimeintransit = $this->_upsGetTimeServices();

To:

		// debug only:
	/*  echo '<pre>Packages and variables:<br />';
	 print_r($this);
	 echo '<br />';
	 exit; */
	// make sure that when TimeinTransit fails to get results (error or not available)
	// this is not obvious to the client
	$_upsGetTimeServicesResult = $this->_upsGetTimeServices();
	if ($_upsGetTimeServicesResult != false && is_array($_upsGetTimeServicesResult)) {
	$this->servicesTimeintransit = $_upsGetTimeServicesResult;
	}

and somewhere around line 1123 to return false instead of $errorMsg:

			// log errors to file ups_error.log when set
		if ($this->ups_error_file) {
			error_log(date('Y-m-d H:i:s')."\tTimeInTransit\t" . $errorMsg . "\t" . $_SESSION['customer_id'] ."\n", 3, $this->ups_error_file);	
		}
	   //  return $errorMsg;
	   return false;

also is there going to be a fix to figure out what item was being looked at when i get ups errors like this?

or do i just have to go through my catalog and look at all the dimensions and calculate it myself?

Actually, I don't understand the error. My understanding is (and I guess I tested that but I forgot) that you just get charged for an oversized package. Is this a customer in a place where they don't ship oversized packages?

 

The latest version of UPS contains a module to save the information of packed cartons to the database. But in a busy shop where you get lots of orders this is probably not too practical because that table will grow big very quickly.

 

Anyway, what do you mean with "item being looked at". UPSXML is a shipping module :huh:

Share this post


Link to post
Share on other sites
Actually, I don't understand the error. My understanding is (and I guess I tested that but I forgot) that you just get charged for an oversized package. Is this a customer in a place where they don't ship oversized packages?

 

The latest version of UPS contains a module to save the information of packed cartons to the database. But in a busy shop where you get lots of orders this is probably not too practical because that table will grow big very quickly.

 

Anyway, what do you mean with "item being looked at". UPSXML is a shipping module :huh:

 

Well for oversized packages, when you try to get a shipping quote via the checkout method, UPS usually gives an error saying that the pricing can't be given because of the dimensions and such and to call the shop. When that happens we usually get that dimensional error sent to our inbox. I'd just like if there is any way to know what product was added in the cart and fired off that error. I hope that makes sense.

Share this post


Link to post
Share on other sites
I'd just like if there is any way to know what product was added in the cart and fired off that error. I hope that makes sense.

You get an email with the customer_id because without a customer_id you can't get to checkout_shipping. Perhaps you can check the table customers_basket if the customer gave up and logged-out, the item should still be in there.

 

Of course you could run that size test on your database too (provided length is indeed the largest dimension that was entered) using phpMyAdmin:

select products_id, (products_length + 2*products_width + 2*products_height) as size from products where (products_length + 2*products_width + 2*products_length > 165);

Share this post


Link to post
Share on other sites
You get an email with the customer_id because without a customer_id you can't get to checkout_shipping. Perhaps you can check the table customers_basket if the customer gave up and logged-out, the item should still be in there.

 

Of course you could run that size test on your database too (provided length is indeed the largest dimension that was entered) using phpMyAdmin:

select products_id, (products_length + 2*products_width + 2*products_height) as size from products where (products_length + 2*products_width + 2*products_length > 165);

 

thank you. i have it all figured out now :thumbsup:

Share this post


Link to post
Share on other sites
You can't really, UPS is giving you these quotes. Shouldn't be a problem though. What do you mean with quotations not being nice?

 

Hi Jan,

 

Sorry for getting back late to this issue...

 

My osCommerce website is from a music recording label and we sell Audio CDs.

 

So a set of 1 to 5 CDs may cost $40 USD to ship from Mexico to USA, this sound reasonable.

 

But I´m getting $150 USD shiping rate within Mexico!!! this is impossible. The real cost is about $15 ~ $17 USD.

 

Thanks for your attention,

 

Benito Estrada

Share this post


Link to post
Share on other sites
But I´m getting $150 USD shiping rate within Mexico!!! this is impossible.

Why are you so sure it is quoted in dollars? Try setting up logging (see the upsxml.php file itself for directions, use a full path) and see what is inside the response:

<CurrencyCode>USD</CurrencyCode>

According to oanda the rate on November 1 for MXN was:

Thursday, November 1, 2007

150 Mexican Peso = 13.99576 US Dollar

That sounds more like the ballpark figure you expect.

Share this post


Link to post
Share on other sites
Is anyone updaing this module for USPS V3?

 

Here is what I received by email -

 

+++++++++++++++++++++++++++++++++++++++++=

Dear Customer,

 

 

 

On May 14 2007, the United States Postal Service® will implement changes for Domestic Mail. In response to these changes, a new Domestic Rates Application Program Interface (API), RateV3, will be released by USPS Web Tools®.

 

 

 

A staging environment will be available to test the new API on April 19th. Please go to:

 

http://stg-production.shippingapis.com/

 

 

 

 

 

RateV2 will still be available after the release of RateV3, and will suffice unless rates need to be calculated for Large Priority Mail packages. USPS is introducing a new dimensional weight pricing model for Large Priority Mail pieces. Dimensional weighting is a mechanism that converts the cubic size of a piece into a weight. If a large box is very light, it will be charged as a higher-weight piece, based on the International Air Transport Association (IATA) standard. This change only affects Priority Mail pieces larger than 1 cubic foot, and traveling to destinations within zones 5-8. The Rate V3 API still requires dimensions if an item is large, regardless of the zone.

 

 

 

 

 

To capture the dimensional weight for Large Priority Mail pieces, RateV3 will require three new dimension tags for rectangular Priority Mail pieces: Length, Width, and Height; and four new dimension tags for non-rectangular pieces: Length, Width, Height, and Girth. Shippers will specify in the existing Container tag whether a Large Priority Mail piece is rectangular or non-rectangular.

 

 

 

RateV3 also implements changes to First Class Mail. A new tag, First Class Mail Type, will be used to specify whether a First Class Mail piece is a letter, flat, or parcel. Today, First Class Mail pieces are charged identical rates, regardless of the type of package. With the change, the postage for each type of First Class Mail piece will more accurately reflect the processing costs for each. The Machineable tag will also be applied to First Class Mail, in addition to Parcel Post.

 

 

 

An example of an XML request of the Rate V3 is:

 

<RateV3Request USERID="000AAAAA9999">

 

<Package ID="1ST">

 

<Service>FIRST CLASS</Service>

 

<FirstClassMailType>LETTER</FirstClassMailType>

 

<ZipOrigination>44106</ZipOrigination>

 

<ZipDestination>90210</ZipDestination>

 

<Pounds>0</Pounds>

 

<Ounces>0.75</Ounces>

 

<Size>REGULAR</Size>

 

<Machinable>false</Machinable>

 

</Package>

 

<Package ID="2ND">

 

<Service>PRIORITY</Service>

 

<ZipOrigination>44106</ZipOrigination>

 

<ZipDestination>20770</ZipDestination>

 

<Pounds>5</Pounds>

 

<Ounces>8</Ounces>

 

<Container>NONRECTANGULAR</Container>

 

<Size>LARGE</Size>

 

<Width>15</Width>

 

<Length>30</Length>

 

<Height>15</Height>

 

<Girth>55</Girth>

 

</Package>

 

<Package ID="3RD">

 

<Service>ALL</Service>

 

<ZipOrigination>90210</ZipOrigination>

 

<ZipDestination>20770</ZipDestination>

 

<Pounds>8</Pounds>

 

<Ounces>32</Ounces>

 

<Container>RECTANGULAR</Container>

 

<Size>LARGE</Size>

 

<Width>15</Width>

 

<Length>30</Length>

 

<Height>15</Height>

 

<Machinable>true</Machinable>

 

</Package>

 

</RateV3Request>

 

 

 

 

 

If you have any questions, concerns or technical inquiries, please contact the USPS Internet customer Care Center via email at icustomercare@usps.com or phone 1-800-344-7779.

 

 

Sincerely,

 

 

Patti Mason

 

Manager, USPS.com

 

 

I would like USPS to also use dimensions like this UPS can use.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×