9

私が制御していない SOAP サービスにアクセスしようとしています。アクションの 1 つが呼び出され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 アプリの違いは、そのタグだけです。その1つのタグの前にある名前空間を取り除き、その"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を試しましたが、ハンドソープよりもさらに混乱しています。

4

4 に答える 4

10

配列を soap.input に渡す必要があります。その 2 番目の要素は名前空間の詳細を含むハッシュです。

soap.input = [ 
  "ProcessMessage", 
  {"xmlns" => "http://www.starstandards.org/webservices/2005/10/transport"}
]

これにより、メイン要素への属性として名前空間宣言が確実に終了するはずです。

おそらく、要素の前に名前空間宣言が行われることになるでしょう。

<env:Body>
    <wsdl:ProcessMessage xmlns="........." >
        <payload>
            ......
        </payload>
    </wsdl:ProcessMessage>
</env:Body>

しかし、これは私にとっては問題ではありませんでした。要素の前に名前空間が存在することではなく、名前空間属性がないことが問題でした。

于 2010-03-16T09:20:06.173 に答える
7

"wsdl"私の Web サービスでは、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
于 2011-08-06T22:26:01.037 に答える
4

スティーブ、wsdl: が ProcessMessage タグの前にあるのがわかりますか? - 私はそれが私を失望させていた唯一のものだと思っていましたが、そうではありませんでした (ちなみに、160 行目の Savon lib の soap.rb でハードに設定されています)。それをsoap.namespacesで指定しなくても、最終的なxmlで生成して添付するのは難しいです。これは私のサービスでは許可されていません。

生成された xml は有効な xml ですが、通信しようとしているサービスの要件によっては完全ではありません。すなわち:生成されたxmlで、

<?xml version="1.0" encoding="UTF-8"?>

タグがありません。また、ヘッダーに 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

これは最終的に機能します!!!!

これを rubii に提案します - このオプションが利用可能になると、多くのまれなケースが解決されます - カスタム xml を生成し、savon lib の残りの部分を使用できます。

于 2010-03-16T20:39:12.030 に答える