试图测试UPS" Quantum" interface - XML文档格式不正确

时间:2014-07-24 23:24:43

标签: php xml web-services ups

我们正在尝试测试联合包裹服务(UPS)“昆腾”接口测试获取订单状态信息。我们得到了跟踪号API,但是遇到了QVEvents问题。

UPS“出站订阅帐户”已设置,有效并链接到我的帐号。用户访问在“用户设置”屏幕中选中“昆腾视图数据”视图。我很幸运地得到了跟踪API使用类似的代码,所以认为我可以排除用户名或密码问题。这两个API有什么不同的操作吗? (例如:SSL要求,HTTP标头设置?)

以下是跟踪API的代码(“Tack by Waybill”),它对我有用:

 <?php
  //  UPS Tracker API - track specfic Waybill
  //  DEV server
  $access      = '99999999399999999';
  $userid      = '9999999';
  $passwd      = '999999999999';
  $endpointUrl = 'https://www.ups.com/ups.app/xml/Track';
  $outFileName = './XOLTResult.xml'; 


  // Note: you need at least a UPS DEV account to test this
  $data ="<?xml version=\"1.0\"?><AccessRequest xml:lang='en-US'>
    <AccessLicenseNumber>$access</AccessLicenseNumber>
    <UserId>$userid</UserId>
    <Password>$passwd</Password>
    </AccessRequest>
    <?xml version=\"1.0\"?>
    <TrackRequest>
        <Request>
            <TransactionReference>
                <CustomerContext>
                    <InternalKey>hello</InternalKey>
                </CustomerContext>
                <XpciVersion>1.0</XpciVersion>
            </TransactionReference>
            <RequestAction>Track</RequestAction>
        </Request>
        <TrackingNumber>9999999999999999</TrackingNumber>
    </TrackRequest>";

    $ch = curl_init("https://www.ups.com/ups.app/xml/Track");
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch,CURLOPT_POST,1);
    curl_setopt($ch,CURLOPT_TIMEOUT, 60);
    curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
    $result=curl_exec ($ch);
    $data = strstr($result, '<?');
    $xml=simplexml_load_string($data);
    echo "<pre>";
    print_r($xml);

以下是提供错误消息的Quantum API代码......

<?php
 //  UPS Quantum API ("Show list of recent tracking information")
 //  DEV server
 $access      = '99999999399999999';
 $userid      = '9999999';
 $passwd      = '999999999999';
 $endpointUrl = 'https://wwwcie.ups.com/ups.app/xml/QVEvents';      // URL for testing Quantum
 $outFileName = './XOLTResult.xml'; 


try
{

$data ="<?xml version=\"1.0\"?>
        <AccessRequest xml:lang=\"en-US\">
        <AccessLicenseNumber>$access</AccessLicenseNumber>
        <UserId>$userid</UserId>
        <Password>$passwd</Password>
        </AccessRequest>
        <?xml version=\"1.0\"?>    
        <QuantumViewRequest xml:lang=\"en-US\">
            <Request>
                <TransactionReference>
                    <CustomerContext>Test XML</CustomerContext>
                    <XpciVersion>1.0007</XpciVersion>
                 </TransactionReference>
                 <RequestAction>QVEvents</RequestAction>
                 <IntegrationIndicator></IntegrationIndicator>
            </Request> 
        </QuantumViewRequest>";

  $postData = array
    (
      'content' =>  $data
    );


        $ch = curl_init();

        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_POST,1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);      
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch, CURLOPT_URL,$endpointUrl);
        curl_setopt($ch, CURLOPT_VERBOSE, 1 );
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/x-www-form-urlencoded'));     
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);                // disable SSL verification if not installed
        //curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);             
        curl_setopt($ch, CURLOPT_SSLVERSION, 3);                        // use Secure Socket v3 SSL3
        curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'SSLv3');             
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);        
        curl_setopt($ch,CURLOPT_POSTFIELDS,$postData);


        if( ! $result = curl_exec($ch))
        {
            trigger_error(curl_error($ch));
        } 


        echo $result;

        $data = strstr($result, '<?');
        $xml=simplexml_load_string($data);


        echo "<pre>";
        print_r($xml);

}
catch(Exception $ex)
{
   echo ($ex . "!");
}

curl_close($ch);        

这是实际发送给UPS的XML ... [注意双xml标头是他们要求的,它适用于所有其他API,所以不要怪我]

<?xml version="1.0"?>
<AccessRequest xml:lang="en-US">
<AccessLicenseNumber>999</AccessLicenseNumber>
<UserId>999</UserId>
<Password>999</Password>
</AccessRequest>
<?xml version="1.0"?>    
<QuantumViewRequest xml:lang="en-US">
    <Request>
        <TransactionReference>
            <CustomerContext>Test XML</CustomerContext>
            <XpciVersion>1.0007</XpciVersion>
         </TransactionReference>
         <RequestAction>QVEvents</RequestAction>
         <IntegrationIndicator></IntegrationIndicator>
    </Request> 
</QuantumViewRequest>

错误消息如下所示:

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Fri, 25 Jul 2014 22:50:57 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: application/xml

<QuantumViewResponse><Response><TransactionReference><XpciVersion>1.0</XpciVersion>
</TransactionReference><ResponseStatusCode>0</ResponseStatusCode>
<ResponseStatusDescription>Failure</ResponseStatusDescription><Error>
<ErrorSeverity>Hard</ErrorSeverity><ErrorCode>10001</ErrorCode>
<ErrorDescription>The XML document is not well formed</ErrorDescription></Error>
 </Response></QuantumViewResponse><pre>

我没有使用UPS SCA_SDO库,因为它不会安装在我的电脑上。也许我应该再看一遍,但我的程序员向我保证这不是必要的,与此问题无关。双重堆叠的XML看起来很可疑,但手动说这是UPS想要的方式。我想UPS会根据请求运行预处理器。

3 个答案:

答案 0 :(得分:1)

根据2014年7月的量子视图Developers Guide,未使用IntegrationIndicator

IntegrationIndicator

Request节点删除它,它应该按预期运行:

<Request>
    <TransactionReference>
        <CustomerContext>Test XML</CustomerContext>
        <XpciVersion>1.0007</XpciVersion>
     </TransactionReference>
     <RequestAction>QVEvents</RequestAction>
</Request> 

答案 1 :(得分:1)

问题

我对特定的UPS Api不熟悉,但错误消息提示不是well-formed XML document

  

错误代码10001: XML文档格式不正确

根据Quantum View Package - XML Developers Guide,您在HTTP请求中使用了错误的后期数据编码和内容类型,这会破坏XML,使其不再格式化。这会导致错误代码10001.

相反,使用正确的内容类型的HTTP请求正文(您正在使用 multipart/form-data 这是错误的,正确的内容类型是 {{1}使用您对UPS XML API端点的HTTP POST请求并对XML数据进行编码也是正确的,您应该使用XML库来创建XML(不是您的具体问题,但是当您知道XML是正确的,并且创建不会像在字符串连接中那样容易出错,这有助于排除相同错误代码的大量错误情况。)

如何解决?

要修复代码中错误内容类型的具体问题,请替换以下行:

application/x-www-form-urlencoded

$postData = array
(
    'content' =>  $data
);

这可确保curl库将$postData = $data; 用作 Content-Type 而不是application/x-www-form-urlencoded。然后,您会收到许可证号无效的正确错误消息:

  

错误代码250003:无效的访问许可证号

替代代码示例

作为替代方案,这是另一个小例子,展示了如何使用标准PHP HTTP包装器和用于XML处理的SimpleXML库以及使用DOMDocument的响应的更好输出:

multipart/form-data

此示例使用您在示例中提供的数据,而不是代码10001(代码生成的数据),它提供了有关数据样本中真实已知错误的更精确的错误信息:

  

错误代码250003:无效的访问许可证号

/*
 * UPS API XML PHP Example (Open Source)
 */

# Every UPS XML API request needs an AccessRequest XML payload first
$accessRequest                      = new SimpleXMLElement("<AccessRequest xml:lang='en-US'/>");
$accessRequest->AccessLicenseNumber = '99999999399999999';
$accessRequest->UserId              = '9999999';
$accessRequest->Password            = '999999999999';

# Exemplary testing QuantumViewRequest
$url     = 'https://wwwcie.ups.com/ups.app/xml/QVEvents';
$request = new SimpleXMLElement('<QuantumViewRequest xml:lang="en-US"/>');

# UPS XML API requires two concatenated XML documents send via a HTTP POST
# request with a HTTP request body and the content-type set to 
# application/x-www-form-urlencoded
$options = array(
    'http' => array(
        'header'  => "Content-type: application/x-www-form-urlencoded",
        'method'  => 'POST',
        'content' => $accessRequest->asXML() . $request->asXML(),
    ),
);
$context = stream_context_create($options);
$result  = file_get_contents($url, false, $context);

# output the response nicely formatted
$dom = new DOMDocument();
$dom->loadXML($result);
$dom->preserveWhiteSpace = false;
$dom->formatOutput       = true;
echo $dom->saveXML();

我确信这是正确的错误信息。

为了简洁示例,我已将<?xml version="1.0"?> <QuantumViewResponse> <Response> <TransactionReference/> <ResponseStatusCode>0</ResponseStatusCode> <ResponseStatusDescription>Failure</ResponseStatusDescription> <Error> <ErrorSeverity>Hard</ErrorSeverity> <ErrorCode>250003</ErrorCode> <ErrorDescription>Invalid Access License number</ErrorDescription> </Error> </Response> </QuantumViewResponse> file_get_contents的错误处理权移除。

答案 2 :(得分:0)

IntegrationIndicator已被弃用。也不要将数据作为数组传递。