利用VC6.0设计淘宝应用程序的研究心得
去年我为一家公司用VC6.0设计了一个淘宝应用程序。当时想着从网上搜一些现成的例子,可是找了半天一个也没找到。于是只有自己研究摸索了。淘宝API官方网站说他们的API可以应用于任何开发工具,但淘宝只是为常见的开发工具如.NET、PHP等写了API举例和集成开发工具。下面以用taobao.trades.sold.get API(用来得交易订单列表)为例把我的研究心得说一下。
首先,用淘宝API访问淘宝网站,当然我们也可以用浏览按按照淘宝要求的格式化URL来访问也是可以得交易订单数据的,但我们的程序无法获取数据,所以我在网上找了一个FCDownloadFileWndBase模板类,通过调用该类中的DownloadFile函数实现HTTP多线程访问,然后调用Cmarkup类分析XML得到我们需的数据,最后把数据存入SQLite数据库中。
一、 通过带TOP API的HTTP URL访问淘宝网站
1、准备URL
按照淘宝的要求在语句加入调用入口、系统参数、应用参数,然后签名,再拼装URL。最后还要进行UTF-8格式转码。这部分详细要求可以参考淘宝官方http://open.taobao.com/doc/detail.htm?spm=0.0.0.0.aD4IUf&id=111链接。源代码中用到了STL中的MAP类。具体代码下:
CString CDwDlg::FormatstrURL( )//准备请求URL
{
//准备参数
map<string,string> tMap;
tMap["method"]="taobao.trades.sold.get";//得到交易订单的API
tMap["session"]=Getsession();//得到SESSION,请参考淘宝API文档
tMap["timestamp"]=GetCTime();//得到当前时间
tMap["app_key"]=GetAppkey();//得到程序KEY,请参考淘宝API文档
tMap["v"]="2.0";//API版本
tMap["sign_method"]="md5";//加密方式
tMap["page_size"]="100";//每页信息数
tMap["fields"]="buyer_nick,status,receiver_name,pay_time,payment,total_fee,post_fee,tid,receiver_city,receiver_phone,receiver_mobile,receiver_zip"//需得到的字段
tMap["start_created"]=GetStrTime();//订单建立时间,得到的订单为这个时间以后的所有订单
CStringtStatus=GetStatus( );
if(!tStatus.IsEmpty( ))tMap["status"]=tStatus;
stringtstrurl;
map<string,string>::iterator iter;
for(iter = tMap.begin(); iter != tMap.end();iter++)
{
tstrurl+=iter->first;
tstrurl+=iter->second;
}
stringtsecret=this->Getsecret( );
tstrurl.insert (0,tsecret);
tstrurl+=tsecret;
//签名
CMD5Checksum tJsMd5;
CString tMd5=tJsMd5.GetMD5((unsignedchar*)tstrurl.c_str( ),tstrurl.size ( ));
tMd5.MakeUpper ( );
tMap["sign"]=tMd5;
CString strUrlTotal;
string str1;
//UTF-8转码
for(iter = tMap.begin(); iter != tMap.end();iter++)
{
str1+=iter->first;
str1+="=";
str1+=iter->second;
str1+="&";
}
str1.resize (str1.size ( )-1);
strUrlTotal=str1.c_str ( );
strUrlTotal.Replace (":","%3A");
strUrlTotal.Replace ("","+");
CString RetstrUrlTotal;
//拼装URL
RetstrUrlTotal.Format("http://gw.api.taobao.com/router/rest?%s",strUrlTotal);
return RetstrUrlTotal;
}
2、访问淘宝网站下载XML数据
访问淘宝网站需要用到FCDownloadFileWndBase模板类,在我的程序中,通过FCDownloadFileWndBase实例定义了CDwDlg类,然后在CDwDlg类中调用DownloadFile函数来访问淘宝网站下载XML数据。DownloadFile函数可以实现多线同时进行,这样为了增加效率我们可以开设多个线程同时访问淘宝网站。具体代码下:
void CDwDlg::OnButtonadd()
{
m_strURL=FormatstrURL( );//格式化URL,上面有具体代码。
if(!m_strURL.IsEmpty()){DownloadFile(m_strURL);WorkFlag=true;}//调用该函数//下载XML数据。
}
3、利用Cmarkup类对得到XML数据进行分析,并把有用数据写SQL文件
当下载完成时,FCDownloadFileWndBase类通过发送消息调用DownloadFile_OnFinished 函数,该函数的参数中有XML数据,我们把该数据放到m_Task 变量中,Cmarkup类从m_Task中得XML数据进行分析,分析时我们主要用到该类中的FindChildElem函类来定位子元素,用GetChildData函数来得元素值。
对分析得到的数据我们以SQL语句的形式保存到SQL文件中,再利用相应函数来执行SQL文件即可保存到SQLite数据库中。具体代码如下:
void CDwDlg::AnalyticXml( )//分析XML并写入SQL文件
{
CMarkupxml;
xml.SetDoc(xml.UTF8ToA (m_Task.Context.c_str( )));//装入XML数据
CStringtValue;
CStringtKey;
CStringtFileds;
CStringtValues;
CStringtSql;
CStringSqlFileName=::GetExeFileName( );//得SQL文件名
DeleteFile(SqlFileName);
CStdioFiletFile;
if(!tFile.Open(SqlFileName,CFile::modeCreate+CFile::modeWrite))
{
AfxMessageBox("新建SQL文件错误");
return;
}
while(xml.FindChildElem("trades"))//开始分析XML
{
xml.IntoElem();//进入trades
while(xml.FindChildElem("trade"))
{
xml.IntoElem();//进入trade
while(xml.FindChildElem())
{
tKey=xml.GetChildTagName();//得到标签,相当于数据库中的字段名
tValue=xml.GetChildData();//得到元素值,相当于数据库中的字段值
tFileds+=tKey;tFileds+=",";
tValues+="'";
tValues+=tValue;
tValues+="'";
tValues+=",";
}
tSql.Format("INSERT INTO tread1(%s) VALUES(%s)\n",tFileds,tValues);//格式SQL语句
tFile.WriteString(tSql);//写入SQL文件
tFileds.Empty( );
tValues.Empty( );
xml.OutOfElem( );//退出trade
tbtidflag=false;
}
xml.OutOfElem( );//退出TRADES
}
tFile.Close( );
}
4、执行SQL文件,写SQLite数据库。至此从淘宝网站得到的订单写到了数据库中。
具体代码如下:
int ExeSqlFile(CStringExeSqlFileName)//传入参数为SQL文件名
{
CStdioFilefile;
if(!file.Open(ExeSqlFileName,CFile::modeRead))//打开SQL文件
{
OutEventMsg("打开SQL文件错误。");
returnFALSE;
}
sqlite3* db;
intresult;
char*errmsg =NULL;
result= sqlite3_open(SQLITETPFILE, &db );//打开数据库SQLITETPFILE是个宏,定义数据库文件名
if(result != SQLITE_OK )
{
OutEventMsg("打开数据库错误。");
returnFALSE;
}
CStringtSqlStr;
result= sqlite3_exec(db, "begin transaction", 0, 0, &errmsg); //开始一个事务
CStringtMsg;
while(file.GetPosition( )<file.GetLength ( ))//循环执行SQL语句
{
file.ReadString(tSqlStr);
result=sqlite3_exec(db,tSqlStr.GetBuffer(0),NULL,NULL, &errmsg);//执行SQL语句
if(result != SQLITE_OK )
{
tMsg.Format("%s语句出现错误。错误原因:%s。",tSqlStr,errmsg);
OutEventMsg(tMsg);
}
}
result= sqlite3_exec( db, "commit transaction", 0, 0, &errmsg); //提交一个事务
file.Close( );
sqlite3_close(db);
returnTRUE;
}