C++通过 soap调用webservice接口 实现交互

时间: 2023-08-15 admin 互联网

C++通过 soap调用webservice接口 实现交互

C++通过 soap调用webservice接口 实现交互

文章记录我学习C++调用webservice接口

目录

  • 准备
    • 测试接口
    • 工具准备
      • soap工具下载
      • wsdl文件生成
      • c++所需文件生成
  • 代码部分
    • 头文件
    • 代码实现
  • 错误处理
  • 结尾

准备

测试接口

postman测试webservice接口

  1. 首先请求类型为post 填写上ws地址 ,url地址后不追加?wsdl

  2. 设置请求头 header Content-type text/xml

  3. 填写请求体内容 raw

详细说明:

(1) getWeather是方法名。

(2)theCityCode、theUserID是方法参数。

响应报文也为xml格式

工具准备

soap工具下载

C++调用webservice接口需要第三方工具,
gsoap下载地址:
(我所使用版本为gsoap-2.8)

解压进入到文件夹 gsoap-2.8\gsoap\bin\win32 找到如下四个文件

wsdl文件生成

  1. .asmx?wsdl 以该wenservice地址为例,复制该地址并通过浏览器生成.xml文件,
  2. 然后修改文件名为CardService.wsdl文件(文件名随意后缀为 .wsdl 即可)。

c++所需文件生成

  1. 环境准备
    .wsdl文件,例如 CardService.wsdl
    stdsoap2.cpp
    stdsoap2.h
    文件拷贝到win32目录

  2. 生产头文件
    控制台目录切换到win32 //wsdl2h.exe目录
    wsdl2h.exe -o CardService.h CardService.wsdl

    生成 CardCenterPubInterface.h

  3. 通过头文件生成源码接口
    soapcpp2.exe CardService.h

  4. 加入工程
    将下列文件加入到VS工程中,或者生成动态库
    CardService.h

    soapH.h
    soapStub.h
    stdsoap2.h
    soapC.cpp
    soapClient.cpp
    stdsoap2.cpp

    CardWebServiceServiceSoapBinding.nsmap

    一共为八个文件

    工程属性 C/C+±>预处理器–>预处理器定义加入 _CRT_SECURE_NO_WARNINGS;
    C/C+±>预编译头–>预编译头选择“不适用预编译头”

代码部分

头文件

下面为所需要包含的 头文件

#include "gosal\callBusinessHttpBinding.nsmap"
#include "gosal\soapStub.h"

需要包含 .nsmap 文件以及 soapStub.h 文件

代码实现

下面为 代码实现部分

 int __stdcall GetKey(CString path, char* Key)
{

	USES_CONVERSION;
	std::string s(W2A(path));//webservice地址(.asmx)
	const char* cstr = s.c_str();
	int r = 0;
	/// SOAP的客户端
	struct soap clientSOAP;

	/// WebService调用对象
	class _ns1__callBusiness_USCOREfzyw callBusinessObject;

	/// WebService返回对象
	class _ns1__callBusiness_USCOREfzywResponse callBusinessResponseObject;

	/// SOAP初始化
	soap_init(&clientSOAP);

	// 编码方式是UTF-8 20190722
	soap_set_mode(&clientSOAP, SOAP_C_UTFSTRING);

	/// 调用函数的参数赋值	
	char utf_arg0[2048] = { 0 };
	char a[1024] = { 0 };
	strcpy(a, CstrToStr(ToData(Data)).data());

	GBKtoU8(a, utf_arg0);
	string strConetxt = utf_arg0;
	callBusinessObject.in0 = &strConetxt;

	/// 发送WebService请求,并获得返回结果
	int nResult = soap_call___ns1__callBusiness_USCOREfzyw(&clientSOAP, NULL, NULL, &callBusinessObject, callBusinessResponseObject);

	/// 操作成功
	if (SOAP_OK == nResult)
	{
		/// 输出返回结果
		strcpy(Key, callBusinessResponseObject.out->data());
		/*fputs("返回:\n", fp);
		fputs(output, fp);
		fputs("\n", fp);
		fputs(callBusinessResponseObject.out->data(), fp);
		fputs("\n\n", fp);*/
		USES_CONVERSION;

		char reta[4096] = { 0 };

		UtfToGbk(Key,reta);
		CString beforch = CString(reta);

		//AfxMessageBox(beforch);

		CString afterch;
		r = getCchar(beforch, afterch, &Data);//此函数为获取所需要信息

		strcpy(Key, CstrToStr(afterch).data());
		afterch.ReleaseBuffer();

	}
	else
	{
		r = nResult;
		if (callBusinessResponseObject.out->data() == NULL)
		{
			return r;
		}
		strcpy(Key, callBusinessResponseObject.out->data());
		//fputs("返回:\n失败\n\n", fp);	
	}
	//fclose(fp);

	/// 关闭SOAP
	soap_destroy(&clientSOAP);
	soap_end(&clientSOAP);
	soap_done(&clientSOAP);

	return r;
}

所调用接口函数在 soapClient.cpp

错误处理

在代码书写完成编译release文件会出现如下问题

在如下修改不使用预编译头
之后再次编译会出现如下报错则是需要添加库
Debug在输入里面添加mfcs140ud.lib
Release在输入里面添加mfcs140u.lib
再次编译文件会显示编译成功。

结尾

gsoap的核心内部入和出都是UTF8编码的,由于中文是多字节的,所以将多字节的按照UTF8转换,最终结果就是乱码。正确的方式应该是:soap_set_mode(&soap,SOAP_C_MBSTRING);这样中文便不会乱码,可正常返回
或者调用GBK与UTF-8转换函数,在之前文章提到过
/?articleId=109748667