2011-07-29 7 views
3

UPS Ratings 웹 서비스를 이용하기 위해 PHP와 SoapClient를 사용하려고합니다. 나는 서비스 요청을 만들기위한 시작 지점 라이브러리를 만들 WSDLInterpreter라는 좋은 도구를 발견,하지만 난 같은 (비 설명) 오류가 점점 계속 시도에 상관없이 무엇을 : 도대체 무엇을,PHP + SoapClient 예외 및 헤더? (UPS 등급)

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

확인 음을 이거는?

구현 한 다른 웹 서비스 도구와 달리 UPS 비누는 보안 블록을 헤더에 넣기를 원합니다. 원시 연관 배열 데이터를 시도했지만 헤더 부분을 정확하게 주입하는 경우 100 %를 확신하지 못했습니다. WSDLInterpreter를 사용하여 RateRequest 및 UPSSecurity 부분에 대한 자체 (인스턴스) 데이터 구조를 제외한 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); 
     } 
    } 

} 

심지어 전송하는 지점에 도착하지 않는 것 Soap에 대한 것이므로 WSDL 정보와 일치하지 않는 결과로 인해 죽어 가고 있다고 가정하고 있습니다. (마음에, 나는 똑같은 결과와 동일한 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); 

    } 

} 

그런 다음 비누 호출 전에 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