gpt4 book ai didi

PHP+SoapClient 异常和 header ? (UPS 评级)

转载 作者:搜寻专家 更新时间:2023-10-31 21:16:46 25 4
gpt4 key购买 nike

我正在尝试使用 PHP 和 SoapClient 来利用 UPS Ratings 网络服务。我找到了一个名为 WSDLInterpreter 的好工具来创建用于创建服务请求的起点库,但无论我尝试什么,我都会不断收到相同的(非描述性)错误:

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

嗯,好的,这到底是什么意思?

与我实现的其他一些 Web 服务工具不同,UPS Soap 需要在 header 中放入一个安全 block 。我尝试做原始关联数组数据,但我不能 100% 确定我是否正确注入(inject)了 header 部分。使用 WSDLInterpreter,它提取了一个带有 ProcessRate 方法的 RateService 类,除了它自己的 RateRequest 和 UPSSecurity 部分的(实例)数据结构,但以上所有都会产生相同的错误。

这是我正在使用的调用解释器定义的类的代码示例:


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 soap 实现并没有给我留下深刻印象!

最佳答案

我知道这个答案可能为时已晚,但无论如何我都会提供一些反馈。为了制作自定义 SOAP header ,您必须重写 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));

关于PHP+SoapClient 异常和 header ? (UPS 评级),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6876872/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com