Hi
I have a shopping cart written in perl. I need to install a real-time shipping script to get data from Canada Post server but I have no idea how to do this. Canada Post server uses XML without API. My shopping cart came with USPS script, here is the script of USPS and the file of Canada Post (xml). Hopefully someone will be able to help me with this.
Thanks
Frank webmaster@fludan.com
USPS Script
**********************************************
package Business::USPS;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require 5.003;
require Exporter;
@ISA = qw(Exporter AutoLoader);
#########
######### Items to export into callers namespace by default.
######### Note: do not export names by default without a
######### very good reason. Use EXPORT_OK instead. Do not simply
######### export all your public functions/methods/constants.
#########
@EXPORT = qw(
getUSPSdom
getUSPSint
);
#########
######### Copyright 2002 Nick Hendler <webmaster@kryptronic.com>
######### See GNU GPL. This work is derived from the excellent
######### module Business::UPS which is Copyright 1998 Mark Solomon
######### <msolomon@seva.net>. Major mods include the use of
######### HTTP::Request::Common and the post method to handle
######### the post/response. Also, USPS uses XML but does not
######### require XML:
arser.
#########
######### This module was written as part of the development
######### of the ClickCartPro Version 5 (CCP5) e-commerce
######### application. For details, please visit:
######### or
######### #########
#########
######### Version must be all one line, for MakeMaker.
#########
$VERSION = do { my @r = (q$Revision: 1.00 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
#######################################################################
# getUSPSdom #
#######################################################################
sub getUSPSdom {
#########
######### This routine gets domestic (US to US) USPS rates.
#########
my ($merchantCPID,$url,$ziporigin,$zipdest,$pounds) = @_;
my $api = "Rate";
my $pkgid = "0";
my $container = "None";
my $size = "Regular";
my $machinable = "False";
my $ounces = "";
($pounds,$ounces) = getweight($pounds);
my $xml = "<eparcel merchantCPID=\"$merchantCPID\"><fromPostalCode>$ziporigin</fromPostalCode><postalCode>$zipdest</postalCode><Weight>$pounds<Weight></eparcel>";
$xml = encode($xml);
my ($return_status,$return_service,$return_postage) = handleconnectdom($url,$api,$xml);
return ($return_status,$return_service,$return_postage);
} ######### End of subroutine.
#######################################################################
# getUSPSint #
#######################################################################
sub getUSPSint {
#########
######### This routine gets international (US to Non-US) USPS rates.
#########
my ($username,$password,$url,$country,$pounds) = @_;
my $api = "IntlRate";
my $mailtype = "Package";
my $pkgid = "0";
my $ounces = "";
($pounds,$ounces) = getweight($pounds);
my $xml = "<IntlRateRequest USERID=\"$username\" PASSWORD=\"$password\"><Package ID=\"$pkgid\"><Pounds>$pounds</Pounds><Ounces>$ounces</Ounces><MailType>$mailtype</MailType><Country>$country</Country></Pakage></IntlRateRequest>";
$xml = encode($xml);
my ($return_status,@return_service) = handleconnectint($url,$api,$xml);
return ($return_status,@return_service);
} ######### End of subroutine.
#######################################################################
# GetWeight #
#######################################################################
sub getweight {
#########
######### This routine handles the calculation of total pounds
######### and ounces from a decimal based pounds number.
#########
my $pounds = shift;
my $ounces = "";
my $whole_pounds = sprintf("%.0f", $pounds);
my $partial_pounds = "0";
if ($whole_pounds > "$pounds"
{
$whole_pounds = ($whole_pounds - 1);
} ######### End of if statement.
my $partial_pounds = ($pounds - $whole_pounds);
if ($partial_pounds eq "0"
{
$ounces = "0";
} else {
$ounces = (16 * $partial_pounds);
$ounces = sprintf("%.0f", $ounces);
} ######### End of if statement.
return ($whole_pounds,$ounces);
} ######### End of subroutine.
#######################################################################
# Encode #
#######################################################################
sub encode {
#########
######### This routine handles the mime encoding of the XML string
######### for posting to the USPS URL.
#########
$_ = shift;
s/\|//gs;
s/\n//gs;
return $_;
} ######### End of subroutine.
#######################################################################
# HandleConnectDom #
#######################################################################
sub handleconnectdom {
#########
######### This routine handles the connection to the USPS server and
######### the parsing of the XML response.
#########
my ($url,$api,$xml) = @_;
my $return_status = "";
my $return_service = "";
my $return_postage = "";
#########
######### Make the connection to the USPS server.
#########
my $field_api = "API";
my $field_xml = "XML";
my $ua = LWP::UserAgent->new;
my $response = $ua->request(POST $url,
[$field_api => $api,
$field_xml => $xml]);
#########
######### If the response is a success, we parse the output
######### as XML and return the service name and price.
#########
if ($response->is_success) {
my $reply = $response->content;
#########
######### Get information from the Service node.
#########
$reply =~ s/<Service>(.*?)<\/Service>//gs;
$return_service = "$1";
#########
######### Get information from the Postage node.
#########
$reply =~ s/<Postage>(.*?)<\/Postage>//gs;
$return_postage = "$1";
#########
######### Base our return value on whether we
######### have a failure or not.
#########
if ($return_service eq "" || $return_postage eq ""
{
$return_status = "FAIL_ERROR";
} else {
$return_status = "ACCEPT";
} ######### End of if statement.
#########
######### If there was no response, we return an error.
#########
} else {
$return_status = "FAIL_CONNECT";
} ######### End of if statement.
return ($return_status,$return_service,$return_postage);
} ######### End of subroutine.
#######################################################################
# HandleConnectInt #
#######################################################################
sub handleconnectint {
#########
######### This routine handles the connection to the USPS server and
######### the parsing of the XML response.
#########
my ($url,$api,$xml) = @_;
my $return_status = "";
my $return_service = "";
my $return_postage = "";
my @return_service = ();
my @return_servicedet = ();
my $reply_prefix = "";
my $reply_id = "";
my $reply_contents = "";
#########
######### Make the connection to the USPS server.
#########
my $field_api = "API";
my $field_xml = "XML";
my $ua = LWP::UserAgent->new;
my $response = $ua->request(POST $url,
[$field_api => $api,
$field_xml => $xml]);
#########
######### If the response is a success, we parse the output
######### as XML and return the service name and price.
#########
if ($response->is_success) {
my $reply = $response->content;
while ($reply =~ /<Service ID=".*?">.*?<\/Service>/) {
@return_servicedet = ();
$reply =~ s/^(.*?)<Service ID="(.*?)">(.*?)<\/Service>//s;
$reply_prefix = "$1";
$reply_id = "$2";
$reply_contents = "$3";
#########
######### Get information from the SvcDescription node.
#########
$reply_contents =~ s/<SvcDescription>(.*?)<\/SvcDescription>//gs;
$return_service = "$1";
#########
######### Get information from the Postage node.
#########
$reply_contents =~ s/<Postage>(.*?)<\/Postage>//gs;
$return_postage = "$1";
if ($return_service ne "" && $return_postage ne ""
{
@return_servicedet = ($return_service,$return_postage);
push(@return_service,[@return_servicedet]);
} ######### End of if statement.
} ######### End of while statement.
#########
######### Base our return value on whether we
######### have a failure or not.
#########
if (!(@return_service)) {
$return_status = "FAIL_ERROR";
} else {
@return_service = reverse(@return_service);
$return_status = "ACCEPT";
} ######### End of if statement.
#########
######### If there was no response, we return an error.
#########
} else {
$return_status = "FAIL_CONNECT";
} ######### End of if statement.
return ($return_status,@return_service);
} ######### End of subroutine.
#######################################################################
# Return True Value For End Of File #
#######################################################################
END {}
1;
__END__
=head1 NAME
Business::USPS - A USPS Interface Module
=head1 AUTHOR
Nick Hendler <webmaster@kryptronic.com>
mailto:webmaster@kryptronic.com
NOTE: USPS is a registered trademark of the United States
Postal Service.
=head1 SEE ALSO
perl(1).
=cut
******************************************
Canada Post File
******************************************
<?xml version="1.0" ?>
- <!--
***********************************************************************
This file is an example of XML file sent to the Sell Online server
to get the shipping rates and delivery dates of a shopping bag.
It is sent to Sell Online by opening a TCP socket port on:
IP address : 206.191.4.228
TCP Port : 30000
You can use an HTTP POST and submit this XML document to the server
(same IP and same TCP Port). We highly recommand you to open this url
to see an interactive example of the HTTP POST:
Note: The address below is for test purpose. If your web site
is going live, please contact eparcel@canadapost.ca to get the
IP address of our production server (or look at the FAQ)
***********************************************************************
-->
<!DOCTYPE eparcel (View Source for full doctype...)>
- <eparcel>
- <!--
************************************
* Language of choice :
* en=ENGLISH
* fr=FRENCH
* Note: This parameter is OPTIONAL (english = default)
************************************
-->
<language>en</language>
- <ratesAndServicesRequest>
- <!--
************************************
* Merchant ID assigned by Canada Post
* If you don't have one, send a request
* to eparcel@canadapost.ca
* Note: The merchant ID is used by the Sell Online
* server to retrieve the :
* - list of boxes used to pack the items
* - origin postal code
* - ...
************************************
-->
<merchantCPCID>{Insert your merchant ID here}</merchantCPCID>
- <!--
**********************************
From Postal Code.
This parameter will overwrite the one
defined in the merchant's profile
Note: This parameter is OPTIONAL
**********************************
-->
<fromPostalCode>{Insert the postal code your are shipping from}</fromPostalCode>
- <!--
**********************************
Turnaroundtime in hours
If declared here, this parameter will
overwrite the one
defined in the merchant's profile
Note: This parameter is OPTIONAL
**********************************
-->
<turnAroundTime>{Insert your turnaround time}</turnAroundTime>
- <!--
************************************
Total price of the items in this request.
Price is in CA$ and should not include
taxes.
The items price is used to calculate
the insurance and signature fees.
Note: This parameter is OPTIONAL
************************************
-->
<itemsPrice>{Insert items $ here}</itemsPrice>
- <!--
************************************
* Insert here the items in the shopping basket
* The example below show 2 different items
* Each item has the following attributes:
* - Quantity
* - Weight in kg
* - Length, Width and Height in cm
* - Description
************************************
-->
- <lineItems>
- <item>
- <!--
************************************
Item #1 (ordered 3 times)
************************************
-->
<quantity>3</quantity>
<weight>0.6</weight>
<length>10.0</length>
<width>25.0</width>
<height>5.0</height>
<description>My Item #1</description>
</item>
- <item>
- <!--
************************************
Item #2 (ordered 1 time)
************************************
-->
<quantity>3</quantity>
<weight>0.2</weight>
<length>5.0</length>
<width>2.0</width>
<height>1.0</height>
<description>My Item #2</description>
</item>
</lineItems>
- <!--
************************************
Address of destination
(*) For a canadian destination, 'country' and 'postalCode' have
to be valid ('city', 'provOrState' are not used).
(*) For a US destination, 'country' and 'provOrState' have
to be valid. ('city', 'postalCode' are not used for now but zip
code will be used in the future). State can be either full state
name or state code.
(*) For an International destination, only 'country' has
to be valid ('city', 'postalCode' and 'provOrState' are not used).
Country can be fullname or 2-letters country code (ISO 3166)
************************************
-->
<city>Longueuil</city>
<provOrState>Quebec</provOrState>
<country>Canada</country>
<postalCode>J9J1K1</postalCode>
</ratesAndServicesRequest>
</eparcel>
I have a shopping cart written in perl. I need to install a real-time shipping script to get data from Canada Post server but I have no idea how to do this. Canada Post server uses XML without API. My shopping cart came with USPS script, here is the script of USPS and the file of Canada Post (xml). Hopefully someone will be able to help me with this.
Thanks
Frank webmaster@fludan.com
USPS Script
**********************************************
package Business::USPS;
use HTTP::Request::Common qw(POST);
use LWP::UserAgent;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
require 5.003;
require Exporter;
@ISA = qw(Exporter AutoLoader);
#########
######### Items to export into callers namespace by default.
######### Note: do not export names by default without a
######### very good reason. Use EXPORT_OK instead. Do not simply
######### export all your public functions/methods/constants.
#########
@EXPORT = qw(
getUSPSdom
getUSPSint
);
#########
######### Copyright 2002 Nick Hendler <webmaster@kryptronic.com>
######### See GNU GPL. This work is derived from the excellent
######### module Business::UPS which is Copyright 1998 Mark Solomon
######### <msolomon@seva.net>. Major mods include the use of
######### HTTP::Request::Common and the post method to handle
######### the post/response. Also, USPS uses XML but does not
######### require XML:
#########
######### This module was written as part of the development
######### of the ClickCartPro Version 5 (CCP5) e-commerce
######### application. For details, please visit:
######### or
######### #########
#########
######### Version must be all one line, for MakeMaker.
#########
$VERSION = do { my @r = (q$Revision: 1.00 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
#######################################################################
# getUSPSdom #
#######################################################################
sub getUSPSdom {
#########
######### This routine gets domestic (US to US) USPS rates.
#########
my ($merchantCPID,$url,$ziporigin,$zipdest,$pounds) = @_;
my $api = "Rate";
my $pkgid = "0";
my $container = "None";
my $size = "Regular";
my $machinable = "False";
my $ounces = "";
($pounds,$ounces) = getweight($pounds);
my $xml = "<eparcel merchantCPID=\"$merchantCPID\"><fromPostalCode>$ziporigin</fromPostalCode><postalCode>$zipdest</postalCode><Weight>$pounds<Weight></eparcel>";
$xml = encode($xml);
my ($return_status,$return_service,$return_postage) = handleconnectdom($url,$api,$xml);
return ($return_status,$return_service,$return_postage);
} ######### End of subroutine.
#######################################################################
# getUSPSint #
#######################################################################
sub getUSPSint {
#########
######### This routine gets international (US to Non-US) USPS rates.
#########
my ($username,$password,$url,$country,$pounds) = @_;
my $api = "IntlRate";
my $mailtype = "Package";
my $pkgid = "0";
my $ounces = "";
($pounds,$ounces) = getweight($pounds);
my $xml = "<IntlRateRequest USERID=\"$username\" PASSWORD=\"$password\"><Package ID=\"$pkgid\"><Pounds>$pounds</Pounds><Ounces>$ounces</Ounces><MailType>$mailtype</MailType><Country>$country</Country></Pakage></IntlRateRequest>";
$xml = encode($xml);
my ($return_status,@return_service) = handleconnectint($url,$api,$xml);
return ($return_status,@return_service);
} ######### End of subroutine.
#######################################################################
# GetWeight #
#######################################################################
sub getweight {
#########
######### This routine handles the calculation of total pounds
######### and ounces from a decimal based pounds number.
#########
my $pounds = shift;
my $ounces = "";
my $whole_pounds = sprintf("%.0f", $pounds);
my $partial_pounds = "0";
if ($whole_pounds > "$pounds"
$whole_pounds = ($whole_pounds - 1);
} ######### End of if statement.
my $partial_pounds = ($pounds - $whole_pounds);
if ($partial_pounds eq "0"
$ounces = "0";
} else {
$ounces = (16 * $partial_pounds);
$ounces = sprintf("%.0f", $ounces);
} ######### End of if statement.
return ($whole_pounds,$ounces);
} ######### End of subroutine.
#######################################################################
# Encode #
#######################################################################
sub encode {
#########
######### This routine handles the mime encoding of the XML string
######### for posting to the USPS URL.
#########
$_ = shift;
s/\|//gs;
s/\n//gs;
return $_;
} ######### End of subroutine.
#######################################################################
# HandleConnectDom #
#######################################################################
sub handleconnectdom {
#########
######### This routine handles the connection to the USPS server and
######### the parsing of the XML response.
#########
my ($url,$api,$xml) = @_;
my $return_status = "";
my $return_service = "";
my $return_postage = "";
#########
######### Make the connection to the USPS server.
#########
my $field_api = "API";
my $field_xml = "XML";
my $ua = LWP::UserAgent->new;
my $response = $ua->request(POST $url,
[$field_api => $api,
$field_xml => $xml]);
#########
######### If the response is a success, we parse the output
######### as XML and return the service name and price.
#########
if ($response->is_success) {
my $reply = $response->content;
#########
######### Get information from the Service node.
#########
$reply =~ s/<Service>(.*?)<\/Service>//gs;
$return_service = "$1";
#########
######### Get information from the Postage node.
#########
$reply =~ s/<Postage>(.*?)<\/Postage>//gs;
$return_postage = "$1";
#########
######### Base our return value on whether we
######### have a failure or not.
#########
if ($return_service eq "" || $return_postage eq ""
$return_status = "FAIL_ERROR";
} else {
$return_status = "ACCEPT";
} ######### End of if statement.
#########
######### If there was no response, we return an error.
#########
} else {
$return_status = "FAIL_CONNECT";
} ######### End of if statement.
return ($return_status,$return_service,$return_postage);
} ######### End of subroutine.
#######################################################################
# HandleConnectInt #
#######################################################################
sub handleconnectint {
#########
######### This routine handles the connection to the USPS server and
######### the parsing of the XML response.
#########
my ($url,$api,$xml) = @_;
my $return_status = "";
my $return_service = "";
my $return_postage = "";
my @return_service = ();
my @return_servicedet = ();
my $reply_prefix = "";
my $reply_id = "";
my $reply_contents = "";
#########
######### Make the connection to the USPS server.
#########
my $field_api = "API";
my $field_xml = "XML";
my $ua = LWP::UserAgent->new;
my $response = $ua->request(POST $url,
[$field_api => $api,
$field_xml => $xml]);
#########
######### If the response is a success, we parse the output
######### as XML and return the service name and price.
#########
if ($response->is_success) {
my $reply = $response->content;
while ($reply =~ /<Service ID=".*?">.*?<\/Service>/) {
@return_servicedet = ();
$reply =~ s/^(.*?)<Service ID="(.*?)">(.*?)<\/Service>//s;
$reply_prefix = "$1";
$reply_id = "$2";
$reply_contents = "$3";
#########
######### Get information from the SvcDescription node.
#########
$reply_contents =~ s/<SvcDescription>(.*?)<\/SvcDescription>//gs;
$return_service = "$1";
#########
######### Get information from the Postage node.
#########
$reply_contents =~ s/<Postage>(.*?)<\/Postage>//gs;
$return_postage = "$1";
if ($return_service ne "" && $return_postage ne ""
@return_servicedet = ($return_service,$return_postage);
push(@return_service,[@return_servicedet]);
} ######### End of if statement.
} ######### End of while statement.
#########
######### Base our return value on whether we
######### have a failure or not.
#########
if (!(@return_service)) {
$return_status = "FAIL_ERROR";
} else {
@return_service = reverse(@return_service);
$return_status = "ACCEPT";
} ######### End of if statement.
#########
######### If there was no response, we return an error.
#########
} else {
$return_status = "FAIL_CONNECT";
} ######### End of if statement.
return ($return_status,@return_service);
} ######### End of subroutine.
#######################################################################
# Return True Value For End Of File #
#######################################################################
END {}
1;
__END__
=head1 NAME
Business::USPS - A USPS Interface Module
=head1 AUTHOR
Nick Hendler <webmaster@kryptronic.com>
mailto:webmaster@kryptronic.com
NOTE: USPS is a registered trademark of the United States
Postal Service.
=head1 SEE ALSO
perl(1).
=cut
******************************************
Canada Post File
******************************************
<?xml version="1.0" ?>
- <!--
***********************************************************************
This file is an example of XML file sent to the Sell Online server
to get the shipping rates and delivery dates of a shopping bag.
It is sent to Sell Online by opening a TCP socket port on:
IP address : 206.191.4.228
TCP Port : 30000
You can use an HTTP POST and submit this XML document to the server
(same IP and same TCP Port). We highly recommand you to open this url
to see an interactive example of the HTTP POST:
Note: The address below is for test purpose. If your web site
is going live, please contact eparcel@canadapost.ca to get the
IP address of our production server (or look at the FAQ)
***********************************************************************
-->
<!DOCTYPE eparcel (View Source for full doctype...)>
- <eparcel>
- <!--
************************************
* Language of choice :
* en=ENGLISH
* fr=FRENCH
* Note: This parameter is OPTIONAL (english = default)
************************************
-->
<language>en</language>
- <ratesAndServicesRequest>
- <!--
************************************
* Merchant ID assigned by Canada Post
* If you don't have one, send a request
* to eparcel@canadapost.ca
* Note: The merchant ID is used by the Sell Online
* server to retrieve the :
* - list of boxes used to pack the items
* - origin postal code
* - ...
************************************
-->
<merchantCPCID>{Insert your merchant ID here}</merchantCPCID>
- <!--
**********************************
From Postal Code.
This parameter will overwrite the one
defined in the merchant's profile
Note: This parameter is OPTIONAL
**********************************
-->
<fromPostalCode>{Insert the postal code your are shipping from}</fromPostalCode>
- <!--
**********************************
Turnaroundtime in hours
If declared here, this parameter will
overwrite the one
defined in the merchant's profile
Note: This parameter is OPTIONAL
**********************************
-->
<turnAroundTime>{Insert your turnaround time}</turnAroundTime>
- <!--
************************************
Total price of the items in this request.
Price is in CA$ and should not include
taxes.
The items price is used to calculate
the insurance and signature fees.
Note: This parameter is OPTIONAL
************************************
-->
<itemsPrice>{Insert items $ here}</itemsPrice>
- <!--
************************************
* Insert here the items in the shopping basket
* The example below show 2 different items
* Each item has the following attributes:
* - Quantity
* - Weight in kg
* - Length, Width and Height in cm
* - Description
************************************
-->
- <lineItems>
- <item>
- <!--
************************************
Item #1 (ordered 3 times)
************************************
-->
<quantity>3</quantity>
<weight>0.6</weight>
<length>10.0</length>
<width>25.0</width>
<height>5.0</height>
<description>My Item #1</description>
</item>
- <item>
- <!--
************************************
Item #2 (ordered 1 time)
************************************
-->
<quantity>3</quantity>
<weight>0.2</weight>
<length>5.0</length>
<width>2.0</width>
<height>1.0</height>
<description>My Item #2</description>
</item>
</lineItems>
- <!--
************************************
Address of destination
(*) For a canadian destination, 'country' and 'postalCode' have
to be valid ('city', 'provOrState' are not used).
(*) For a US destination, 'country' and 'provOrState' have
to be valid. ('city', 'postalCode' are not used for now but zip
code will be used in the future). State can be either full state
name or state code.
(*) For an International destination, only 'country' has
to be valid ('city', 'postalCode' and 'provOrState' are not used).
Country can be fullname or 2-letters country code (ISO 3166)
************************************
-->
<city>Longueuil</city>
<provOrState>Quebec</provOrState>
<country>Canada</country>
<postalCode>J9J1K1</postalCode>
</ratesAndServicesRequest>
</eparcel>