【问题标题】:SOAP API call - How to insert TokenSOAP API 调用 - 如何插入 Token
【发布时间】:2022-02-06 22:29:00
【问题描述】:

我正在调用返回 XML 的 SOAP API 并收到以下错误

错误 -

    title>401 - Unauthorized: Access is denied due to invalid credentials.</title>

我已经使用了我可以在其他 SO 查询、SOAP 信息和我的特定调用文档中找到的信息,这是我迄今为止为它整理的代码

String soap = 
  '''<?xml version="1.0"?>
 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 xmlns:ns1="http://thalesgroup.com/RTTI/2014-02-20/ldb/" 
 xmlns:ns2="http://thalesgroup.com/RTTI/2017-10-01/ldb/GetDepartureBoard">
  <SOAP-ENV:Header>
    <ns2:AccessToken>
      <ns2:TokenValue>my_token</ns2:TokenValue>
    </ns2:AccessToken>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body>
    <ns1:GetDepartureBoardRequest>
      <ns1:numRows>10</ns1:numRows>
      <ns1:crs>MAN</ns1:crs>
    </ns1:GetDepartureBoardRequest>
  </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>''';

  // Send the POST request, with full SOAP envelope as the request body.
 http.Response response = await http.post(Uri.parse(
  'https://lite.realtime.nationalrail.co.uk/OpenLDBWS/ldb11.asmx'),
  headers: {
    'Content-Type': 'text/xml; charset=utf-8',
    'SOAPAction': 'http://thalesgroup.com/RTTI/2017-10-01/ldb/GetDepartureBoard'
  },
  body: soap
);


var rawXmlResponse = response.body;


final parsedXml = XmlDocument.parse (rawXmlResponse);
print(parsedXml);


}

API 的提供者在他们的文档中声明

    This token shall be passed as a SOAP Header value.

我包含在body 中是否足够或我如何在该部分中引用它...

headers: {
    'Content-Type': 'text/xml; charset=utf-8',
    'SOAPAction': 'http://thalesgroup.com/RTTI/2017-10-01/ldb/GetDepartureBoard'

这是一个例子 - https://wiki.openraildata.com/index.php/GetDepBoardWithDetails

数据来自 - https://realtime.nationalrail.co.uk/OpenLDBWS/

谢谢

更新调用

String soap = 
  '''
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns1="http://thalesgroup.com/RTTI/2017-10-01/ldb/"
xmlns:ns2="http://thalesgroup.com/RTTI/2013-11-28/Token/ns2es">
 <SOAP-ENV:Header>
   <ns2:AccessToken>
     <ns2:TokenValue>my_token</ns2:TokenValue>
   </ns2:AccessToken>
 </SOAP-ENV:Header>
 <SOAP-ENV:Body>
   <ns1:GetDepartureBoardRequest>
     <ns1:numRows>10</ns1:numRows>
     <ns1:crs>MAN</ns1:crs>
   </ns1:GetDepartureBoardRequest>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>''';
 

  // Send the POST request, with full SOAP envelope as the request body.
 http.Response response = await http.post(Uri.parse(
  'https://realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01'),
  headers: {
    'SOAPAction': 'http://thalesgroup.com/RTTI/2017-10-01/ldb/GetDepartureBoard'
  },
  body: soap
);

更新回复

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://thalesgroup.com/RTTI/2017-10-01/ldb/" targetNamespace="http://thalesgroup.com/RTTI/2017-10-01/ldb/">
<wsdl:import namespace="http://thalesgroup.com/RTTI/2017-10-01/ldb/" location="rtti_2017-10-01_ldb.wsdl"/>
<wsdl:service name="ldb">
  <wsdl:port name="LDBServiceSoap" binding="tns:LDBServiceSoap">
    <soap:address location="https://realtime.nationalrail.co.uk/OpenLDBWS/ldb11.asmx"/>
  </wsdl:port>
  <wsdl:port name="LDBServiceSoap12" binding="tns:LDBServiceSoap12">
    <soap12:address location="https://realtime.nationalrail.co.uk/OpenLDBWS/ldb11.asmx"/>
  </wsdl:port>
</wsdl:service>
</wsdl:definitions>

这是哪个网页 - https://realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01

【问题讨论】:

  • 您的ns2 看起来完全错误。将其与链接的示例进行比较,您会发现它应该是 "http://thalesgroup.com/RTTI/2013-11-28/Token/types" 您是否尝试过示例中的确切 XML(但使用您的访问令牌)?另一件小事:你已经说过你的内容在内容标题中是 utf-8,所以让正文 utf8.encode(soap) 否则 http 将为你编码它在 Latin-1 中,大部分时间都是一样的,直到它不是...

标签: xml flutter dart soap


【解决方案1】:

正确的 SOAP 消息应该如下所示:

<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns1="http://thalesgroup.com/RTTI/2017-10-01/ldb/"
xmlns:ns2="http://thalesgroup.com/RTTI/2013-11-28/Token/ns2es">
 <SOAP-ENV:Header>
   <ns2:AccessToken>
     <ns2:TokenValue>my_token</ns2:TokenValue>
   </ns2:AccessToken>
 </SOAP-ENV:Header>
 <SOAP-ENV:Body>
   <ns1:GetDepartureBoardRequest>
     <ns1:numRows>10</ns1:numRows>
     <ns1:crs>MAN</ns1:crs>
   </ns1:GetDepartureBoardRequest>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

注意ns1ns2 命名空间。

根据您发布的文档,要使用的 WSDL 位于 https://realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01,基于该 WSDL 使用的命名空间是我发布的消息中的命名空间。您使用的示例看起来较旧;该页面于 2016 年 10 月 18 日 20:51 发布,但 WSDL 上的版本参数显示为 2017)。

在编写代码之前,我建议您将该 WSDL 链接提供给 SoapUI 并进行一些测试调用,直到您使用 SoapUI 进行调用。然后,您可以编写代码来复制 SoapUI 发出的请求。

显然,您还需要一个有效的令牌才能发送到服务。由于它用于访问,如果您没有发送有效的,那么即使您的 SOAP 消息已正确构建,您显然也无法获得访问权限。

所有获得许可的用户都将获得访问公共网络服务的令牌。该令牌应作为 SOAP 标头值传递。该服务将拒绝所有没有令牌或令牌代码不正确的请求。

您是许可用户吗?您是否从他们那里收到了用于通话的令牌?

编辑:在问题中添加了额外的细节之后。

您没有将 SOAP 消息发送到正确的端点。您需要向https://realtime.nationalrail.co.uk/OpenLDBWS/ldb11.asmx 而非https://realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01 发送POST。

https://realtime.nationalrail.co.uk/OpenLDBWS/wsdl.aspx?ver=2017-10-01 URL 只是为您提供服务的 WSDL,而 WSDL 中的 SOAP 地址告诉您服务的端点实际在哪里:

<soap:address location="https://realtime.nationalrail.co.uk/OpenLDBWS/ldb11.asmx"/>

您可能还想阅读以下内容:

关于如何获取服务及其端点的 WSDL,通常约定是使用POST endpoint 来调用服务,并使用GET endpoint?wsdl 来获取 WSDL。但这只是一个约定。这两件事可以彼此分开,在你的情况下它们是分开的。您在一个端点上获得 WSDL,而调用在另一个端点上完成。这就是您需要使用不同端点的原因。

【讨论】:

  • 感谢您的全面回复。我发现的信息多种多样,有些过时了,所以很难将它们拼凑在一起。我已经实施了您的编辑并有一个新的回复,我已在 Q 中以update 的形式发布。您关于令牌的问题,是的,我是一名许可用户,我拥有可以访问数据的完整令牌
  • @al246:查看我的答案的更新。
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多