我必须使用SOAP API,它基本上是为PHP设计的,并且一直是PHP客户端的用户。问题是,我使用Node.js,我遇到了一个我无法处理的问题。 这是"可能正在工作的一部分"代码:
<?php
try {
$client = new SoapClient(null, array(
'location' => "https://my-soap-server.com/_soap/server.php",
'uri' => "https://my-soap-server.com",
'encoding' => 'ISO-8859-1'
));
$result = $client->myMethod('aaaa', 'bbbb', 'cccc');
var_dump($result);
}
catch (SoapFault $fault) {
trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring:{$fault->faultstring})", E_USER_ERROR);
}
如您所见,参数以特定顺序传递给myMethod,而不是作为对象。 使用node的soap客户端(node-soap或strong-soap),参数2必须是回调函数,它可以提供如下代码:(让我们说文档给我字段1应该是& #39;登录&#39;等)
const soap = require('soap');
soap
.createClientAsync('http://my-soap-server.com')
.then((client) => client.myMethod({
login: 'aaaa',
password: 'bbbb',
randomVar: 'cccc',
}, (error, result) => {
if (error) {
console.error(error);
process.exit(1);
}
console.log(result);
process.exit(0);
})
.catch((error) => {
console.error(error);
process.exit(1);
});
好吧,我没有任何错误,但API没有按照预期的那样做。 所以,我想问题是服务器不期望一个带有键的对象,但是参数是以某种顺序进行的,就像在PHP中一样。有没有办法用Node.js重现它?
我希望我已经足够清楚。
非常感谢你的帮助。
编辑:使用WSDL可能更容易,我想要使用的方法是Ajout_BDD。
编辑2:嗯,经过进一步调查,看起来PHP的SOAP请求和Node.js的SOAP请求在格式上确实不同。 所以我通过使用&#34; request&#34;更简单(并且,不幸的是,更脏)。来自节点的lib并从正在运行的PHP请求中创建模板。 仅供参考,您可以使用以下代码转储PHP SOAP请求:
$client = new SoapClient("http://127.0.0.1:2018/test/test2?WSDL", array(
'trace' => 1
));
[...]
var_dump($client->__getLastRequest());
您也可以通过以下方式转储Node SOAP请求:
soap.createClientAsync('http://my-soap-server/hello?WSDL', (error, client) => client.myMethod({
login: 'aaaa',
password: 'bbbb',
randomVar: 'cccc',
}, (error, result) => {
[...]
console.log(client.lastRequest);
}));
然后只需使用您最喜欢的比较器来查看您的通话之间的差异。
答案 0 :(得分:0)
我已经测试了链接中提供的WSDL,对Ajout_BDD过程的SOAP调用将涉及一个如下所示的HTTP帖子:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:typens="urn:mdworks">
<soap:Body>
<typens:Ajout_BDD>
<login>loginValue</login>
<moddepasse>moddepasseValue</moddepasse>
<bdd>bddValue</bdd>
<ligne>
<typens:someField>someFieldValue</typens:someField>
</ligne>
</typens:Ajout_BDD>
</soap:Body>
</soap:Envelope>
响应应如下所示:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typens="urn:mdworks">
<soap:Body>
<typens:Ajout_BDDResponse>
<typens:output>
<typens:Ajout_BDDReturn>true</typens:Ajout_BDDReturn>
</typens:output>
</typens:Ajout_BDDResponse>
</soap:Body>
</soap:Envelope>
对于需要PHP客户端调用它的服务,应该没有任何具体内容。在Node.js中,您的客户端代码应如下所示:
"use strict";
var url = 'http://localhost:8001/mdworksService';
var wsdlFileName = 'example-service-original.wsdl';
const soap = require('soap');
const path = require('path');
soap
.createClientAsync(path.join(__dirname, wsdlFileName), {endpoint: url})
.then((client) => client.Ajout_BDD({
login: 'loginValue', moddepasse: 'moddepasseValue', bdd: 'bddValue', ligne: { someField: 'someFieldValue'}
}, (error, result) => {
if (error) {
console.error(error);
process.exit(1);
}
console.log(result);
process.exit(0);
}))
.catch( (error) => {
console.error(error);
process.exit(1);
});
您需要将url替换为服务的实际URL,并创建WSDL文件(使用您链接到的WSDL)。为了测试客户端代码,可以轻松地创建此服务的Node.js模拟。你可以这样做:
"use strict";
var soap = require('soap');
var http = require('http');
var service = {
mdworksService: {
MDWORKSPort: {
Ajout_BDD : function(args) {
console.log('Calling Ajout_BDD: args: ' + JSON.stringify(args));
return { output: { Ajout_BDDReturn : true } };
}
}
}
}
var xml = require('fs').readFileSync('example-service-original.wsdl', 'utf8');
var server = http.createServer(function(request,response) {
response.end("404: Not Found: "+request.url);
});
server.listen(8001);
var soapServer = soap.listen(server, '/mdworksService', service, xml);
soapServer.log = function(type, data) {
// type is 'received' or 'replied'
console.log(new Date().toISOString() + ": " + type + ': ' + data);
};
同样,您需要将WSDL文件包含在与服务器相同的目录中。这种方法对于测试SOAP客户端非常有用。