朋友要帮忙写一个ARM上可用的微信扫码支付的DEMO以便应用到他的系统上去,而张大神只给了JAVA,C#和PHP的DEMO,没办法,只能自己用QT来写了,而我的QT等级可怜到只是知道有QT这门语言。。。
我们先来简单了解一下扫码支付的模式
【模式一】:商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号)。用户扫码后,微信支付系统将productid和用户唯一标识(openid)回调商户后台系统(需要设置支付回调URL),商户后台系统根据productid生成支付交易,最后微信支付系统发起用户支付流程。
【模式二】:商户后台系统调用微信支付【统一下单API】生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易。注意:该模式的预付单有效期为2小时,过期后无法支付。--微信支付
需要实现的目标是模式二,那我们可以细分成以下步骤:
1.调用微信支付生成预付费
2.将接口返回的链接生成二维码
3.用户扫码支付
OK,我对于这个DEMO的做法就是,把任务拆分成不可拆分的部分,然后实现它。对于QT我也不太了解,看了微信的文档,要生成预付费交易要完成以下几个部分
-字典转换为XML
-XML转换为字典
-通过HTTPS,向服务器发送一个POST的请求,接收返回数据并生成二维码
至于后面的部分,就是进入到支付环节了,我们在这里不考虑。
而需要将字典与XML之间转换,我是这么做的
class WxPayData
{
public:
WxPayData();
//采用排序的Dictionary的好处是方便对数据包进行签名,不用再签名之前再做一次排序
QMap<QString,QString> myMap;
/*
* 设置某个字段的值
* @param key 字段名
* @param value 字段值
*/
void SetValue(QString key, QString value);
/*
* 根据字段名获取某个字段的值
* @param key 字段名
* @return key对应的字段值
*/
QString GetValue(QString key);
/*
* 判断某个字段是否已设置
* @param key 字段名
* @return 若字段key已被设置,则返回true,否则返回false
*/
bool IsSet(QString key);
/*
* @将Dictionary转成xml
* @return 经转换得到的xml串
* @throws WxPayException
**/
QString ToXml(void);
/*
* @将xml转为WxPayData对象并返回对象内部的数据
* @param QString 待转换的xml串
* @return 经转换得到的Dictionary
* @throws WxPayException
*/
QMap<QString,QString>FromXml(QString xml);
};
类的实现
#include "wxpaydata.h"
#include <QtXml/QDomDocument>
#include <QMessageBox>
WxPayData::WxPayData()
{
}
/*
* 设置某个字段的值
* @param key 字段名
* @param value 字段值
*/
void WxPayData::SetValue(QString key, QString value)
{
myMap[key] = value;
}
/*
* 根据字段名获取某个字段的值
* @param key 字段名
* @return key对应的字段值
*/
QString WxPayData::GetValue(QString key)
{
QString str = myMap.value(key);
return str;
}
/*
* 判断某个字段是否已设置
* @param key 字段名
* @return 若字段key已被设置,则返回true,否则返回false
*/
bool WxPayData::IsSet(QString key)
{
QString str = myMap.value(key);
if (str.isEmpty())
return true;
else
return false;
}
/*
* @将Dictionary转成xml
* @return 经转换得到的xml串
* @throws WxPayException
*/
QString WxPayData::ToXml(void)
{
QString xml = "<xml>";
QMap<QString,QString>::iterator i; //遍历map
for ( i = myMap.begin(); i != myMap.end(); ++i )
{
if(i.value().isNull())
{
throw QString("WxPayData内部含有值为null的字段!");
}
if(i.key() == "detail")
{
xml += "<" + i.key() + ">" + "<![CDATA[" + i.value() + "]]></" + i.key() + ">";
}
else
{
xml += "<" + i.key() + ">" + i.value() + "</" + i.key() + ">";
}
}
return xml + "</xml>";
}
/*
* @将xml转为WxPayData对象并返回对象内部的数据
* @param string 待转换的xml串
* @return 经转换得到的Dictionary
* @throws WxPayException
*/
QMap<QString,QString> WxPayData::FromXml(QString xml)
{
QDomDocument doc;
QDomElement root = doc.documentElement();
if(xml.isEmpty() || xml.isNull())
{
throw QString("将空的xml串转换为WxPayData不合法!");
}
for (QDomNode node = root.firstChild(); !node.isNull(); node = node.nextSibling())
{
QDomElement element = node.toElement();
myMap[element.tagName()] = element.text().replace("\"","");
}
//2015-06-29 错误是没有签名
if(myMap["return_code"] != "SUCCESS")
{
return myMap;
}
CheckSign();//验证签名,不通过会抛异常
return myMap;
}