如何创建具有多个命名空间的 PHP SOAP 请求

2021-12-24 00:00:00 namespaces php soap

我正在尝试从 SOAP 服务获取运输报价.我已经能够成功创建身份验证标头并使用不需要正文参数的基本请求来查询 SOAP 服务.

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.

示例代码:

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

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

所以我使用以下代码来构建请求正文(仅填写必填字段):我还尝试将所有内容放入数组并将其转换为 SoapVar,我尝试在正文请求创建中包含 ns1: 和 ns2: 但这也不起作用.我相信在请求创建中需要调整一些东西......不确定最好的方法..

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; 

它生成以下 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: 在适当的地方).上述请求返回缺少关税名称的错误代码.

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

以下是 xml 请求的示例:

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>

感谢任何建议/方向!

推荐答案

好的...经过太多小时的测试我终于有了解决方案...

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

我将授权令牌重新创建为一个类并构建了 Soap 请求,而无需处理任何命名空间、SoapVars 等.这非常简单.

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

// 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 "
Response: " . $last_response;

}

相关文章