朋友要幫忙寫一個(gè)ARM上可用的微信掃碼支付的DEMO以便應(yīng)用到他的系統(tǒng)上去,而張大神只給了JAVA闹击,C#和PHP的DEMO镶蹋,沒辦法,只能自己用QT來寫了赏半,而我的QT等級(jí)可憐到只是知道有QT這門語言贺归。。断箫。
我們先來簡單了解一下掃碼支付的模式
【模式一】:商戶后臺(tái)系統(tǒng)根據(jù)微信支付規(guī)則鏈接生成二維碼牧氮,鏈接中帶固定參數(shù)productid(可定義為產(chǎn)品標(biāo)識(shí)或訂單號(hào))。用戶掃碼后瑰枫,微信支付系統(tǒng)將productid和用戶唯一標(biāo)識(shí)(openid)回調(diào)商戶后臺(tái)系統(tǒng)(需要設(shè)置支付回調(diào)URL)踱葛,商戶后臺(tái)系統(tǒng)根據(jù)productid生成支付交易,最后微信支付系統(tǒng)發(fā)起用戶支付流程光坝。
【模式二】:商戶后臺(tái)系統(tǒng)調(diào)用微信支付【統(tǒng)一下單API】生成預(yù)付交易尸诽,將接口返回的鏈接生成二維碼,用戶掃碼后輸入密碼完成支付交易盯另。注意:該模式的預(yù)付單有效期為2小時(shí)性含,過期后無法支付。--微信支付
需要實(shí)現(xiàn)的目標(biāo)是模式二鸳惯,那我們可以細(xì)分成以下步驟:
1.調(diào)用微信支付生成預(yù)付費(fèi)
2.將接口返回的鏈接生成二維碼
3.用戶掃碼支付
OK商蕴,我對(duì)于這個(gè)DEMO的做法就是,把任務(wù)拆分成不可拆分的部分芝发,然后實(shí)現(xiàn)它绪商。對(duì)于QT我也不太了解,看了微信的文檔辅鲸,要生成預(yù)付費(fèi)交易要完成以下幾個(gè)部分
-字典轉(zhuǎn)換為XML
-XML轉(zhuǎn)換為字典
-通過HTTPS格郁,向服務(wù)器發(fā)送一個(gè)POST的請(qǐng)求,接收返回?cái)?shù)據(jù)并生成二維碼
至于后面的部分,就是進(jìn)入到支付環(huán)節(jié)了例书,我們?cè)谶@里不考慮锣尉。
而需要將字典與XML之間轉(zhuǎn)換,我是這么做的
class WxPayData
{
public:
WxPayData();
//采用排序的Dictionary的好處是方便對(duì)數(shù)據(jù)包進(jìn)行簽名决采,不用再簽名之前再做一次排序
QMap<QString,QString> myMap;
/*
* 設(shè)置某個(gè)字段的值
* @param key 字段名
* @param value 字段值
*/
void SetValue(QString key, QString value);
/*
* 根據(jù)字段名獲取某個(gè)字段的值
* @param key 字段名
* @return key對(duì)應(yīng)的字段值
*/
QString GetValue(QString key);
/*
* 判斷某個(gè)字段是否已設(shè)置
* @param key 字段名
* @return 若字段key已被設(shè)置自沧,則返回true,否則返回false
*/
bool IsSet(QString key);
/*
* @將Dictionary轉(zhuǎn)成xml
* @return 經(jīng)轉(zhuǎn)換得到的xml串
* @throws WxPayException
**/
QString ToXml(void);
/*
* @將xml轉(zhuǎn)為WxPayData對(duì)象并返回對(duì)象內(nèi)部的數(shù)據(jù)
* @param QString 待轉(zhuǎn)換的xml串
* @return 經(jīng)轉(zhuǎn)換得到的Dictionary
* @throws WxPayException
*/
QMap<QString,QString>FromXml(QString xml);
};
類的實(shí)現(xiàn)
#include "wxpaydata.h"
#include <QtXml/QDomDocument>
#include <QMessageBox>
WxPayData::WxPayData()
{
}
/*
* 設(shè)置某個(gè)字段的值
* @param key 字段名
* @param value 字段值
*/
void WxPayData::SetValue(QString key, QString value)
{
myMap[key] = value;
}
/*
* 根據(jù)字段名獲取某個(gè)字段的值
* @param key 字段名
* @return key對(duì)應(yīng)的字段值
*/
QString WxPayData::GetValue(QString key)
{
QString str = myMap.value(key);
return str;
}
/*
* 判斷某個(gè)字段是否已設(shè)置
* @param key 字段名
* @return 若字段key已被設(shè)置树瞭,則返回true拇厢,否則返回false
*/
bool WxPayData::IsSet(QString key)
{
QString str = myMap.value(key);
if (str.isEmpty())
return true;
else
return false;
}
/*
* @將Dictionary轉(zhuǎn)成xml
* @return 經(jīng)轉(zhuǎn)換得到的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內(nèi)部含有值為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轉(zhuǎn)為WxPayData對(duì)象并返回對(duì)象內(nèi)部的數(shù)據(jù)
* @param string 待轉(zhuǎn)換的xml串
* @return 經(jīng)轉(zhuǎn)換得到的Dictionary
* @throws WxPayException
*/
QMap<QString,QString> WxPayData::FromXml(QString xml)
{
QDomDocument doc;
QDomElement root = doc.documentElement();
if(xml.isEmpty() || xml.isNull())
{
throw QString("將空的xml串轉(zhuǎn)換為WxPayData不合法!");
}
for (QDomNode node = root.firstChild(); !node.isNull(); node = node.nextSibling())
{
QDomElement element = node.toElement();
myMap[element.tagName()] = element.text().replace("\"","");
}
//2015-06-29 錯(cuò)誤是沒有簽名
if(myMap["return_code"] != "SUCCESS")
{
return myMap;
}
CheckSign();//驗(yàn)證簽名,不通過會(huì)拋異常
return myMap;
}