Summary of c++ calling https-based webservice interface through gsop

ww steps:

Step 1: Generate header files

The webservice interface generally has an external interface document. For example: http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

The parameter after the question mark represents the WSDL document, which is an XML document. It doesn’t matter if you don’t understand the configuration. Next, we need to generate a c++ header file through this document.

(1) Download gsoap tool

Download link: gSOAP Toolkit download | SourceForge.net

 After the download is completed, unzip it and enter the gsoap\bin\win32 directory. There are two files in this directory, wsdl2h.exe and soapcpp2.exe. wsdl2h.exe is used to generate header files. Generating the header file alone is not enough. At this time, soapcpp2.exe must be used to generate the corresponding C++ file structure, which can be used for calling in the project (introduced in the second step). Let’s first look at how to generate the header file.

 Open the cmd command in the gsoap\bin\win32 directory. enter:

wsdl2h.exe -o head.h http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 After the execution is completed, you can see that there is an additional header file head.h in the current directory. You can open it and take a look. There are some interface functions inside.

 Note: The webservice uses UTF-8 encoding by default during the transmission process. Of course, gsoap also defaults to narrow characters when generating the header file. Such as string or char*. At this time, if the parameters have Chinese characters during the call again, the characters will be garbled. There are two solutions.

Method 1: Add a sentence to the code when calling later (the specific place to add will be introduced later):

soap_set_mode(&m_soap, SOAP_C_UTFSTRING);

 Method 2: By default, typemap.dat in the root directory is used to compile into narrow characters. We do not apply it at this time, but create a new mytypemap.dat in the current directory. The content is as follows: xsd__string = | std::wstring | wchar_t*. Then re-execute the cmd command.

wdsl2h.exe -o head.h -t mytypemap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL

 After regeneration, you can find that the string types in head.h have changed to wchar_t * or wstring type.

Step 2: Generate a callable API

Execute cmd command in the current directory:

soapcpp2.exe -C -x -I ..\..\import head.h

  

Among them, -C only generates client code. -x means not to generate xml (we only need c++ code) -I means to specify the import directory.
After successful execution, there are some more files in the current directory:

 Step 3: Import into project
Add the files in the red box in the picture above to your project. There are two more files that need to be added. stdsoap2.h and stdsoap2.cpp in the gsoap root directory also need to be added to the project.
Right-click on the three added cpp files->Properties->All Configurations->c/c+±>Precompiled headers and select not to use precompiled headers. As shown below.

After the configuration is complete, you can start writing code.

Step 4: Write the code

Create a new MFC-based application project named: soapTest 

Create a new soapTestDlg.cpp and introduce the header file

#include "WeatherWebServiceSoap.nsmap"
#include "soap.h"

When I referenced these two header files in the project, the compilation reported crazy errors. I checked carefully and found that they were all overlapping definitions. The reason is that the namespace in the header file WeatherWebServiceSoap.nsmap conflicts with the original socket library in the project. The solution is to write #include "WeatherWebServiceSoap.nsmap" to the front. If used Precompiled headers are best written in the stdafx.h file. After the header file is introduced, compile again and no error will be reported. If you do not add precompiled headers, you need to set soapC.cpp, soapClientLib.cpp, soapClient.cpp, and stdsoap2.cpp to not use precompiled headers.


All interfaces of the service can be seen in soapClient.cpp. The function name is in the form of soap_call __ns1_XXX.
First create the soap object and initialize it:

struct soap m_soap;
//SOAP初始化
soap_init(&m_soap);
soap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);

Which soap_set_mode(&m_oSoap, SOAP_C_UTFSTRING);is exactly what was said at the beginning to adapt to Chinese characters. If wstring or wchar_t * is used initially, it can be ignored. Then define the reqXml string and call the interface function. Double quotes in xml strings need to be escaped.

char* _reqXml = "<root>.....</root>";
char* _Return;
soap_call_ns1__XXX(&m_soap, NULL, NULL, G2U(_reqXml), _Return);
string ret = U2G(_Return);

Since the above code uses narrow characters as parameters, that is, char *, it needs to be converted to UTF-8 format. The specific functions are as follows:

char* U2G(const char* utf8)
{
	int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
	len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

char* G2U(const char* gb2312)
{
	int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
	wchar_t* wstr = new wchar_t[len + 1];
	memset(wstr, 0, len + 1);
	MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
	len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	char* str = new char[len + 1];
	memset(str, 0, len + 1);
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
	if (wstr) delete[] wstr;
	return str;
}

At this point the compilation should pass. However, the reality is cruel. The returned _Return value is NULL, indicating that something went wrong. My address is https. If I directly use http to request, 301 will be returned. The search information says that 301 means redirection, which means that you cannot enter http in the address bar like a browser, and the browser will redirect you to https. At this time, you still have to change it to https. Compile again. Um~ Still reporting an error. . . For the error code, you can check the value of the error field in the m_soap structure during debugging. If it is always 0, it means there is no problem. You can check the specific error codes online.
After changing to https and then debugging, you can see that the value of m_soap->error is 30. Check the documentation and find that 30 means that SSL security authentication is not performed. Okay ~
add the following code after soap_init(&m_soap):

soap_ssl_init();
if (soap_ssl_server_context(&m_soap, SOAP_SSL_NO_AUTHENTICATION, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
	soap_print_fault(&m_soap, stderr);
	exit(-1);
}

If there is an SSL certificate in the soap_ssl_server_context parameter, fill in the password. It's fine if it's not all NULL.
After compiling again, I still couldn't check the code through ~ and found that WITH_OPENSSLstdsoap2.h was not defined in the header file . It's gray below.

 Solution: Right-click on the project properties->C/C+±>Preprocessor->Add WITH_OPENSSL in the preprocessor definition

 After adding it, I found that the gray color was gone.

 After compilation, an error is reported again. The error message is soap_ssl_server_contextan external symbol that cannot be resolved by the function.

reason

        The implementation of this function is not defined. Forgot to introduce the openssl library. Download address: https://slproweb.com/products/Win32OpenSSL.html

Download completed, installation, installation complete directory.

 Then right-click the project in vs->Properties->Configuration Properties->Add the include directory and library directory in the VC++ directory, as shown below.

 Right-click the project in vs->Properties->Configuration Properties->Link Library->Input->Add libcrypto.lib and libssl.lib to the additional dependent library items, as shown below

File structure

 Notice:

If an error is reported that xx has been defined in soapClient.obj, as shown below

 Solution:

        Comment out all soapClientLib.cpp and compile again

 The following is the gsoap+opensll tool

https://download.csdn.net/download/my_angle2016/88220982

Guess you like

Origin blog.csdn.net/my_angle2016/article/details/132302759