Гем Ruby Savon 2: невозможно указать дочерние и дочерние элементы XML для выполнения действительного запроса к веб-сервису SOAP API

Провел огромное количество поисковых запросов и просмотрел документацию по Savon 2, но я не думаю, что правильно указываю в своем рубиновом коде дочерние и дочерние элементы XML, которые мне нужны для успешного запроса к этому веб-сервису SOAP.

В main2.rb я попытался использовать синтаксис квадратных скобок, чтобы перейти по документу от BookReservationRequest до Booker к UserWithoutALogin. (Этот подход с квадратными скобками работал в другом примере на стороне ответа). Почему-то я не указываю их должным образом в Ruby, поскольку, когда я удаляю эти теги в пользовательском интерфейсе SOAP, я получаю точно такое же сообщение об ошибке ниже. (N.B Я все еще новичок в Ruby!)

Полная трассировка ошибки:

ruby main2.rb
/Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:85:in `raise_soap_and_http_errors!': (soap:Server) System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. (Savon::SOAPFault)
   at Services.Internal.Helpers.CustomerHelper.GetCustomerIdFromGuestOrBookerType(Nullable`1 partnerServiceId, GuestOrBookerType guestOrBookerType) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Helpers\CustomerHelper.cs:line 64
   at Services.Internal.Service.BookReservation(BookReservationRequest bookReservationRequest) in c:\TeamCity\LB-QA-04\work\e2ec20c745b940f9\Source\Services\Internal\Service.asmx.cs:line 289
   --- End of inner exception stack trace ---
    from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:14:in `initialize'
    from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `new'
    from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:72:in `create_response'
    from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/operation.rb:58:in `call'
    from /Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/client.rb:36:in `call'
    from main2.rb:11:in `core_info'
    from main2.rb:23:in `<main>'

Код Ruby (main2.rb):

require 'savon'

class BookReservation

  def client
    client = Savon.client(wsdl: "http://some-example-soap-wsdl-link", follow_redirects: :follow_redirects)
  end

  def core_info(partner_code, restaurant_location_id, session_id, dining_date_and_time, size)
    message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
    response = client.call(:book_reservation, message: message)
    response.hash[:book_reservation_response]
  end

  def booker_info(first_name, last_name, email, guest_accepts_email_marketing)
    message = { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing }
    response = client.call([:book_reservation][:booker][:user_without_a_login], message: message)
    response.body[:book_reservation_response]
  end
end

  book = BookReservation.new
  puts book.core_info("DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2", )
  puts book.booker_info("John", "Smith", "[email protected]", "true")

Этот xml-документ в SoapUI каждый раз возвращает действительный / успешный ответ:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
    <soapenv:Header/>
    <soapenv:Body>      
        <ns:BookReservationRequest>            
            <ns:PartnerCode>DEV-DAN-BETH:73411</ns:PartnerCode>
            <ns:RestaurantLocationId>10799</ns:RestaurantLocationId>
            <ns:SessionId>DINNER</ns:SessionId>
            <ns:DiningDateAndTime>2015-06-20T21:00:00</ns:DiningDateAndTime>
            <ns:Size>2</ns:Size>
            <ns:Booker>
                <ns:UserWithoutALogin>
                    <ns:FirstName>John</ns:FirstName>
                    <ns:LastName>Smith</ns:LastName>
                    <ns:EMail>[email protected]</ns:EMail>                      
                    <ns:GuestAcceptsEmailMarketingFromPartner>true</ns:GuestAcceptsEmailMarketingFromPartner>
               </ns:UserWithoutALogin>
            </ns:Booker>       
        </ns:BookReservationRequest>
    </soapenv:Body>
</soapenv:Envelope>

Пример успешного ответа в SoapUI:

<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">
   <soap:Body>
      <BookReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
         <ConfirmationNumber>T2NVGBUN</ConfirmationNumber>
         <ReservationId>34277666</ReservationId>
         <AllowedToCancelOnline>true</AllowedToCancelOnline>
      </BookReservationResponse>
   </soap:Body>
</soap:Envelope>

Большое спасибо заранее!


person daneasterman    schedule 18.06.2015    source источник
comment
Также я попытался преобразовать символы букера и user_without_a_login в квадратных скобках в исходные строки XML-регистра верблюда - то есть: ['Booker'] ['UserWithoutALogin'], но это тоже не работает - получите точно такое же сообщение об ошибке!   -  person daneasterman    schedule 18.06.2015


Ответы (1)


Ваш пример сообщения SOAP содержит тело, которое содержит запрос на резервирование книги, который включает блок Booker.

ваш BookReservation класс, однако, содержит два метода, которые вызывают клиента Savon - один из них отправляет BookReservationRequest, но вы никогда не добавляете Booker в хэш сообщения до его отправки.

Почти на 100% уверен, что ваш клиент отправляет недопустимый запрос SOAP, потому что вы не указали блок <ns:Booker> в своем теле SOAP.

Я подозреваю, что если вы обновили свой класс, чтобы он содержал один метод, который выглядел бы следующим образом:

def execute(partner_code, restaurant_location_id, session_id, dining_date_and_time, size, first_name, last_name, email, guest_accepts_email_marketing)
    message = { 'PartnerCode' => partner_code, 'RestaurantLocationId' => restaurant_location_id, 'SessionId' => session_id, 'DiningDateAndTime' => dining_date_and_time, 'Size' => size }
    message.merge!('Booker' => { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing })

    response = client.call(:book_reservation, message: message)
    response.hash[:book_reservation_response]

конец

И назвал его:

book.execute(
  "DEV-DAN-BETH:73411", "10799", "DINNER", "2015-06-20T21:00:00", "2",
   "John", "Smith", "[email protected]", "true" )

Тебе повезет больше.

person mcfinnigan    schedule 18.06.2015
comment
Спасибо, @macfinnigan, кажется, мы почти у цели. Я только что попробовал ваше решение, но теперь получаю новую ошибку: System.ArgumentNullException: Value cannot be null. (Savon::SOAPFault) конечно, мне нужно также указать UserWithoutALogin в Букере - как мне это сделать в коде? - person daneasterman; 18.06.2015
comment
Также все значения в вызове execute должны быть строками? т.е. также 2 и правда? - person daneasterman; 18.06.2015
comment
Я отредактировал его так: message.merge!('Booker' => {'UserWithoutALogin' => { 'FirstName' => first_name, 'LastName' => last_name, 'EMail' => email, 'GuestAcceptsEmailMarketingFromPartner' => guest_accepts_email_marketing }}) и при запуске не было ошибок, но данные не распечатывались. - person daneasterman; 18.06.2015
comment
Не волнуйтесь, внесли несколько мелких правок и получили данные ответа на печать. Спасибо! - person daneasterman; 18.06.2015
comment
Рад слышать, что вы попали туда. Я всегда использую метод сброса сгенерированного XML в журнал или на консоль, чтобы понять, почему он отличается от того, каким должен быть. XML - это заноза в заднице. :) - person mcfinnigan; 18.06.2015
comment
вы действительно помогли мне раньше, но теперь у меня возникла еще одна аналогичная проблема - но на этот раз для доступа к сильно вложенному хэшу (проанализированному из xml) - мне нужно получить доступ ко всем значениям и установить их как переменные экземпляра - какие-либо идеи? Это необработанные данные, с которыми я работаю: gist.github.com/daneasterman/4dafacbd6d5a5e3dbcb1 - person daneasterman; 02.07.2015