如何使用PHP处理带有会话的API(XML 307响应)

时间:2019-03-05 08:06:59

标签: php xml api soap

我这里有情况。目前,我开发了一个网站,需要创建一个与设备API进行通信的功能。现在,我受困于 307(临时重定向)

因此,流程是,首先我需要使用登录功能进行会话。如果登录成功,它将给出响应 307(临时重定向),并且响应头(sessionId)中有Location。因此,要发布另一个请求,我们需要遵循Location(sessionId)。当我在Postman中尝试始终成功执行登录功能以获取Location(SessionId),但是从这些Location发出另一个请求时,有时成功,有时不成功。我试图用PHP制作它,以使登录总是成功并获得Location,但是当POST另一个请求时,它总是失败。

这是用于登录的XML函数:

 POST / HTTP/1.1
 Host: 111.222.123.123:8001
 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lgi="http://www.qwerty.org/func/LGI">
     <soapenv:Header/>
     <soapenv:Body>
         <lgi:LGI>
             <lgi:OPNAME>username</lgi:OPNAME>
             <lgi:PWD>password</lgi:PWD>
         </lgi:LGI>
     </soapenv:Body>
 </soapenv:Envelope>

这是登录功能的标题响应:

HTTP/1.1 307 Temporary Redirect
Location: http://111.222.123.123:8001/00112233
Server: Qwerty web server
Content-Type: text/xml; charset="utf-8"
Content-Length: 411

00112233 是发布另一个请求的位置(SessionId)。但是同样,如果来自邮递员,有时会成功,有时不会成功。并且如果从PHP获取位置(SessionId)后始终无法发出POST请求

这是我的登录功能的PHP脚本:

    $soapUrl = "http://111.222.123.123:8001/";

    $xml_post_string1 = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lgi="http://www.qwerty.org/func/LGI">
                            <soapenv:Header/>
                            <soapenv:Body>
                                <lgi:LGI>
                                    <lgi:OPNAME>username</lgi:OPNAME>
                                    <lgi:PWD>password</lgi:PWD>
                                </lgi:LGI>
                            </soapenv:Body>
                        </soapenv:Envelope>';

    $headers1 = array(
                    "Content-type: text/xml;charset=\"utf-8\"",
                    "Accept: text/xml",
                    "Cache-Control: no-cache",
                    "Pragma: no-cache",
                    "SOAPAction: http://www.qwerty.org/func/LGI", 
                    "Content-length: ".strlen($xml_post_string1),
                );

        $url = $soapUrl;

        $ch1 = curl_init();
        curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, 1);
        curl_setopt($ch1, CURLOPT_URL, $url);
        curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch1, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
        curl_setopt($ch1, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch1, CURLOPT_POST, true);
        curl_setopt($ch1, CURLOPT_POSTFIELDS, $xml_post_string1);
        curl_setopt($ch1, CURLOPT_HTTPHEADER, $headers1);

        curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch1, CURLOPT_VERBOSE, 1);
        curl_setopt($ch1, CURLOPT_HEADER, 1);

        $response1 = curl_exec($ch1); 

        $header_size = curl_getinfo($ch1, CURLINFO_HEADER_SIZE);
        $header = substr($response1, 0, $header_size);

        $break1= explode('/', $header);
        $break2= preg_split('/[\s]+/', $break1[4]);
        $sessionId = $break2[0];

这是我获得位置/会话ID后的请求

    $soapUrlToken1 = "http://111.222.123.123:8001/";
    $soapUrlToken2 = $soapUrlToken1.$sessionId ;

    $xml_post_string2 = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sh="http://www.qwerty.org/func/SH_SUB">
                           <soapenv:Header/>
                           <soapenv:Body>
                              <sh:SH_SUB>
                                 <sh:USER>USERNAME</sh:USER>
                                 <sh:DETAIL>TRUE</sh:DETAIL>
                              </sh:SH_SUB>
                           </soapenv:Body>
                        </soapenv:Envelope>';

    $headers2 = array(
                    "POST /$token HTTP/1.1",
                    "Host: 111.222.123.123:8001",
                    "Content-type: text/xml;charset=\"utf-8\"",
                    "Accept: text/xml",
                    "Accept-Encoding: gzip,deflate",
                    "User-Agent: City Commons-HttpClient/3.1",
                    "SOAPAction: http://www.qwerty.org/func/SH_SUB",

                    "Content-length: ".strlen($xml_post_string2),
                );

    $urlToken = $soapUrlToken2;
    //echo "<br />".$urlToken."<br />";

    $ch2 = curl_init();
    curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch2, CURLOPT_URL, $urlToken);
    curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch2, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
    curl_setopt($ch2, CURLOPT_TIMEOUT, 10);
    curl_setopt($ch2, CURLOPT_POST, true);
    curl_setopt($ch2, CURLOPT_POSTFIELDS, $xml_post_string2);
    curl_setopt($ch2, CURLOPT_HTTPHEADER, $headers2);

    $response2 = curl_exec($ch2); 

    $response3 = str_replace("<SOAP-ENV:Body>","",$response2);
    $response4 = str_replace("</SOAP-ENV:Body>","",$response3);
    $parser2 = simplexml_load_string($response4);

在php中,关于sessionId的响应始终无效或超时。我已经向API小组询问过,他们仅解释登录后必须维护会话和端口才能发出另一个请求

那么用PHP处理 307(临时重定向)的最佳解决方案是什么?

谢谢

1 个答案:

答案 0 :(得分:1)

已经找到了解决方案。获取位置(SessionId)后,我不需要再次使用curl_init()curl_init()初始化一个新会话,这是问题所在,之前已经获得的位置(sessionId)将被curl_init()

破坏。