Я пытаюсь получить доступ к сервису 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>
Это ProcessMessage
тег должен быть:
<ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport">
Вот что это значит, когда это сгенерировано демонстрационным приложением 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
Я попробовал handsoap, но он не поддерживает HTTPS и сбивает с толку. Я попробовал soap4r, но но это еще более сбивает с толку, чем handsoap.
Стив, ты видишь этот wsdl: перед тегом ProcessMessage? - Я думал, что это единственная вещь, которая выводит меня из строя, но это не так (кстати, это жестко задано в soap.rb в Savon lib на строке 160). То есть даже если я не прописываю его в soap.namespaces - он жестко генерируется и подключается в финальном xml. Что не разрешено моим сервисом.
Хотя сгенерированный xml является валидным xml - он не является полным по требованиям сервиса, с которым я пытаюсь общаться. Т.е.: в сгенерированном xml не хватает
<?xml version="1.0" encoding="UTF-8"?>
tag, также мне нужен PayloadManifest в заголовке, плюс мне нужны wsu:created и wsu:expires в моем wsse: tag, но они не реализованы, и т.д., и т.п. куча других мелких причуд, которые слишком специфичны для моего случая. Однако у soap есть приватный метод = xml_body. Также либа soap в методе to_xml проверяет, был ли уже установлен @xml_body, прежде чем генерировать свой собственный xml. В итоге я слегка изменил поведение мыла, сделав soap.xml_body = publicly accessable. Таким образом, я смог сделать:
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
Что наконец-то работает!!!!
Я предложу это rubii - если эта опция станет доступной, это решит много редких случаев - когда люди могут генерировать свои собственные xml и использовать остальную часть savon lib.
Вам нужно передать массив в soap.input, второй элемент которого является хешем, содержащим детали пространства имен.
soap.input = [
"ProcessMessage",
{"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"}
]
Это должно гарантировать, что вы закончите с объявлением пространства имен в качестве атрибута для основного элемента.
Вы, вероятно, также получите объявление пространства имен перед элементом вроде этого
<env:Body>
<wsdl:ProcessMessage xmlns="........." >
<payload>
......
</payload>
</wsdl:ProcessMessage>
</env:Body>
, но это не было проблемой для меня, проблема заключалась в отсутствии атрибута пространства имен, а не в наличии пространства имен раньше элемент.