You need to sign in to do that
Don't have an account?
Max B
Example of using Python & SOAPpy to invoke sfroce methods using Partner.WSDL
#!/usr/bin/env python
# Copyright (c) 2004 eBridge Software Inc. All rights reserved
from SOAPpy import WSDL
from SOAPpy import structType
from SOAPpy import headerType
# SOAPpy Configuration
#WSDL.Config.debug=1
WSDL.Config.namespaceStyle = '2001'
# For some reason SOAPpy treats SOAP Header as a data on dumping
# and uses "http://www.w3.org/1999/XMLSchema" namespace
# for validation instead of "http://schemas.xmlsoap.org/soap/envelope" namespace
# as you would expect that causes an exception in Types.anyType._validNamespaceURI
WSDL.Config.strictNamespaces = 0
email = "yourname@yourcompany.com"
psw = "yourpassword"
# URL to Partner.wsdl.xml
wsdl = "partner.wsdl"
# Create SOAP Proxy from WSDL
server = WSDL.Proxy(wsdl)
# Assigning sforce namespace to each sfroce method
#
# For some reason WSDLTools does not assign "urn:partner.soap.sforce.com"
# namespace to operations when it parses binding
for method in server.methods.itervalues():
method.namespace = "urn:partner.soap.sforce.com"
# Loggin in sforce using username and password
#
# Parameter names have to be explicitly specified, otherwise
# SOAPBuilder uses fake auto-incremented names
loginResult = server.login(username=email, password=psw)
print "The session id is:", loginResult.sessionId
print "The new server URL is:", loginResult.serverUrl
print "The user id is:", loginResult.userId
print
# Change the binding to a new endpoint
#
# For some reason SOAPpy replaces static soapproxy.proxy endpoint
# with service location for each operation
for method in server.methods.itervalues():
method.location = loginResult.serverUrl
# Assigning returned sessionId to SOAP header
ct = structType(data = {"sessionId" : loginResult.sessionId})
# SOAP Header support in SOAPpy does not allow us to access types declared
# in WSDL, so it has to be done manually
# The idea is from http://sourceforge.net/mailarchive/forum.php?thread_id=4990257&forum_id=1729
"""
#(06/27/05) seems to work fine with SF API 6 and SOAPpy 0.12.0
# Uncomment the double quotted block if you have SOAPpy > 0.12.0
#Ditch the standard namespaces
ct._validURIs = []
#Set the one we want to use
ct._ns = ("ns1", "urn:partner.soap.sforce.com")
"""
hd = headerType(data = {"SessionHeader" : ct})
server.soapproxy.header = hd
# Requesting sforce Server Timestamp
gstr = server.getServerTimestamp()
print "Server's timestamp is:", gstr.timestamp
print
# Requesting sforce user info for the user logged in
ui = server.getUserInfo()
print "User Name:", ui.userFullName
print "User Email:", ui.userEmail
print "User Language:", ui.userLanguage
print "User Locale:", ui.userLocale
print "User Time Zone:", ui.userTimeZone
print "User Default Currency ISO Code:", ui.userDefaultCurrencyIsoCode
print "User Id:", ui.userId
print "Orginization:", ui.organizationName
print "Orginization Id:", ui.organizationId
print "Multi-currency:", ui.organizationMultiCurrency
print "Currency Symbol:", ui.currencySymbol
print
# Listing sforce objects available for the user logged in
dgr = server.describeGlobal()
print "sforce objects available:"
for type in dgr.types:
print type
# Copyright (c) 2004 eBridge Software Inc. All rights reserved
from SOAPpy import WSDL
from SOAPpy import structType
from SOAPpy import headerType
# SOAPpy Configuration
#WSDL.Config.debug=1
WSDL.Config.namespaceStyle = '2001'
# For some reason SOAPpy treats SOAP Header as a data on dumping
# and uses "http://www.w3.org/1999/XMLSchema" namespace
# for validation instead of "http://schemas.xmlsoap.org/soap/envelope" namespace
# as you would expect that causes an exception in Types.anyType._validNamespaceURI
WSDL.Config.strictNamespaces = 0
email = "yourname@yourcompany.com"
psw = "yourpassword"
# URL to Partner.wsdl.xml
wsdl = "partner.wsdl"
# Create SOAP Proxy from WSDL
server = WSDL.Proxy(wsdl)
# Assigning sforce namespace to each sfroce method
#
# For some reason WSDLTools does not assign "urn:partner.soap.sforce.com"
# namespace to operations when it parses binding
for method in server.methods.itervalues():
method.namespace = "urn:partner.soap.sforce.com"
# Loggin in sforce using username and password
#
# Parameter names have to be explicitly specified, otherwise
# SOAPBuilder uses fake auto-incremented names
loginResult = server.login(username=email, password=psw)
print "The session id is:", loginResult.sessionId
print "The new server URL is:", loginResult.serverUrl
print "The user id is:", loginResult.userId
# Change the binding to a new endpoint
#
# For some reason SOAPpy replaces static soapproxy.proxy endpoint
# with service location for each operation
for method in server.methods.itervalues():
method.location = loginResult.serverUrl
# Assigning returned sessionId to SOAP header
ct = structType(data = {"sessionId" : loginResult.sessionId})
# SOAP Header support in SOAPpy does not allow us to access types declared
# in WSDL, so it has to be done manually
# The idea is from http://sourceforge.net/mailarchive/forum.php?thread_id=4990257&forum_id=1729
"""
#(06/27/05) seems to work fine with SF API 6 and SOAPpy 0.12.0
# Uncomment the double quotted block if you have SOAPpy > 0.12.0
#Ditch the standard namespaces
ct._validURIs = []
#Set the one we want to use
ct._ns = ("ns1", "urn:partner.soap.sforce.com")
"""
hd = headerType(data = {"SessionHeader" : ct})
server.soapproxy.header = hd
# Requesting sforce Server Timestamp
gstr = server.getServerTimestamp()
print "Server's timestamp is:", gstr.timestamp
# Requesting sforce user info for the user logged in
ui = server.getUserInfo()
print "User Name:", ui.userFullName
print "User Email:", ui.userEmail
print "User Language:", ui.userLanguage
print "User Locale:", ui.userLocale
print "User Time Zone:", ui.userTimeZone
print "User Default Currency ISO Code:", ui.userDefaultCurrencyIsoCode
print "User Id:", ui.userId
print "Orginization:", ui.organizationName
print "Orginization Id:", ui.organizationId
print "Multi-currency:", ui.organizationMultiCurrency
print "Currency Symbol:", ui.currencySymbol
# Listing sforce objects available for the user logged in
dgr = server.describeGlobal()
print "sforce objects available:"
for type in dgr.types:
print type
Message Edited by Max B on 06-27-2005 11:38 AM
Hi Max,
Thanks for all the postings. I need some help to get things started. I first looked at the Python SF integration toolkit using ZSI, and realize that seems to be too complicated. Without trying, I decided to go the SOAPpy route.
I tried to use the sample codes, then I ran into the following problems:
Do you experience anything similar to that? Any pointer? Thank you.
A note, we are running a very old version of Python (2.1.3), so I am also running SOAPpy 0.11.1. Upgrading the version is not an option for this project, maybe in the future...
Thank you very much for your help.
Best Regards
Elaine
I was using Python 2.3, SOAPpy 0.11.6, salesforce.com API 4.0 and partner.wsdl (the one that is common across all companies that use salesforce.com)
It looks like it fails when XMLSchema parses enterprise.wsdl file. You may want to try using partner.wsdl instead.
Also, for deep debugging I would recommend using Wing IDE (http://wingware.com/)
Max
Message Edited by Max B on 06-24-2005 02:20 PM
Hi Max,
That is very helpful. After some tweak, I got pass the problem but fail in log. I got a Internal 500 error back without any information to help me further investigate. Here is the trace which I also output the payload before calling.
==================================================================
==================================================================
Any suggestion? Thank you. I have checked the login and password, which are correct. So close yet so far...
Best Regards
Elaine
I have re-built partner.wsdl from salesforce.com and run the sample. Here is the trace:
=== Start dump ===
*** Outgoing HTTP headers **********************************************
POST /services/Soap/u/6.0 HTTP/1.0
Host: www.salesforce.com
User-agent: SOAPpy 0.12.0 (http://pywebsvcs.sf.net)
Content-type: text/xml; charset="UTF-8"
Content-length: 614
SOAPAction: "login"
************************************************************************
*** Outgoing SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
>
<SOAP-ENV:Body>
<ns1:login xmlns:ns1="urn:partner.soap.sforce.com" SOAP-ENC:root="1">
<username xsi:type="xsd:string">username@mycompany.com</username>
<password xsi:type="xsd:string">mypass</password>
</ns1:login>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
************************************************************************
code= 200
msg= OK
headers= Server: Resin/3.0.s040331
Content-Type: text/xml; charset=utf-8
Connection: close
Date: Fri, 24 Jun 2005 15:42:02 GMT
content-type= text/xml; charset=utf-8
data= <?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soapenv:Body>
<loginResponse xmlns="urn:partner.soap.sforce.com">
<result>
<passwordExpired>false</passwordExpired>
<serverUrl>https://na1-api.salesforce.com/services/Soap/u/6.0</serverUrl>
<sessionId>8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=</sessionId>
<userId>00530000000dGDuAAM</userId>
<userInfo>
<currencySymbol>$</currencySymbol>
<organizationId>XXXXXXXXXXXXX</organizationId>
<organizationMultiCurrency>false</organizationMultiCurrency>
<organizationName>XXXXXXXXXXXXXXX</organizationName>
<userDefaultCurrencyIsoCode xsi:null="true"/>
<userEmail>username@mycompany.com</userEmail>
<userFullName>XXXXXXXXXXXXX</userFullName>
<userId>XXXXXXXXXXX</userId>
<userLanguage>en_US</userLanguage>
<userLocale>en_CA</userLocale>
<userTimeZone>America/New_York</userTimeZone>
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
*** Incoming HTTP headers **********************************************
HTTP/1.? 200 OK
Server: Resin/3.0.s040331
Content-Type: text/xml; charset=utf-8
Connection: close
Date: Fri, 24 Jun 2005 15:42:02 GMT
************************************************************************
*** Incoming SOAP ******************************************************
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<soapenv:Body>
<loginResponse xmlns="urn:partner.soap.sforce.com">
<result>
<passwordExpired>false</passwordExpired>
<serverUrl>https://na1-api.salesforce.com/services/Soap/u/6.0</serverUrl>
<sessionId>8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=</sessionId>
<userId>XXXXXXXXXXXXXX</userId>
<userInfo>
<currencySymbol>$</currencySymbol>
<organizationId>XXXXXXXX</organizationId>
<organizationMultiCurrency>false</organizationMultiCurrency>
<organizationName>XXXXXXXXXXXXX</organizationName>
<userDefaultCurrencyIsoCode xsi:null="true"/>
<userEmail>username@mycompany.com</userEmail>
<userFullName>XXXXXXXXXXXX</userFullName>
<userId>XXXXXXXXXXX</userId>
<userLanguage>en_US</userLanguage>
<userLocale>en_CA</userLocale>
<userTimeZone>America/New_York</userTimeZone>
</userInfo>
</result>
</loginResponse>
</soapenv:Body>
</soapenv:Envelope>
************************************************************************
The session id is: 8TPjQ5MQQp7BIZgc4RSSMjNeYiqiUC.Pa55ual6Mv.WuxNx5RzQmTrmTj_IKGfScnNmpINuL6ASCBkgIgUv5PxhD2wYHcrlK4SNdGN37zi4=
The new server URL is: https://na1-api.salesforce.com/services/Soap/u/6.0
The user id is: XXXXXXXXXXXXXXXXXX
=== Finish dump ===
I believe it may have something to do with SOAP Service End Point, there may not be a service processing your request. Check your WSDL:
<!-- Soap Service Endpoint -->
<service name="SforceService">
<documentation>Sforce SOAP API</documentation>
<port binding="tns:SoapBinding" name="Soap">
<soap:address location="https://www.salesforce.com/services/Soap/u/6.0"/>
</port>
</service>
Best regards,
Max
Using Max's original example, near the top with similar lines, add:
WSDL.Config.simplify_objects = 1
WSDL.Config.typed = 0
simplify_objects auto-unpacks responses into Python dictionaries so you don't have to do it with the response objects' _asdict() call every time. This is especially nice when the response has nested structures, such as with describeSObject.
typed (among other things) affects how lists are passed when making SOAP calls. If types is true, lists elements are wrapped as an arrayType which the sforce web service does not like. As a result, you cannot do a retrieve on a list of object IDs, for example. Setting this to False (or 0) alters this behavior so that a list is sent as a series of like-named elements, in accordance the soap message examples found in the resources section of sforce.com.
Finally, when doing a multiple-ID retrieve (or delete, I presume), you must ensure that the ID list is unique. If a duplicate exists, SOAPpy sends a badly broken message to sforce which replies with an INVALID_SESSION_ID fault. This seems like a strange response and it makes no sense unless you look at the dreck that SOAPpy inadvertantly has sent.
--Kevin