2010-03-05 132 views
15

所以我試圖使用SUDS訪問這個API https://www.clarityaccounting.com/api-docs/。下面是應該工作的代碼:你能幫我解決這個SUDS/SOAP問題嗎?

from suds.client import Client 
client = Client('https://www.clarityaccounting.com/api/v1?wsdl') 
token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000) 

但我得到這個錯誤:

WebFault: Server raised fault: 'No such operation: (HTTP GET PATH_INFO: /api/v1)' 

他們的支持傢伙說,要求應該是這樣的:

<SOAP-ENV:Envelope 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:api="http://api.service.books/"> 
    <SOAP-ENV:Body> 
    <api:doLogin> 
     <username>demo</username> 
     <password>demo</password> 
     <siteName>www.kashoo.com</siteName> 
     <locale>en_US</locale> 
     <duration>300000</duration> 
    </api:doLogin> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

但肥皂水」看起來像這樣:

<?xml version="1.0" encoding="UTF-8"?> 
<SOAP-ENV:Envelope 
xmlns:ns0="http://api.service.books/" 
xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header/> 
    <ns1:Body> 
     <ns0:doLogin> 
     <username>demo</username> 
     <password>demo</password> 
     <siteName>www.kashoo.com</siteName> 
     <locale>en_US</locale> 
     <duration>300000</duration> 
     </ns0:doLogin> 
    </ns1:Body> 
</SOAP-ENV:Envelope> 

我是一個真正的SOAP和SUDS新手,但我聽說SUDS是從這裏使用最好的SOAP庫:What SOAP client libraries exist for Python, and where is the documentation for them?

所以我的問題是什麼是不同的關鍵部分,並使請求失敗以及如何配置SUDS以發送格式正確的請求?

回答

35

初看起來您正在使用SSL的問題。您正在訪問https URL,並且suds.client的傳輸處理程序會默認通知http。

問題
如果你看看它指定的默認位置爲http://www.clarityaccounting.com/api/v1,這是一個HTTP URL的WSDL的底部,但WSDL是SSL。

<wsdl:service name="v1"> 
    <wsdl:port binding="tns:v1SoapBinding" name="BooksApiV1Port"> 
     <soap:address location="http://www.clarityaccounting.com/api/v1"/> 
    </wsdl:port> 
</wsdl:service> 

如果你做一個HTTP GET在該網址上,你得到你所收到的錯誤消息:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <soap:Fault> 
      <faultcode>soap:Server</faultcode> 
      <faultstring>No such operation: (HTTP GET PATH_INFO: /api/v1)</faultstring> 
     </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

解決方案
要解決這個問題,你需要你的時候覆蓋默認位置請致電Client構造函數使其與https粘貼:

>>> url 
'https://www.clarityaccounting.com/api/v1?wsdl' 
>>> client = Client(url, location='https://www.clarityaccounting.com/api/v1') 
>>> token = client.service.doLogin('demo', 'demo', 'www.kashoo.com', 'en_US', 300000) 
>>> token 
(authToken){ 
    authenticationCode = "ObaicdMJZY6UM8xZ2wzGjicT0jQ=" 
    expiryDate = 2010-03-05 12:31:41.000698 
    locale = "en_US" 
    myUserId = 4163 
    site = "www.kashoo.com" 
} 

勝利!

專業提示用於未來的調試目的:打開完整日誌記錄調試。 SUDS使用標準的logging庫,因此它給你很多控制權。所以我拍成了這一切給DEBUG

import logging 
logging.basicConfig(level=logging.INFO) 
logging.getLogger('suds.client').setLevel(logging.DEBUG) 
logging.getLogger('suds.transport').setLevel(logging.DEBUG) 
logging.getLogger('suds.xsd.schema').setLevel(logging.DEBUG) 
logging.getLogger('suds.wsdl').setLevel(logging.DEBUG) 

這是幫我縮小它,因爲它清楚地說是通過HTTP發送:

DEBUG:suds.transport.http:sending: 
URL:http://www.clarityaccounting.com/api/v1 
(xml output omitted) 

然後響應,從而說well:

DEBUG:suds.client:http failed: 
+1

很高興幫助!在星期五下午搞清楚是個有趣的問題。 – jathanism 2010-03-05 22:06:36

+3

+1 Nice touch包含調試幫助 – Draemon 2010-03-17 11:51:12

+0

謝謝!我只是遇到了與其他Web服務相同的問題,但同樣的https/http問題。即使WSDL表示使用http,我也無法找到如何設置客戶端使用https。 – 2010-09-16 14:21:34

1

它不應該是通過HTTPS連接到服務的問題。我用泡沫做同樣的事情。我已經嘗試了一些WSDL文件的方法(而不是專家),並且遇到了同樣的錯誤。用泡沫練習你應該做的是使用工廠方法,例如,

login = client.factory.create('doLogin') 
login.username = 'username' 
etc... 

發送到create函數的任何東西都是WSDL文件中定義的類型之一。如果您在shell中創建該類型,則可以運行「print login」以查看其附加屬性。

希望這至少告訴你問題不在何處(使用HTTPS)。另外,我注意到soapAction頭文件沒有在WSDL文件中設置,不確定如果沒有這些文件,suds或服務如何處理請求。

+0

正如您在修改後的答案中所看到的,問題不在於通過https連接,而在於通過https服務的WSDL不一致,同時指向SOAP的SOAP調用。我的猜測是,他們配置服務的方式將傳入URL從http重定向到https是問題的根源。我們所做的一切都是圍繞着它而做的。 – jathanism 2010-03-05 20:46:53

+0

調試zee win! – bennylope 2010-03-05 21:24:19

1

使用泡沫 - jurko https://pypi.python.org/pypi/suds-jurko這是一個維護的泡沫叉。 您可以傳入一個__inject選項,您可以在其中輸入要發送的原始xml。

from suds.client import Client 

username, password, sitename, locale, duration = 'demo', 'demo', 'www.kashoo.com', 'en_US', 300000 

raw_xml = """<SOAP-ENV:Envelope 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:api="http://api.service.books/"> 
    <SOAP-ENV:Body> 
    <api:doLogin> 
     <username>{0}</username> 
     <password>{1}</password> 
     <siteName>{2}</siteName> 
     <locale>{3}</locale> 
     <duration>{4}</duration> 
    </api:doLogin> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>""".format(username, password, sitename, locale, duration) 

client = Client(url, location) 
result = client.service.doLogin(__inject={'msg':raw_xml}) 

我覺得我應該記錄所有可以檢查泡沫在這裏產生的生肥皂的方式。

  1. 構建客戶端時使用鼻子標誌。請注意,將該標誌設置爲True,泡沫只會生成肥皂但不會發送。

    client =Client(url, nosend=True)
    res = client.service.example()
    print res.envelope #prints原肥皂

  2. 使用記錄。這裏我們只記錄suds.transport.http,所以它只會輸出發送/接收的任何內容。

    import logging
    import sys
    handler = logging.StreamHandler(sys.stderr)
    logger = logging.getLogger('suds.transport.http')
    logger.setLevel(logging.DEBUG), handler.setLevel(logging.DEBUG)
    logger.addHandler(handler)

  3. 使用MessagePlugin

    from suds.plugin import MessagePlugin
    class MyPlugin(MessagePlugin):
    def marshalled(self, context):
    #import pdb; pdb.set_trace()
    print context.envelope.str()

    client = Client(url, plugins=[MyPlugin()])

不僅在MessagePlugin給你檢查所產生的肥皂,但你也可以在發送之前修改它的能力,見式>https://jortel.fedorapeople.org/suds/doc/suds.plugin.MessagePlugin-class.html

相關問題