Has anyone been able to get the suds soap library to work with the NetSuite WSDL?
Has anyone been able to get the suds soap library to work with the NetSuite WSDL? I get this error when I try to create a client.
from suds.client import Client
#url = 'http://mssoapinter开发者_运维问答op.org/asmx/simple.asmx?WSDL'
url = 'https://webservices.netsuite.com/wsdl/v2009_2_0/netsuite.wsdl'
client = Client(url)
print client
Traceback (most recent call last):
client = Client(url)
File "build\bdist.win32\egg\suds\client.py", line 112, in __init__
File "build\bdist.win32\egg\suds\reader.py", line 152, in open
File "build\bdist.win32\egg\suds\wsdl.py", line 158, in __init__
File "build\bdist.win32\egg\suds\wsdl.py", line 207, in resolve
File "build\bdist.win32\egg\suds\wsdl.py", line 662, in resolve
File "build\bdist.win32\egg\suds\wsdl.py", line 757, in resolvefaults
Exception: fault 'ExceededRecordCountFault' not defined in portType 'NetSuitePortType'
Yes, suds can connect to NetSuite, but it takes a long time to process the WSDL.
Here's some sample code:
# Open NetSuite Session
wsdlNetSuite = 'https://webservices.netsuite.com/wsdl/v2010_1_0/netsuite.wsdl'
client = Client(wsdlNetSuite)
# Login
passport = client.factory.create('ns4:Passport')
passport.email = 'username@web.com'
passport.password = 'ABC123'
passport.account = 123
loginResponse = client.service.login(passport)
print 'Login Response: '
print loginResponse.status
# Get a record
recordRef = client.factory.create('ns4:RecordRef')
recordRef._internalId = 127842
recordRef._type = 'invoice'
record = client.service.get(recordRef)
print record
You might also need to try various combinations of Python and SUDS versions. It's not a particularly reliable library.
It is a bit late, but for the record I attach a way of how one can work with NetSuite SuiteTalk SOAP API using Python Zeep.
Example of NetSuite SOAP login with Python and Zeep followed by adding a customer.
# pip3 install zeep
from zeep import Client
WSDL_URL = 'https://webservices.sandbox.netsuite.com/wsdl/v2016_1_0/netsuite.wsdl'
NS_EMAIL = 'admin@example.com'
NS_PASSWORD = '*********'
NS_ROLE = '1111'
NS_ACCOUNT = '1111111'
NS_APPID = 'FFFFFFFF-FFFF-0000-0000-FFFFFFFFFFFF'
def login_client():
client = Client(WSDL_URL)
Passport = client.get_type('ns1:Passport')
AppInfo = client.get_type('ns5:ApplicationInfo')
passport = Passport(email=NS_EMAIL, password=NS_PASSWORD, account=NS_ACCOUNT)
app_info = AppInfo(applicationId=NS_APPID)
login = client.service.login(passport=passport,
_soapheaders={'applicationInfo': app_info})
print('Login Response: ', login.status)
return client
# Example usage
client = login_client()
# add a customer
Customer = client.get_type('ns14:Customer')
customer = Customer(
lastName='Joe',
firstName='Bloggs',
email='joe@example.com'
)
response = client.service.add(customer)
print(response)
See also: https://github.com/fmalina/python-netsuite
Though not the best way to do things, if you're desperate, you can keep trying different versions of their wsdl. I was getting the same error message, so I kept trying until one worked. I went in this order:
'https://webservices.netsuite.com/wsdl/v2010_2_0/netsuite.wsdl'
'https://webservices.netsuite.com/wsdl/v2010_1_0/netsuite.wsdl'
'https://webservices.netsuite.com/wsdl/v2009_2_0/netsuite.wsdl'
'https://webservices.netsuite.com/wsdl/v2009_1_0/netsuite.wsdl'
'https://webservices.netsuite.com/wsdl/v2009_1_0/netsuite.wsdl' finally worked for me
EDIT: Based on tponthieux's answer, I realize now that you can use the suds plugin feature to fix the wsdl (I would simply comment on his answer, but I don't have the reputation yet :( ):
import re
from suds.client import Client
from suds.plugin import DocumentPlugin
NetSuite_wsdl = 'https://webservices.netsuite.com/wsdl/v2010_2_0/netsuite.wsdl'
class Fix_NS_wsdl(DocumentPlugin):
bad_fault = re.compile(r"(ExceededRequestLimitFault)"
r"(\">\s*<soap:fault name=\")(ExceededRecordCountFault)")
def loaded(self, context):
if context.url == NetSuite_wsdl:
context.document = self.bad_fault.sub(r"\1\2\1", context.document)
client = Client(NetSuite_wsdl, plugins=[Fix_NS_wsdl()])
If you want to do a one-off fix on a saved WSDL instead of doing the fix every time (which takes a while) here is a VIM substitution command that I used
:%s/RequestLimitFault">\n\t*<soap\:fault name=\"ExceededRecordCountFault/RequestLimitFault\"\>\r\t\t\t\t<soap\:fault name=\"Exce ededRequestLimitFault/gc
This works on the 2010 Netsuite WSDL and also had to do it for the 2012 Netsuite WSDL (you think they would have fixed it after two years)
https://webservices.netsuite.com/wsdl/v2010_2_0/netsuite.wsdl
I found that it was failing on a validation between this part:
<operation name="checkAsyncStatus">
<input name="checkAsyncStatusRequest" message="tns:checkAsyncStatusRequest"/>
<output name="checkAsyncStatusResponse" message="tns:checkAsyncStatusResponse"/>
<fault name="InvalidSessionFault" message="tns:InvalidSessionFault"/>
<fault name="InvalidCredentialsFault" message="tns:InvalidCredentialsFault"/>
<fault name="ExceededRequestLimitFault" message="tns:ExceededRequestLimitFault"/> -- mismatch
<fault name="UnexpectedErrorFault" message="tns:UnexpectedErrorFault"/>
<fault name="AsyncFault" message="tns:AsyncFault"/>
</operation>
and this part:
<operation name="checkAsyncStatus">
<soap:operation soapAction="checkAsyncStatus"/>
<input name="checkAsyncStatusRequest">
<soap:header message="tns:headers" part="passport" use="literal"/>
<soap:header message="tns:headers" part="applicationInfo" use="literal"/>
<soap:header message="tns:headers" part="partnerInfo" use="literal"/>
<soap:header message="tns:headers" part="preferences" use="literal"/>
<soap:body use="literal"/>
</input>
<output name="checkAsyncStatusResponse">
<soap:header message="tns:headers" part="documentInfo" use="literal"/>
<soap:body use="literal"/>
</output>
<fault name="InvalidSessionFault">
<soap:fault name="InvalidSessionFault" use="literal"/>
</fault>
<fault name="InvalidCredentialsFault">
<soap:fault name="InvalidCredentialsFault" use="literal"/>
</fault>
<fault name="ExceededRequestLimitFault">
<soap:fault name="ExceededRecordCountFault" use="literal"/> -- mismatch
</fault>
<fault name="UnexpectedErrorFault">
<soap:fault name="UnexpectedErrorFault" use="literal"/>
</fault>
<fault name="AsyncFault">
<soap:fault name="AsyncFault" use="literal"/>
</fault>
</operation>
I changed this:
<fault name="ExceededRequestLimitFault">
<soap:fault name="ExceededRecordCountFault" use="literal"/>
</fault>
to this:
<fault name="ExceededRequestLimitFault">
<soap:fault name="ExceededRequestLimitFault" use="literal"/>
</fault>
The modification allows Suds to create the client. Like John mentioned, it does take forever to parse(more than two minutes). I haven't tried using checkAsyncStatus to see if it works.
精彩评论