我需要使用SOAP和XML发布到客户端的URL(如果客户端在.Net平台上很重要)。该请求应如下所示:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:XXX="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX" xmlns:XXX1="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"> <soap:Header/> <soap:Body>
<tem:SaveXXXStatus>
<!--Optional:-->
<tem:req>
<!--Optional:-->
<XXX:AWBNumber>69184678146</XXX:AWBNumber>
<!--Optional:-->
… etc. …
<!--Optional:-->
<XXX:pincode></XXX:pincode>
</tem:req>
<!--Optional:-->
<tem:profile>
<!--Optional:-->
<XXX1:Api_type>S</XXX1:Api_type>
<!--Optional:-->
<XXX1:Area></XXX1:Area>
<!--Optional:-->
<XXX1:LicenceKey>xxxxxxxxxxxxxxxxxxx</XXX1:LicenceKey>
<!--Optional:-->
<XXX1:LoginID>XXXYYY</XXX1:LoginID>
<!--Optional:-->
<XXX1:Version>1</XXX1:Version>
</tem:profile>
</tem:SaveXXXStatus> </soap:Body> </soap:Envelope>
我正在使用以下代码:
$ch = curl_init();
//var_dump($ch);
curl_setopt($ch, CURLOPT_URL,"https://example.com?wsdl");
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'tem:"http://tempuri.org/"',
'Content-Type: text/xml',
'XXX:"http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX"'
'XXX1:"http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"'
));
//curl_setopt($ch, CURLOPT_USERPWD, "XXXYYY:xxxxxxxxxxxxx"); //Probably not needed
curl_setopt($ch, CURLOPT_POST, 1);
$strRequest = "";
$strRequest .= "AWBNumber=69184678161";
… etc….
$strRequest .= "&pincode=";
$strRequest .= "&Api_type=S";
$strRequest .= "&Area=";
$strRequest .= "&LicenceKey=xxxxxxxx";
$strRequest .= "&LoginID=XXXYYY";
$strRequest .= "&Version=1";
curl_setopt($ch, CURLOPT_POSTFIELDS,$strRequest);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($ch);
var_dump($server_output);
This post显示可以将标头(信封等)简单地添加到POSTFIELDS字符串中,但是我尝试了一下,但是它没有用。除此之外,这似乎是一种骇客!
无论如何,没有任何组合有效-我得到一个长度为零的字符串($ server_output)。传递标头的正确方法是什么,还有什么需要在此处解决的?
答案 0 :(得分:1)
几天前我也陷入困境...但是尝试过这种方式并获得了结果
$xml_post_string ='<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:XXX="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX" xmlns:XXX1="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.Admin"> <soap:Header/> <soap:Body>
<tem:SaveXXXStatus>
<!--Optional:-->
<tem:req>
<!--Optional:-->
<XXX:AWBNumber>69184678146</XXX:AWBNumber>
<!--Optional:-->
… etc. …
<!--Optional:-->
<XXX:pincode></XXX:pincode>
</tem:req>
<!--Optional:-->
<tem:profile>
<!--Optional:-->
<XXX1:Api_type>S</XXX1:Api_type>
<!--Optional:-->
<XXX1:Area></XXX1:Area>
<!--Optional:-->
<XXX1:LicenceKey>xxxxxxxxxxxxxxxxxxx</XXX1:LicenceKey>
<!--Optional:-->
<XXX1:LoginID>XXXYYY</XXX1:LoginID>
<!--Optional:-->
<XXX1:Version>1</XXX1:Version>
</tem:profile>
</tem:SaveXXXStatus> </soap:Body> </soap:Envelope>';
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: url",
"Content-length: " . strlen($xml_post_string),
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_URL, 'yoururl');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
print_r($response);
答案 1 :(得分:0)
正如我在评论中已经提到的,使用PHP SoapClient
类中的构建和将对象作为实体会容易得多。这是一个小例子,说明如何解决问题。
PHP Soap客户端
PHP在SoapClient
中拥有自己的构建,可以很好地运行。看看如何初始化客户端以进行开发。
try {
$client = new \SoapClient('https://example.com?wsdl', [
'cache_wsdl' )> WSDL_CACHE_NONE,
'exceptions' => true,
'trace' => true,
]);
} catch (\SoapFault $fault) {
echo "<pre>";
var_dump($fault->getMessage());
echo "</pre>";
if ($client) {
echo "<pre>";
var_dump($client->__getLastRequest(), $client->__getLastResponse());
echo "</pre>";
}
}
这是SoapClient
类的简单初始化,带有开发选项。将trace
选项设置为true可启用客户端内部功能__getLastRequest()
和__getLastResponse()
的使用。因此,您可以看到客户端发送的内容以及响应的内容(如果有)。我正在用它来检查客户端已发送的xml。
简单的实体,可以被肥皂使用
SOAP将自身定义为复杂和简单的类型定义。如果调用客户端自己的__getTypes()
函数,则可以看到此信息。将显示许多结构和简单的类型定义,它们存储在给定的wsdl文件或wsdl文件中提到的xsd文件中。有了这些信息,我们就能构建自己的对象。在此示例中,我使用简单的stdClass
对象。在生产方式中,应该使用自己计算的对象。
$req = new \stdClass();
$req->AWBNumber = new \SoapVar(
69184678146,
XSD_INT,
null,
null,
'AWBNumber',
'http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX'
);
$encodedReq = new \SoapVar($req, SOAP_ENC_OBJECT, null, null, 'req', 'http://tempuri.org/');
$saveXXXStatus = new \stdClass();
$saveXXXStatus->req = $encodedReq;
$encodedSaveXXXStatus = new \SoapVar($saveXXXStatus, SOAP_ENC_OBJECT, null, null, 'SaveXXXStatus, 'http://tempuri.org/');
// send the content with the soap client
$result = $client->SaveXXXStatus($encodedSaveXXXStatus);
请记住,这是一个简短的示例,不完整,会导致肥皂故障。但是我在这里做了什么? xml中的req节点是一个对象。您可以在上面提到的__getTypes()
函数输出中找到该对象的定义。在此示例中,我将该对象编译为具有属性stdClass
的{{1}}。 AWBNumber
本身是AWBNumber
对象。由于soap客户端使用的命名空间,我们使用soap var。定义属性后,我们将SoapVar
对象编码为肥皂对象,它也是一个req
实例。
毕竟,我们使用编码参数调用webservice方法SoapVar
。
最后一个请求
如果发送此示例,则最后一个请求应类似于:
SaveXXXStatus
正如我之前所说,这只是一个例子。您必须将所有节点编码为<ns1:envelope xmlns:ns1="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns2="http://tempuri.org/"
xmlns:ns3="http://schemas.datacontract.org/2004/07/XXXAPI.Entities.XXX">
<ns1:body>
<ns2:SaveXXXStatus>
<ns2:req>
<ns3:AWBNumber>69184678146</ns3:AWBNumber>
</ns2:req>
</ns2:SaveXXXStatus>
</ns1:body>
</ns1:envelope>
对象,并将其附加到父对象,最后使用完整的编码数据调用webservice方法。
像馅饼一样简单,嗯?