2011-07-29 19 views
3

UPS Ratings Webサービスを利用するためにPHPとSoapClientを使用しようとしています。私は、サービス要求を作成するための出発点ライブラリを作成するためにWSDLInterpreterと呼ばれる便利なツールを見つけましたが、関係なく、私は私が同じ(非説明的)エラーを取得維持しようとするもの:PHP + SoapClientの例外とヘッダー? (UPS Rating)

EXCEPTION=SoapFault::__set_state(array(
    'message' => 'An exception has been raised as a result of client data.', 
    'string' => '', 
    'code' => 0, 

あのOK、地獄が何をしますかこれはどういう意味ですか?

私が実施している他のWebサービスツールのいくつかとは異なり、UPSソープは、ヘッダーに入れてセキュリティブロックを望んでいます。私は生の連想配列データを試してみましたが、ヘッダ部分を正しく注入していたのかどうかはわかりませんでした。 WSDLInterpreterを使用 、それはRateRequestとUPSSecurity部分に対する自身の(例えば)データ構造だが、上記のすべては、同じエラーを生成exceptsでProcessRate方法でRateServiceクラスを引き出します。ここで

が、私はそれがインタプリタによって定義されたクラスを呼び出して使用しているコードのサンプルです:


require_once "Shipping/UPS/RateService.php"; // WSDLInterpreter class library 

class Query 
{ 

    // constants removed for stackoverflow that define (proprietary) security items 
    private $_upss; 
    private $_shpr; 

    // use Interpreter code's RateRequest class to send with ProcessRate 
    public function soapRateRequest(RateRequest $req, UPSSecurity $upss = null) 
    { 
     $res = false; 
     if (!isset($upss)) { 
      $upss = $this->__getUPSS(); 
     } 
     echo "SECURITY:\n" . var_export($upss, 1) . "\n"; 
     $upsrs = new RateService(self::UPS_WSDL); 
     try { 
      $res = $upsrs->ProcessRate($req, $upss); 
     } catch (SoapFault $exception) { 
      echo 'EXCEPTION=' . var_export($exception, 1) . "\n"; 
     } 
     return $res; 
    } 

    // create a soap data structure to send to web service from shipment 
    public function getRequestSoap(Shipment $shpmnt) 
    { 
     $qs = new RateRequest(); 
     // pickup information 
     $qs->PickupType->Code = '01'; 
     $qs->Shipment->Shipper = $this->__getAcctInfo(); 
     // Ship To address 
     $qs->Shipment->ShipTo->Address->AddressLine = $this->__getAddressArray($shpmnt->destAddress->address1, $shpmnt->destAddress->address2); 
     $qs->Shipment->ShipTo->Address->City = $shpmnt->destAddress->city; 
     $qs->Shipment->ShipTo->Address->StateProvinceCode = $shpmnt->destAddress->state; 
     $qs->Shipment->ShipTo->Address->PostalCode = $shpmnt->destAddress->zip; 
     $qs->Shipment->ShipTo->Address->CountryCode = $shpmnt->destAddress->country; 
     $qs->Shipment->ShipTo->Name = $shpmnt->destAddress->name; 
     // Ship From address 
     $qs->Shipment->ShipFrom->Address->AddressLine = $this->__getAddressArray($shpmnt->origAddress->address1, $shpmnt->origAddress->address2); 
     $qs->Shipment->ShipFrom->Address->City = $shpmnt->origAddress->city; 
     $qs->Shipment->ShipFrom->Address->StateProvinceCode = $shpmnt->origAddress->state; 
     $qs->Shipment->ShipFrom->Address->PostalCode = $shpmnt->origAddress->zip; 
     $qs->Shipment->ShipFrom->Address->CountryCode = $shpmnt->origAddress->country; 
     $qs->Shipment->ShipFrom->Name = $shpmnt->origAddress->name; 
     // Service type 
     // TODO cycle through available services 
     $qs->Shipment->Service->Code = "03"; 
     $qs->Shipment->Service->Description = "UPS Ground"; 
     // Package information 
     $pkg = new PackageType(); 
     $pkg->PackagingType->Code = "02"; 
     $pkg->PackagingType->Description = "Package/customer supplied"; 
     // dimensions 
     $pkg->Dimensions->UnitOfMeasurement->Code = $shpmnt->dimensions->dimensionsUnit; 
     $pkg->Dimensions->Length = $shpmnt->dimensions->length; 
     $pkg->Dimensions->Width = $shpmnt->dimensions->width; 
     $pkg->Dimensions->Height = $shpmnt->dimensions->height; 

     $pkg->PackageServiceOptions->DeclaredValue->CurrencyCode = "USD"; 
     $pkg->PackageServiceOptions->DeclaredValue->MonetaryValue = $shpmnt->dimensions->value; 

     $pkg->PackageServiceOptions->DeclaredValue->CurrencyCode = "USD"; 
     $pkg->PackageWeight->UnitOfMeasurement = $this->__getWeightUnit($shpmnt->dimensions->weightUnit); 
     $pkg->PackageWeight->Weight = $shpmnt->dimensions->weight; 
     $qs->Shipment->Package = $pkg; 
     $qs->CustomerClassification->Code = 123456; 
     $qs->CustomerClassification->Description = "test_rate_request"; 
     return $qs; 
    } 

    // fill out and return a UPSSecurity data structure 
    private function __getUPSS() 
    { 
     if (!isset($this->_upss)) { 
      $unmt = new UsernameToken(); 
      $unmt->Username = self::UPSS_USERNAME; 
      $unmt->Password = self::UPSS_PASSWORD; 
      $sat = new ServiceAccessToken(); 
      $sat->AccessLicenseNumber = self::UPSS_ACCESS_LICENSE_NUMBER; 
      $upss = new UPSSecurity(); 
      $upss->UsernameToken = $unmt; 
      $upss->ServiceAccessToken = $sat; 
      $this->_upss = $upss; 
     } 
     return $this->_upss; 
    } 

    // get our shipper/account info (some items blanked for stackoverflow) 
    private function __getAcctInfo() 
    { 
     if (!isset($this->_shpr)) { 
      $shpr = new ShipperType(); 
      $shpr->Address->AddressLine = array(
       "CONTACT", 
       "STREET ADDRESS" 
      ); 
      $shpr->Address->City = "CITY"; 
      $shpr->Address->StateProvinceCode = "MI"; 
      $shpr->Address->PostalCode = "ZIPCODE"; 
      $shpr->Address->CountryCode = "US"; 

      $shpr = new ShipperType(); 
      $shpr->Name = "COMPANY NAME"; 
      $shpr->ShipperNumber = self::UPS_ACCOUNT_NUMBER; 
      $shpr->Address = $addr; 

      $this->_shpr = $shpr; 
     } 

     return $this->_shpr; 
    } 

    private function __getAddressArray($adr1, $adr2 = null) 
    { 
     if (isset($adr2) && $adr2 !== '') { 
      return array($adr1, $adr2); 
     } else { 
      return array($adr1); 
     } 
    } 

} 

それも、送信のポイントになっていないようです私はそれがWSDL情報と一致しない何かの結果として死んでいると仮定しているので、Soap上の何か。私が知っているように、エラーを取得するために、それはちょうどいいだろう (覚えておいて、私は結果として同じエラーで同じWSDLファイルを使用して手動で作成したのSoapClientにキー/値の詳細のちょうど適切に播種配列を送信しようとしました) 「クライアントデータ」はどういう問題ですか?これはPHPの石鹸の実装は私に印象的ではありません!

答えて

2

私はこの答えはあまりにも遅く、おそらくですけど、私はとにかく、いくつかのフィードバックを提供します。カスタムSOAPヘッダーを作成するには、SoapHeaderクラスをオーバーライドする必要があります。

/* 
* Auth Class to extend SOAP Header for WSSE Security 
* Usage: 
* $header = new upsAuthHeader($user, $password); 
* $client = new SoapClient('{...}', array("trace" => 1, "exception" => 0)); 
* $client->__setSoapHeaders(array($header)); 
*/ 

class upsAuthHeader extends SoapHeader 
{ 
... 
    function __construct($user, $password) 
    { 

     // Using SoapVar to set the attributes has proven nearly impossible; no WSDL. 
     // It might be accomplished with a combined SoapVar and stdClass() approach. 

     // Security Header - as a combined XSD_ANYXML SoapVar 
     // This method is much easier to define all of the custom SoapVars with attributes. 
     $security = '<ns2:Security xmlns:ns2="'.$this->wsse.'">'. // soapenv:mustUnderstand="1" 
         '<ns2:UsernameToken ns3:Id="UsernameToken-49" xmlns:ns3="'.$this->wsu.'">'. 
          '<ns2:Username>'.$user.'</ns2:Username>'. 
          '<ns2:Password Type="'.$this->password_type.'">'.htmlspecialchars($password).'</ns2:Password>'. 
         '</ns2:UsernameToken>'. 
        '</ns2:Security>'; 
     $security_sv = new SoapVar($security, XSD_ANYXML); 
     parent::__construct($this->wsse, 'Security', $security_sv, false); 

    } 

} 

次に、soapコールの前にupsAuthHeader()を呼び出します。

$client = new SoapClient($this->your_ups_wsdl, 
    array('trace' => true, 
     'exceptions' => true, 
     'soap_version' => SOAP_1_1 
    ) 
); 
// Auth Header - Security Header 
$header = new upsAuthHeader($user, $password); 
// Set Header 
$client->__setSoapHeaders(array($header)); 
+0

おかげで、今でも感謝しています。私は回避策をとったが、もう一度それに戻らなければならない場合は、ここではっきりと言及する。 – Scott