Jump to content
torinwalker

New UPS XML Shipping Module available

Recommended Posts

Paul,

If what you posted was the complete response.... that's not valid xml.

 

The log pretty well catches the whole response in my opinion. Using cURL will also show the headers, that is true.

 

You don't use the test server of UPS? Perhaps the production server gives different results....

Firstly, I did notice that the 700 package contribution was way too much and works great if reuced to a more human level. :P Also, I have seen different prices returned between test and production. UPS is aware of this and says it is fine becuase it should only be used to make sure your script is working correctly, not to get accurate quotes. B)

Share this post


Link to post
Share on other sites
Firstly, I did notice that the 700 package contribution was way too much and works great if reuced to a more human level. :P Also, I have seen different prices returned between test and production. UPS is aware of this and says it is fine becuase it should only be used to make sure your script is working correctly, not to get accurate quotes. B)

 

Hey JanZ and Hallmarc,

 

I'm using the production server at the moment.

 

JanZ - the XML is definitely being truncated. Because XML support is apparently built into this module using a rather proprietary method, my suspicion is that when you try to send an oversize package over there, it's not properly parsing the xml. That's why the log entry seems truncated in this instance.

 

I'm writing a perl script which will post this very same request and get the response back, just to see what it's supposed to look like. That should then give me an idea what exactly is causing this mod to trip up. I will let you know.

 

Hallmarc - absolutely after getting rid of all of the "Oversize" package definitions, and implementing your suggestion on sorting by volume rather than package id, it's almost 99% there. I'm getting great quotes and package numbers now.....comparing back to old shipments and getting almost to the penny rates and almost exact package breakdowns.

 

I will let ya all know what happens with the perl script and what exactly is wrong with the xml parsing in this mod (if that is indeed what is happening.....)

 

-Paul

Share this post


Link to post
Share on other sites

Found it. The Perl script revealed the entire story. :thumbsup:

 

Here are the conditions under which this will happen when using this mod:

 

(1) you are using PHP without CURL support installed.

(2) you send a request to UPS with an oversized package size, but without the oversized flag set in the xml

 

UPS comes back with the following value within every "RatedShipment" tag:

 

'RatedShipmentWarning' => 'Oversize 3/Large Package indicator has automatically been set on Package 1.
Large Package Surcharge has been added to Package 1.'

 

Note: There is a "newline" ("\n") character after the period in the first sentence. This is the problem.

 

Since using PHP w/o CURL installed results in the exec() command being executed, the $xmlResponse variable comes back from the exec() as an Array, rather than a string. When this happens, the first slice of the Array, [0], ends with the first encountered Newline character (that's why the XML response was truncated in the logfile, JanZ.)

 

Problem is, this mod returns from the _post subroutine with only the first slice of the array.....$xmlResponse[0]. The original author probably thought that was a safe thing to do. Unfortunately, the Array's first slice, [0], only includes the value up to and including the first Newline character it encounters. And leave it up to UPS to have included a Newline character in this stinking "RatedShipment" tag:. :angry:

 

Anyway, the solution to the problem was to include in the _post subroutine, after these lines:

 

$command = "".$curl_path." -k -d \"".addslashes($xmlRequest)."\" ".$url."";
exec($command, $xmlResponse);

 

The following code:

 

foreach ($xmlResponse as $xmlSlice) {
$temp .= $xmlSlice;
}

$xmlResponse[0] = $temp;

 

Now, the first slice, [0], of the $xmlResponse Array contains ALL of the slices that were caused by the newline characters. And the _post subroutine comes back with this first slice fully populated with the ENTIRE data back from UPS. And all is well with the world again.

 

Hallmarc - this, coupled with your sort on volume, has made our shipping quotes 99% there.

 

I will be packaging this up and including a new release....for those of us unfortunate souls without CURL support compiled into PHP.

 

Whew.

Share this post


Link to post
Share on other sites

Ok.... so this problem with the dimensional support putting things in the wrong boxes got out of hand on my clients site...

 

this problem may not be as noticeable on most sites because you probably don't ship stuff that is of the same mass as my client. At any rate... here's my interpretation of the problem and my version of the solution, please feel free to take this and put it in the code tree if you like. I've hacked my copy of the file apart so much I don't really want to pollute the tree with it at this point.

 

The issue is that if you have items that are of different weights and dimensions in the shopping cart. The "fitProductsInBox" function will end up trying to put most of the small items into the largest packages you have defined. This happens when the smaller items are listed in the cart before the larger items, and what the function tries to do, is fit as many products into a box as possible, so in its attempt to fit the larger item in the box with the smaller items, it will place the smaller items in the biggest box available, and then figure out that it still won't fit. But instead of using the smallest box that those smaller items can fit into, it will keep them in the largest box. Thus totally skewing the dimensions/quote.

 

Now. Since I didn't write the fitProductsInBox function, and I'm crunched for time right now in my development cycle, I couldn't really make sense of what exactly I should add/change to that function to make it work properly. So instead, I came up with this workaround.

 

Currently the $productsRemaining array gets sorted to put the ready_to_ship items first so that it can get those out of the way. So what I did was seperate the while clause that does the packing into 2 while clauses, one doing the ready_to_ship items and the other doing the rest. I then have the $productsRemaining array resorted by weight, highest to lowest, so the things that are big get packed in their big boxes first and the small stuff can't end up stuck in a big box because of a big item. I then run the while clause for the fitProductsInBox function using the resorted array.

 

At this point this seems to be working. JanZ you may find a flaw with this, and I may too, but if it works for now, that is what I need... Oh and by the way, this will only work properly if you keep the packages_query ordered by volume...

 

So here is the code breakdown.

 

Currently you have this section of the packProducts function:

		// make sure the products that did not fit the largest box and are now set as ready-to-ship
	// are out of the way as soon as possible
	usort($productsRemaining, ready_to_shipCmp);
	// Worst case, you'll need as many boxes as products ordered.
	while (count($productsRemaining)) {
		// Immediately set aside products that are already packed and ready.
		if ($productsRemaining[0]['ready_to_ship'] == '1') {
			$packedBoxesArray[] = array (
			'length' => $productsRemaining[0]['length'],
			'width' => $productsRemaining[0]['width'],
			'height' => $productsRemaining[0]['height'],
			'price' => $productsRemaining[0]['price'],
			'current_weight' => $productsRemaining[0]['weight']);
			$productsRemaining = array_slice($productsRemaining, 1);
			continue;
		}
		//Cycle through boxes, increasing box size if all doesn't fit.
		if (count($emptyBoxesArray) == 0) {
			print("ERROR: No boxes to ship unpackaged product<br />\n");
			break;
		}
		for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
			$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
			$packedBoxesArray = $result['packed_boxes'];
			$productsRemaining = $result['remaining'];
		}
	} // end while

	return $packedBoxesArray;

 

Which I changed to this:

		// make sure the products that did not fit the largest box and are now set as ready-to-ship
	// are out of the way as soon as possible
	usort($productsRemaining, ready_to_shipCmp);

	while (count($productsRemaining)) {
		// Immediately set aside products that are already packed and ready.
		if ($productsRemaining[0]['ready_to_ship'] == '1') {
			$packedBoxesArray[] = array (
			'length' => $productsRemaining[0]['length'],
			'width' => $productsRemaining[0]['width'],
			'height' => $productsRemaining[0]['height'],
			'price' => $productsRemaining[0]['price'],
			'current_weight' => $productsRemaining[0]['weight']);
			$productsRemaining = array_slice($productsRemaining, 1);
			continue;
		} else {
		  break;
		}
	} // end while

	usort($productsRemaining, weightCmp);
	// Worst case, you'll need as many boxes as products ordered.
	while (count($productsRemaining)) {
		//Cycle through boxes, increasing box size if all doesn't fit.
		if (count($emptyBoxesArray) == 0) {
			print("ERROR: No boxes to ship unpackaged product<br />\n");
			break;
		}
		for ($b = 0; $b < count($emptyBoxesArray) && tep_not_null($productsRemaining); $b++) {
			$result = $this->fitProductsInBox($productsRemaining, $emptyBoxesArray[$b], $packedBoxesArray, $b, count($emptyBoxesArray) -1 );
			$packedBoxesArray = $result['packed_boxes'];
			$productsRemaining = $result['remaining'];
		}
	} // end while

	return $packedBoxesArray;

 

Then down at the bottom of the file I just added another comparison function next to the ready_to_shipCmp one:

//******************************
function ready_to_shipCmp( $a, $b) {
if ( $a['ready_to_ship'] == $b['ready_to_ship'] )
return 0;
if ( $a['ready_to_ship'] > $b['ready_to_ship'] )
return -1;
return 1;
}

function weightCmp( $a, $b) {
if ( $a['weight'] == $b['weight'] )
return 0;
if ( $a['weight'] > $b['weight'] )
return -1;
return 1;
}

 

At this point it is working for me... YMMV good luck!!!

 

Jay

Share this post


Link to post
Share on other sites

Ok, I want to use this but I have a few questions and I am sure some are easy. :)

 

What is the link to sign up to get the access to the xml from UPS?

 

I have a UPS account now and the come once a day to pick up so not sure If I just use the account I have now, Do I?

 

Thanks Much

Share this post


Link to post
Share on other sites

Also do you need curl running on the server(version)?

 

Anything else needed to be running server side?

 

Thanks

Share this post


Link to post
Share on other sites
What is the link to sign up to get the access to the xml from UPS?
There is none. UPS has information about their online tools though on their website (www.ups.com as you probably know).
I have a UPS account now and the come once a day to pick up so not sure If I just use the account I have now, Do I?
Yes, the only thing you need additionally (as far as I know and remember) is a developer's key you should ask for at UPS.

 

And yes, you need curl with openSSH on the server side (but most providers have I think).

Share this post


Link to post
Share on other sites

Jay,

At this point this seems to be working. JanZ you may find a flaw with this, and I may too, but if it works for now, that is what I need... Oh and by the way, this will only work properly if you keep the packages_query ordered by volume...
The scenario of the small items getting stuck in a big box when a big item is next in the shopping cart is exactly what might happen. As long as you don't have any oversized boxes available I don't think UPS will charge you for that though.

 

The additional code you use sound like a good solution (provided weight equals volume, I think it could be refined for volume too) if you have one big item. If you have two I suppose the same thing might happen.

 

Perhaps it would be better to add code to check the remaining volume of the packed boxes. Boxes that are only filled to a certain level (say 70%) might be "re-packaged" to see if they fit in a smaller box. Not ideal either since it might be better to check if smaller items could be added to half full boxes with big items but there is only a limited time available for those algorithms. Packing algorithms are the subject of academic research....

Share this post


Link to post
Share on other sites

I'm numb after reading throught all these pages.

 

I've just installed version 1.2.3 without dimensional support. I get no errors but the module does not show up in the admin section. I rechecked everything 3 times to be sure everything was done right.

 

Any one have any ideas on where to look?

Share this post


Link to post
Share on other sites

Hello all,

 

has someone a solution for servers without curl and PHP3

 

for example with socket insead curl.

 

my php is to bad itryed some but it dose not work.

 

$ch = fsockopen ($host , (int)$port);

fputs ($ch, $header . $xmlRequest);

while (!feof($ch)) {

$buffer = fgets($ch, 4096);

echo '$buffer: ' . $buffer;

$xmlResponse += fgets($ch,128);

}

echo '$xmlResponse: ' . $xmlResponse;

 

 

this is not working !.

 

has anybuddy a idea

 

regards

kai

Share this post


Link to post
Share on other sites
Jay,

The scenario of the small items getting stuck in a big box when a big item is next in the shopping cart is exactly what might happen. As long as you don't have any oversized boxes available I don't think UPS will charge you for that though.

 

The additional code you use sound like a good solution (provided weight equals volume, I think it could be refined for volume too) if you have one big item. If you have two I suppose the same thing might happen.

 

Perhaps it would be better to add code to check the remaining volume of the packed boxes. Boxes that are only filled to a certain level (say 70%) might be "re-packaged" to see if they fit in a smaller box. Not ideal either since it might be better to check if smaller items could be added to half full boxes with big items but there is only a limited time available for those algorithms. Packing algorithms are the subject of academic research....

 

 

yeah I knew it wasn't the be all-end all... we're working with an imperfect science here, and I'm just trying to narrow down the number of completely freakish quotes this thing can spew out... lol.

 

I agree it would be nice to have code to repackage based on fitting things in the smallest box they can fit in if they can't go in a bigger box with something else... but at the same time. We're running into big speed issues, at least I am. This module is slooooooowwww as mud for me. I just use it because I have no choice. If there were a way to speed it up, I'd be on it like a fat boy on a milkshake.

 

B)

Edited by mucter

Share this post


Link to post
Share on other sites

kai,

has someone a solution for servers without curl and PHP3

 

for example with socket insead curl.

IMO that is not possible: to connect with the server you have to use https (you are logging in with a user name and password, you don't want to do that on a http connection anyway). For the https protocol you need curl (and OpenSSH I assume). No way around it I'm afraid.

Share this post


Link to post
Share on other sites

Jay,

We're running into big speed issues, at least I am. This module is slooooooowwww as mud for me. I just use it because I have no choice. If there were a way to speed it up, I'd be on it like a fat boy on a milkshake.
What part of it is slow, did you test? Is it the packaging stuff or the UPS servers that take such a long time. I tested a few things, but with a few items and a few boxes it took about 0.03 seconds to get to the part that contacts the UPS servers and then in about three seconds everything was done....

Share this post


Link to post
Share on other sites

:-" so if i enable ready to ship only in the module area.

does this mean i can ship by weight for some products and then selet products (oversize) i can put in the size specs and click the ready to ship box and it will ship by weight and size for that specific product?


Check out my fully customized oscommerce site by viewing my profile.

Share this post


Link to post
Share on other sites
Jay,

What part of it is slow, did you test? Is it the packaging stuff or the UPS servers that take such a long time. I tested a few things, but with a few items and a few boxes it took about 0.03 seconds to get to the part that contacts the UPS servers and then in about three seconds everything was done....

 

yeah, its probably the XML at this point that is so slow. The code probably isn't a real issue, but I'm just skiddish about slowing things down at this point, since, to me, the XML portion takes an eternity. Yeah its only like 3 or 4 seconds, but when I'm used to all of the other pages in OSC opening in under a second, it just makes me nervous (I'm editing and hosting everything in house over a LAN)... occasionally though it will time out while trying to get a quote...

Share this post


Link to post
Share on other sites

Hello All,

 

Im having a strange problem with the UPS XML module. I installed it fine with no errors, but shipping options dont show up for every user. I created an account for myself prior to the install of the UPS module, any user created after the install does not have any shipping options. If I log in as myself, the ship options are all there, now if I log in with any of the new user accounts I created, there is no shipping options listed during checkout. Anyone ever run into a problem like this?

 

Thanks,

Jim

Share this post


Link to post
Share on other sites
Anyone ever run into a problem like this?
The only time I have heard about this is when someone had installed Separate Pricing Per Customer and didn't enable this shipping method after installing UPS XML. But what you describe seems to be something different because you can still "see" it and new accounts don't. No clue.

Share this post


Link to post
Share on other sites
The only time I have heard about this is when someone had installed Separate Pricing Per Customer and didn't enable this shipping method after installing UPS XML. But what you describe seems to be something different because you can still "see" it and new accounts don't. No clue.

 

FYI Im an idiot. I figured out the problem, I set the shipping zone to PA by accident and the account I created had my PA address which is why the shipping would work fine for me, all the dummy accounts I created had out of state address which is why it DIDNT work. I set the shipping zone back to NONE and now every account i create the shipping works fine.......at least I figured it out.

 

Next question, is there a way to disable the estimated delivery dates next to the rates? I have the shipping delay set blank, but delivery dates still show up. Most of my stuff is made to order to the ship dates will vary. Thanks for the help.

 

Jim

Share this post


Link to post
Share on other sites
FYI Im an idiot.
At least you figured it out on your own, so you can't be that much of an idiot :)
Next question, is there a way to disable the estimated delivery dates next to the rates? I have the shipping delay set blank, but delivery dates still show up.
If I remember correctly the simplest (and best) way of doing that is to outcomment the part between // BOF Time In Transit and // EOF Time In Transit in the function quote in includes/modules/shipping/upsxml.php (around line 207).

Share this post


Link to post
Share on other sites

Does anyone here know about Multi-vendor shipping? They say they have UPS XML as part of that contribution but it does not add dimensions to products. As far as I can see you need to have dimensions for each product for that to work. So I am assuming I need to partly install this contribution (that product part) to get it to work with MVS?

Share this post


Link to post
Share on other sites

How does one have the UPX XML Shipping module put products into one box instead of separate packages for each item in the cart?

 

Ive had 1.1.5a and so updated to the latest version since it was putting each item into a separate box. I still have not gotten it to work.

 

My products have dimensions inputed into them and are rdy to ship. I also tried using the 700+ box addition, but with no luck.

 

I would not mind this happening if customers paid the $100 shipping cost to ship 100 tiny keychains worth $10. Unfortunately, my customers are smarter than this :=\

 

I can't get my head wrapped around this.

Share this post


Link to post
Share on other sites
How does one have the UPX XML Shipping module put products into one box instead of separate packages for each item in the cart?

 

Ive had 1.1.5a and so updated to the latest version since it was putting each item into a separate box. I still have not gotten it to work.

 

My products have dimensions inputed into them and are rdy to ship. I also tried using the 700+ box addition, but with no luck.

 

I would not mind this happening if customers paid the $100 shipping cost to ship 100 tiny keychains worth $10. Unfortunately, my customers are smarter than this :=\

 

I can't get my head wrapped around this.

 

Solved: The reason why it was packaging the products into their own separate boxes was because the products were checked as "Rdy to ship". Unchecking this box solved the problem, though I do not understand the function of rdy to ship now.

Share this post


Link to post
Share on other sites
I do not understand the function of rdy to ship now.
The idea behind ready-to-ship is, that a product marked as such can and will be shipped in it's own box. So does not need to be packed (with possibly other items in a box), since it is ready-to-ship...

Share this post


Link to post
Share on other sites

This is a great contribution and a real asset to OSC.

 

I've been using it for a couple weeks but I'm stumped by a box problem. We use a 48x8x6 inch box for some long items we sell like bamboo and such. For some reason this module will not use that box, but it will use it when I change it to 48x10x10. However, 48x10x10 is an OS1 box so that's a little bit of a problem that I need to solve. Basically, I can take an item that is 42x1x1 and it will not put that in the 48x8x6 box. I've changed the box size all around but it doesn't work until I get the width and the height to 10 each.

 

Any ideas?


John Wisdom

Share this post


Link to post
Share on other sites

Hello, all. I have to agree with the kudos in past posts. This is a wonderful application, and I am greatly appreciative of all the time and hard work everyone puts into open source. I am just learning the modern website design using PHP/MySQL and postgresql, so I know how time consuming this can be.

 

I do have a problem I can't seem to track down. I have followed the readme.txt for installation of the UPS module, have the key, etc. And I still get this error:

 

 

This is currently the only shipping method available to use on this order.

United Parcel Service (XML)

Rating and Service 1.0001 0 An unknown error occured while attempting to contact the UPS gateway : Rating and Service 1.0001 0 An unknown error occured while attempting to contact the UPS gateway

If you prefer to use ups as your shipping method, please contact Attitude Boutique via Email.

 

 

I get this error when attempting to run tests, on the second page of checkout. After reviewing my cart and clicking continue, this comes up.

 

Any ideas? I have double checked the userid, password, and access key several times, and double checked all the installation instructions to make sure I have added the needed code correctly. I'm stumped.

 

Aaron

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

×