Commit 79fb9d12 by NitefullWind

1. 实现实体卡激活(软件激活、硬件激活、数据库保存、日志记录)。

parent f6369531
......@@ -34,7 +34,8 @@ SOURCES += main.cpp\
fmloading.cpp \
fmsetting.cpp \
cardreader.cpp \
fmmsgwnd.cpp
fmmsgwnd.cpp \
fmlogger.cpp
HEADERS += \
fmbackup.h \
......@@ -45,7 +46,9 @@ HEADERS += \
fmloading.h \
fmsetting.h \
cardreader.h \
fmmsgwnd.h
fmmsgwnd.h \
fmp_logstream.h \
fmlogger.h
FORMS += \
rechargewnd.ui \
......
......@@ -17,7 +17,11 @@ void CardReader::run()
_isRunning = true;
int port = FMSetting::GetValue("Port", 0).toInt();
int baud = FMSetting::GetValue("Baud", 115200).toInt();
ConnectDevice(port, baud);
_isRunning &= ConnectDevice(port, baud);
if(!_isRunning) {
return;
}
def_sector = FMSetting::GetValue("DefaultSector", 4).toInt();
def_pwd = FMSetting::GetValue("DefaultPwd", "ffffffffffff").toString();
......@@ -27,10 +31,12 @@ void CardReader::run()
_isRunning &= LoadKeyHex(def_sector, def_pwd);
_isRunning &= LoadKeyHex(0, def_pwd);
_isRunning &= LoadKeyHex(sector, password);
_isRunning &= LoadKeyHex(15, "000000000000");
willActiveCard = needActiveCard = "";
while(_isRunning) {
ReadVipNo();
Sleep(500);
OperatorCard();
Sleep(300);
}
}
......@@ -42,6 +48,7 @@ void CardReader::Stop()
void CardReader::setError(const QString &error)
{
_error = error;
FM_ERROR() << error;
emit hadError(_error);
}
......@@ -111,8 +118,20 @@ bool CardReader::ReadData(qint8 sec, QString &data, qint8 blockNums, bool isHex)
return true;
}
bool CardReader::ReadVipNo()
bool CardReader::OperatorCard()
{
// 检查是否需要激活卡
if(needActiveCard != "" && needActiveCard==willActiveCard) {
FM_INFO() << "Active card: " << needActiveCard;
activedSuccess = Active(needActiveCard);
FM_INFO() << "Active card success: " << activedSuccess;
needActiveCard = willActiveCard = lastUUID = "";
waitActive.wakeAll();
}
// 故意鉴权失败,使卡片不用离开读卡器即可再次寻卡
rf_authentication(_handle, 0, 15);
bool isActived = true;
QString data, uuid, vipNo="";
unsigned long snr;
if(rf_card(_handle, 0, &snr) != 0) {
......@@ -124,23 +143,99 @@ bool CardReader::ReadVipNo()
}
uuid = data.mid(0, 10);
// 验证sector扇区密码是否正确,以区分是否是激活过的卡
if(rf_authentication(_handle, 0, sector) != 0) {
// 重新寻卡
unsigned long snr;
if(rf_card(_handle, 0, &snr) != 0) {
return false;
}
// 未激活的卡,从def_sector扇区读取账号
if(ReadData(def_sector, data)){
vipNo = data.mid(16);
// 判断是否还是上一张卡
if(uuid == lastUUID) {
// 同一张卡,直接返回
return false;
} else {
lastUUID = uuid;
activedSuccess = false;
needActiveCard = willActiveCard = "";
FM_INFO() << "Find new card: " << lastUUID;
}
// 读默认扇区,看是否是激活过的卡(不用rf_authentcation,因为验证密码出错需重新寻卡)
if(ReadData(def_sector, data)) {
if(data == "00000000000000000000000000000000") {
if(ReadData(sector, data, 2, false)) {
vipNo = data;
isActived = true;
}
} else {
// 从def_sector扇区读取账号
if(ReadData(def_sector, data)){
vipNo = data.mid(16);
isActived = false;
needActiveCard = vipNo;
}
}
} else if(ReadData(sector, data, 2, false)) {
vipNo = data;
}
FM_INFO() << "Vip No: " << vipNo << " Is actived: " << isActived;
if(vipNo!="") {
emit hadVipNo(vipNo, uuid);
emit hadVipNo(vipNo, uuid, isActived);
}
return false;
}
bool CardReader::ActiveCard(QString vipNo)
{
mutex.lock();
willActiveCard = vipNo;
waitActive.wait(&mutex);
mutex.unlock();
return activedSuccess;
}
bool CardReader::Active(const QString &vipNo)
{
// 将卡号写入sec的扇区
if(!LoadKeyHex(sector, def_pwd)) {
return false;
}
// 鉴权
if(rf_authentication(_handle, 0, sector) != 0){
setError(QString("%1扇区密码错误").arg(sector));
return false;
}
// 写入卡号
char* writeData = vipNo.toLatin1().toHex().mid(0,32).data();
if(rf_write_hex(_handle, sector*4, writeData) !=0 ) {
setError("写入卡号失败");
return false;
}
// 修改密码
QByteArray tmpData = password.toLatin1();
unsigned char wkey[7];
ZeroMemory(wkey, 7);
a_hex(tmpData.data(), wkey, 12);
if(rf_changeb3(_handle, sector, wkey, 0, 0, 0, 1, 0, wkey) != 0) {
setError("修改密码失败");
return false;
}
// 删除原扇区内容
LoadKeyHex(def_sector, def_pwd);
// 鉴权
if(rf_authentication(_handle, 0, def_sector) != 0) {
setError(QString("%1扇区密码错误").arg(def_sector));
return false;
}
// 初始化为0
char zeroData[33] = "00000000000000000000000000000000";
if(rf_write_hex(_handle, def_sector*4, zeroData) !=0 ){
setError("擦除原数据失败");
return false;
}
rf_beep(_handle, 30);
rf_halt(_handle);
return true;
}
void CardReader::ClearInfo()
{
willActiveCard = needActiveCard = lastUUID = "";
activedSuccess = false;
}
#ifndef CARDREADER_H
#define CARDREADER_H
#include "fmlogger.h"
#include <QThread>
#include <windows.h>
#include <QMutex>
#include <QWaitCondition>
class CardReader : public QThread
{
Q_OBJECT
public:
explicit CardReader(QObject *parent = 0);
~CardReader();
......@@ -18,25 +22,13 @@ public:
bool ConnectDevice(int port, int baud);
void DisConnectDevice();
bool LoadKeyHex(qint8 sec, const QString &password);
/**
* @brief ReadData
* @param sec 扇区号0-15
* @param data 数据
* @param blockNums 块数量
* @param isHex 是否是16进制
* @return
*/
bool ReadData(qint8 sec, QString &data, qint8 blockNums=1, bool isHex=true);
bool ActiveCard();
bool ActiveCard(QString vipNo);
void ClearInfo();
signals:
void hadError(const QString &error);
void hadVipNo(const QString &vipNo, const QString &uuid);
public slots:
void hadVipNo(const QString &vipNo, const QString &uuid, bool isActived);
protected:
void run();
......@@ -49,9 +41,28 @@ private:
qint8 def_sector, sector;
QString def_pwd, password;
QString willActiveCard, needActiveCard, lastUUID;
QMutex mutex;
QWaitCondition waitActive;
bool activedSuccess;
void setError(const QString& error);
bool ReadVipNo();
bool OperatorCard();
bool LoadKeyHex(qint8 sec, const QString &password);
/**
* @brief ReadData
* @param sec 扇区号0-15
* @param data 数据
* @param blockNums 块数量
* @param isHex 是否是16进制
* @return
*/
bool ReadData(qint8 sec, QString &data, qint8 blockNums=1, bool isHex=true);
bool Active(const QString &vipNo);
};
#endif // CARDREADER_H
#include "fmbackup.h"
#include "fmlogger.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
......@@ -6,7 +7,6 @@
#include <QDir>
#include <QFile>
#include <QApplication>
#include <QDebug>
FMBackup::FMBackup()
{
......@@ -36,9 +36,9 @@ bool FMBackup::connect()
isOk =_db.open();
}
qDebug() << "连接数据库:" << dbname;
FM_INFO() << "连接数据库:" << dbname;
if(!isOk) {
qDebug() << "连接失败:" << _db.lastError().text();
setError("连接数据库失败:" + _db.lastError().text());
}
return isOk;
......@@ -51,39 +51,60 @@ bool FMBackup::createTable(const QString &dbname)
_db.open();
QSqlQuery query(_db);
// 创建表
bool isOk = query.exec("create table tbl_card(card_no char(20) NOT NULL PRIMARY KEY, inner_no char(20), active_date char(10), active_time char(8))");
bool isOk = query.exec("create table tbl_recharge("
"id integer PRIMARY KEY autoincrement,"
"card_no char(20) NOT NULL,"
"inner_no char(20),"
"recharge_amount double,"
"after_amount double,"
"fm_id char(25),"
"recharge_date char(10), "
"recharge_time char(8))");
qDebug() << "创建数据库:" << dbname;
FM_DEBUG() << "创建表:" << dbname;
if (!isOk) {
qDebug() << "创建数据库失败:" << query.lastError().text();
setError("创建表失败:" + query.lastError().text());
}
return isOk;
}
bool FMBackup::insert(QString card_no, QString inner_no, QString date, QString time)
bool FMBackup::insert(QString card_no, QString inner_no,
double recharge_amount, double after_amount,
QString fm_id,
QString date, QString time)
{
if(!_db.isOpen()) {
connect();
}
QSqlQuery query(_db);
bool isOk = query.exec(QString("insert into tbl_card('card_no','inner_no', 'active_date', 'active_time') values('%1','%2', '%3', '%4');")
bool isOk = query.exec(QString("insert into tbl_recharge("
"'card_no',"
"'inner_no',"
"'recharge_amount',"
"'after_amount',"
"'fm_id',"
"'recharge_date',"
"'recharge_time') values('%1','%2', '%3', '%4', '%5', '%6', '%7');")
.arg(card_no)
.arg(inner_no)
.arg(recharge_amount)
.arg(after_amount)
.arg(fm_id)
.arg(date)
.arg(time));
if(!isOk) {
qDebug() << "插入失败:" << query.lastError().text();
setError("插入失败:" + query.lastError().text());
}
return isOk;
}
QSqlQuery FMBackup::cardQuery(QString date) const
QSqlQuery FMBackup::cardQuery(QString date)
{
QSqlQuery query(_db);
bool isOk = query.exec(QString("select * from tbl_card where 'date'='%1'").arg(date));
bool isOk = query.exec(QString("select * from tbl_recharge where 'date'='%1'").arg(date));
if(!isOk) {
qDebug() << "查询数据时出现错误:" << query.lastError().text();
setError("查询数据时出现错误:" + query.lastError().text());
}
return query;
}
......@@ -92,6 +113,17 @@ bool FMBackup::reset()
{
QSqlQuery query(_db);
bool isOk = query.exec("VACUUM");
qDebug() << "数据库重置: " << isOk;
setError("数据库重置: " + isOk ? "成功" : "失败");
return isOk;
}
void FMBackup::setError(const QString &error)
{
_error = error;
FM_ERROR() << error;
}
QString FMBackup::lastError() const
{
return _error;
}
......@@ -8,16 +8,20 @@ class FMBackup
public:
static FMBackup* instance();
QSqlDatabase database() { return _db;}
bool insert(QString card_no, QString inner_no, QString date, QString time);
QSqlQuery cardQuery(QString date) const;
bool insert(QString card_no, QString inner_no, double recharge_amount, double after_amount, QString fm_id, QString date, QString time);
QSqlQuery cardQuery(QString date);
bool reset();
QString lastError() const;
private:
FMBackup();
QSqlDatabase _db;
QString _error;
bool connect();
bool createTable(const QString &dbname);
void setError(const QString &error);
};
#endif // FMBACKUP_H
#include "fmloading.h"
#include "fmloading.h"
#include "ui_fmloading.h"
FMLoading::FMLoading(QDialog *parent) :
......@@ -10,7 +10,7 @@ FMLoading::FMLoading(QDialog *parent) :
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
setAttribute(Qt::WA_TranslucentBackground, true);
movie = new QMovie(":/loading.gif");
movie = new QMovie(":/img/loading.gif");
movie->start();
connect(movie, SIGNAL(finished()), movie, SLOT(start()));
ui->loading_lbl->setMovie(movie);
......
#include "fmlogger.h"
#include "fmsetting.h"
#include <QApplication>
#include <QDateTime>
#include <QFile>
#include <QDir>
FMLogger::FMLogger(QObject *parent) : QObject(parent),
_file(nullptr)
{
}
FMLogger::~FMLogger()
{
if(_file != nullptr) {
_file->close();
delete _file;
_file = nullptr;
}
}
FMLogger *FMLogger::Instance()
{
static FMLogger logger;
return &logger;
}
QIODevice *FMLogger::getIODevice()
{
if(_file == nullptr) {
QString fileName = _NewFileName();
_file = new QFile(fileName);
qDebug() << "New File: " << fileName;
_file->open(QIODevice::Append);
}
return _file;
}
QString FMLogger::GetLogPath()
{
QString path = FMSetting::GetValue("LogPath", qApp->applicationDirPath()+"/log").toString();
path.replace("\\", "/");
QDir log_dir;
if (!log_dir.isAbsolutePath(path)) {
path = qApp->applicationDirPath() + "/" + path;
}
return path;
}
QString FMLogger::_NewFileName()
{
QString log_path = GetLogPath();
QDir log_dir(log_path);
if (!log_dir.exists()) {
if (log_dir.mkdir(log_path)) {
qDebug() << "Create log dir:" << log_path;
}
else {
qDebug() << "Create log dir" << log_path << "failed!";
}
}
QString fileName = log_path + "/" + qApp->applicationName() + "_" +QString::number(QDateTime::currentMSecsSinceEpoch()) + ".log";
return fileName;
}
#ifndef FMLOGGER_H
#define FMLOGGER_H
#include "fmp_logstream.h"
#include <QObject>
class QFile;
class FMLogger : public QObject
{
Q_OBJECT
public:
enum {
LOG_ERROR = 1, LOG_WARNING, LOG_INFO, LOG_DEBUG
};
static FMLogger *Instance();
QIODevice *getIODevice();
QString GetLogPath();
~FMLogger();
private:
explicit FMLogger(QObject *parent = 0);
QString _NewFileName();
QFile *_file;
};
#define FMLOG(level, ioDevice) ((ioDevice == nullptr) ? \
FMPNullLogStream(level, __FILE__, __FUNCTION__, __LINE__) :\
FMPLogStream(level, __FILE__, __FUNCTION__, __LINE__, ioDevice))
#define FM_DEBUG() FMLOG(FMLogger::LOG_DEBUG, FMLogger::Instance()->getIODevice())
#define FM_INFO() FMLOG(FMLogger::LOG_INFO, FMLogger::Instance()->getIODevice())
#define FM_WARN() FMLOG(FMLogger::LOG_WARNING, FMLogger::Instance()->getIODevice())
#define FM_ERROR() FMLOG(FMLogger::LOG_ERROR, FMLogger::Instance()->getIODevice())
#endif // FMLOGGER_H
......@@ -25,12 +25,6 @@
background: transparent;
}
#close_btn {
min-width: 30px; min-height: 30px;
max-width: 30px; max-height: 30px;
border-image: url(&quot;:/img/btn_alert_close.png&quot;);
}
#alertIconLab
{
color: rgb(0, 0, 0);
......@@ -93,6 +87,19 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="close_btn">
<property name="maximumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
......
#include "fmnetwork.h"
#include "fmlogger.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>
#include <QTimer>
#include <QDebug>
FMNetwork::FMNetwork(QObject *parent) :
QObject(parent),
......@@ -23,8 +23,8 @@ FMNetwork::~FMNetwork()
bool FMNetwork::send(const QString &url, const QByteArray &reqData, QByteArray &rspData, QString &error)
{
bool isOk = false;
qDebug() << "Send Url: " << url;
qDebug() << "Send Data: " << reqData;
FM_INFO() << "Send Url: " << url;
FM_INFO() << "Send Data: " << reqData;
_req->setUrl(url);
......
#ifndef FMP_LOGGERSTREAM_H
#define FMP_LOGGERSTREAM_H
#include <QDebug>
#include <QDateTime>
class FMPLogStream : public QDebug
{
public:
enum {
ERROR = 1, WARNING, INFO, DEBUG
};
explicit FMPLogStream(short level, const char* file, const char* func, int line, QIODevice* d = 0)
: QDebug(d),
_level(level),
_file(file),
_func(func),
_line(line),
_device(d)
{
_lvmap[ERROR] = "[ERROR]";
_lvmap[WARNING] = "[WARNING]";
_lvmap[INFO] = "[INFO]";
_lvmap[DEBUG] = "[DEBUG]";
}
~FMPLogStream()
{
if (this->_device) {
QDebug::operator <<(endl);
}
}
template <typename T>
QDebug & operator<<(const T& t)
{
qDebug() << t;
QDebug & stream = *(this);
if (!_device) {
stream = qDebug();
}
QString extra;
if (_level != INFO) {
QString filename(_file);
filename = filename.section("\\", -1);
filename = filename.section("/", -1);
extra += QString("%1(%2)").arg(filename).arg(QString::number(_line));
extra += QString("%1:").arg(_func);
}
QString s = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
s.append(_lvmap[_level]);
stream.noquote() << s << extra << t;
return stream;
}
protected:
int _level;
QMap<int, QString> _lvmap;
const char * _file;
const char * _func;
int _line;
QIODevice* _device;
};
class FMPNullLogStream : public FMPLogStream
{
public:
explicit FMPNullLogStream(short level, const char* file, const char* func, int line)
: FMPLogStream(level, file, func, line)
{}
};
#endif // FMP_LOGSTREAM_H
#include "fmvip.h"
#include "fmlogger.h"
#include <QCryptographicHash>
#include <QJsonParseError>
#include <QJsonDocument>
......@@ -12,65 +13,49 @@ FMVip::FMVip(QObject *parent) : QObject(parent)
void FMVip::login(const QString &vipNo, const QString &innerCode, QJsonObject &rspObj)
{
QJsonObject reqJob;
reqJob["appId"] = APP_ID;
reqJob["business_date"] = QDate::currentDate().toString("yyyyMMdd");
reqJob["t"] = QString::number(QDateTime::currentMSecsSinceEpoch());
reqJob["fm_cmd"] = "member_check_request";
reqJob["partner_id"] = PARTNER_ID;
reqJob["store_id"] = "117017";
reqJob["pos_id"] = "8888";
reqJob["operator_id"] = "8888";
reqJob["member_sign"] = vipNo;
reqJob["inner_code"] = innerCode;
reqJob["member_type"] = (int)memberType(vipNo);
QJsonDocument jsonDoc(reqJob);
QString signStr = sign(reqJob);
QString url = QString("http://member.lxj.sandload.cn/member/service/restful/pos?sign=%1").arg(signStr);
QByteArray rspData;
QString error;
QJsonParseError jsonError;
QJsonDocument rspJsonDoc;
if(networker.send(url, jsonDoc.toJson(), rspData, error))
{
qDebug() << "Server Response:" << QString::fromUtf8(rspData);
rspJsonDoc = QJsonDocument::fromJson(rspData, &jsonError);
if(jsonError.error == QJsonParseError::NoError) {
rspObj = rspJsonDoc.object();
} else {
rspObj["statuc_code"] = 101;
rspObj["msg"] = jsonError.errorString();
}
} else {
rspObj["status_code"] = 102;
rspObj["msg"] = error;
}
QJsonObject reqObj;
reqObj["fm_cmd"] = "member_check_request";
reqObj["member_sign"] = vipNo;
reqObj["inner_code"] = innerCode;
reqObj["member_type"] = (int)memberType(vipNo);
sendToServer(reqObj, rspObj);
}
void FMVip::recharge(const QString &fm_open_id, int amount, QJsonObject &rspObj)
{
QJsonObject reqJob;
reqJob["appId"] = APP_ID;
reqJob["business_date"] = QDate::currentDate().toString("yyyyMMdd");
reqJob["t"] = QString::number(QDateTime::currentMSecsSinceEpoch());
reqJob["fm_cmd"] = "order_recharge_request";
reqJob["partner_id"] = PARTNER_ID;
reqJob["store_id"] = "117017";
reqJob["pos_id"] = "8888";
reqJob["operator_id"] = "8888";
reqJob["trans_id"] = createTransId("117017", "8888");
QJsonObject reqObj;
reqObj["fm_cmd"] = "order_recharge_request";
reqObj["trans_id"] = createTransId("117017", "8888");
QJsonObject transObj;
transObj["account"] = fm_open_id;
transObj["amount"] = amount;
transObj["cash_amount"] = amount;
reqJob["transaction"] = transObj;
reqObj["transaction"] = transObj;
sendToServer(reqObj, rspObj);
}
void FMVip::reversal(const QString &fmId)
{
QJsonObject reqObj;
reqObj["fm_cmd"] = "order_correct_request";
reqObj["fm_id"] = fmId;
QJsonObject rspObj;
sendToServer(reqObj, rspObj);
}
void FMVip::sendToServer(QJsonObject &reqObj, QJsonObject &rspObj)
{
reqObj["appId"] = APP_ID;
reqObj["business_date"] = QDate::currentDate().toString("yyyyMMdd");
reqObj["t"] = QString::number(QDateTime::currentMSecsSinceEpoch());
reqObj["partner_id"] = PARTNER_ID;
reqObj["store_id"] = "117017";
reqObj["pos_id"] = "8888";
reqObj["operator_id"] = "8888";
QJsonDocument jsonDoc(reqJob);
QJsonDocument jsonDoc(reqObj);
QString signStr = sign(reqJob);
QString signStr = sign(reqObj);
QString url = QString("http://member.lxj.sandload.cn/member/service/restful/pos?sign=%1").arg(signStr);
QByteArray rspData;
......@@ -79,17 +64,22 @@ void FMVip::recharge(const QString &fm_open_id, int amount, QJsonObject &rspObj)
QJsonDocument rspJsonDoc;
if(networker.send(url, jsonDoc.toJson(), rspData, error))
{
qDebug() << "Server Response:" << QString::fromUtf8(rspData);
FM_INFO() << "Server Response:" << QString::fromUtf8(rspData);
rspJsonDoc = QJsonDocument::fromJson(rspData, &jsonError);
if(jsonError.error == QJsonParseError::NoError) {
rspObj = rspJsonDoc.object();
if(rspObj.contains("errcode")) {
rspObj["status_code"] = rspObj["errcode"];
rspObj["msg"] = rspObj["errmsg"];
}
} else {
rspObj["statuc_code"] = 101;
rspObj["status_code"] = 101;
rspObj["msg"] = jsonError.errorString();
}
} else {
rspObj["status_code"] = 102;
rspObj["status_code"] = 300;
rspObj["msg"] = error;
FM_ERROR() << "Network error: " << error;
}
}
......@@ -117,7 +107,6 @@ FMVip::MemberType FMVip::memberType(const QString &vipNo) const
QString FMVip::sign(const QJsonObject &reqJob) const
{
qDebug() << __FUNCTION__;
// 解析JSON插入MAP中按字典排序
QMap<QString, QString> mapData;
......@@ -142,7 +131,7 @@ QString FMVip::sign(const QJsonObject &reqJob) const
QByteArray bt;
bt.append(sb);
qDebug() << "Sign String: " << bt;
FM_INFO() << "Sign String: " << bt;
QByteArray md5Bt = QCryptographicHash::hash(bt, QCryptographicHash::Md5);
return md5Bt.toHex();
......
......@@ -25,8 +25,10 @@ public:
void login(const QString &vipNo, const QString &innerCode, QJsonObject &rspObj);
void recharge(const QString &fm_open_id, int amount, QJsonObject &rspObj);
void reversal(const QString &fmId);
private:
void sendToServer(QJsonObject &reqObj, QJsonObject &rspObj);
QString createTransId(const QString &storeId, const QString posId) const;
MemberType memberType(const QString &vipNo) const;
QString sign(const QJsonObject &reqJob) const;
......
......@@ -2,11 +2,12 @@
#include "ui_rechargewnd.h"
#include "fmsetting.h"
#include "cardreader.h"
#include "fmbackup.h"
#include "fmmsgwnd.h"
#include "fmvip.h"
#include <QDateTime>
#include <QJsonObject>
#include <QButtonGroup>
#include <QStyle>
#include <QDebug>
RechargeWnd::RechargeWnd(QDialog *parent) :
......@@ -18,6 +19,7 @@ RechargeWnd::RechargeWnd(QDialog *parent) :
ui->setupUi(this);
initUi();
initReader();
FMBackup::instance();
connect(_cardReader, &CardReader::hadVipNo, this, &RechargeWnd::onHadVipNo);
}
......@@ -59,8 +61,10 @@ void RechargeWnd::initUi()
void RechargeWnd::clearUi()
{
card_no = inner_no = _fm_open_id = "";
ui->card_label->setText("未知");
ui->max_recharge_label->setText("0.00");
ui->amount_label->setText("0.00");
ui->amount_edit->setText("0.00");
ui->recharge_info_label->clear();
foreach (QAbstractButton *btn, _amountBtnGroup->buttons()) {
......@@ -84,11 +88,14 @@ void RechargeWnd::initReader()
void RechargeWnd::onHadError(const QString &error)
{
setIsBusy(false);
FMMsgWnd::FailureWnd(error);
}
void RechargeWnd::onHadVipNo(const QString &vipNo, const QString &uuid)
void RechargeWnd::onHadVipNo(const QString &vipNo, const QString &uuid, bool isActived)
{
_fm_open_id = card_no = inner_no = "";
_needActived = !isActived;
clearUi();
setIsBusy(true);
QJsonObject job;
......@@ -96,8 +103,17 @@ void RechargeWnd::onHadVipNo(const QString &vipNo, const QString &uuid)
setIsBusy(false);
if(job["status_code"] != 100) {
FMMsgWnd::FailureWnd(job["msg"].toString());
_cardReader->ClearInfo();
} else {
card_no = vipNo;
inner_no = uuid;
ui->card_label->setText(vipNo);
double amount = job["amount"].toInt()/100.0;
ui->amount_label->setText(QString::number(amount, 'f', 2));
_fm_open_id = job["fm_unique_id"].toString();
double min_recharge = job["min_recharge_value"].toInt()/100.0;
double max_recharge = job["max_recharge_value"].toInt()/100.0;
QString max_recharge_str = QString::number(max_recharge, 'f', 2);
......@@ -121,5 +137,50 @@ void RechargeWnd::onHadVipNo(const QString &vipNo, const QString &uuid)
void RechargeWnd::on_recharge_btn_clicked()
{
_cardReader
int recharge_amount = (int)ui->amount_edit->text().toDouble()*100;
setIsBusy(true);
QJsonObject job;
_fmvip->recharge(_fm_open_id, recharge_amount, job);
if(job["status_code"] == 100) {
double after_amount = job["after_value"].toInt()/100.0;
QString fm_id = job["fm_id"].toString();
QDateTime dateTime = QDateTime::currentDateTime();
// 备份
bool isSuccess = FMBackup::instance()->insert(card_no, inner_no,
recharge_amount/100, after_amount,
fm_id, dateTime.toString("yyyy-MM-dd"),
dateTime.toString("hh:mm:ss"));
if(!isSuccess) {
ui->recharge_info_label->setText(FMBackup::instance()->lastError());
}
// 激活
if(isSuccess && _needActived) {
isSuccess = _cardReader->ActiveCard(ui->card_label->text());
}
setIsBusy(false);
// 是否成功
if(isSuccess) {
_needActived = false;
QString after_amount_str = QString::number(after_amount, 'f', 2);
ui->amount_label->setText(after_amount_str);
ui->recharge_info_label->setText("充值成功!");
ui->amount_edit->setText("0.00");
_fm_open_id = card_no = inner_no = "";
} else {
// 硬件激活失败,发起冲正
_fmvip->reversal(job["fm_id"].toString());
}
} else {
setIsBusy(false);
ui->recharge_info_label->setText("充值失败:"+job["msg"].toString());
}
}
......@@ -31,11 +31,13 @@ private:
CardReader *_cardReader;
FMVip *_fmvip;
bool _needActived;
QString card_no, inner_no, _fm_open_id;
private slots:
void onAmountBtnClicked(QAbstractButton* button);
void onHadError(const QString &error);
void onHadVipNo(const QString &vipNo, const QString &uuid);
void onHadVipNo(const QString &vipNo, const QString &uuid, bool isActived);
void on_recharge_btn_clicked();
};
......
......@@ -106,6 +106,7 @@ QPushButton#recharge_btn:hover {
}
#recharge_info_label {
max-width: 200;
color: rgb(255, 0, 0);
}</string>
</property>
......@@ -313,9 +314,30 @@ QPushButton#recharge_btn:hover {
</item>
<item>
<widget class="QLabel" name="recharge_info_label">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::AutoText</enum>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment