tapi.cpp 14 KB

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