#21023 [Opn->Fbk]: Out Put Error from United Parcel Service Rate/Service CGI File
| From: | iliaa@php.net | Date: | Sun, 15 Dec 2002 05:38:37 +0000 |
| Subject: | #21023 [Opn->Fbk]: Out Put Error from United Parcel Service Rate/Service CGI File | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-27741@lists.php.net to get a copy of this message | ||
ID: 21023
Updated by: iliaa@php.net
Reported By: webmaster@crescentart.com
-Status: Open
+Status: Feedback
Bug Type: Output Control
Operating System: Red Hat Linux 7.1
PHP Version: 4.3.0RC3
New Comment:
Shorter & to the point please :)
Previous Comments:
------------------------------------------------------------------------
[2002-12-14 22:52:25] webmaster@crescentart.com
I have create a php script that generates a shipping cost from a United
Parcel Service host. The script has worked fine on all on all PHP
releases prior to version 4.3.0RC2.
Example Script:
##########################START###########################
<?
/*
This is a UPS Shipping Program created with PHP (http://www.php.net).
This program is design to be flexiable have the ability to perform
several task including:
(1) Generate live shippping rates from a UPS server.
(2) Add the retail item cost per distributor if the retailer uses
multiple distributors.
(3) Add the whole sale cost per item while categorizing the whole sales
cost per distributor.
(4) Add the item weight per item while catagorizing the item weight per
distributor.
(5) Add any applicable distributor handling fees to the final shipping
cost.
(6) Seperate the UPS shipping fee(s), distributor handling fee(s), per
item whole sale cost and per item retal cost of CHECK OUT ITEMS and
Pre-Order items.
REQUIRMENTS:
(1) MYSQL 3.x or later.
(2) PHP 4.x (version 4.3.0RC2 is not compatable)or later compilled with
MYSQL and BCMATH.
(3) A Web Server.
Special Note(s):
(1) The Check Out Items and Pre-Orders Items scripts are on seperate
files to reduce the number of lines of code.
(2) The PHP code uses objects. There fore a MYSQL Table will be needed
with columns named as shown in the code bellow.
(3) The mysql_fetch_object names ($string->string) names can be changed
but changing any other codeing will cause this program to error out.
(4) To simplify the file to file linking the following (INCLUDE/REQUIRE
functions) codes are located on a seperate file.
//Set the bcmath scale to two digits aftr the decimal point.
bcscale(2);
//Decode shoping cart, check out subtotal and pre-order sub totlal
strings for later use.
$decode_basket = base64_decode($basket);
//Explode the shop cart string into an array for use in the shipping
calculators bellow.
$percent_sym = explode("%","$decode_basket");
//Shipping calculator.
if($check_out_sub_total != ""){
include "../check_out_items_shipping.php";
$decode_check_out_sub_total = base64_decode($check_out_sub_total);
}
if($pre_order_sub_total != ""){
include "../pre_order_items_shipping.php";
$decode_pre_order_sub_total = base64_decode($pre_order_sub_total);
}
*/
//Arrays for use in the $post_codes array_push function.
$check_out_postal_codes = array();
$check_out_dist_handle_fee_array = array();
//A loop to seperate the basket string and extract the DB table name,
item number and purchase quantity
foreach($check_out_percent_syms as $items){
//Seperate the basket string into speices to determine which table to
target and perform various DB selects.
$carot = explode("^", "$items");
$asterk = explode("*", "$carot[1]");
$get_shipping_info = mysql_query("select * from $carot[0] where
item_num = '$asterk[0]'");
$shipper_info = mysql_fetch_object($get_shipping_info);
//An if statment to isolate the check out items from the pre-order
items.
if($shipper_info->availability !== "pre-order"){
//Push the postal codes into an array.
array_push($check_out_postal_codes,
$shipper_info->shipper_postal_code);
//Multiply the retail and whole sale items by their perspective
quantities.
$check_out_retail_cost[$shipper_info->distributor] +=
"$shipper_info->retail_price" * "$asterk[1]";
$check_out_wholesale_cost[$shipper_info->distributor] +=
"$shipper_info->wholesale_price" * "$asterk[1]";
$check_out_distributor_weight[$shipper_info->distributor] +=
"$shipper_info->box_weight" * "$asterk[1]";
/*If there are duplicate postal codes and handling fees the items
are probalby from the same distributor and duplicate shipping fees
should not be applicable.
The folowing PHP functions array_unique removes duplicate postal
codes.*/
$check_out_duplicate_postal_codes =
array_values(array_unique($check_out_postal_codes));
//Strings for the shipping calculator.
$first_codes = "POST /using/services/rave/qcost_dss.cgi
HTTP/1.0\n";
$first_codes .= "Content-type:
application/x-www-form-urlencoded\n";
//Notice that the content length is inside of a loop bellow.
$second_codes = "AppVersion=1.2&";
$second_codes .= "AcceptUPSLicenseAgreement=YES&";
$second_codes .= "ResponseType=application/x-ups-rss&";
$second_codes .= "ActionCode=3&";
$second_codes .= "ServiceLevelCode=$ship_method&";
$second_codes .= "RateChart=Regular+Daily+Pickup&";
//Notice that the shipper postal code is inside of a loop bellow.
$third_codes = "ConsigneePostalCode=$ship_postal_code&";
$third_codes .= "ConsigneeCountry=$ship_country&";
//Notice that the weight is inside of a loop bellow.
//In a previous page I have a company text field to determine if the
shipping destination is residential or commercial.
if($ship_company != "") {
$fourth_codes = "ResidentialInd=0&";
}
else{$fourth_codes .= "ResidentialInd=1&";}
$fourth_codes .= "PackagingType=00\n\n";
}//END FIRST FOREACH LOOP.
}//END FIRST IF STATEMENT
//A SECOND IF STATEMENT TO DETERMINE IF GENERATING A SHIPPING RATE IS
NECESSARY.
if(isset($check_out_duplicate_postal_codes)){
foreach($check_out_duplicate_postal_codes as
$check_out_postal_code){
$get_dist_info = mysql_query("select * from distributors where
dist_ship_postal_code = '$check_out_postal_code'");
$dist_info = mysql_fetch_object($get_dist_info);
mysql_free_result($get_dist_info);
//The list function is used inside of a if statement to determin if
multile distributors are present and to
//extract the weight per distribtor. The $value variable is the
actual weight.
if(count($check_out_distributor_weight) <= "1"){
$value = $check_out_distributor_weight[$dist_info->dist_code];
}
elseif(count($check_out_distributor_weight) > "1" ){
list(,$value) = each($check_out_distributor_weight);
}
//A series of ifelse statments for use with the contentlengt. The
starting lavue of 265 is an educated guess of a begining
contentlength.
if(strlen($value) == "1"){
$length = "265"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "2"){
$length = "266"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "3"){
$length = "267"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "4"){
$length = "268"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "5"){
$length = "269"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "6"){
$length = "270"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "7"){
$length = "271"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "8"){
$length = "272"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "9"){
$length = "273"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "10"){
$length = "274"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "11"){
$length = "275"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "12"){
$length = "276"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "13"){
$length = "277"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "14"){
$length = "278"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "15"){
$length = "279"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "16"){
$length = "280"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "17"){
$length = "281"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "18"){
$length = "82"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "19"){
$length = "283"+(strlen($ship_postal_code));
}
elseif(strlen($value) == "20"){
$length = "284"+(strlen($ship_postal_code));
}
//All of the above codes are joined together. The $all_codes
variable will be POSTED to the
www.ups.com/using/services/rave/qcost_dss.cgi file.
$all_codes = "$first_codes"."Content-length:
$length\n\n"."$second_codes"."ShipperPostalCode=$dist_info->dist_ship_postal_code&"."$third_codes"."PackageActualWeight=$value&"."$fourth_codes";
//Open a socket to ups.com to get shipping rates.
$open_sock = fsockopen("www.ups.com",80, $errno, $errstr,30);
if(!($open_sock)){
die(header("location:
http://$none_secured_domain/shipping_error.php?ship_method=$ship_method&ups=false"));
}
else {
while(!(feof($open_sock))){
fputs($open_sock, $all_codes);
while($line = fgets($open_sock, 1000)){
$contents .= $line;
$check_out_find_rate = explode("%", $contents);
break;
}
}
}
//if the shipping rate can not be found the script dies and directs
the user to a error page.
if($check_out_find_rate[14] == false){
fclose($open_sock);
mysql_close($connect);
die(header("location:
http://$none_secured_domain/shipping_error.php?ship_method=$ship_method"));
}
//Use this variable string to store the shipping cost for each
distcode in a $key.
//Example: $check_out_dist_ups_rates[abc] will print $0.00.
$check_out_dist_ups_rates[$dist_info->dist_code] +=
"$check_out_find_rate[14]";
//Increment the ups rate to add all of the UPS shipping charges.
$check_out_ship_rate += $check_out_find_rate[14];
//This script has problems with not over writting $contents so the
unset function is used to clear out the $contents variable.
unset($contents);
fclose($open_sock);
}//END FOREACH LOOP
//Loop through each wholesale price to determine if a handling fee
is applicable and to obtain the per item
//wholesale cost and per distributor handling fee(s).
//The $value variable represents a Distributors minmum order dollare
amount that will be aplied unless
//a order oabove the minimum. Example: Techdata charges $5.00 per
customer address unless the order excedds $500.00.
while(list($key, $value) = each ($check_out_wholesale_cost)){
$check_out_wholesale .= "$key"."_"."$value"."%";
$get_handling_fee_minimum = mysql_query("select * from distributors
where dist_code = '$key'");
$handling_fee = mysql_fetch_object($get_handling_fee_minimum);
mysql_free_result($get_handling_fee_minimum);
if("$value" < "$handling_fee->dist_shipp_minimum"){
$check_out_ship_fee += "$handling_fee->dist_shipp_fee";
}
}
//Cut the last percent character off of the strings above.
//$check_out_dist_handle_fee_string =
substr("$check_out_dist_handle_fee", 0,
strlen($check_out_dist_handle_fee)-1);
$check_out_wholesale_items_cost_string =
substr("$check_out_wholesale", 0, strlen($wholesale)-1);
//Loop through each retail price to extract the retail cost per
item.
while(list($key, $value) = each ($check_out_retail_cost)){
$check_out_retail .= "$key"."_"."$value"."%";
}
//Cut the last percent character off of the $check_out_retail
above.
$check_out_retail_items_cost_string = substr("$check_out_retail", 0,
strlen($retail)-1);
//Loop throught the UPS rates to extract the UPS shipping rates per
distributor and to assemble
//string to represent the distributor handling fees.
while(list($key, $value) = each ($check_out_dist_ups_rates)){
$check_out_ups .= "$key"."_"."$value"."%";
$get_dist_check_out_handle_fee = mysql_query("select * from
distributors where dist_code = '$key'") or die(mysql_error());
$check_out_dist_handle_fee =
mysql_fetch_object($get_dist_check_out_handle_fee);
$check_out_dist_handle_fee_string .=
"$key"."_"."$check_out_dist_handle_fee->dist_shipp_fee"."%";
mysql_free_result($get_dist_check_out_handle_fee);
}
//Cut the last percent character off.
$check_out_items_ups_dist_rates = substr("$check_out_ups", 0,
strlen($check_out_ups)-1);
//Add the DISTRIBUTOR HANDLING FEE(S) and the UPS SHIPPING RATE(S) to
calculate a complete SHIPING & HANDLING CHARGE for the customer. This
charge is for CHECK OUT ITEMS only.
$complete_check_out_items_shipping_handling_charge =
bcadd($check_out_ship_rate, $check_out_ship_fee);
}//END IF STATEMENT
?>
#########################END###########################
The way the script works is that the scipt contacts a
www.ups.com/using/services/rave/qcost_dss.cgi server which outputs text
like the one bellow:
#########################START############################
HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Sun, 15 Dec 2002 04:21:03 GMT
Content-type: multipart/mixed;boundary=UPSBOUNDARY
Content-length: 267
Connection: close
POST /using/services/rave/qcost_dss.cgi HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-length: 270
AppVersion=1.2&AcceptUPSLicenseAgreement=YES&ResponseType=application/x-ups-rss&ActionCode=3&ServiceLevelCode=GND&RateChart=Regular+Daily+Pickup&ShipperPostalCode=55428&ConsigneePostalCode=48235&ConsigneeCountry=US&PackageActualWeight=2&ResidentialInd=0&PackagingType=00
<HTML>
<BODY>
</BODY>
</HTML>
--UPSBOUNDARY
Content-type: application/x-ups-rss
Content-length: 78
UPSOnLine%1.2%0000%0000Success%3%GND%55428%US%48235%US%004%2%3.92%0.00%3.92%-1
--UPSBOUNDARY--
###########################END##############################
The script will then join(.=) the text into an array which is exploded
by a % symbol in this case the rate is 3.92 as indicated by $var[14].
Unfortunatly PHP version 4.3.0RC2 only outputes the folowing line:
##############################START#########################
HTTP/1.1 200 OK
##############################END###########################
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=21023&edit=1