Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create PHP SOAP request with multiple namespaces

I'm attempting to get a shipping quote from an SOAP service. I've been able to successfully create authentication headers and query the SOAP service with basic requests that require no body parameters.

I'm able to create the proper structure for the request but the namespace values are not showing up in the request output.

Example code:

$client = new SoapClient("http://demo.smc3.com/AdminManager/services/RateWareXL?wsdl",
                   array('trace' => TRUE));

$headerParams = array('ns1:licenseKey'    => $key,
                      'ns1:password'      => $pass,
                      'ns1:username'      => $user);

$soapStruct = new SoapVar($headerParams, SOAP_ENC_OBJECT);
$header = new SoapHeader($ns, 'AuthenticationToken', $soapStruct, false);
$client->__setSoapHeaders($header);

// Check if shipping is ready - base call
$ready_to_ship = $client->isReady();

The above works just fine and returns true if the shipping service is available.

So I use the following code to build the request body (only filling required fields): I've also tried putting everything into an array and converting that to a SoapVar, I've tried including ns1: and ns2: in the body request creation but that hasn't worked either. I believe something needs to be adjusted in the request creation... not sure of the best approach..

$rate_request = $client->LTLRateShipment;
$rate_request->LTLRateShipmentRequest->destinationCountry = $destination_country;
$rate_request->LTLRateShipmentRequest->destinationPostalCode = $destination_postal_code;
$rate_request->LTLRateShipmentRequest->destinationPostalCode = $destination_postal_code;
$rate_request->LTLRateShipmentRequest->details->LTLRequestDetail->nmfcClass = $ship_class;
$rate_request->LTLRateShipmentRequest->details->LTLRequestDetail->weight = $ship_weight;
$rate_request->LTLRateShipmentRequest->originCountry = $origin_country;
$rate_request->LTLRateShipmentRequest->originPostalCode = $origin_postal_code;
$rate_request->LTLRateShipmentRequest->shipmentDateCCYYMMDD = $ship_date; 
$rate_request->LTLRateShipmentRequest->tariffName = $tariff; 

And it produces the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://webservices.smc.com">
        <SOAP-ENV:Header>
            <ns1:AuthenticationToken>
                <ns1:licenseKey>xxxxxxxx</ns1:licenseKey>
                <ns1:password>xxxxxxxx</ns1:password>
                <ns1:username>xxxxxxxxm</ns1:username>
                    </ns1:AuthenticationToken>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns1:LTLRateShipment>
            <LTLRateShipmentRequest>
                <destinationCountry>USA</destinationCountry>
                <destinationPostalCode>10001</destinationPostalCode>
        <details>
              <LTLRequestDetail>
          <nmfcClass>60</nmfcClass>
          <weight>300</weight>
                          </LTLRequestDetail>
        </details> 
                          <originCountry>USA</originCountry>
                <originPostalCode>90210</originPostalCode>
                <shipmentDateCCYYMMDD>20110516</shipmentDateCCYYMMDD>
                <tariffName>DEMOLTLA</tariffName>
            </LTLRateShipmentRequest>
        </ns1:LTLRateShipment>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

But the output should include the namespaces (web: and web1: where appropriate). The above request returns an error code of missing tariffName.

Here's an example of what the xml request should look like:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:web="http://webservices.smc.com" xmlns:web1="http://web.ltl.smc.com"> 
   <soapenv:Header> 
      <web:AuthenticationToken> 
         <web:licenseKey> string </web:licenseKey> 
         <web:password> string </web:password> 
         <web:username> string </web:username> 
      </web:AuthenticationToken> 
   </soapenv:Header> 
   <soapenv:Body> 
      <web:LTLRateShipment> 
         <web:LTLRateShipmentRequest> 
            <web1:LTL_Surcharge> string </web1:LTL_Surcharge> 
            <web1:TL_Surcharge> string </web1:TL_Surcharge> 
            <web1:destinationCity> string </web1:destinationCity> 
            <web1:destinationCountry> string </web1:destinationCountry> 
            <web1:destinationPostalCode> string </web1:destinationPostalCode> 
            <web1:destinationState> string </web1:destinationState> 
            <web1:details> 
               <!--Zero or more repetitions:--> 
               <web1:LTLRequestDetail> 
                  <web1:nmfcClass> string </web1:nmfcClass> 
                  <web1:weight> string </web1:weight> 
               </web1:LTLRequestDetail> 
            </web1:details> 
            <web1:discountApplication> string </web1:discountApplication> 
            <web1:mcDiscount> string </web1:mcDiscount> 
            <web1:orgDestToGateWayPointFlag> string </web1:orgDestToGateWayPointFlag> 
            <web1:originCity> string </web1:originCity> 
            <web1:originCountry> string </web1:originCountry> 
            <web1:originPostalCode> string </web1:originPostalCode> 
            <web1:originState> string </web1:originState> 
            <web1:rateAdjustmentFactor> string </web1:rateAdjustmentFactor> 
            <web1:shipmentDateCCYYMMDD> string </web1:shipmentDateCCYYMMDD> 
            <web1:shipmentID> string </web1:shipmentID> 
            <web1:stopAlternationWeight> string </web1:stopAlternationWeight> 
            <web1:surchargeApplication> string </web1:surchargeApplication> 
            <web1:tariffName> string </web1:tariffName> 
            <web1:weightBreak_Discount_1> string </web1:weightBreak_Discount_1> 
         </web:LTLRateShipmentRequest> 
      </web:LTLRateShipment> 
   </soapenv:Body> 
</soapenv:Envelope>

Any suggestions / direction appreciated!

like image 706
zinger Avatar asked May 13 '11 22:05

zinger


1 Answers

Ok... After too many hours of testing I finally have a solution..

I recreated the Authorization Token as a class and built the Soap Request without having to deal with any namespaces, SoapVars etc. it's surprisingly easy.

/* Object for holding authentication info 
   this could probably be accomplished using stdClass too */
class AuthHeader {
    var $licenseKey;
    var $password;
    var $username;

    function __construct($loginInfo) {
      $this->licenseKey = $loginInfo['licenseKey'];
      $this->password   = $loginInfo['password'];
      $this->username   = $loginInfo['username'];
    }
}

// set current soap header with login info
$client = new SoapClient("http://demo.smc3.com/AdminManager/services/RateWareXL?wsdl",
                     array('trace' => TRUE
                        ));
// create header params array
$headerParams = array('licenseKey'        => $key,
                      'password'          => $pass,
                      'username'          => $user);
// create AuthHeader object
$auth = new AuthHeader($headerParams);

// Turn auth header into a SOAP Header
$header = new SoapHeader($ns, 'AuthenticationToken', $auth, false);

// set the header
$client->__setSoapHeaders($header);

// Check if shipping is ready - base call
$ready_to_ship = $client->isReady();
// $last_request = $client->__getLastRequest();
$last_response = $client->__getLastResponse();

//print $last_request;
if ($last_response == true) {

  print "Ready to ship\n";

// Create the shipping request
$d = new stdClass;
$d->nmfcClass = $ship_class;
$d->weight    = $ship_weight;

$p = new stdClass;
$p->LTLRateShipmentRequest->destinationCountry       = $destination_country;
$p->LTLRateShipmentRequest->destinationPostalCode    = $destination_postal_code;
$p->LTLRateShipmentRequest->details                  = array($d);
$p->LTLRateShipmentRequest->originCountry            = $origin_country;
$p->LTLRateShipmentRequest->originPostalCode         = $origin_postal_code;
$p->LTLRateShipmentRequest->shipmentDateCCYYMMDD     = $ship_date;
$p->LTLRateShipmentRequest->tariffName               = $tariff;

$quote = $client->LTLRateShipment($p);

$last_request = $client->__getLastRequest();
$last_response = $client->__getLastResponse();

print "Request: " . $last_request;
print "\nResponse: " . $last_response;

}
like image 186
zinger Avatar answered Nov 10 '22 08:11

zinger