文章记录我学习C++调用webservice接口
准备
测试接口
postman测试webservice接口
-
首先请求类型为post 填写上ws地址 ,url地址后不追加?wsdl
-
设置请求头 header Content-type text/xml
-
填写请求体内容 raw
详细说明:
(1) getWeather是方法名。
(2)theCityCode、theUserID是方法参数。
响应报文也为xml格式
工具准备
soap工具下载
C++调用webservice接口需要第三方工具,
gsoap下载地址:http://sourceforge.net/projects/gsoap2
(我所使用版本为gsoap-2.8)
解压进入到文件夹 gsoap-2.8\gsoap\bin\win32 找到如下四个文件
wsdl文件生成
- http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 以该wenservice地址为例,复制该地址并通过浏览器生成.xml文件,
- 然后修改文件名为CardService.wsdl文件(文件名随意后缀为 .wsdl 即可)。
c++所需文件生成
-
环境准备
.wsdl文件,例如 CardService.wsdl
stdsoap2.cpp
stdsoap2.h
文件拷贝到win32目录 -
生产头文件
控制台目录切换到win32 //wsdl2h.exe目录
wsdl2h.exe -o CardService.h CardService.wsdl生成 CardCenterPubInterface.h
-
通过头文件生成源码接口
soapcpp2.exe CardService.h -
加入工程
将下列文件加入到VS工程中,或者生成动态库
CardService.hsoapH.h
soapStub.h
stdsoap2.h
soapC.cpp
soapClient.cpp
stdsoap2.cppCardWebServiceServiceSoapBinding.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地址(http://webservice.webxml.com.cn/WebServices/MobileCodeWS.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转换函数,在之前文章提到过
https://editor.csdn.net/md/?articleId=109748667