【问题标题】:Has anyone been able to get the suds soap library to work with the NetSuite WSDL?有没有人能够让 suds soap 库与 NetSuite WSDL 一起使用?
【发布时间】:2026-02-01 08:05:02
【问题描述】:

是否有人能够让 suds soap 库与 NetSuite WSDL 一起使用?我在尝试创建客户端时收到此错误。

from suds.client import Client

#url = 'http://mssoapinterop.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'

【问题讨论】:

  • 看起来它没有处理 WSDL 中的导入。您是否确认 suds 可用于外部进口?

标签: python soap netsuite


【解决方案1】:

是的,suds 可以连接到 NetSuite,但处理 WSDL 需要很长时间。

这里有一些示例代码:

# 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

您可能还需要尝试 Python 和 SUDS 版本的各种组合。它不是一个特别可靠的库。

【讨论】:

  • 我仍然遇到与您的语法示例相同的错误。我正在使用 Python 2.7 和 Suds 0.4。您是否使用不同的版本?
  • 以上示例使用 Python 2.4.3 和 SUDS 0.3.6。 Client() 调用返回需要 2 分钟。
【解决方案2】:

有点晚了,但为了记录,我附上了一种如何使用的方法 使用 Python Zeep 的 NetSuite SuiteTalk SOAP API。

使用 Python 和 Zeep 登录 NetSuite SOAP 并添加客户的示例。

# 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)

另请参阅:https://github.com/fmalina/python-netsuite

【讨论】:

  • 请注意python-netsuite 库的链接已过时。不过,谢谢你的例子:)
  • 修复了链接。
  • client = Client(WSDL_URL) 行引发了连接错误,因此我将 WSDL_URL 更改为https://webservices.netsuite.com/wsdl/v2018_1_0/netsuite.wsdl,虽然需要几秒钟,但它连接良好,但我想就是这样。然后它在下一行Passport = client.get_type('ns1:Passport') 再次中断,错误为LookupError: No type 'Passport' in namespace urn:types.core_2018_1.platform.webservices.netsuite.com 你能提供更新吗?
  • 有人对它进行了分叉并对库进行了大量更新,试试分叉
【解决方案3】:

虽然不是最好的做事方式,但如果你绝望了,你可以继续尝试不同版本的 wsdl。我收到了同样的错误信息,所以我一直在尝试,直到一个成功。我是按这个顺序去的:

'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'终于为我工作了

编辑: 根据 tponthieux 的回答,我现在意识到您可以使用 suds 插件功能来修复 wsdl(我只想评论他的回答,但我还没有声誉:():

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()])

【讨论】:

    【解决方案4】:

    如果您想对保存的 WSDL 进行一次性修复,而不是每次都进行修复(这需要一段时间),这里是我使用的 VIM 替换命令

    :%s/RequestLimitFault">\n\t*<soap\:fault name=\"ExceededRecordCountFault/RequestLimitFault\"\>\r\t\t\t\t<soap\:fault name=\"Exce   ededRequestLimitFault/gc
    

    这适用于2010 Netsuite WSDL,也必须为2012 Netsuite WSDL 这样做(你认为他们会在两年后修复它)

    【讨论】:

      【解决方案5】:

      https://webservices.netsuite.com/wsdl/v2010_2_0/netsuite.wsdl

      我发现这部分之间的验证失败:

      <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>
      

      这部分:

      <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>
      

      我改变了这个:

      <fault name="ExceededRequestLimitFault">
          <soap:fault name="ExceededRecordCountFault" use="literal"/>
      </fault>
      

      到这里:

      <fault name="ExceededRequestLimitFault">
          <soap:fault name="ExceededRequestLimitFault" use="literal"/>
      </fault>
      

      修改允许 Suds 创建客户端。就像约翰提到的那样,解析确实需要很长时间(超过两分钟)。我还没有尝试使用 checkAsyncStatus 来查看它是否有效。

      【讨论】:

        最近更新 更多