VC++6.0 调用webservices
这几日实现用vc调用XFire做的webservices,主要是在社保卡驱动中能直接调用服务实现加密和解密,以及计算MAC和TAC,总工设计思路不要我直接连接加密机。
辛苦的在网上搜了两天资料,终于做出了成功的例子,可是很多地方值得总结:
一是VC++要直接调用而不通过.net或C# 时,首先要安装SOAP Toolkit3.0,呵呵在安装完它以后我不知道怎么去用,后来一不相识同行鼓励自学,于是自己就反复琢磨,还好自己弄会了,没有看什么资料,凭感觉用它监听了发往服务的正确报文,这是例子能做成功的最大关键。
在调用类中首先得添加下段代码,主要是把要用的动态库加入到工程中
#include <stdio.h>
#import "msxml4.dll"
using namespace MSXML2;
#import "C:/Program Files/Common Files/MSSOAp/Binaries/mssoap30.dll" /
exclude("IStream", "IErrorInfo", "ISequentialStream", "_LARGE_INTEGER", /
"_ULARGE_INTEGER", "tagSTATSTG", "_FILETIME")
using namespace MSSOAPLib30;
void CHsmDriver::HSM_Encrypt()
{
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
ISoapConnectorPtr Connector;
// Connect to the service.
int i=0;
HRESULT hr= CoInitialize(NULL);//初始化com环境写了这句下面才不出错
if(FAILED(hr))
{
i++; //调试是否初始化成功,若失败大多数可能是没有安装SOAPToolkit3.0
}
hr=Connector.CreateInstance(__uuidof(HttpConnector30));
if(FAILED(hr))
{
i++;//
}
Connector->Property["EndPointURL"]= = "http://192.168.0.9:7000/HSMServer/services/SJL05"; //写了上句这句不出错服务所在地址和端口
Connector->Connect();
// Begin the message.
Connector->Property["SoapAction"] = "";
Connector->BeginMessage();
Serializer.CreateInstance(__uuidof(SoapSerializer30));
// Connect the serializer object to the input stream of the connector object.
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream));
// Build the SOAP Message.
/* 截获的底层报文
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <soap:Body>
- <HSM_Encrypt xmlns="http://server.hsm.zr">
<in0 xmlns="http://server.hsm.zr">1</in0>
<in1>2</in1>
<in2>3</in2>
<in3>3</in3>
<in4>6</in4>
<in5>6</in5>
<in6>6</in6>
<in7>6</in7>
<in8>6</in8>
</HSM_Encrypt>
</soap:Body>
</soap:Envelope>
*/
Serializer->StartEnvelope("soap","http://schemas.xmlsoap.org/soap/envelope/","");//1
// 就填soap 缺省为SOAP-ENV
Serializer->StartBody("");
Serializer->StartElement("HSM_Encrypt","http://server.hsm.zr","",""); // 4
// 方法名
Serializer->StartElement("in0","","","");
Serializer->WriteString("1");
Serializer->EndElement();
Serializer->StartElement("in1","","","");
Serializer->WriteString("2");
Serializer->EndElement();
Serializer->StartElement("in2","","","");
Serializer->WriteString("3");
Serializer->EndElement();
Serializer->StartElement("in3","","","");
Serializer->WriteString("3");
Serializer->EndElement();
Serializer->StartElement("in4","","","");
Serializer->WriteString("6");
Serializer->EndElement();
Serializer->StartElement("in5","","","");
Serializer->WriteString("6");
Serializer->EndElement();
Serializer->StartElement("in6","","","");
Serializer->WriteString("6");
Serializer->EndElement();
Serializer->StartElement("in7","","","");
Serializer->WriteString("6");
Serializer->EndElement();
Serializer->StartElement("in8","","","");
Serializer->WriteString("6");
Serializer->EndElement();
Serializer->EndElement();
Serializer->EndBody();
Serializer->EndEnvelope();
// Send the message to the XML Web service.
/* 我发送的报文
<?xml version="1.0" encoding="UTF-8" standal ?>
- <soap:Envelope soap:encodingStyle="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" xmlns:SOAPSDK2="http://www.w3.org/2001/XMLSchema-
instance" xmlns:SOAPSDK3="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Body soap:encodingStyle="">
- <SOAPSDK4:HSM_Encrypt xmlns:SOAPSDK4="http://server.hsm.zr" soap:encodingStyle="">
<in0 soap:encodingStyle="">1</in0>
<in1 soap:encodingStyle="">2</in1>
<in2 soap:encodingStyle="">3</in2>
<in3 soap:encodingStyle="">3</in3>
<in4 soap:encodingStyle="">6</in4>
<in5 soap:encodingStyle="">6</in5>
<in6 soap:encodingStyle="">6</in6>
<in7 soap:encodingStyle="">6</in7>
<in8 soap:encodingStyle="">6</in8>
</SOAPSDK4:HSM_Encrypt>
</soap:Body>
</soap:Envelope>
*/
Connector->EndMessage();
// Read the response.
Reader.CreateInstance(__uuidof(SoapReader30));
// Connect the reader to the output stream of the connector object.
Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
// Display the result.
AfxMessageBox((const char*)Reader->RpcResult->text);// 显示收到的结果
}
其中组织底层报文很重要,一定要按截获的报文格式发送才能成功