Как создать запрос PHP SOAP с несколькими пространствами имен

#php #soap #namespaces

#php #soap #пространства имен

Вопрос:

Я пытаюсь получить квоту на доставку от службы SOAP. Я смог успешно создать заголовки аутентификации и запросить службу SOAP с помощью базовых запросов, которые не требуют параметров тела.

Я могу создать правильную структуру для запроса, но значения пространства имен не отображаются в выходных данных запроса.

Пример кода:

 $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();
  

Вышеуказанное работает просто отлично и возвращает true, если служба доставки доступна.

Итак, я использую следующий код для построения тела запроса (заполняя только обязательные поля): Я также пытался поместить все в массив и преобразовать это в SoapVar, я пытался включить ns1: и ns2: в создание основного запроса, но это тоже не сработало. Я считаю, что что-то нужно скорректировать при создании запроса… не уверен в лучшем подходе..

 $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; 
  

И он выдает следующий 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>
  

Но выходные данные должны включать пространства имен (web: и web1:, где это уместно). Приведенный выше запрос возвращает код ошибки с отсутствующим именем тарифа.

Вот пример того, как должен выглядеть запрос xml:

     <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>
  

Любые предложения / направление приветствуются!

Ответ №1:

ОК… После слишком многих часов тестирования у меня наконец есть решение..

Я воссоздал токен авторизации как класс и создал запрос Soap без необходимости иметь дело с какими-либо пространствами имен, SoapVars и т.д. это на удивление просто.

 /* 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 shipn";

// 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;

}