views:

518

answers:

2

I'm trying to communicate with a soap service and I know that I should send a SOAP Envelope like this:

POST /webpay_test/SveaWebPay.asmx HTTP/1.1
Host: webservices.sveaekonomi.se
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "https://webservices.sveaekonomi.se/webpay/CreateOrder"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  <soap:Body>
    <CreateOrder xmlns="https://webservices.sveaekonomi.se/webpay"&gt;
      <request>
        <Order>
          <ClientOrderNr>string</ClientOrderNr>
          <CustomerReference>string</CustomerReference>
          <OrderDate>dateTime</OrderDate>
          <CountryCode>string</CountryCode>
          <SecurityNumber>string</SecurityNumber>
          <CustomerEmail>string</CustomerEmail>
          <IsCompany>boolean</IsCompany>
          <PreApprovedCustomerId>long</PreApprovedCustomerId>
          <AddressSelector>string</AddressSelector>
        </Order>
        <InvoiceRows>
          <ClientInvoiceRowInfo>
            <ArticleNr>string</ArticleNr>
            <Description>string</Description>
            <PricePerUnit>double</PricePerUnit>
            <NrOfUnits>double</NrOfUnits>
            <Unit>string</Unit>
            <VatPercent>int</VatPercent>
            <DiscountPercent>int</DiscountPercent>
            <ClientOrderRowNr>int</ClientOrderRowNr>
          </ClientInvoiceRowInfo>
          <ClientInvoiceRowInfo>
            <ArticleNr>string</ArticleNr>
            <Description>string</Description>
            <PricePerUnit>double</PricePerUnit>
            <NrOfUnits>double</NrOfUnits>
            <Unit>string</Unit>
            <VatPercent>int</VatPercent>
            <DiscountPercent>int</DiscountPercent>
            <ClientOrderRowNr>int</ClientOrderRowNr>
          </ClientInvoiceRowInfo>
        </InvoiceRows>
      </request>
    </CreateOrder>
  </soap:Body>
</soap:Envelope>

here is the code I've wrote:

client = Savon::Client.new("https://webservices.sveaekonomi.se/webpay_test/SveaWebPay.asmx?wsdl")
res = client.create_order do |soap|  
    soap.namespace = "https://webservices.sveaekonomi.se/webpay_test/CreateOrder.asmx"
    soap.body = { :auth         => {  :username => "username", :password => "pass", :client_number => "1111" }, 
                  :order        => {  :client_order_nr => "1000000", :customer_reference => "4212", :order_date => Date.today, 
                                      :country_code => "SE", :security_number => "1111111111", :is_company => false, 
                                      :customer_email => "[email protected]", :pre_approved_customer_id => 0 },
                  :invoice_rows => { :client_invoice_row_info => { :article_nr => "x100", :description => "something cool -- description",
                                      :price_per_unit => 100, :nr_of_units => 3, :unit => "SEK", :vat_percent => 25,
                                      :discount_percent => 0, :client_order_row_nr => "1"},
                                     :client_invoice_row_info => { :article_nr => "x200", :description => "something cooler -- description",
                                      :price_per_unit => 200, :nr_of_units => 2, :unit => "SEK", :vat_percent => 25,
                                      :discount_percent => 0, :client_order_row_nr => "1" }  
                                   }
    }
end

and it generates this, which is different from what I have as the template and that's why I'm getting an error:

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:wsdl="https://webservices.sveaekonomi.se/webpay_test/CreateOrder.asmx" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"&gt;
<env:Body>
<wsdl:CreateOrder>
<invoiceRows>
  <clientInvoiceRowInfo>
    <clientOrderRowNr>1</clientOrderRowNr>
    <pricePerUnit>200</pricePerUnit>
    <nrOfUnits>2</nrOfUnits>
    <unit>SEK</unit>
    <vatPercent>25</vatPercent>
    <articleNr>x200</articleNr>
    <discountPercent>0</discountPercent>
    <description>something cooler -- description</description>
  </clientInvoiceRowInfo>
</invoiceRows>
<order>
    <customerEmail>[email protected]</customerEmail>
    <preApprovedCustomerId>0</preApprovedCustomerId>
    <countryCode>SE</countryCode>
    <clientOrderNr>1000000</clientOrderNr>
    <securityNumber>11111111</securityNumber>
    <customerReference>4212</customerReference>
    <isCompany>false</isCompany>
    <orderDate>2010-06-28</orderDate>
</order>
<auth>
    <password>pass</password>
    <clientNumber>1111</clientNumber>
    <username>username</username>
</auth>
</wsdl:CreateOrder>
</env:Body>
</env:Envelope>

and here is the response:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  <soap:Body>
    <CreateOrderResponse xmlns="https://webservices.sveaekonomi.se/webpay"&gt;
      <CreateOrderResult>
        <Accepted>false</Accepted>
        <ErrorMessage>Failed to create or authorize order</ErrorMessage>
        <SveaOrderNr>0</SveaOrderNr>
        <RejectionCode>Error</RejectionCode>
        <WillBuyInvoices xsi:nil="true" />
        <AuthorizeId>0</AuthorizeId>
        <AuthorizedAmount xsi:nil="true" />
        <ExpirationDate xsi:nil="true" />
      </CreateOrderResult>
    </CreateOrderResponse>
  </soap:Body>
</soap:Envelope>

could anyone tell me how can I solve this problem. and since I'm a newbie when it comes to SOAP would you also tell me if the order of the xml tags in the soap:Body tag is important or not?

+2  A: 

You are missing the <request> element.

Try replacing your soap.body with a single hash with a key of ::request and a value of the existing hash record that you have already.

EDIT 1

Your namespace line within your code should be "https://webservices.sveaekonomi.se/webpay" not the full URL you have there currently.

Steve Weet
Thanks for mentioning that. I added the request tag, but I still get the error. one thing is that savon generate env tags while the it should be soap tags. although both are sharing the same xmlns attribute? could it be the source of problm? the other thing is on CreateOrder tag. the specification asked for something like <CreateOrder xmlns="https://......"> while the savon is generating some like this <wsdl:CreateOrder>
Allen Bargi
Edited with another possible issue.
Steve Weet
A: 

Thanks to Steve, I found this post where Nick and Steve were talking about a similar problem. like Nick, my problem was in the way Savon is cooking up a soap Envlope. As recommended by Nick, I ended up monkey patching a couple of methods in soap class of savon gem. it's in lib/savon/soap.rb and I'm good to go now.

I'm a novice when it comes to SOAP and it's my first time writing a SOAP client, but honestly it SUCKS! I still remember my first time writing a client for a REST service and gush it was fun.

REST ROCKS, SOAP SUCKS. that's all!

Allen Bargi