I am trying to create a test pickup request using Estes web services. This particular service requires Basic Authentication using my login credentials. However, I can't seem to figure out how to perform the authentication using PHP and SoapClient. I keep getting the following error:
PHP Fatal error: Uncaught SoapFault exception: [soapenv:Client] [ISS.0088.9164] Access to WSDescriptor estesrtpickup.base.ws.provider.soapws:pickupRequestSSL denied.
My last attempt I tried to pass the credentials into WSDL address, but to no avail. Like so:
$client_pickup = new SoapClient('https://USERNAME:PASSWORD#apitest.estes-express.com/tools/pickup/request/v1.0?wsdl');
Here is my current block of PHP code for the Pickup Webservice:
public static function estesFreightPickupRequest($option) {
self::$ShipToCity = preg_replace("/[^a-zA-Z0-9\s]/", "", $option->ShipToCity);
self::$ShipToStateProvinceCode = preg_replace("/[^a-zA-Z0-9\s]/", "", $option->ShipToStateProvinceCode);
self::$ShipToPostalCode = (string)$option->ShipToPostalCode;
self::$ShipToPostalCode = substr(trim(self::$ShipToPostalCode), 0, 5);
self::$ShipToPostalCode = str_pad(self::$ShipToPostalCode, 5, "0", STR_PAD_LEFT);
self::$ShipToAddressLine = preg_replace("/[^a-zA-Z0-9\s]/", "", $option->ShipToAddressLine);
$Weight = $option->weight;
$d = strtotime("tomorrow");
$request_date = date("Y-m-d", $d);
$path_to_wsdl_pickup = "https://apitest.estes-express.com/tools/pickup/request/v1.0?wsdl";
ini_set("soap.wsdl_cache_enabled", "0");
$client_pickup = new SoapClient('https://USERNAME:PASSWORD#apitest.estes-express.com/tools/pickup/request/v1.0?wsdl');
ini_set("soap.wsdl_cache_enabled", "0");
$header_pickup = new SoapHeader('http://www.estes-express.com/tools/pickup');
$client_pickup->__setSoapHeaders($header_pickup);
//Enter the body data for WSDL
$request_pickup = array(
'requestNumber' => date("Y-m-d"),
'shipper' => array(
'shipperName' => 'COMPANY NAME',
'accountCode' => 'ACCOUNT CODE',
'shipperAddress' => array(
'addressInfo' => array(
'addressLine1' => '1620 TEST CT',
'city' => 'SOMETOWN',
'stateProvince' => 'MO',
'postalCode' => '65222',
'countryAbbrev' => 'US'
)
)
),
'requestAction' => 'LL',
'pickupDate'=> date("Y-m-d"),
'pickupStartTime' => '1200',
'pickupEndTime' => '1500',
'totalPieces' => '1',
'totalWeight' => '100',
'totalHandlingUnits' => '1',
'whoRequested' => 'S'
);
try {
$response_pickup = $client_pickup->createPickupRequestWS($request_pickup);
//Error log the request and response
error_log($client->__getLastRequest());
error_log($client->__getLastResponse());
//$rateReply = $response->quoteInfo->quote->pricing->totalPrice;
//Get the response data
$result_array = array();
$result_array['totalPrice'] = $estes_total_rate_amount;
return $result_array;
} catch (SoapFault $exception) {
error_log('ERROR LOG::' . $exception, $client);
}
}
I have been attempting to get this to work for a while. I am hoping someone familiar with it happens to run across the question and can explain WHY this isnt working and what is wrong with the code. Estes has been useless in helping thus far. They have provided me a bunch of information but none of it works.
The code below is returning this error
Fatal error: Uncaught SoapFault exception: [Client] SOAP-ERROR:
Encoding: object has no 'requestID' property in
/home/xxxxxxxxxx/public_html/inc/estes/estesapi.php:41 Stack trace: #0
/home/xxxxxxxxxx/public_html/inc/estes/estesapi.php(41):
SoapClient->__call('getQuote', Array) #1 {main} thrown in
/home/xxxxxxxxxx/public_html/inc/estes/estesapi.php on line 41
$client = new SoapClient("https://www.estes-express.com/tools/rating/ratequote/v3.0/services/RateQuoteService?wsdl");
$request_object = array(
"header"=>array(
"auth"=>array(
"user"=>"xxxxxxxxx",
"password"=>"xxxx",
)
),
"rateRequest"=>array(
"requestID"=>"abc",
"account"=>"############",
"originPoint"=>array(
"countryCode"=>"US",
"postalCode"=>"28366",
"city"=>"Newton Grove",
"stateProvince"=>"NC",
),
"destinationPoint"=>array(
"countryCode"=>"US",
"postalCode"=>"28334",
),
"payor"=> "S",
"terms"=> "P",
"stackable"=> "N",
"baseCommodities"=>array(
"commodity"=>array(
"class"=>"50",
"weight"=>"1200",
)
)
)
);
$result = $client->getQuote($request_object);
var_dump($result);
print_r($result);
I cant figure out why RequestID isnt being passed into the soap request.
This is our Estes Soap call. See if you see anything in it that helps:
// define transaction arrays
$url = "http://www.estes-express.com/rating/ratequote/services/RateQuoteService?wsdl";
$username = 'xxxxxxxx';
$password = 'xxxxxxxx';
// setting a connection timeout of five seconds
$client = new SoapClient($url, array("trace" => true,
"exceptions" => true,
"connection_timeout" => 5,
"features" => SOAP_WAIT_ONE_WAY_CALLS,
"cache_wsdl" => WSDL_CACHE_NONE));
$old = ini_get('default_socket_timeout');
ini_set('default_socket_timeout', 5);
//Prepare SoapHeader parameters
$cred = array(
'user' => $username,
'password' => $password
);
$header = new SoapHeader('http://ws.estesexpress.com/ratequote', 'auth', $cred);
$client->__setSoapHeaders($header);
$params = array(
"requestID" => "xxxxxxxx",
"account" => "xxxxxxxx",
"originPoint" => array('countryCode' => 'US', 'postalCode' => $fromzip),
"destinationPoint" => array('countryCode' => 'US', 'postalCode' => $shipzip),
"payor" => 'T',
"terms" => 'PPD',
"stackable" => 'N',
"baseCommodities" => array('commodity' => $comArray ),
"accessorials" => array('accessorialCode' => $accArray)
);
// remove accessorials entry if no accessorial codes
if(count($accArray) == 0){
$params = array_slice($params, 0, 8); // remove accesorials entry
}
// call Estes API and catch any errors
try {
$reply = $client->getQuote($params);
}
catch(SoapFault $e){
// handle issues returned by the web service
//echo "Estes soap fault<br>" . $e . "<br>";
$edit_error_msg = "Estes quote API timed out or failed to return a quote";
return "0.00";
}
catch(Exception $e){
// handle PHP issues with the request
//echo "PHP soap exception<br>" . $e . "<br>";
$edit_error_msg = "Estes quote API timed out or failed to return a quote";
return "0.00";
}
unset($client);
ini_set('default_socket_timeout', $old);
// print_r($reply);
What do I need:
I need some help figuring out an error that i receive from calling a function from a WSDL file with soapclient. Or I would like some help extracting data from a cURL response.
What am I trying to reach:
I am trying to reach to call a function from a WSDL, and get a response from the action.
What are my experiences:
I can call the actions storeOrders succesfull with a cURL statement, I do also get a response.
But with the given response i guess a string. I am not able to extract the data out of it.
So I tried to request the same action from the server but then using soapclient, but I keep getting a error.
What I already tried:
I tried to make the cURL response a new SimpleXMLElement, but it always returns a emty object. Also when I try to reach one of the children.
I tried to make the cURL reponse return as an array and loop trough it with a foreach, also here I got an empty object.
I tried to explode the cURL reponse, but also there i had some problems with the wrong data being returned.
I tried to call it with SoapClient, but I keep getting this error.
So I would like some help with extracting data from cURL, or processing the request with SoapClient.
My cURL request (with answer, all the variables are set with the correct data):
function storeOrderAndGetLabel($delisId, $auth_token, $messageLanguage, $printerLanguage, $paperFormat, $identificationNumber,
$sendingDepot, $product, $mpsCompleteDelivery, $send_name, $send_street, $send_country, $send_zipcode, $send_city,
$send_customerNumber, $rec_name, $rec_street, $rec_state, $rec_country, $rec_zipcode, $rec_city, $parcelLabelNumber,
$orderType)
{
$xml = '
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://dpd.com/common/service/types/Authentication/2.0" xmlns:ns1="http://dpd.com/common/service/types/ShipmentService/3.1">
<soapenv:Header>
<ns:authentication>
<delisId>'.$delisId.'</delisId>
<authToken>'.$auth_token.'</authToken>
<messageLanguage>'.$messageLanguage.'</messageLanguage>
</ns:authentication>
</soapenv:Header>
<soapenv:Body>
<ns1:storeOrders>
<printOptions>
<printerLanguage>'.$printerLanguage.'</printerLanguage>
<paperFormat>'.$paperFormat.'</paperFormat>
</printOptions>
<order>
<generalShipmentData>
<identificationNumber>'.$identificationNumber.'</identificationNumber>
<sendingDepot>'.$sendingDepot.'</sendingDepot>
<product>'.$product.'</product>
<mpsCompleteDelivery>'.$mpsCompleteDelivery.'</mpsCompleteDelivery>
<sender>
<name1>'.$send_name.'</name1>
<street>'.$send_street.'</street>
<country>'.$send_country.'</country>
<zipCode>'.$send_zipcode.'</zipCode>
<city>'.$send_city.'</city>
<customerNumber>'.$send_customerNumber.'</customerNumber>
</sender>
<recipient>
<name1>'.$rec_name.'</name1>
<street>'.$rec_street.'</street>
<state>'.$rec_state.'</state>
<country>'.$rec_country.'</country>
<zipCode>'.$rec_zipcode.'</zipCode>
<city>'.$rec_city.'</city>
</recipient>
</generalShipmentData>
<parcels>
<parcelLabelNumber>'.$parcelLabelNumber.'</parcelLabelNumber>
</parcels>
<productAndServiceData>
<orderType>'.$orderType.'</orderType>
</productAndServiceData>
</order>
</ns1:storeOrders>
</soapenv:Body>
</soapenv:Envelope>
';
$headers = array(
"POST HTTP/1.1",
"Content-type: application/soap+xml; charset=\"utf-8\"",
"SOAPAction: \"http://dpd.com/common/service/ShipmentService/3.1/storeOrders\"",
"Content-length: ".strlen($xml)
);
$cl = curl_init('https://public-ws-stage.dpd.com/services/ShipmentService/V3_1/');
curl_setopt($cl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($cl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($cl, CURLOPT_POST, 1);
curl_setopt($cl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($cl, CURLOPT_POSTFIELDS, "$xml");
curl_setopt($cl, CURLOPT_RETURNTRANSFER, 1);
$output_cl = json_decode(trim(json_encode(curl_exec($cl))), TRUE);
return $output_cl;
//return $output_cl;
}
And from this code i get the reponse, i guess it is a string but i don't know for sure:
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<ns2:storeordersresponse xmlns:ns2="http://dpd.com/common/service/types/ShipmentService/3.1">
<orderresult>
<parcellabelspdf>pdfkey</parcellabelspdf>
<shipmentresponses>
<identificationnumber>identificationnumber</identificationnumber>
<mpsid>mpsid</mpsid>
<parcelinformation>
<parcellabelnumber>labelnr</parcellabelnumber>
</parcelinformation>
</shipmentresponses>
</orderresult>
</ns2:storeordersresponse>
</soap:body>
</soap:envelope>
Now my function calling the SoapClient function:
$label = storeOrderAndGetLabel($delisId, $auth_token, $messageLanguage, $printerLanguage, $paperFormat, $identificationNumber,
$sedingDepot, $product, $mpsCompleteDelivery, $send_name, $send_street, $send_country, $send_zipcode, $send_city,
$send_customerNumber, $rec_name, $rec_street, $rec_state, $rec_country, $rec_zipcode, $rec_city, $parcelLabelNumber,
$orderType);
print_r($label);
now the soap call itself:
function storeOrderAndGetLabel($delisId, $auth_token, $messageLanguage, $printerLanguage, $paperFormat, $identificationNumber,
$sendingDepot, $product, $mpsCompleteDelivery, $send_name, $send_street, $send_country, $send_zipcode, $send_city,
$send_customerNumber, $rec_name, $rec_street, $rec_state, $rec_country, $rec_zipcode, $rec_city, $parcelLabelNumber,
$orderType)
{
$client = new SoapClient('https://public-ws-stage.dpd.com/services/ShipmentService/V3_1?WSDL');
$label = $client->storeOrders
(array
(
"printOptions" => array
(
"printerLanguage" => "$printerLanguage",
"paperFormat" => "$paperFormat"
),
"order" => array
(
"generalShipmentData" => array
(
"identificationNumber" => "$identificationNumber",
"sendingDepot" => "$sendingDepot",
"product" => "$product",
"mpsCompleteDelivery" => "$mpsCompleteDelivery",
"sender" => array
(
"name1" => "$send_name",
"street" => "$send_street",
"country" => "$send_country",
"zipCode" => "$send_zipcode",
"city" => "$send_city",
"customerNumber" => "$send_customerNumber"
),
"recipient" => array
(
"name1" => "$rec_name",
"street" => "$rec_street",
"state" => "$rec_state",
"country" => "$rec_country",
"zipCode" => "$rec_zipcode",
"city" => "$rec_city"
)
),
"parcels" => array
(
"parcelLabelNumber" => "$parcelLabelNumber"
),
"productAndServiceData" => array
(
"orderType" => "$orderType"
)
)
)
);
return $label;
}
The error I receive from the soapcall:
Fatal error: Uncaught SoapFault exception: [soap:Server] Fault occurred while processing. in getLabel.php:107 Stack trace: #0 getLabel.php(107): SoapClient->__call('storeOrders', Array) #1 getLabel.php(107): SoapClient->storeOrders(Array) #2 getLabel.php(38): storeOrderAndGetLabel('username', 'password...', 'nl_NL', 'PDF', 'A4', '77777', '0163', 'CL', '0', 'uname', 'straat', 'NL', 'zipcode', 'City', '341546246451...', 'Test-Empfaenger', 'Test-Strasse', 'BY', 'DE', '123451', 'ahahaha', '16231545', 'consignment') #3 {main} thrown in getLabel.php on line 107
I would like to extract the parcellabelspdf key and the mpsid from the response. It would be really nice if someone could take a look at it.
Two possible problems:
You need to authenticate when calling the DPD ShipmentService. See below for a working example.
Make sure, that the parameter mpsCompleteDelivery is passed as an integer (0), not the string "false". Consider changing this line:
"mpsCompleteDelivery" => "$mpsCompleteDelivery"
to:
"mpsCompleteDelivery" => $mpsCompleteDelivery
Here is a full example including the login and output of a DPD-label as PDF:
// Let's log in first...
$c = new SoapClient('https://public-ws-stage.dpd.com/services/LoginService/V2_0?wsdl');
$res = $c->getAuth(array(
'delisId' => 'your-Id',
'password' => 'your-Password',
'messageLanguage' => 'de_DE'
));
// ...and remember the token.
$auth = $res->return;
// ...and then generate a label
$c = new SoapClient('https://public-ws-stage.dpd.com/services/ShipmentService/V3_1?wsdl');
$token = array(
'delisId' => $auth->delisId,
'authToken' => $auth->authToken,
'messageLanguage' => 'de_DE'
);
// Set the header with the authentication token
$header = new SOAPHeader('http://dpd.com/common/service/types/Authentication/2.0', 'authentication', $token);
$c->__setSoapHeaders($header);
try {
$res = $c->storeOrders( array
(
"printOptions" => array(
"paperFormat" => "A4",
"printerLanguage" => "PDF"
),
"order" => array(
"generalShipmentData" => array(
"sendingDepot" => $auth->depot,
"product" => "CL",
"mpsCompleteDelivery" => false,
"sender" => array(
"name1" => "Sender Name",
"street" => "Sender Street 2",
"country" => "DE",
"zipCode" => "65189",
"city" => "Wiesbaden",
"customerNumber" => "123456789"
),
"recipient" => array(
"name1" => "John Malone",
"street" => "Johns Street 34",
"country" => "DE",
"zipCode" => "65201",
"city" => "Wiesbaden"
)
),
"parcels" => array(
"parcelLabelNumber" => "09123829120"
),
"productAndServiceData" => array(
"orderType" => "consignment"
)
)
)
);
} catch (SoapFault $exception) {
echo $exception->getMessage();
die();
}
// Et voilĂ !
header('Content-type: application/pdf');
echo $res->orderResult->parcellabelsPDF;
Check here for more information:
http://labor.99grad.de/2014/10/05/deutscher-paket-dienst-dpd-soap-schnittstelle-mit-php-nutzen-um-versandetikett-als-pdf-zu-generieren/
I have a script that consumes a webservice through SOAP. I'm wondering why I don't receive a response from the server/endpoint URL. The other side said that they're receiving my requests so it means the script works. The only problem is that it doesn't give me a response. I also tried to get the last request, last request header and last response but nothing happens.
Do you have any idea why this is happening?
Here's my code:
$wsdl = "http://imupost.co.za/momentum/CRMLeadService.wsdl";
$momurl = "https://integrationdev.momentum.co.za/sales/CRMService/CRMLeadService_v1_0";
echo("Post to URL: {$momurl}\n");
$username = "817221";
$password = "1234";
echo("<pre>");
$client = new SoapClient ($wsdl, array('location' => $momurl, 'style' => SOAP_DOCUMENT, 'trace' => 1, 'soap_version' => SOAP_1_1, 'exceptions' => true, 'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP, 'ssl_method' => SOAP_SSL_METHOD_TLS));
$header='
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken wsu:Id="UsernameToken-45">
<wsse:Username>'.$username.'</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">'.$password.'</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
';
$headerSoapVar = new SoapVar($header,XSD_ANYXML);
$soapheader = new SoapHeader('wsse', "Security" , $headerSoapVar , true);
$client->__setSoapHeaders($soapheader);
$params['createLead'] = array(
'LeadSourceId' => '07d3d6fe-7682-e311-a16d-005056b81ea8',
'AffiliateLeadReference' => '852800020',
'Title' => array('Code' => '852800018'),
'Initials' => 'MH',
'PreferredName' => 'Jane',
'FirstName' => 'Hudson',
'LastName' => 'Craig',
'PreferredCorrespondenceLanguage' => array('Code' => '852800001'),
'PreferredCommunicationMethod' => array('Code' =>'852800000'),
'HomePhoneNumber' => '0725222427',
'BusinessPhoneNumber' => '0725584155',
'MobilePhoneNumber' => '0723694259',
'EmailAddress' => 'jhudson#gmail.com',
'Notes' => 'IMU',
'ProductCategories' => array('Code' => '9c7d3878-5295-e211-9330-005056b81ea8', 'Description' => 'Health - Personal')
);
$result = $client->__soapCall("createLead", array($params));
echo "REQUEST:\n" . htmlentities($client->__getLastRequest()) . "\n";
echo "RESPONSE:\n" . $client->__getLastResponse() . "\n";
print_r($client->__getLastRequestHeaders());
I would suggest using a try catch.
try {
$client->__soapCall("createLead", array($params));
echo $client->__getLastResponse();
} catch (Exception $e) {
echo "<pre>Exception: ".print_r($e, true)."</pre>\n";
}
I have looked all over stack overflow and only found a couple threads related but they did not solve my problem. Also, for what it's worth, this is an LTL carrier by the name of Estes that I am trying to get this to work through.
Here's the code I'm using:
$url = "http://www.estes-express.com/rating/ratequote/services/RateQuoteService?wsdl";
$username = 'un';
$password = 'pw';
$client = new SoapClient($url);
//Prepare SoapHeader parameters
$cred = array(
'user' => $username,
'password' => $password
);
$headers = new SoapHeader('http://ws.estesexpress.com/ratequote', 'auth', $cred);
$client->__setSoapHeaders($header);
$params = array(
"requestID" => "20131724",
"account" => "9252066",
"originPoint" => array('countryCode' => 'US', 'postalCode' => "43537"),
"destinationPoint" => array('countryCode' => 'US', 'postalCode' => "43460"),
"payor" => 'S',
"terms" => 'PPD',
"stackable" => 'N',
"baseCommodities" => array('commodity' => array('class' => "55", 'weight' => "500") )
);
$return = $client->getQuote(array("rateRequest"=>$params));
return $return;
Here is the response I am getting:
[Client] SOAP-ERROR: Encoding: object has no 'requestID' property
Any help on this would be great!
PS. I have already tried putting them in stdClass() objects with not result. Also, their WSDL is in the code if you want to check it out.
EDITED:
Here is a dump of what the request should look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:rat="http://ws.estesexpress.com/ratequote" xmlns:rat1="http://ws.estesexpress.com/schema/2012/12/ratequote">
<soapenv:Header>
<rat:auth>
<rat:user>xxxxx</rat:user>
<rat:password>xxxxxx</rat:password>
</rat:auth>
</soapenv:Header>
<soapenv:Body>
<rat1:rateRequest>
<rat1:requestID>20131724</rat1:requestID>
<rat1:account>9252066</rat1:account>
<rat1:originPoint>
<rat1:countryCode>US</rat1:countryCode>
<rat1:postalCode>43537</rat1:postalCode>
<!--Optional:-->
<rat1:city>Maumee</rat1:city>
<!--Optional:-->
<rat1:stateProvince>OH</rat1:stateProvince>
</rat1:originPoint>
<rat1:destinationPoint>
<rat1:countryCode>US</rat1:countryCode>
<rat1:postalCode>23237</rat1:postalCode>
<rat1:stateProvince>VA</rat1:stateProvince>
</rat1:destinationPoint>
<rat1:payor>S</rat1:payor>
<rat1:terms>PPD</rat1:terms>
<rat1:stackable>N</rat1:stackable>
<rat1:baseCommodities>
<!--1 to 99 repetitions:-->
<rat1:commodity>
<rat1:class>50</rat1:class>
<rat1:weight>100</rat1:weight>
</rat1:commodity>
</rat1:baseCommodities>
</rat1:rateRequest>
</soapenv:Body>
</soapenv:Envelope>
This caught me out the other day, too: the parameters expected by the SoapClients called should not include the outermost XML tag within the body, in this case rateRequest, as this is generated automatically based on the description in the WSDL. Instead, you need to pass a structure (array or object) containing each of the parameters defined within that outer tag.
So in your case, you just need to change this:
$return = $client->getQuote(array("rateRequest"=>$params));
to this:
$return = $client->getQuote($params);
Incidentally, your code as pasted also has a typo where you define $headers but then reference $header. A live demo with both changes shows instead a "User authentication failed." fault (presumably because you were wise enough not to give us your real login details!)
In case anyone is still having trouble with this, in order to get this to work I had to change the $params into an object or else I would receive an error, "Object Property Does Not Exist"
$params = new stdClass();
$params->requestID = "20131724";
$params->account = "123456";
$params->originPoint = array('countryCode' => 'US', 'postalCode' => "43537");
$params->destinationPoint = array('countryCode' => 'US', 'postalCode' => "43460");
$params->payor = "S";
$params->terms = "PPD";
$params->stackable = "N";
$params->baseCommodities = array('commodity' => array('class' => "55", 'weight' => "100") );
$return = $client->getQuote($params);