One would think that writing a client application using the Simple Object Access Protocol (SOAP) in Visual C++ would be a non-trivial task. SOAP interface calls are (more or less) human-readable text transported across HTTP, a ubiquitous Internet transport protocol. It should be a simple matter of putting together the proper data payload, wrapped in properly formatted HTTP and SOAP headers, and sending the message across the wire, taking into account SSL security. The reality is interacting with eBay using SOAP and C++ is not as straightforward as one might think.
First, despite being the most widely used programming language that has ever existed in the history of mankind and its universal support on every modern computing platform, eBay has chosen not to support C++. There are no code examples for C++. Support queries regarding C++ are either summarily ignored, or responses refer to non-C++ examples. Second, eBay does not strictly adhere to the W3C SOAP standard. This is seen in two distinct areas, which will be covered later in this document. Lastly, the sheer size of the API is overwhelming, both intellectually and technically. Add to that, a clunky developer support website, poor API documentation, and nebulous, if not completely incorrect, server error messages. Any one of these would give the average developer a headache.
This article describes the process for creating a basic application for interacting with eBay using SOAP in Visual C++. The application will retrieve the official eBay time from the eBay server using Visual C++ 2008, gSOAP, OpenSSL, and the eBay API.
Step 1: Use gSOAP
Download gSOAP from Sourceforge. I have used gsoap_2.7.11.tar.gz, released July 27, 2008. This file contains the precompiled Windows binaries and the required source. Uncompress the archive to your hard drive. Assuming you’re running Windows, once uncompressed, gSOAP is ready to run. The precompiled binaries will work perfectly. There’s no need to (re-)compile gSOAP.
Step 2: Compiling WSDL
Here is the command line to compile the WSDL:
wsdl2h -I \gsoap-2.7\gsoap\WS -f -k -o
wsdl2h.exe is the parser application provided by gSoap. The –I parameter tells the parser where to find the required gSoap include files. The –f parameter tells the compiler to generate C++ code (as opposed to C code). The –o parameter specifies the name of the output file. The path at the end is the URI to the eBay SOAP API WSDL file. This process will take some time, as the first thing the tool will do is download the latest version of the 3.7 MB eBaySvc.wsdl file.
As previously mentioned, eBay does not strictly adhere to the W3C SOAP standard, necessitating the use of the –k parameter. The -k parameter tells gSOAP not to generate “
mustUnderstand” qualifiers. From W3C:
mustUnderstand global attribute can be used to indicate whether a header entry is mandatory or optional for the recipient to process. The recipient of a header entry is defined by the SOAP actor attribute. The value of the
mustUnderstand attribute is either "1" or "0". The absence of the SOAP
mustUnderstand attribute is semantically equivalent to its presence with the value "0". […] The SOAP
mustUnderstand attribute allows for robust evolution. Elements tagged with the SOAP
mustUnderstand attribute with a value of "1" must be presumed to somehow modify the semantics of their parent or peer elements. Tagging elements in this manner assures that this change in semantics will not be silently (and, presumably, erroneously) ignored by those who may not fully understand it.
If you send “
mustUnderstand” to eBay, the server will return an error. eBay doesn’t understand
Successful compilation will produce eBaySvc.h.
Step 3: Generating C++ Stubs
Here is the command line to generate the C++ stubs:
soapcpp2 -C -L -I \gsoap-2.7\gsoap\import -w -x eBaySvc.h
soapcpp2.exe is the C++ stub generator application provided by gSOAP. The –C parameter tells the generator to produce client-side code only. (eBay is server-side.) The –L parameter tells the generator not to produce soapClientLib.cpp. (This file can be used to create a static library rather than include the SOAP code directly in your project. Creation of a static library is beyond the scope of this document.) The –I parameter specifies the include file path. The –w parameter tells the generator not to produce schema files. The –x parameter tells the generator not to produce XML message files. In general, I tried to have this tool and wsdl2h.exe do as little work as possible.
Step 4: Open SSL
gSOAP depends upon Open SSL for SSL-secured communications. You will need to download and compile Open SSL to access eBay. Alternatively, Shining Light Productions produces an Open SSL installer. I haven’t used it myself, but it looks like it may prevent the need to compile Open SSL.
Step 5: Visual C++ 2008
For simplicity, create a C++ Win32 Console Application project. Accept all of the default settings.
Step 5a: Add Code Here
Add the following files that were generated by gSOAP to the project:
Add the following files from the gSOAP directory to the project:
Step 5b: File Options
The .cpp files generated by gSOAP from the eBay WSDL are quite large. They will need special handling in Visual Studio. Right click on the file soapC.cpp (only) in the Solution Explorer, and select Properties from the right click menu. Under Configuration Properties and C/C++ tree nodes, select Command Line. In the panel on the right, enter “/bigobj” and click Apply.
Next, under Configuration Properties and Precompiled Headers, change the option for Create/Use Precompiled Header to “Not Using Precompiled Headers”. This will allow the project to use precompiled headers excluding this file. Click Apply.
Repeat this process for soapClient.cpp.
Use the process above to disable the use of precompiled headers for stdsoap2.cpp. (The “/bigobj” command line compiler parameter is not needed for stdsoap2.cpp.)
Step 5c: Project Options
- Right click on the project and select Properties from the right click menu. Under Configuration Properties, C/C++ and General, add include paths to gSOAP and Open SSL. Click Apply.
- Under Configuration Properties, C/C++ and Preprocessor, add “WITH_OPENSSL” (to enable SSL in gSOAP) and “DEBUG” (to enable logging) to the list of Preprocessor Definitions. Click Apply.
- Under Configuration Properties, Linker and General, add the path to the Open SSL binary directory, where the compiled lib files reside, to Additional Library Directories. Click Apply.
- Under Configuration Properties, Linker and Input, add “libeay32.lib” and “ssleay32.lib” to Additional Dependencies. These are the Open SSL libraries. Click Apply.
Step 5d: Time to Write Code! (OK, not really.)
Open the console application C++ file. Add three
#includes to the top of the file just after the stdafx.h include:
Step 5e: Test Build
It’s now time to test to see if everything has been done correctly so far. Build the solution. At this point, the solution should build with 0 errors and 0 warnings. If not, you’ve missed a step above.
Step 5f: Interact with eBay
Using your preferred web browser, go to http://developer.ebay.com. You will need to:
- Establish a developer account.
- Generate a set of sandbox keys (
CertId – also known as an AuthCert).
- Register a user account in the Sandbox.
- Get a user token.
- Use the API Test Tool to verify that you have all of the above.
The exact procedure for accomplishing the above is left as an exercise for the reader. Go forth and experience the clunkiness that is eBay for yourself.
Step 5g: SOAP Configuration
Although gSOAP supports SSL, SSL is not configured out of the box. To configure SSL, you’ll need a file containing the public certificates of trusted certification authorities. gSOAP provides this file. You can download it from here.
Once you have this file, code configuration is needed. Open soapeBayAPISoapBindingProxy.h. Just after the
soap_new() call, add the following code:
if (soap_ssl_client_context(soap, SOAP_SSL_DEFAULT, NULL, NULL,
"C:\\Path\\To\\Certs\\File\\cacerts.pem", NULL, NULL ))
Be sure to update the path to the unarchived cacerts.pem file to match your system.
Warning: The code above was added to a tool-generated file. If you re-run the tool, this change will be over-written. You will need to re-add this code.
Step 5g: Time to Write Code! (Really, this time!)
We’re finally ready to do something meaningful. First, input all of the values obtained in Step 5f above into your application
main(). For example:
std::string sAppId("<your />");
std::string sDevId("<your />");
std::string sCertId("<your />");
std::string sUserToken("<your />");
Next, declare the eBay proxy object and configure the SOAP header:
eBayProxy.soap->header = new SOAP_ENV__Header;
eBayProxy.soap->header->ns1__RequesterCredentials = new ns1__CustomSecurityHeaderType;
eBayProxy.soap->header->ns1__RequesterCredentials->eBayAuthToken = &sUserToken;
eBayProxy.soap->header->ns1__RequesterCredentials->Credentials = new ns1__UserIdPasswordType;
eBayProxy.soap->header->ns1__RequesterCredentials->Credentials->AppId = &sAppId;
eBayProxy.soap->header->ns1__RequesterCredentials->Credentials->DevId = &sDevId;
eBayProxy.soap->header->ns1__RequesterCredentials->Credentials->AuthCert = &sAuthCert;
Prepare the request and response objects:
req.Version = &sVersion;
req.ErrorLanguage = & sLanguage;
The following is the second area where eBay does not adhere to the W3C SOAP standard. With SOAP, parameters should be part of the data payload posted via HTTP. eBay, however, requires that some of the data payload parameters be repeated on the URL to which the SOAP call is posted. (I don’t know why this duplication is needed. Attempts to get an answer from eBay have gone unanswered.)
Therefore, the next step is to hack the app ID and other parameters into the endpoint URL.
eBayProxy.endpoint = "https://api.sandbox.ebay.com/wsapi?callname=GeteBayOfficialTime&
Finally, you make the call!
int err = eBayProxy.__ns1__GeteBayOfficialTime( &req, &resp );
if( err == SOAP_OK )
Step 5h: Build Again
The result of the compilation should result in 0 errors, 0 warnings. Life is good!
Step 5i: Configure Dependencies
The sample application will require the Open SSL DLLs libeay32.dll and ssleay32.dll to be copied to the project directory.
Step 5j: Run, Forrest! Run!
Press F5 to run the application in the debugger. You should see a command prompt window open, a short delay, then the command prompt window will close. Check your project directory for three files: TEST.LOG, SENT.LOG, and RECV.LOG. The largest file, TEST.LOG will contain gSOAP trace output. In my testing, this file hasn’t been useful, but I’m not developing gSOAP. SENT.LOG contains what was sent to the eBay server, including the target, action, HTTP headers, and the XML data payload. RECV.LOG contains what was received from the eBay server. These files have been included in the sample project for review.
Note that the XML received from eBay contains the timestamp in the following format:
The gSOAP response object, however, will provide the programmer a 4-byte
time_t value, having already parsed the XML and converted the text value to C++ friendly binary data.
That’s it. Congratulations! You did all this for four bytes.
- Q1: Why Visual Studio 2008?
- A1: There are actually two questions in this one question:
- Q1.1: Why Visual C++ as opposed to another C++?
- A1.1: My only answer is that my client required Visual C++ for the application I was working on at the time, so that's what I used to create the example application and the article. Implementation using a flavor of C++ other than Visual C++ is left as an exercise for the reader.
- Q1.2: Why Visual C++ 2008 and not earlier versions?
- A1.2: Versions of Visual C++ earlier than 2008 (VC++ compiler version 9.0) will not compile the source files generated from the eBay WDSL file. The source files are so large that they will overwhelm the compilers in VS 2003 and VS 2005. The VC++ 2008 compiler supports the /bigobj flag, not in previous versions.
- 29 October 2008 - Added FAQ and the first question.