Commit 9dc10198 by NitefullWind

实现在网络不好的情况下,缓存非会员订单的结算请求,网络恢复后向服务器重发。

parent 264cc8f9
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# #
#------------------------------------------------- #-------------------------------------------------
QT += core gui network QT += core gui network sql
CONFIG += c++11 CONFIG += c++11
...@@ -24,7 +24,9 @@ SOURCES += main.cpp\ ...@@ -24,7 +24,9 @@ SOURCES += main.cpp\
fmvipforward.cpp \ fmvipforward.cpp \
fmmsgwnd.cpp \ fmmsgwnd.cpp \
fmloading.cpp \ fmloading.cpp \
fmcouponwidget.cpp fmcouponwidget.cpp \
backup/fmbackup.cpp \
backup/resend.cpp
HEADERS += fmviporder.h \ HEADERS += fmviporder.h \
fmviplogin.h \ fmviplogin.h \
...@@ -35,7 +37,9 @@ HEADERS += fmviporder.h \ ...@@ -35,7 +37,9 @@ HEADERS += fmviporder.h \
fmvipforward.h \ fmvipforward.h \
fmmsgwnd.h \ fmmsgwnd.h \
fmloading.h \ fmloading.h \
fmcouponwidget.h fmcouponwidget.h \
backup/fmbackup.h \
backup/resend.h
FORMS += forms/fmviporder.ui \ FORMS += forms/fmviporder.ui \
forms/fmviplogin.ui \ forms/fmviplogin.ui \
......
#include "fmbackup.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QFile>
#include <QApplication>
#include <QDebug>
FMBackup* FMBackup::_instance = nullptr;
FMBackup::FMBackup()
{
connect();
}
FMBackup* FMBackup::instance()
{
if(_instance == nullptr) {
_instance = new FMBackup();
}
return _instance;
}
bool FMBackup::connect()
{
bool isOk;
QString dbname = qApp->applicationDirPath() + "/backup/backupReq.db";
if(!QFile::exists(dbname)) {
isOk = createTable(dbname);
} else {
_db = QSqlDatabase::addDatabase("QSQLITE");
_db.setDatabaseName(dbname);
isOk =_db.open();
}
qDebug() << "连接数据库:" << dbname;
if(!isOk) {
qDebug() << "连接失败:" << _db.lastError().text();
}
return isOk;
}
bool FMBackup::createTable(const QString &dbname)
{
QFile dbFile(dbname);
dbFile.open(QIODevice::WriteOnly);
dbFile.close();
_db = QSqlDatabase::addDatabase("QSQLITE3");
_db.setDatabaseName(dbname);
_db.open();
QSqlQuery query(_db);
// 创建表
bool isOk = query.exec("create table tbl_req(id integer primary key, url varchar(100), req text)");
return isOk;
}
bool FMBackup::insertReqData(const QString url, const QString &reqData)
{
QSqlQuery query(_db);
bool isOk = query.exec(QString("insert into tbl_req('url','req') values('%1','%2')")
.arg(url)
.arg(reqData));
qDebug() << "备份数据:" << reqData;
if (!isOk) {
qDebug() << "备份失败:" << _db.lastError().text();
}
return isOk;
}
bool FMBackup::removeReqData(const int &id)
{
QSqlQuery query(_db);
bool isOk = query.exec(QString("delete from tbl_req where id==%1").arg(id));
isOk = query.exec("VACUUM");
return isOk;
}
QSqlQuery FMBackup::reqDataQuery() const
{
QSqlQuery query(_db);
query.exec("select * from tbl_req");
return query;
}
#ifndef FMBACKUP_H
#define FMBACKUP_H
#include <QSqlDatabase>
#include <QSqlRecord>
class FMBackup
{
public:
static FMBackup* instance();
bool insertReqData(const QString url, const QString &reqData);
bool removeReqData(const int &id);
QSqlQuery reqDataQuery() const;
private:
FMBackup();
static FMBackup* _instance;
QSqlDatabase _db;
bool connect();
bool createTable(const QString &dbname);
private:
class privateFMBackup
{
public:
~privateFMBackup()
{
if(FMBackup::_instance != nullptr) {
delete FMBackup::_instance;
FMBackup::_instance = nullptr;
}
}
};
};
#endif // FMBACKUP_H
#include "resend.h"
#include "backup/fmbackup.h"
#include <QSqlQuery>
#include <QSqlRecord>
#include <QNetworkReply>
#include <QDebug>
ReSend::ReSend()
:_nam(new QNetworkAccessManager(this))
{
connect(this, SIGNAL(doPost()), this, SLOT(onDoPost()));
connect(_nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(onServerFinished(QNetworkReply*)));
}
ReSend::~ReSend()
{
if(_nam != nullptr) {
delete _nam;
_nam = nullptr;
}
}
void ReSend::trySend()
{
QSqlRecord record;
QSqlQuery reqDataQuery = FMBackup::instance()->reqDataQuery();
while(reqDataQuery.next())
{
record = reqDataQuery.record();
int id = record.value(ID).toInt();
QString url = record.value(URL).toString();
_data = record.value(DATA).toByteArray();
_req.setUrl(url);
_req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
_req.setHeader(QNetworkRequest::ContentLengthHeader, _data.length());
mutex.lock();
emit doPost();
waitCondition.wait(&mutex);
mutex.unlock();
// 如果发送失败则不再继续发送
if(!isSuccess) {
break;
}
FMBackup::instance()->removeReqData(id);
}
}
void ReSend::run()
{
while(true)
{
trySend();
QThread::sleep(5);
}
}
void ReSend::onDoPost()
{
_nam->post(_req, _data);
}
void ReSend::onServerFinished(QNetworkReply *reply)
{
if(reply->error() != QNetworkReply::NoError) {
qDebug() << "重发时错误:" << reply->errorString();
isSuccess = false;
} else {
qDebug() << "重发响应成功:"<< reply->readAll();
isSuccess = true;
}
waitCondition.wakeAll();
}
#ifndef RESEND_H
#define RESEND_H
#include <QObject>
#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QMutex>
#include <QWaitCondition>
#define ID 0
#define URL 1
#define DATA 2
class FMApiCfg;
class ReSend : public QThread
{
Q_OBJECT
public:
ReSend();
void trySend();
~ReSend();
signals:
void doPost();
private slots:
void onServerFinished(QNetworkReply *reply);
void onDoPost();
protected:
void run();
private:
QNetworkAccessManager *_nam;
QNetworkRequest _req;
QByteArray _data;
QMutex mutex;
QWaitCondition waitCondition;
bool isSuccess;
};
#endif // RESEND_H
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <QJsonArray> #include <QJsonArray>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDateTime> #include <QDateTime>
#include "backup/fmbackup.h"
#include <QDebug> #include <QDebug>
...@@ -84,7 +85,15 @@ void FMVipForward::request(const QJsonObject &reqJob) ...@@ -84,7 +85,15 @@ void FMVipForward::request(const QJsonObject &reqJob)
_req.setUrl(_urlStr.arg(signStr)); _req.setUrl(_urlStr.arg(signStr));
QJsonDocument json(reqJob); QJsonDocument json(reqJob);
QByteArray reqData = json.toJson(); QByteArray reqData = json.toJson(QJsonDocument::Compact);
// 结算请求时,如果没有account或account字段为空,则为非会员支付。备份请求信息
auto trans = reqJob["transaction"].toObject();
if (reqJob["reqType"]== FM_VIP_FINAL && trans["account"].toString().isEmpty()) {
_needBackupData = reqData;
} else {
_needBackupData = "";
}
qDebug() << "向服务器发送 ===>\n" << json; qDebug() << "向服务器发送 ===>\n" << json;
qDebug() << "请求签名 ===>\n" << signStr; qDebug() << "请求签名 ===>\n" << signStr;
...@@ -94,8 +103,6 @@ void FMVipForward::request(const QJsonObject &reqJob) ...@@ -94,8 +103,6 @@ void FMVipForward::request(const QJsonObject &reqJob)
_req.setHeader(QNetworkRequest::ContentLengthHeader, reqData.length()); _req.setHeader(QNetworkRequest::ContentLengthHeader, reqData.length());
_nam.post(_req, reqData); _nam.post(_req, reqData);
// clearSessionData();
} }
void FMVipForward::onServerFinished(QNetworkReply *reply) void FMVipForward::onServerFinished(QNetworkReply *reply)
...@@ -103,8 +110,20 @@ void FMVipForward::onServerFinished(QNetworkReply *reply) ...@@ -103,8 +110,20 @@ void FMVipForward::onServerFinished(QNetworkReply *reply)
QJsonObject posObj; QJsonObject posObj;
if(reply->error() != QNetworkReply::NoError) { if(reply->error() != QNetworkReply::NoError) {
// 如果有需要备份的请求数据,则直接返回成功
if (!_needBackupData.isEmpty()) {
FMBackup::instance()->insertReqData(_req.url().toString(), _needBackupData);
posObj["statusCode"] = 100;
posObj["msg"] = "结算成功";
posObj["prompt"] = 1;
posObj["print1"] = "";
posObj["print2"] = "";
} else {
posObj["statusCode"] = 404; posObj["statusCode"] = 404;
posObj["msg"] = reply->errorString(); posObj["msg"] = reply->errorString();
}
} else { } else {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
QJsonParseError err; QJsonParseError err;
......
...@@ -104,6 +104,8 @@ private: ...@@ -104,6 +104,8 @@ private:
QMap<QString, QVariant> _sessionDataMap; QMap<QString, QVariant> _sessionDataMap;
QStringList _sessionDataList; QStringList _sessionDataList;
QString _needBackupData;
signals: signals:
void serverResponsed(const QJsonObject& rspData); void serverResponsed(const QJsonObject& rspData);
private slots: private slots:
......
...@@ -9,27 +9,6 @@ FMVipOrder::FMVipOrder(QDialog *parent) : ...@@ -9,27 +9,6 @@ FMVipOrder::FMVipOrder(QDialog *parent) :
FMVipWnd(parent), FMVipWnd(parent),
ui(new Ui::FMVipOrder) ui(new Ui::FMVipOrder)
{ {
// OrderInfo o1("10000","0","1000");
// qDebug() << o1.getMaxWillPay() << "/10";
// OrderInfo o2("2000","0","10000");
// qDebug() << o2.getMaxWillPay() << "/20";
// OrderInfo o3("1000","2000","4000");
// qDebug() << o3.getMaxWillPay() << "/10";
// o3.setUseScore(true);
// qDebug() << o3.getMaxWillPay() << "/10";
// OrderInfo o4("0","5000","1000");
// qDebug() << o4.getMaxWillPay() << "/0";
// o4.setUseScore(true);
// qDebug() << o4.getMaxWillPay() << "/0";
// OrderInfo o5("2000","9000","10000");
// qDebug() << o5.getMaxWillPay() << "/20";
// o5.setUseScore(true);
// qDebug() << o5.getMaxWillPay() << "/10";
ui->setupUi(this); ui->setupUi(this);
QString operator_id = SESSIONDATA_STRING("operator_id"); QString operator_id = SESSIONDATA_STRING("operator_id");
QString business_date = SESSIONDATA_STRING("business_date"); QString business_date = SESSIONDATA_STRING("business_date");
...@@ -41,7 +20,6 @@ FMVipOrder::FMVipOrder(QDialog *parent) : ...@@ -41,7 +20,6 @@ FMVipOrder::FMVipOrder(QDialog *parent) :
QString birthday = SESSIONDATA_STRING("birthday"); QString birthday = SESSIONDATA_STRING("birthday");
double standard_amount = SESSIONDATA_INT("standard_amount") / 100.0; double standard_amount = SESSIONDATA_INT("standard_amount") / 100.0;
// orderInfo = new OrderInfo("1000","4500","4000");
orderInfo = new FMVipOrder::OrderInfo(amount_str, score_str, needPay_str); orderInfo = new FMVipOrder::OrderInfo(amount_str, score_str, needPay_str);
orderInfo->setCouponMap(SESSIONDATA_COUPONMAP("couponMap")); orderInfo->setCouponMap(SESSIONDATA_COUPONMAP("couponMap"));
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#include "fmvipdispatcher.h" #include "fmvipdispatcher.h"
#include "include/fmutils/fmutils.hpp" #include "include/fmutils/fmutils.hpp"
#include <QApplication> #include <QApplication>
#include <QWidget>
#include "backup/resend.h"
#include <QDebug>
bool checkOnly() bool checkOnly()
{ {
...@@ -67,6 +70,10 @@ int main(int argc, char *argv[]) ...@@ -67,6 +70,10 @@ int main(int argc, char *argv[])
if(checkOnly()==false) if(checkOnly()==false)
return 0; return 0;
// 检查重发结算请求
auto reSend = new ReSend();
reSend->start();
qInstallMessageHandler(customMessageHandler); qInstallMessageHandler(customMessageHandler);
FMVipDispatcher relay; FMVipDispatcher relay;
......
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