使用加拿大UPS API开发遇两类SOAP相关错误求助
我正在基于加拿大UPS API开发,官方文档晦涩难懂。编写了调用FreightRate接口的PHP代码,先遇到Class 'SoapClient' not found错误,解决SOAP客户端缺失问题后,又出现SOAP-ERROR: Parsing WSDL: Couldn't load from ''的SoapFault错误,恳请技术帮助。
报错信息
初始错误
Fatal error: Uncaught Error: Class "SoapClient" not found in C:\xampp\htdocs\upsapi\RatingPACKAGE\PACKAGEWebServices\CodeSamples\Rate\PHP\SoapRateClient.php:121 Stack trace: #0 {main} thrown in C:\xampp\htdocs\upsapi\RatingPACKAGE\PACKAGEWebServices\CodeSamples\Rate\PHP\SoapRateClient.php on line 121
后续错误
SoapFault Object ( [message:protected] => SOAP-ERROR: Parsing WSDL: Couldn't load from ' ' : failed to load external entity " " [string:Exception:private] => [code:protected] => 0 [file:protected] => C:\xampp\htdocs\upsapi\ShippingPACKAGE\PACKAGEWebServices\CodeSamples\Ship\PHP\SoapShipClient.php [line:protected] => 185 [trace:Exception:private] => Array ( [0] => Array ( [file] => C:\xampp\htdocs\upsapi\ShippingPACKAGE\PACKAGEWebServices\CodeSamples\Ship\PHP\SoapShipClient.php [line] => 185 [function] => __construct [class] => SoapClient [type] => -> [args] => Array ( [0] => [1] => Array ( [soap_version] => SOAP_1_1 [trace] => 1 ) ) ) ) [previous:Exception:private] => [faultstring] => SOAP-ERROR: Parsing WSDL: Couldn't load from ' ' : failed to load external entity " " [faultcode] => WSDL [faultcodens] => [faultactor] => [detail] => [_name] => [headerfault] => )
我的PHP代码
<?php //Configuration $outputFileName = "XOLTResult.xml"; $access = "XXXX"; $userid = "XXXX"; $passwd = 'XXXX'; $wsdl = file_get_contents("RateWS.WSDL"); $operation = "ProcessRate"; $endpointurl = 'https://wwwcie.ups.com/webservices/FreightRate'; //create soap request $option['RequestOption'] = 'RateChecking Option'; $request['Request'] = $option; $shipfrom['Name'] = 'Good Incorporation'; $addressFrom['AddressLine'] = '2010 WARSAW ROAD'; $addressFrom['City'] = 'Roswell'; $addressFrom['StateProvinceCode'] = 'GA'; $addressFrom['PostalCode'] = '30076'; $addressFrom['CountryCode'] = 'US'; $shipfrom['Address'] = $addressFrom; $request['ShipFrom'] = $shipfrom; $shipto['Name'] = 'Sony Company Incorporation'; $addressTo['AddressLine'] = '2311 YORK ROAD'; $addressTo['City'] = 'TIMONIUM'; $addressTo['StateProvinceCode'] = 'MD'; $addressTo['PostalCode'] = '21093'; $addressTo['CountryCode'] = 'US'; $shipto['Address'] = $addressTo; $request['ShipTo'] = $shipto; $payer['Name'] = 'Payer inc'; $addressPayer['AddressLine'] = '435 SOUTH STREET'; $addressPayer['City'] = 'RIS TOWNSHIP'; $addressPayer['StateProvinceCode'] = 'NJ'; $addressPayer['PostalCode'] = '07960'; $addressPayer['CountryCode'] = 'US'; $payer['Address'] = $addressPayer; $shipmentbillingoption['Code'] = '10'; $shipmentbillingoption['Description'] = 'PREPAID'; $paymentinformation['Payer'] = $payer; $paymentinformation['ShipmentBillingOption'] = $shipmentbillingoption; $request['PaymentInformation'] = $paymentinformation; $service['Code'] = '02'; $service['Description'] = '2nd Day Air'; $request['Service'] = $service; $commodity['CommodityID'] = ''; $commodity['Description'] = 'No Description'; $commodity['Weight'] = array ( 'UnitOfMeasurement' => array ( 'Code' => 'LBS', 'Description' => 'Pounds' ), 'Value' => '11' ); $commodity['Dimensions'] = array ( 'UnitOfMeasurement' => array ( 'Code' => 'IN', 'Description' => 'Inches' ), 'Length' => '23', 'Width' => '17', 'Height' => '45' ); $commodity['NumberOfPieces'] = '1'; $commodity['DangerousGoodsIndicator'] = ''; $commodity['CommodityValue'] = array ( 'CurrencyCode' => 'CAD', 'MonetaryValue' => '500' ); $request['Commodity'] = $commodity; $shipmentserviceoptions['PickupOptions'] = array ( 'HolidayPickupIndicator' => '', 'InsidePickupIndicator' => '', 'ResidentialPickupIndicator' => '', 'WeekendPickupIndicator' => '', 'LiftGateRequiredIndicator' => '' ); try { $mode = array ( 'soap_version' => 'SOAP_1_1', // use soap 1.1 client 'trace' => 1 ); // initialize soap client $client = new SoapClient($wsdl , $mode); //set endpoint url $client->__setLocation($endpointurl); //create soap header $usernameToken['Username'] = $userid; $usernameToken['Password'] = $passwd; $serviceAccessLicense['AccessLicenseNumber'] = $access; $upss['UsernameToken'] = $usernameToken; $upss['ServiceAccessToken'] = $serviceAccessLicense; $header = new SoapHeader('http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','UPSSecurity',$upss); $client->__setSoapHeaders($header); //get response $resp = $client->__soapCall($operation ,array(processFreightRate())); //get status echo "Response Status: " . $resp->Response->ResponseStatus->Description ." "; //save soap request and response to file $fw = fopen($outputFileName , 'w'); fwrite($fw , "Request: " . $client->__getLastRequest() . " "); fwrite($fw , "Response: " . $client->__getLastResponse() . " "); fclose($fw); } catch(Exception $ex) { print_r ($ex); } ?>
问题解决办法
1. SoapClient缺失问题回顾(已解决)
确保PHP的SOAP扩展已启用:
- 打开
php.ini配置文件 - 找到
;extension=soap行,去掉开头的分号; - 重启Web服务器(如XAMPP、Apache)
2. 修复WSDL加载失败问题
代码中错误地用file_get_contents("RateWS.WSDL")读取WSDL内容,但SoapClient的第一个参数需要的是WSDL文件路径或远程WSDL URL,而非文件内容。
修改方案二选一:
- 本地WSDL文件:直接传入文件名(确保文件与脚本同目录)
$wsdl = "RateWS.WSDL"; - 远程WSDL URL(推荐,避免本地路径问题)
$wsdl = "https://wwwcie.ups.com/webservices/FreightRate?wsdl";
3. 其他代码错误修复
__soapCall参数错误:代码中processFreightRate()函数未定义,应传入构建好的$request数组$resp = $client->__soapCall($operation, [$request]);- 确认本地
RateWS.WSDL文件存在、路径正确,且有读取权限
内容的提问来源于stack exchange,提问作者Michael Dugas

