Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Shaun E on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Perl SOAP::Lite - FedEx Webservices 1

Status
Not open for further replies.

phoose

Programmer
Jan 24, 2008
2
US
I'm trying to create a client for the fedex web service but I'm having some problems. I'm new to SOAP so it's possible that I'm just doing something wrong. I've tried two different forms of creating the object:

my $wsdl = 'file:./RateService_v2.wsdl';
my $soap = SOAP::Lite->service($wsdl);

and

my $soap = SOAP::Lite->proxy(' ->uri('
The 2nd 'seems' to work better as I actually get data in the response. Also, I noticed that:

"SOAPAction:"

Changes from:

SOAPAction: "getRate"

to:

SOAPAction: "
as well with that change, but the ns definition in the xml seems to disappear.


The data I'm trying to send is more or less an edited for perl version of what I found in the PHP examples on FedEx's site. However, no matter what I try I see two problems:

1: I always get a 500 error: SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Server Error

2: I always get: "Invalid transaction type" as a return error from the server.

If I use the wsdl version of the soap object creation $response is undef, with the manual one it's got values, so I assume that's better. I'm wondering, if these: c-gensym's that are getting generated are causing it to unrecognized by FedEx (I've seen some examples to turn them off with SOAP::Data, but didn't find anything concrete)? Anyways here's the code:

my $soap = SOAP::Lite->proxy(' ->uri('
my %fedExRequest;

$fedExRequest{'WebAuthenticationDetail'}{UserCredential} = {'Key' => 'XXXX', 'Password' => 'XXXX'};
$fedExRequest{'ClientDetail'} = {'AccountNumber' => 'XXXX', 'MeterNumber' => 'XXXX'};

$fedExRequest{'TransactionDetail'} = {'CustomerTransactionId' => '12345'};
$fedExRequest{'Version'} = {'ServiceId' => 'crs', 'Major' => '2', 'Intermediate' => '0', 'Minor' => '0'};
$fedExRequest{'Origin'} = {'StreetLines' => '1111 Main St', # Origin details
'City' => 'Somewhere',
'StateOrProvinceCode' => 'CA',
'PostalCode' => '11111',
'CountryCode' => 'US'};
$fedExRequest{'Destination'} = {'StreetLines' => '22000 2nd St', # Destination details
'City' => 'Somewhereelse',
'StateOrProvinceCode' => 'CA',
'PostalCode' => '22222',
'CountryCode' => 'US'};
$fedExRequest{'Payment'} = {'PaymentType' => 'SENDER'}; # valid codes RECIPIENT, SENDER and THIRD_PARTY
$fedExRequest{'DropoffType'} = 'REGULAR_PICKUP'; # valid codes BUSINESS_SERVICE_CENTER, DROP_BOX, REGULAR_PICKUP, REQUEST_COURIER and STATION
$fedExRequest{'ServiceType'} = 'FEDEX_GROUND'; # valid codes STANDARD_OVERNIGHT, PRIORITY_OVERNIGHT, FEDEX_GROUND, ...
$fedExRequest{'PackagingType'} = 'YOUR_PACKAGING'; # valid codes FEDEX_BOK, FEDEX_PAK, FEDEX_TUBE, YOUR_PACKAGING, ...
$fedExRequest{'ShipDate'} = '2008-01-31';
$fedExRequest{'RateRequestTypes'} = 'ACCOUNT'; # valid codes ACCOUNT, LIST
$fedExRequest{'RateRequestPackageSummary'} = {'TotalWeight' => {'Value' => '20.0', 'Units' => 'LB'}, # valid codes LB and KG
'TotalInsuredValue' => {'Amount' => 100, 'Currency' => 'USD'},
'PieceCount' => 2,
'SpecialServicesRequested' => {'SpecialServiceTypes' => 'APPOINTMENT_DELIVERY'}}; # valid codes HOLD_AT_LOCATION, ...

my $response = $soap->getRate(%fedExRequest);

If I use the wsdl response is undef, otherwise it contains the XML returned from the server in perl data formats (hash of hashes, arrays, strings, etc...) I've also tried:

my $response = $soap->getRate({parameter => %fedExRequest});

This fixes the gensym issue but then a bunch of the data is left in it's perl format when it's sent in XML IE HASH{XXXX}.

Here's the response with trace on:

Content-Type: text/html; charset=ISO-8859-1

SOAP::Transport::HTTP::Client::send_receive: POST HTTP/1.1
Accept: text/xml
Accept: multipart/*
Accept: application/soap
Content-Length: 3194
Content-Type: text/xml; charset=utf-8
SOAPAction: "
<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:xsi=" xmlns:soapenc=" xmlns:xsd=" soap:encodingStyle=" xmlns:soap=" xmlns=" xsi:type="xsd:string">RateRequestTypes</c-gensym3><c-gensym5 xsi:type="xsd:string">ACCOUNT</c-gensym5><c-gensym7 xsi:type="xsd:string">DropoffType</c-gensym7><c-gensym9 xsi:type="xsd:string">REGULAR_PICKUP</c-gensym9><c-gensym11 xsi:type="xsd:string">ServiceType</c-gensym11><c-gensym13 xsi:type="xsd:string">FEDEX_GROUND</c-gensym13><c-gensym15 xsi:type="xsd:string">RateRequestPackageSummary</c-gensym15><c-gensym17><SpecialServicesRequested><SpecialServiceTypes xsi:type="xsd:string">APPOINTMENT_DELIVERY</SpecialServiceTypes></SpecialServicesRequested><PieceCount xsi:type="xsd:int">2</PieceCount><TotalInsuredValue><Amount xsi:type="xsd:int">100</Amount><Currency xsi:type="xsd:string">USD</Currency></TotalInsuredValue><TotalWeight><Value xsi:type="xsd:float">20.0</Value><Units xsi:type="xsd:string">LB</Units></TotalWeight></c-gensym17><c-gensym19 xsi:type="xsd:string">ClientDetail</c-gensym19><c-gensym21><AccountNumber xsi:type="xsd:int">XXXXXXXX</AccountNumber><MeterNumber xsi:type="xsd:int">XXXXXXXXXXXX</MeterNumber></c-gensym21><c-gensym23 xsi:type="xsd:string">Destination</c-gensym23><c-gensym25><PostalCode xsi:type="xsd:int">22222</PostalCode><StateOrProvinceCode xsi:type="xsd:string">CA</StateOrProvinceCode><City xsi:type="xsd:string">Somewhereelse</City><CountryCode xsi:type="xsd:string">US</CountryCode><StreetLines xsi:type="xsd:string">22000 2nd St</StreetLines></c-gensym25><c-gensym27 xsi:type="xsd:string">ShipDate</c-gensym27><c-gensym29 xsi:type="xsd:date">2008-01-31</c-gensym29><c-gensym31 xsi:type="xsd:string">PackagingType</c-gensym31><c-gensym33 xsi:type="xsd:string">YOUR_PACKAGING</c-gensym33><c-gensym35 xsi:type="xsd:string">Version</c-gensym35><c-gensym37><Minor xsi:type="xsd:int">0</Minor><Major xsi:type="xsd:int">2</Major><Intermediate xsi:type="xsd:int">0</Intermediate><ServiceId xsi:type="xsd:string">crs</ServiceId></c-gensym37><c-gensym39 xsi:type="xsd:string">Payment</c-gensym39><c-gensym41><PaymentType xsi:type="xsd:string">SENDER</PaymentType></c-gensym41><c-gensym43 xsi:type="xsd:string">Origin</c-gensym43><c-gensym45><PostalCode xsi:type="xsd:int">11111</PostalCode><StateOrProvinceCode xsi:type="xsd:string">CA</StateOrProvinceCode><City xsi:type="xsd:string">Somewhere</City><CountryCode xsi:type="xsd:string">US</CountryCode><StreetLines xsi:type="xsd:string">1111 Main St</StreetLines></c-gensym45><c-gensym47 xsi:type="xsd:string">WebAuthenticationDetail</c-gensym47><c-gensym49><UserCredential><Password xsi:type="xsd:string">XXXXXXXXX</Password><Key xsi:type="xsd:string">XXXXXXXXX</Key></UserCredential></c-gensym49><c-gensym51 xsi:type="xsd:string">TransactionDetail</c-gensym51><c-gensym53><CustomerTransactionId xsi:type="xsd:int">12345</CustomerTransactionId></c-gensym53></getRate></soap:Body></soap:Envelope>
SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Server Error
Connection: close
Date: Fri, 25 Jan 2008 06:37:30 GMT
Server: Sun-ONE-Web-Server/6.1
Content-Length: 543
Content-Type: text/xml; charset=utf-8
Client-Date: Fri, 25 Jan 2008 06:37:30 GMT
Client-Peer: X.X.X.X:443
Client-Response-Num: 1
Client-SSL-Cert-Issuer: /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at (c)06/CN=VeriSign Class 3 Extended Validation SSL CA
Client-SSL-Cert-Subject: /1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/2.5.4.15=V1.0, Clause 5.(b)/serialNumber=2803030/C=US/2.5.4.17=38017/ST=Tennessee/L=Collierville/2.5.4.9=80 Fedex Parkway 1st FL H/O=FedEx Corporation/OU=BST/CM/CN=gatewaybeta.fedex.com
Client-SSL-Cipher: RC4-MD5
Client-SSL-Warning: Peer certificate not verified
X-Powered-By: Servlet/2.4 JSP/2.0

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv=" xmlns:soap=" Invalid transaction type</faultstring><detail><con:fault xmlns:con=" transaction type. Transaction could not be routed.</con:reason></con:fault></detail></soap:Fault></soap:Body></soapenv:Envelope>


STATUS:

A fault (soap:Server) occured: 1: Invalid transaction type


Any Ideas?
 
Hello Phoose- Have you gotten anywhere with this? I just spent much to long working it and it seems I've run the same course as you.
 
Actually yes I did. It turns out that WSDL support in perl is not very good. Right now I'm only doing a very simple call to FedEx so I just loaded the xml into my script and interpolated my variables into it. In addition FexEx also released a new version of their web services with different XML data. My current solution isn't using the SOAP module anymore instead I'm using LWP directly to FedEx and reading the response with XML::Simple. Something like this may work for you:

!!WARNING: This is partial code snippets from a much larger script, I haven't tested this as is, but this should help you along. Let me know if it doesn't work out

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common;
use XML::Simple;

my %shippingParams = (
PROVIDER => 'FedEx',
SOURCE_COUNTRY => 'US',
SOURCE_ADDR1 => 'Street Addr1',
SOURCE_CITY => 'Source City',
SOURCE_STATE => 'CA',
SOURCE_ZIP => '90210',
DEST_COUNTRY => 'US',
DEST_ADDR1 => 'Dest Addr1',
DEST_ADDR2 => 'Dest Addr2',
DEST_CITY => 'Dest City',
DEST_STATE => 'DC',
DEST_ZIP => '20007',
AMT_PACKAGES => '1',
WEIGHT_UNITS => 'LB',
WEIGHT => '5',
SHIP_DATE => '2008-03-01',
ACTION => 'rateAvailableServices',
);
my $SOAPRequest = generateSOAP(\%shippingParams);

my $userAgent = LWP::UserAgent->new(agent => 'perlScript');

my $response = $userAgent->request(POST ' Content_Type => 'text/xml',
Content => $SOAPRequest);

if ($response->is_success) {
my $responseXML;
my $isXML = 0;
my @responseArray = split("\n", $response->as_string);
foreach my $line (@responseArray) {
if ($isXML) {
$responseXML .= $line;
}
elsif ($line =~ /\<\?xml.*/) {
$isXML = 1;
$responseXML .= $line;
}
}

my $xml = new XML::Simple;
my $data = $xml->XMLin($responseXML);

==============

$data will now contain a perl data structure of the XML response so you access it like any other perl data structure IE:

my $highestSeverity = $data->{'soapenv:Body'}->{'RateAvailableServicesReply'}->{'HighestSeverity'};

my $serverFault = $data->{'soapenv:Body'}->{'soap:Fault'}->{'faultcode'};

using this method all of the available shipping options would be returned in:

my @options = @{$data->{'soapenv:Body'}->{'RateAvailableServicesReply'}->{'Options'}};

Data::Dumper comes in very here as well as your looking for different responses.

The actual soap data I'm using is contained in a sub which you pass a hashRef containing all the data it looks like this:

sub generateSOAP {

my $params = shift;

my $soapRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>
<soapenv:Envelope xmlns:soapenv=\" xmlns:SOAP-ENC=\" xmlns:xsi=\" xmlns:xsd=\" <soapenv:Body>
<RateAvailableServicesRequest xmlns=\" <WebAuthenticationDetail>
<UserCredential>
<Key>__YOUR__KEY__</Key>
<Password>__YOUR__PASSWORD__</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>__YOUR_ACCOUNT_NUMBER__</AccountNumber>
<MeterNumber>__YOUR__METER__NUMBER__</MeterNumber>
</ClientDetail>
<TransactionDetail>
<CustomerTransactionId>Rate Test</CustomerTransactionId>
</TransactionDetail>
<Version>
<ServiceId>crs</ServiceId>
<Major>3</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<Origin>
<StreetLines>" . $params->{'SOURCE_ADDR1'} . "</StreetLines>
<City>" . $params->{'SOURCE_CITY'} . "</City>
<StateOrProvinceCode>" . $params->{'SOURCE_STATE'} . "</StateOrProvinceCode>
<PostalCode>" . $params->{'SOURCE_ZIP'} . "</PostalCode>
<CountryCode>" . $params->{'SOURCE_COUNTRY'} . "</CountryCode>
</Origin>
<Destination>
<StreetLines>" . $params->{'DEST_ADDR1'} . "</StreetLines>";
if ($params->{'DEST_ADDR2'}) {
$soapRequest .= "<StreetLines>" . $params->{'DEST_ADDR2'} . "</StreetLines>";
}
$soapRequest .= "<City>" . $params->{'DEST_CITY'} . "</City>
<StateOrProvinceCode>" . $params->{'DEST_STATE'} . "</StateOrProvinceCode>
<PostalCode>" . $params->{'DEST_ZIP'} . "</PostalCode>
<CountryCode>" . $params->{'DEST_COUNTRY'} . "</CountryCode>
</Destination>
<ShipDate>" . $params->{'SHIP_DATE'} . "</ShipDate>
<RateRequestPackageSummary>
<PieceCount>" . $params->{'AMT_PACKAGES'} . "</PieceCount>
<TotalWeight>
<Units>" . $params->{'WEIGHT_UNITS'} . "</Units>
<Value>" . $params->{'WEIGHT'} . "</Value>
</TotalWeight>
</RateRequestPackageSummary>
</RateAvailableServicesRequest>
</soapenv:Body>
</soapenv:Envelope>";
}

$soapRequest =~ s/\n//g;
return $soapRequest;

}
 
This is very helpful. I was starting to get the feeling that the perl wsdl support wasn't all there. Thanks-
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top