我正在尝试访问我无法控制的SOAP服务.其中一个动作叫做ProcessMessage.我按照示例生成了一个SOAP请求,但是我收到一条错误,说该操作不存在.我将问题追溯到信封体生成的方式.
<env:Envelope ... ">
<env:Header>
<wsse:Security ... ">
<wsse:UsernameToken ...">
<wsse:Username>USER</wsse:Username>
<wsse:Nonce>658e702d5feff1777a6c741847239eb5d6d86e48</wsse:Nonce>
<wsu:Created>2010-02-18T02:05:25Z</wsu:Created>
<wsse:Password ... >password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
<wsdl:ProcessMessage>
<payload>
......
</payload>
</wsdl:ProcessMessage>
</env:Body>
</env:Envelope>
Run Code Online (Sandbox Code Playgroud)
那个ProcessMessage标签应该是:
<ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport">
Run Code Online (Sandbox Code Playgroud)
这就是样本Java应用程序生成它时的工作原理.该标记是我的Ruby应用程序生成的示例和示例Java应用程序之间的唯一区别.有没有办法摆脱"wsdl:"那个标签前面的命名空间,并添加这样的属性.除此之外,有没有办法强制动作不是通过像身体其他部分一样传递出来的?
这是我的代码:
require 'rubygems'
require 'savon'
client = Savon::Client.new "https://gmservices.pp.gm.com/ProcessMessage?wsdl"
response = client.process_message! do | soap, wsse |
wsse.username = "USER"
wsse.password = "password"
soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport" #makes no difference
soap.action = "ProcessMessage" #makes no difference
soap.input = "ProcessMessage" #makes no difference
#my body at this point is jsut one big xml string
soap.body = "<payload>...</payload>"
# putting <ProccessMessage> tag here doesn't help as it just creates a duplicate tag in the body, since Savon keeps interjecting <wsdl:ProcessMessage> tag.
end
Run Code Online (Sandbox Code Playgroud)
我尝试过handsoap但它不支持HTTPS并且令人困惑.我试过soap4r,但它比handsoap更令人困惑.
Ste*_*eet 10
您需要将数组传递给soap.input,其中第二个元素是包含命名空间详细信息的哈希.
soap.input = [
"ProcessMessage",
{"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"}
]
Run Code Online (Sandbox Code Playgroud)
这应该确保您最终将名称空间声明作为主元素的属性.
您可能还会在元素之前结束命名空间声明
<env:Body>
<wsdl:ProcessMessage xmlns="........." >
<payload>
......
</payload>
</wsdl:ProcessMessage>
</env:Body>
Run Code Online (Sandbox Code Playgroud)
但这对我来说不是问题,缺少名称空间属性是问题,而不是元素之前存在命名空间.
对于我的Web服务,我需要"wsdl"在Steve的解决方案之外摆脱名称空间.
使用Savon 0.9.6测试:
client = Savon::Client.new "https://example.com/webservice/account.asmx?WSDL"
response = client.request "GetAccount" do
# Gotcha 1: set default namespace for body elements
soap.input = ["GetAccount", {"xmlns" => "https://example.com/webservice/"}]
soap.body = {
"AccountID" => 1234
}
# Gotcha 2: get rid of namespace declaration of body elements
soap.element_form_default = :unqualified
# Gotcha 3: set SOAPAction different from default
http.headers["SOAPAction"] = '"https://example.com/webservice/GetAccount"'
end
Run Code Online (Sandbox Code Playgroud)
Steve,您看到 ProcessMessage 标记前面的 wsdl: 了吗?- 我以为这是唯一让我失望的事情,但事实并非如此(顺便说一句,它是在 Savon lib 中的soap.rb 第 160 行中硬设置的)。即使我不在soap.namespaces 中对其进行spacify,它也很难生成并附加在最终的xml 中。这是我的服务不允许的。
虽然生成的 xml 是有效的 xml,但它不符合我尝试与之交谈的服务的要求。即:在生成的 xml 中,
<?xml version="1.0" encoding="UTF-8"?>
Run Code Online (Sandbox Code Playgroud)
标签缺失,另外,我需要在标头中添加 PayloadManifest,另外我需要在 wsse: 标签中使用 wsu:created 和 wsu:expires,但它们没有实现,等等,等等。还有一些太具体的小怪癖就我的情况而言。然而soap有一个私有方法= xml_body。to_xml 方法中的soap lib 还在生成自己的xml 之前检查@xml_body 是否已设置。所以我最终稍微修改了肥皂的行为。通过使soap.xml_body = 可公开访问。所以我能够做到:
response = client.process_message! do |soap|
soap.action = "http://www.starstandards.org/webservices/2005/10/transport/operations/ProcessMessage"
soap.xml_body = "MY XML STRING GENERATED ELSEWHERE GOES HERE"
end
Run Code Online (Sandbox Code Playgroud)
终于有效了!!!
我会向 rubii 建议这个 - 如果这个选项可用,这将解决很多罕见的情况 - 人们可以生成他们的自定义 xml 并使用 savon lib 的其余部分。
| 归档时间: |
|
| 查看次数: |
8636 次 |
| 最近记录: |