Has anyone managed to get TclSOAP to work with eBay's SOAP API? The
sole eBay example on the TclSOAP wiki page doesn't seem to work anymore
(always returns -1.0), and the eBay API's way more complex than that.
My current effort with TclSOAP 1.6.7 is obviously broken, but I can't
figure out exactly what needs to be corrected:
====================================================================
#!/usr/bin/env tclsh
array set a {
-uriBase https://api.sandbox.ebay.com/wsapi
-appID "<myAppID>"
-devID "<myDevID>"
-certID "<myCertID"
-siteID 0
-APIversion 439
-authToken "<myAuthToken>"
}
package require SOAP
package require SOAP::https
package require tls
http::register https 443 ::tls::socket
package require rpcvar
namespace import -force rpcvar::typedef
typedef {
DevId string
AppId string
AuthCert string
} CredentialsType
typedef {
eBayAuthToken string
Credentials CredentialsType
} RequesterCredentialsType
typedef {
Version string
} GeteBayOfficialTimeRequestType
proc mkServiceURI {svcName} {
return "$::a(-uriBase)?callname=${svcName}&siteid=$::a(-siteID)&appid=$::a(-appID)&version=$::a(-APIversion)&routing=default"
}
proc mkRequesterCredentials {} {
return [list eBayAuthToken $::a(-authToken) Credentials \
[list DevId $::a(-devID) AppId $::a(-appID) AuthCert $::a(-certID)]]
}
proc mkTimeRequest {} {
return [list Version $::a(-APIversion)]
}
# For debugging purposes
proc SOAP::Transport::print::print {procVarName url soap} {
puts "procVarName = {$procVarName}"
puts "url = {$url}"
puts "soap = $soap"
}
SOAP::create getEbayTime -uri "urn:ebay:apis:eBLBaseComponents" \
-proxy [mkServiceURI GeteBayOfficialTime] \
-params { RequesterCredentials RequesterCredentialsType \
GeteBayOfficialTimeRequest GeteBayOfficialTimeRequestType }
#SOAP::configure getEbayTime -transport SOAP::Transport::print::print
puts "geteBayTime = {[getEbayTime [mkRequesterCredentials] [mkTimeRequest]]}"
====================================================================
Running the above code throws the following error:
====================================================================
Server response is not well-formed XML.
response was <?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode xmlns:ns1="http://xml.apache.org/axis/">ns1:Client.NoSOAPAction</faultcode>
<faultstring>no SOAPAction header!</faultstring>
<detail/>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
====================================================================
Uncommenting the SOAP::configure line to print the SOAP request instead
of sending it out yields:
====================================================================
procVarName = {::SOAP::_getEbayTime}
url = {https://api.sandbox.ebay.com/wsapi?callname=GeteBayOfficialTime&siteid=0&appid=myAppID&version=439&routing=default}
soap =
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance">
<SOAP-ENV:Body>
<ns:getEbayTime xmlns:ns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken xsi:type="xsd:string">myAuthToken</eBayAuthToken>
<Credentials>
<DevId xsi:type="xsd:string">myDevID</DevId>
<AppId xsi:type="xsd:string">myAppID</AppId>
<AuthCert xsi:type="xsd:string">myCertID</AuthCert>
</Credentials>
</RequesterCredentials>
<GeteBayOfficialTimeRequest>
<Version xsi:type="xsd:string">439</Version>
</GeteBayOfficialTimeRequest>
</ns:getEbayTime>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
====================================================================
I'm new to SOAP, but the SOAP message above looks
structurally different from the corresponding SOAP
message emitted by the equivalent C# program (see Example 3-6 in
<http://developer.ebay.com/DevZone/SOAP/docs/WebHelp/MakingCallCSharp-.html#wp1145554>,
reproduced below):
====================================================================
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<RequesterCredentials soapenv:mustUnderstand="0"
xmlns="urn:ebay:apis:eBLBaseComponents">
<eBayAuthToken>ABC...123</eBayAuthToken>
<ns:Credentials xmlns:ns="urn:ebay:apis:eBLBaseComponents">
<ns:DevId>someDevId</ns:DevId>
<ns:AppId>someAppId</ns:AppId>
<ns:AuthCert>someAuthCert</ns:AuthCert>
</ns:Credentials>
</RequesterCredentials>
</soapenv:Header>
<soapenv:Body>
<GeteBayOfficialTimeRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<ns1:Version xmlns:ns1="urn:ebay:apis:eBLBaseComponents">405</ns1:Version>
</GeteBayOfficialTimeRequest>
</soapenv:Body>
</soapenv:Envelope>
====================================================================
So does anyone know how to do it right, or is TclSOAP unable to work with
the eBay SOAP service at this stage?
Thks much!
- Adrian
Well, after trying to get TclSOAP to do what I needed, I finally gave up
and did a hack instead. I wrote a replacement wrapProc that generated
the XML I needed to send to eBay directly. My revised test script is
below, in case anyone finds it useful.
Oh, and I stumbled upon this really useful C/C++ SOAP interface generator
called gSOAP <http://www.cs.fsu.edu/~engelen/soap.html>. I was originally
planning to interface its output to Tcl using SWIG or some such tool,
but when I saw that it also generated sample XML files for each request
and response...well, you know the rest. 8-)
Now all I need to do is to figure out how to get TclSOAP to return its
SOAP response in tag-value pairs instead of just the values, otherwise
my code would break if eBay decides to rearrange the order of the
returned values...
- Adrian
#!/usr/bin/env tclsh
array set a {
-uriBase https://api.sandbox.ebay.com/wsapi
-appID <myAppID>
-devID <myDevID>
-certID <myAuthCert>
-siteID 0
-APIversion 439
-authToken <myAuthToken>
}
if {$argc > 0} {
array set a $argv
}
package require dom 2.0
package require SOAP
package require SOAP::https
package require tls
http::register https 443 ::tls::socket
package require rpcvar
namespace import -force rpcvar::typedef
proc mkServiceURI {svcName} {
return "$::a(-uriBase)?callname=${svcName}&siteid=$::a(-siteID)&appid=$::a(-appID)&version=$::a(-APIversion)&routing=default"
}
array set xml {
GeteBayOfficialTime {<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
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:ns1="urn:ebay:apis:eBLBaseComponents">
<SOAP-ENV:Header>
<ns1:RequesterCredentials>
<ns1:eBayAuthToken>${eBayAuthToken}</ns1:eBayAuthToken>
<ns1:Credentials>
<ns1:AppId>${AppId}</ns1:AppId>
<ns1:DevId>${DevId}</ns1:DevId>
<ns1:AuthCert>${AuthCert}</ns1:AuthCert>
</ns1:Credentials>
</ns1:RequesterCredentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GeteBayOfficialTimeRequest>
<ns1:Version>${Version}</ns1:Version>
</ns1:GeteBayOfficialTimeRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>}
}
proc GeneBayXML {procVarName args} {
set procName [lindex [split $procVarName {_}] end]
foreach {key val} $args {
set $key $val
}
return [subst $::xml($procName)]
}
SOAP::create GeteBayOfficialTime \
-proxy [mkServiceURI GeteBayOfficialTime] \
-wrapProc GeneBayXML \
-params { AppId string DevId string AuthCert string eBayAuthToken string Version string } \
-action { }
proc getEbayTime {} {
return [GeteBayOfficialTime \
AppId $::a(-appID) DevId $::a(-devID) AuthCert $::a(-certID) \
eBayAuthToken $::a(-authToken) \
Version $::a(-APIversion) \
]
}
puts "getEbayTime = [getEbayTime]"