inossidabile / wash_out

Dead simple Rails 4/5 SOAP server library
Other
342 stars 241 forks source link

Formatting issue in return #73

Closed ben-ward closed 11 years ago

ben-ward commented 11 years ago

I need to format a return as "<tns:AuthenticateResult>", but I have not been able to find a way. Instead I get "<AuthenticateResult xsi:type="tns:AuthenticateResult">". I've tried changing both snakecase and camelcase values. Any help would be greatly appreciated.


What I need

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://developer.intuit.com/">
    <SOAP-ENV:Body>
        <ns1:authenticateResponse>
            <ns1:authenticateResult>
                <ns1:string>15c9ce293bd3f41b761c21635b14fa06</ns1:string>
                <ns1:string></ns1:string>
            </ns1:authenticateResult>
        </ns1:authenticateResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

What I am getting

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://developer.intuit.com/">
  <soap:Body>
    <tns:authenticateResponse>
      <AuthenticateResult xsi:type="tns:AuthenticateResult">
        <String xsi:type="xsd:string">abf36037372fa6cf089dbdbc33b11771908afe57</String>
        <String xsi:type="xsd:string"></String>
      </AuthenticateResult>
    </tns:authenticateResponse>
  </soap:Body>
</soap:Envelope>

My code

soap_action "authenticate",
              :args => {:strUserName => :string, :strPassword => :string},
              :return => { :authenticate_result => [{string: [:string]}]}
  def authenticate
    username = params[:strUserName]
    password = params[:strPassword]
    if (Role.find_by_token(username))
      if QuickbooksImportStatus.find_by_token(username).blank?
        QuickbooksImportStatus.create(:username => User.find(Role.find_by_token(username).user_id).username, :password => password, :token => username, :returnqid => 25, :company_id => Role.find_by_token(username).company_id, :querystatus => "")
      end
      render :soap => {:authenticate_result => [{string: [username, '']}]}
end
inossidabile commented 11 years ago

SOAP is not a protocol where you typically care what's going on inside XML transport. Can you please describe me a reason of all this? Why would you want to have exactly this output?

ben-ward commented 11 years ago

My apologies. I'm attempting to use washout as a SOAP server to take requests from QBWC. The Authenticate request from QBWC is getting processed fine in Rails but QBWC doesn't like the response. QBWC returns "There is an error in XML document (10, 28)." This is poor error messaging from the Quickbooks Web Connector (QBWC). If I knew what was malformed about it, I could work on it. I guess I need to check the Intuit forums instead.

Here is the log from QBWC.

20121130.03:23:07 UTC : QBWebConnector.SOAPWebService.do_authenticate() : Authenticating to application 'ImportQuickbookToCheqbook_BenCo', username = 'abf36037372fa6cf089dbdbc33b11771908afe57' 20121130.03:23:07 UTC : QBWebConnector.SOAPWebService.do_authenticate() : *\ Calling authenticate() with following parameters:<password= 20121130.03:23:07 UTC : QBWebConnector.SOAPWebService.do_authenticate() : QBWC1012: Authentication failed due to following error message. There is an error in XML document (10, 28). More info: StackTrace = at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events) at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle) at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) at QBWebConnector.localhost.WCWebServiceRPC.authenticate(String strUserName, String strPassword) at QBWebConnector.localhost.WCWebService.authenticate(String strUserName, String strPassword) at QBWebConnector.SOAPWebService.authenticate(String UserName, String Password) at QBWebConnector.WebService.do_authenticate(String& ticket, String& companyFileName)

ben-ward commented 11 years ago

Quickbooks makes a validator tool that checks the xml.

Here is a good request altered by hand. Note the fifth line. <tns:authenticateResult>

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://developer.intuit.com/">
  <soap:Body>
    <tns:authenticateResponse>
      <tns:authenticateResult>
        <String xsi:type="xsd:string">abc111</String>
        <String xsi:type="xsd:string">none</String>
      </tns:authenticateResult>
    </tns:authenticateResponse>
  </soap:Body>
</soap:Envelope>

Here is a bad request I'm currently sending. Note the fifth line. <AuthenticateResult xsi:type="tns:AuthenticateResult">

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://developer.intuit.com/">
  <soap:Body>
    <tns:authenticateResponse>
      <AuthenticateResult xsi:type="tns:AuthenticateResult">
        <String xsi:type="xsd:string">abc111</String>
        <String xsi:type="xsd:string">none</String>
      </AuthenticateResult>
    </tns:authenticateResponse>
  </soap:Body>
</soap:Envelope>

Here is the error.

Requested validation for QB US or Online Ed. (qbxml), file has processing instruction indicating <?qwc... obeying processing instruction
Line: 5
LinePos: 61
Src Text: <AuthenticateResult xsi:type="tns:AuthenticateResult">
Reason: Type '{http://developer.intuit.com/}AuthenticateResult' is not found in Schema.

Thanks again for your help.

inossidabile commented 11 years ago

You can achieve that by turning camelization off and forcing the following options:

soap_action "authenticate",
  :args => {:strUserName => :string, :strPassword => :string},
  :return => { "tns:authenticateResult" => [{"tns:string" => [:string]}] },
  :response_tag => "tns:authenticateResponse"

Don't forget to update wash_out to the latest (0.5.4) release and also use same string values among render :soap => ... result hash keys.

ben-ward commented 11 years ago

Thanks! This was a huge help. :response_tag was the option I was missing!

klancaster commented 11 years ago

I am trying to use the example code you posted above and am not getting the expected output. Using the soap_action as defined in your last response, I am getting

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="urn:WashOut">
  <soap:Body>
    <tns:authenticateResponse>
      <tns:authenticateResult xsi:type="tns:tns:authenticateResult">
        <tns:string xsi:type="xsd:string">sokAF1syyAr2Ci2Hay1K</tns:string>
        <tns:string xsi:type="xsd:string">none</tns:string>
      </tns:authenticateResult>
    </tns:authenticateResponse>
  </soap:Body>
</soap:Envelope>

The render soap call is

    render soap: {"tns:authenticateResult" => [{"tns:string" => response}]}

Any thoughts on how to get rid of the xsi:type="tns:tns:authenticateResult ?

inossidabile commented 11 years ago

Do you use QuickBook too? :)

klancaster commented 11 years ago

Yes - I am also dealing with the abominations that is Quickbooks :-(

klancaster commented 11 years ago

Do you have a solution for the issue I posted? Am I going something wrong?

inossidabile commented 11 years ago

Give me a bit of time. I'll take a closer look soon.

inossidabile commented 11 years ago

@klancaster well. After playing with it a bit... Can you just remove tns prefixes?

  soap_action "authenticate",
    :args => {:strUserName => :string, :strPassword => :string},
    :return => { "authenticateResult" => [{"string" => [:string]}] },
    :response_tag => "tns:authenticateResponse"

I need to know what Quickbooks responds to this. It's pretty difficult to debug without a client :\

bobmacneal commented 9 years ago

@inossidabile For anyone else who runs into this issue with the authenticate SOAP response for Quickbooks Web Connector (QBWC), the following worked for me:

soap_action 'authenticate',   :args => {:strUserName => :string, :strPassword => :string},   :return => {'tns:authenticateResult' => {'tns:string' => [:string]}},   :response_tag => 'authenticateResponse'

My authenticate method has the follow return: render :soap => {'tns:authenticateResult' => {'tns:string' => auth_array}} where auth_array is a ruby array with the two string values QBWC is expecting.

wash_out is a well-executed and helpful gem :+1:. Thank you. Quickbooks is awful to integrate with :-1:

niteshguptaoyo commented 6 years ago

how to get rid of "xsi:type" in each element?