tapi.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "tapi.h"
  2. #include "appevent.h"
  3. #include "qcoreapplication.h"
  4. #include "qglobal.h"
  5. #include "qjsonobject.h"
  6. #include "qobject.h"
  7. #include <functional>
  8. #include <optional>
  9. #include <QApplication>
  10. #include <QFile>
  11. #include <QFileInfo>
  12. #include <QHttpMultiPart>
  13. #include <QJsonArray>
  14. #include <QJsonDocument>
  15. #include <QJsonObject>
  16. #include <QNetworkReply>
  17. #include <QUrlQuery>
  18. #include "private/qhttpmultipart_p.h"
  19. #include <QMessageBox>
  20. #include "basemainTr.h"
  21. #include "api/tloginapi.h"
  22. namespace TC {
  23. // 创建一个映射来存储错误码和对应的信息
  24. static QMap<RequestCode, QString> errorMessages
  25. = {{RequestCode::OK, Tr::tr("OK")},
  26. {RequestCode::GeneralServerError, Tr::tr("General Server Error")},
  27. {RequestCode::InvalidRequest, Tr::tr("Invalid Request")},
  28. {RequestCode::TokenExpired, Tr::tr("Token Expired")},
  29. {RequestCode::DatabaseError, Tr::tr("Database Error")},
  30. {RequestCode::UsernameError, Tr::tr("Username Error")},
  31. {RequestCode::InvalidPhoneFormat, Tr::tr("Invalid Phone Format")},
  32. {RequestCode::PasswordRequirementsNotMet, Tr::tr("Password Requirements Not Met")},
  33. {RequestCode::PhoneAlreadyRegistered, Tr::tr("Phone Already Registered")},
  34. {RequestCode::IncorrectCredentials, Tr::tr("Incorrect Credentials")},
  35. {RequestCode::GetPhoneCodeError, Tr::tr("Get Phone Code Error")},
  36. {RequestCode::PhoneCodeExists, Tr::tr("Phone Code Exists")},
  37. {RequestCode::PhoneCodeNotFound, Tr::tr("Phone Code Not Found")},
  38. {RequestCode::CorrectVerificationCode, Tr::tr("Correct Verification Code")},
  39. {RequestCode::UpdateLoginPasswordFailed, Tr::tr("Update Login Password Failed")},
  40. {RequestCode::RealNameVerificationFailed, Tr::tr("Real Name Verification Failed")},
  41. {RequestCode::VIPExpirationTimeFailed, Tr::tr("VIP Expiration Time Failed")}};
  42. static QString base_url("http://ver.stem993.cn");
  43. // static const QLatin1String scCode("code");
  44. // static const QLatin1String scMessage("message");
  45. // static const QLatin1String scData("data");
  46. void critical(const QString &text, const QString &title = Tr::tr("Error"))
  47. {
  48. const QWidgetList widgetList = QApplication::topLevelWidgets();
  49. QWidget *parentWidget = nullptr;
  50. if (!widgetList.isEmpty()) {
  51. parentWidget = widgetList.first();
  52. }
  53. Q_UNUSED(parentWidget)
  54. qDebug() << parentWidget << text;
  55. // 获取当前活动窗口
  56. // QMessageBox::critical(parentWidget, title, text);
  57. }
  58. void information(const QString &text, const QString &title = Tr::tr("information"))
  59. {
  60. const QWidgetList widgetList = QApplication::topLevelWidgets();
  61. QWidget *parentWidget = nullptr;
  62. if (!widgetList.isEmpty()) {
  63. parentWidget = widgetList.first();
  64. }
  65. Q_UNUSED(parentWidget)
  66. qDebug() << parentWidget << text;
  67. // 获取当前活动窗口
  68. // QMessageBox::information(parentWidget, title, text);
  69. }
  70. // 响应拦截
  71. static bool InterceptorsResponse(QNetworkReply *reply, QJsonValue &data)
  72. {
  73. if (reply->error() == QNetworkReply::NoError) {
  74. const QByteArray allData = reply->readAll();
  75. QJsonParseError jsonError;
  76. QJsonDocument jsonDoc = QJsonDocument::fromJson(allData, &jsonError);
  77. if (jsonError.error != QJsonParseError::NoError) {
  78. qDebug() << "error:" << data << jsonError.errorString();
  79. return false;
  80. }
  81. #ifdef QT_DEBUG
  82. qDebug() << QString::fromUtf8(jsonDoc.toJson());
  83. #endif
  84. data = jsonDoc.object();
  85. // if (jsonDoc.isObject()) {
  86. // const QJsonObject &object = jsonDoc.object();
  87. // if (object.contains(scCode)) {
  88. // int code = object.value(scCode).toInt();
  89. // if (code != 200) {
  90. // // 获取当前活动窗口
  91. // critical(object[scMessage].toString());
  92. // // if (errorMessages.contains(requestCode)) {
  93. // // //Core::MessageManager::writeFlashing(errorMessages[requestCode]);
  94. // // } else {
  95. // // //Core::MessageManager::writeFlashing(Tr::tr("unknown error"));
  96. // // }
  97. // return false;
  98. // }
  99. // }
  100. // if (object.contains(scMessage)) {
  101. // const QString &message = object.value(scMessage).toString();
  102. // // Core::MessageManager::writeFlashing(message);
  103. // }
  104. // if (object.contains(scData)) {
  105. // data = object.value(scData);
  106. // }
  107. // }
  108. return true;
  109. } else if (reply->error() == QNetworkReply::InternalServerError) { //权限错误
  110. critical(reply->errorString(), Tr::tr("Server Error"));
  111. return false;
  112. } else { //其他错误
  113. AppEvent::instance()->setJwtToken(QString());
  114. critical(reply->errorString(), Tr::tr("Server Error"));
  115. return false;
  116. }
  117. return false;
  118. }
  119. }; // namespace TC
  120. namespace TC {
  121. static NetworkAccessManager *namInstance = nullptr;
  122. void cleanupNetworkAccessManager()
  123. {
  124. delete namInstance;
  125. namInstance = nullptr;
  126. }
  127. NetworkAccessManager *NetworkAccessManager::instance()
  128. {
  129. if (!namInstance) {
  130. namInstance = new NetworkAccessManager;
  131. qAddPostRoutine(cleanupNetworkAccessManager);
  132. }
  133. return namInstance;
  134. }
  135. NetworkAccessManager::NetworkAccessManager(QObject *parent)
  136. : QNetworkAccessManager(parent)
  137. {
  138. // const QString ip = AppEvent::instance()->configValue("serverIP").toString();
  139. // const QString port = AppEvent::instance()->configValue("serverPort").toString();
  140. // base_url = QString("http://%1:%2").arg(ip).arg(port);
  141. }
  142. QNetworkReply *NetworkAccessManager::createRequest(Operation op,
  143. const QNetworkRequest &request,
  144. QIODevice *outgoingData)
  145. {
  146. QString agentStr = QString::fromLatin1("%1/%2 (QNetworkAccessManager %3; %4; %5; %6 bit)")
  147. .arg(QCoreApplication::applicationName(),
  148. QCoreApplication::applicationVersion(),
  149. QLatin1String(qVersion()),
  150. QSysInfo::prettyProductName(),
  151. QLocale::system().name())
  152. .arg(QSysInfo::WordSize);
  153. QNetworkRequest req(request);
  154. req.setRawHeader("User-Agent", agentStr.toLatin1());
  155. req.setRawHeader("Machine_code", AppEvent::instance()->machineCode().toUtf8());
  156. QHttpMultiPartIODevice *multiPart = dynamic_cast<QHttpMultiPartIODevice *>(outgoingData);
  157. if (multiPart) {
  158. // req.setHeader(QNetworkRequest::ContentTypeHeader, "multipart");
  159. } else {
  160. req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
  161. }
  162. const QUrl &url = request.url();
  163. const QString urlPath = url.path();
  164. qDebug() << url;
  165. //设置白名单
  166. if (urlPath.indexOf(RefreshToken().url) >= 0 || urlPath.indexOf(Login().url) >= 0) {
  167. } else {
  168. //需要刷新token
  169. // qDebug() << "RefreshToken" << urlPath;
  170. if (AppEvent::instance()->isRefreshToken()) {
  171. RefreshToken().get();
  172. }
  173. }
  174. //这里考虑处理 JWT 数据
  175. const QString &token = AppEvent::instance()->jwtToken();
  176. // 加个事件校验 防止token 失效导致异常
  177. if (!token.isEmpty()) {
  178. req.setRawHeader("Authorization", "Bearer " + token.toUtf8());
  179. }
  180. return QNetworkAccessManager::createRequest(op, req, outgoingData);
  181. }
  182. //
  183. std::optional<QJsonValue> sendRequest(QNetworkAccessManager::Operation op,
  184. const QString &url,
  185. const QByteArray &postData = QByteArray())
  186. {
  187. QNetworkAccessManager *manager = NetworkAccessManager::instance();
  188. manager->setTransferTimeout(3000);
  189. QNetworkReply *reply = nullptr;
  190. QUrl fullUrl(QString(base_url).append(url));
  191. switch (op) {
  192. case QNetworkAccessManager::HeadOperation:
  193. reply = manager->head(QNetworkRequest(fullUrl));
  194. break;
  195. case QNetworkAccessManager::GetOperation:
  196. reply = manager->get(QNetworkRequest(fullUrl));
  197. break;
  198. case QNetworkAccessManager::PutOperation:
  199. reply = manager->put(QNetworkRequest(fullUrl), postData);
  200. break;
  201. case QNetworkAccessManager::PostOperation:
  202. reply = manager->post(QNetworkRequest(fullUrl), postData);
  203. break;
  204. case QNetworkAccessManager::DeleteOperation:
  205. reply = manager->deleteResource(QNetworkRequest(fullUrl));
  206. break;
  207. case QNetworkAccessManager::CustomOperation:
  208. break;
  209. default:
  210. break;
  211. }
  212. if (!reply) {
  213. qDebug() << "sendRequest Operation error";
  214. }
  215. //等待请求结束
  216. QEventLoop loop;
  217. QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  218. loop.exec();
  219. QJsonValue data;
  220. if (!InterceptorsResponse(reply, data)) {
  221. return std::nullopt;
  222. }
  223. return data;
  224. }
  225. bool downRequest(const QString &url,
  226. const QByteArray &fileName,
  227. std::function<bool(QNetworkReply *)> callback)
  228. {
  229. QNetworkAccessManager *manager = NetworkAccessManager::instance();
  230. manager->setTransferTimeout(30000);
  231. QUrl fullUrl(QString(base_url).append(url));
  232. QUrlQuery query;
  233. query.addQueryItem("file", fileName);
  234. fullUrl.setQuery(query);
  235. QNetworkReply *reply = manager->get(QNetworkRequest(fullUrl));
  236. if (!reply) {
  237. qDebug() << "sendRequest Operation error";
  238. }
  239. //等待请求结束
  240. QEventLoop loop;
  241. QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  242. loop.exec();
  243. return callback(reply);
  244. }
  245. std::optional<QJsonValue> uploaderRequest(const QString &url, const QStringList &fileList)
  246. {
  247. QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
  248. // Create a file part
  249. QVector<QFile *> files;
  250. for (const QString &filePath : fileList) {
  251. QFile *file = new QFile(filePath);
  252. if (!file->open(QIODevice::ReadOnly)) {
  253. qWarning() << "Cannot open file:" << file->errorString();
  254. return false;
  255. }
  256. QHttpPart filePart;
  257. filePart.setBodyDevice(file);
  258. filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
  259. filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
  260. QString("form-data; name=\"file\"; filename=\"%1\"")
  261. .arg(QFileInfo(filePath).fileName()));
  262. file->setParent(multiPart); // Ensure file is deleted with multiPart
  263. multiPart->append(filePart);
  264. files.append(file);
  265. }
  266. QNetworkAccessManager *manager = NetworkAccessManager::instance();
  267. QUrl fullUrl(QString(base_url).append(url));
  268. QNetworkReply *reply = manager->post(QNetworkRequest(fullUrl), multiPart);
  269. if (!reply) {
  270. qDebug() << "sendRequest Operation error";
  271. delete multiPart;
  272. qDeleteAll(files);
  273. return std::nullopt;
  274. }
  275. QObject::connect(reply, &QNetworkReply::finished, [multiPart, files]() {
  276. multiPart->deleteLater();
  277. qDeleteAll(files);
  278. });
  279. //等待请求结束
  280. QEventLoop loop;
  281. QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  282. loop.exec();
  283. QJsonValue data;
  284. if (!InterceptorsResponse(reply, data)) {
  285. reply->deleteLater();
  286. return std::nullopt;
  287. }
  288. reply->deleteLater();
  289. return data;
  290. }
  291. } // namespace TC