使用Node.js 创建WebService服务端
最近几天任务是用node.js去对接第三方的OA系统,对方OA系统属于太古老的代码了,还在使用WebService,用node.js调用WebService 很简单,用soap模块调用即可,网上已经有很多教程
但是当Node.js提供一个接口,供对方的webService调用,在网上找到对应教程。
- 难点:如何解析对方用soap调用该接口,获取参数,
- 方式1:可以自己实现xml的解析
- 方式2:调用soap模块
在实验多次之后终于解决该问题
npm install soap
- 阅读官方test代码。
server-test
// 服务端代码:
var soap = require('soap');
var fs = require('fs'),
http = require('http'),
lastReqAddress;
var test = {};
test.wsdl = fs.readFileSync('stockquote.wsdl', 'utf8');
test.server = null;
test.service = {
StockQuoteService: {
StockQuotePort: {
GetLastTradePrice: function(args, cb, soapHeader) {
if (soapHeader)
return { price: soapHeader.SomeToken };
if (args.tickerSymbol === 'trigger error') {
throw new Error('triggered server error');
} else if (args.tickerSymbol === 'Async') {
return cb({ price: 19.56 });
} else if (args.tickerSymbol === 'Promise Error') {
return new Promise((resolve, reject) => {
reject(new Error('triggered server error'));
});
} else if (args.tickerSymbol === 'Promise') {
return new Promise((resolve) => {
resolve({ price: 13.76 });
});
} else if (args.tickerSymbol === 'SOAP Fault v1.2') {
throw {
Fault: {
Code: {
Value: "soap:Sender",
Subcode: { value: "rpc:BadArguments" }
},
Reason: { Text: "Processing Error" }
}
};
} else if (args.tickerSymbol === 'SOAP Fault v1.1') {
throw {
Fault: {
faultcode: "soap:Client.BadArguments",
faultstring: "Error while processing arguments"
}
};
} else {
return { price: 19.56 };
}
},
SetTradePrice: function(args, cb, soapHeader) {
},
IsValidPrice: function(args, cb, soapHeader, req) {
lastReqAddress = req.connection.remoteAddress;
var validationError = {
Fault: {
Code: {
Value: "soap:Sender",
Subcode: { value: "rpc:BadArguments" }
},
Reason: { Text: "Processing Error" },
statusCode: 500
}
};
var isValidPrice = function() {
var price = args.price;
if(isNaN(price) || (price === ' ')) {
return cb(validationError);
}
price = parseInt(price, 10);
var validPrice = (price > 0 && price < Math.pow(10, 5));
return cb(null, { valid: validPrice });
};
setTimeout(isValidPrice, 10);
}
}
}
};
test.server = http.createServer(function(request,response) {
response.end('404: Not Found: ' + request.url);
});
test.server.listen(15099, null, null, function() {
test.soapServer = soap.listen(test.server, '/stockquote', test.service, test.wsdl);
test.baseUrl = 'http://' + test.server.address().address + ":" + test.server.address().port;
if (test.server.address().address === '0.0.0.0' || test.server.address().address === '::') {
test.baseUrl = 'http://127.0.0.1:' + test.server.address().port;
}
})
对应的wsdl代码,我是直接复制官方的wsdl,
<?xml version="1.0"?>
<wsdl:definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/stockquote.xsd" xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
<xsd:element name="TradePriceRequest">
<xsd:complexType>
<xsd:all>
<xsd:element name="tickerSymbol" type="string"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="TradePrice">
<xsd:complexType>
<xsd:all>
<xsd:element name="price" type="float"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="TradePriceSubmit">
<xsd:complexType>
<xsd:all>
<xsd:element name="tickerSymbol" type="string"/>
<xsd:element name="price" type="float"/>
</xsd:all>
</xsd:complexType>
</xsd:element>
<xsd:element name="valid" type="boolean"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="GetLastTradePriceInput">
<wsdl:part name="body" element="xsd1:TradePriceRequest"/>
</wsdl:message>
<wsdl:message name="GetLastTradePriceOutput">
<wsdl:part name="body" element="xsd1:TradePrice"/>
</wsdl:message>
<wsdl:message name="SetTradePriceInput">
<wsdl:part name="body" element="xsd1:TradePriceSubmit"/>
</wsdl:message>
<wsdl:message name="IsValidPriceInput">
<wsdl:part name="body" element="xsd1:TradePrice"/>
</wsdl:message>
<wsdl:message name="IsValidPriceOutput">
<wsdl:part name="body" element="xsd1:valid"/>
</wsdl:message>
<wsdl:portType name="StockQuotePortType">
<wsdl:operation name="GetLastTradePrice">
<wsdl:input message="tns:GetLastTradePriceInput"/>
<wsdl:output message="tns:GetLastTradePriceOutput"/>
</wsdl:operation>
<wsdl:operation name="SetTradePrice">
<wsdl:input message="tns:SetTradePriceInput"/>
</wsdl:operation>
<wsdl:operation name="IsValidPrice">
<wsdl:input message="tns:IsValidPriceInput"/>
<wsdl:output message="tns:IsValidPriceOutput"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="StockQuoteSoapBinding" type="tns:StockQuotePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetLastTradePrice">
<soap:operation soapAction="http://example.com/GetLastTradePrice"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="SetTradePrice">
<soap:operation soapAction="http://example.com/SetTradePrice"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="IsValidPrice">
<soap:operation soapAction="http://example.com/IsValidPrice"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="StockQuoteService">
<wsdl:port name="StockQuotePort" binding="tns:StockQuoteSoapBinding">
<soap:address location="http://localhost:15099/stockquote"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
用户端调用
var soap = require('soap');
var url = 'http://127.0.0.1:15099/stockquote?wsdl';
//使用soap,根据wsdl地址创建客户端
soap.createClient(url,function(err,client){
console.log(client)
if(err){
console.log(err);
}
//返回一个客户端,并且传参调用Java的接口,接收返回的数据
client.GetLastTradePrice({ tickerSymbol: 'Async'},function(error,result){
//打印接收到的数据
console.log(result);
});
})