UserBusinessImpl.cs 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. using Common;
  2. using Common.Constant;
  3. using Common.Http;
  4. using Common.Logic;
  5. //using Esim.Apis.Logic;
  6. using Esim.Apis.Singleton;
  7. using Database;
  8. using Database.Database;
  9. using log4net;
  10. using Microsoft.AspNetCore.Mvc;
  11. using Microsoft.VisualBasic;
  12. using Newtonsoft.Json;
  13. using System;
  14. using System.Threading.Tasks;
  15. using System.Xml.Serialization;
  16. namespace Esim.Apis.Business
  17. {
  18. public class UserBusinessImpl : IUserBusiness
  19. {
  20. private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
  21. typeof(UserBusinessImpl)
  22. );
  23. private ModelContext dbContext;
  24. IConfiguration configuration;
  25. public UserBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
  26. {
  27. dbContext = _dbContext;
  28. configuration = _configuration;
  29. }
  30. private string GetParameter(string key)
  31. {
  32. return configuration.GetSection(key).Value ?? "";
  33. }
  34. //public async Task<IActionResult> DetectMsisdn(
  35. // HttpRequest httpRequest,
  36. // DetectMsisdnReq request
  37. //)
  38. //{
  39. // var url = httpRequest.Path;
  40. // var json = JsonConvert.SerializeObject(request);
  41. // log.Debug("URL: " + url + " => Request: " + json);
  42. // try
  43. // {
  44. // //// add prize to user
  45. // //var addPrizeResult = await QuestLogic.AddPrizeForUser(
  46. // // dbContext,
  47. // // "67075723423",
  48. // // 101
  49. // //);
  50. // var msisdn = DotnetLib.Logic.ReuseLogic.TelemorValidateMsisdn(GetParameter("CountryCode"), request.msisdn);
  51. // if (msisdn == null)
  52. // {
  53. // return DotnetLib.Http.HttpResponse.BuildResponse(
  54. // log,
  55. // url,
  56. // json,
  57. // CommonErrorCode.Error,
  58. // ConfigManager.Instance.GetConfigWebValue("MSISDN_INVALID"),
  59. // new { }
  60. // );
  61. // }
  62. // Account? account = null;
  63. // if (request.accessToken != null)
  64. // {
  65. // // check access token
  66. // account = dbContext
  67. // .Accounts.Where(x => x.Msisdn == msisdn)
  68. // .FirstOrDefault();
  69. // if (account == null)
  70. // {
  71. // // create account
  72. // Account accountCreate = new Account
  73. // {
  74. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "ACCOUNT_SEQ"),
  75. // Msisdn = msisdn,
  76. // Password = CommonLogic.GenPassword(6),
  77. // RefreshToken = request.accessToken,
  78. // Username = msisdn,
  79. // Birthday = DateTime.Now,
  80. // CreatedDate = DateTime.Now,
  81. // };
  82. // dbContext.Accounts.Add(accountCreate);
  83. // await dbContext.SaveChangesAsync();
  84. // account = accountCreate;
  85. // }
  86. // }
  87. // else if (request.msisdn != null && request.password != null)
  88. // {
  89. // // after checking access token
  90. // // check user
  91. // account = dbContext
  92. // .Accounts.Where(x => x.Msisdn == msisdn && x.Password == request.password)
  93. // .FirstOrDefault();
  94. // if (account == null)
  95. // {
  96. // return DotnetLib.Http.HttpResponse.BuildResponse(
  97. // log,
  98. // url,
  99. // json,
  100. // CommonErrorCode.Error,
  101. // "Invalid msisdn or password",
  102. // new { }
  103. // );
  104. // }
  105. // }
  106. // else
  107. // {
  108. // return DotnetLib.Http.HttpResponse.BuildResponse(
  109. // log,
  110. // url,
  111. // json,
  112. // CommonErrorCode.Error,
  113. // "Invalid msisdn or password",
  114. // new { }
  115. // );
  116. // }
  117. // // gen token
  118. // string token = CommonLogic.GenToken(configuration, account.Msisdn, account.Id.ToString());
  119. // string refreshToken = CommonLogic.GenRefreshToken(configuration, account.Msisdn);
  120. // // update token
  121. // account.RefreshToken = token;
  122. // dbContext.Accounts.Update(account);
  123. // await dbContext.SaveChangesAsync();
  124. // // get inviting mission
  125. // var mission = dbContext
  126. // .Missions.Where(x =>
  127. // x.Type == CommonConstant.TypeInviting
  128. // && x.Status == CommonConstant.StatusActive
  129. // && x.FromTime <= DateTime.Now
  130. // && x.ToTime >= DateTime.Now
  131. // ).FirstOrDefault();
  132. // if (mission != null)
  133. // {
  134. // // check user inviting
  135. // var inviting = dbContext.InvitingHistories.Where(
  136. // x => x.Receiver == account.Msisdn && x.Status == CommonConstant.StatusSuccess && x.InvitedTime >= mission.FromTime && x.InvitedTime <= mission.ToTime
  137. // ).FirstOrDefault();
  138. // if (inviting != null)
  139. // {
  140. // inviting.Status = CommonConstant.StatusClaimed;
  141. // dbContext.InvitingHistories.Update(inviting);
  142. // await dbContext.SaveChangesAsync();
  143. // // check time required
  144. // var invitingClaimed = dbContext.InvitingHistories.Where(x => x.Msisdn == inviting.Msisdn && x.Status == CommonConstant.StatusClaimed && x.InvitedTime >= mission.FromTime && x.InvitedTime <= mission.ToTime).Count();
  145. // if (invitingClaimed >= mission.RequiredTime)
  146. // {
  147. // log.Debug("User invited, add prize for user");
  148. // var accountInviting = dbContext.Accounts.Where(x => x.Msisdn == inviting.Msisdn).FirstOrDefault();
  149. // if (accountInviting == null)
  150. // {
  151. // log.Error("Not found account for inviting msisdn: " + inviting.Msisdn);
  152. // }
  153. // else
  154. // {
  155. // // update mission completed status to claimed
  156. // await QuestLogic.SetCompletedMissionForUserAsync(dbContext, accountInviting.Msisdn, accountInviting.Id, mission);
  157. // // add prize for user
  158. // var addPrizeRes = await QuestLogic.AddPrizeForUser(
  159. // dbContext,
  160. // accountInviting.Msisdn,
  161. // mission.Id
  162. // );
  163. // // send mt to owner
  164. // await MtLogic.SendMt(
  165. // dbContext,
  166. // accountInviting.Msisdn,
  167. // ConfigManager.Instance.GetConfigSmsValue("OWNER_INVITE_SUCCESS")
  168. // );
  169. // }
  170. // }
  171. // }
  172. // else
  173. // {
  174. // log.Debug($"No inviting mission implement for {account.Msisdn}");
  175. // }
  176. // }
  177. // bool canPlay = true;
  178. // decimal? vendorPackageId = null;
  179. // // check if user completed vendor package
  180. // var campaignOpening = dbContext
  181. // .Campaigns.Where(
  182. // x =>
  183. // x.Status == CommonConstant.StatusActive
  184. // && x.FromTime <= DateTime.Now
  185. // && x.ToTime >= DateTime.Now
  186. // )
  187. // .FirstOrDefault();
  188. // if (campaignOpening != null)
  189. // {
  190. // // check login history
  191. // var now = DateTime.Now;
  192. // // get config
  193. // var timeDiff = ConfigManager.Instance.GetConfigAppValue("LOGIN_TIME_DIFF") ?? "1440";
  194. // var missionLogin = dbContext
  195. // .Missions.Where(x => x.Type == CommonConstant.TypeLogin && x.CampaignId == campaignOpening.Id)
  196. // .FirstOrDefault();
  197. // if (missionLogin != null)
  198. // {
  199. // // kiểm tra mission đã được set completed chưa
  200. // var checkCompleted = dbContext
  201. // .MissionCompleteds.Where(
  202. // x =>
  203. // x.Msisdn == account.Msisdn
  204. // && x.AccountId == account.Id
  205. // && x.MissionId == missionLogin.Id
  206. // )
  207. // .Count();
  208. // if (checkCompleted > 0)
  209. // {
  210. // // mission completed rồi, không cần check login nữa
  211. // log.Debug($"Misson login {missionLogin.Id} has completed for {msisdn}");
  212. // }
  213. // else
  214. // {
  215. // log.Debug($"Checking login mission {missionLogin.Id} for {msisdn}");
  216. // // check time required
  217. // var start = DateTime.Now.AddMinutes(-(int)missionLogin.RequiredTime * int.Parse(timeDiff));
  218. // var completedLogin = dbContext
  219. // .MissionHistories.Where(
  220. // x =>
  221. // x.Msisdn == account.Msisdn
  222. // && x.AccountId == account.Id
  223. // && x.MissionId == missionLogin.Id
  224. // && x.ExecutedTime >= start
  225. // && x.ExecutedTime <= DateTime.Now
  226. // )
  227. // .Count();
  228. // // lần login này đc tính vào completed login
  229. // if (completedLogin >= missionLogin.RequiredTime - 1)
  230. // {
  231. // // save history for this login
  232. // var missionHistory = new MissionHistory
  233. // {
  234. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "MISSION_HISTORY_SEQ"),
  235. // Msisdn = account.Msisdn,
  236. // MissionId = missionLogin.Id,
  237. // ExecutedTime = DateTime.Now,
  238. // Status = CommonConstant.StatusSuccess,
  239. // AccountId = account.Id
  240. // };
  241. // dbContext.MissionHistories.Add(missionHistory);
  242. // await dbContext.SaveChangesAsync();
  243. // // set completed mission
  244. // var completedMission = await QuestLogic.SetCompletedMissionForUserAsync(
  245. // dbContext,
  246. // account.Msisdn,
  247. // account.Id,
  248. // missionLogin
  249. // );
  250. // if (completedMission != CommonErrorCode.Success)
  251. // {
  252. // log.Error("Set completed mission error: " + completedMission);
  253. // }
  254. // else
  255. // {
  256. // log.Debug("Set completed mission successfully");
  257. // }
  258. // }
  259. // else
  260. // {
  261. // // check time diff to save history
  262. // var startDay = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0);
  263. // var endDay = startDay.AddMinutes(int.Parse(timeDiff));
  264. // var loginHistory = dbContext
  265. // .MissionHistories.Where(
  266. // x =>
  267. // x.Msisdn == account.Msisdn
  268. // && x.AccountId == account.Id
  269. // && x.ExecutedTime >= startDay
  270. // && x.ExecutedTime <= endDay
  271. // && x.MissionId == missionLogin.Id
  272. // )
  273. // .FirstOrDefault();
  274. // if (loginHistory == null)
  275. // {
  276. // // add history
  277. // var missionHistory = new MissionHistory
  278. // {
  279. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "MISSION_HISTORY_SEQ"),
  280. // Msisdn = account.Msisdn,
  281. // MissionId = missionLogin.Id,
  282. // ExecutedTime = DateTime.Now,
  283. // Status = CommonConstant.StatusSuccess,
  284. // AccountId = account.Id
  285. // };
  286. // dbContext.MissionHistories.Add(missionHistory);
  287. // await dbContext.SaveChangesAsync();
  288. // // add prize for user
  289. // if (missionLogin.PrizeIdEachTime != null && missionLogin.PrizeIdEachTime > 0)
  290. // {
  291. // var addPrizeRes = await QuestLogic.AddPrizeForUser(
  292. // dbContext,
  293. // account.Msisdn,
  294. // missionLogin.Id,
  295. // missionLogin.PrizeIdEachTime
  296. // );
  297. // }
  298. // }
  299. // else
  300. // {
  301. // log.Debug($"User already login in {timeDiff}");
  302. // }
  303. // }
  304. // }
  305. // }
  306. // // check vendor package
  307. // var vendorPackage = dbContext
  308. // .VendorPackages.Where(
  309. // x =>
  310. // (x.Id == campaignOpening.VendorPackageId)
  311. // && x.Status == CommonConstant.StatusActive
  312. // )
  313. // .FirstOrDefault();
  314. // if (vendorPackage == null)
  315. // {
  316. // log.Error("Not found vendor package");
  317. // canPlay = true;
  318. // }
  319. // else
  320. // {
  321. // vendorPackageId = vendorPackage.Id;
  322. // // check history
  323. // var vendorPackageHistory = dbContext
  324. // .VendorPackageHistories.Where(
  325. // x =>
  326. // x.Msisdn == account.Msisdn
  327. // && x.VendorPackageId == vendorPackage.Id
  328. // && x.Status == CommonConstant.StatusSuccess
  329. // // && x.CompletedTime >= startDay
  330. // // && x.CompletedTime <= endDay
  331. // )
  332. // .OrderByDescending(x => x.CompletedTime)
  333. // .FirstOrDefault();
  334. // bool canCheckRegister = false;
  335. // if (vendorPackageHistory != null)
  336. // {
  337. // // check if completed today
  338. // var endTime = vendorPackage.Period == "DAILY"
  339. // ? vendorPackageHistory.CompletedTime.AddDays(1)
  340. // : vendorPackage.Period == "WEEKLY"
  341. // ? vendorPackageHistory.CompletedTime.AddDays(7)
  342. // : vendorPackage.Period == "MONTHLY"
  343. // ? vendorPackageHistory.CompletedTime.AddMonths(1)
  344. // : vendorPackage.Period == "YEARLY"
  345. // ? vendorPackageHistory.CompletedTime.AddYears(1)
  346. // : vendorPackageHistory.CompletedTime;
  347. // if (DateTime.Now <= endTime)
  348. // {
  349. // log.Debug($"User {account.Msisdn} has completed vendor package {vendorPackage.Code} today");
  350. // canPlay = true;
  351. // }
  352. // else
  353. // {
  354. // canCheckRegister = true;
  355. // }
  356. // }
  357. // else
  358. // {
  359. // canCheckRegister = true;
  360. // }
  361. // if (canCheckRegister)
  362. // {
  363. // // check user registered service
  364. // int checkRegistered = await QuestLogic.CheckRegisterServiceForUserAsync(dbContext, account.Msisdn, vendorPackage.Code);
  365. // if (checkRegistered == CommonConstant.UserRegistered)
  366. // {
  367. // log.Debug($"User {account.Msisdn} registered vendor package {vendorPackage.Code}");
  368. // canPlay = true;
  369. // // save vendor package history
  370. // var vendorPackageHistoryNew = new VendorPackageHistory
  371. // {
  372. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "VENDOR_PACKAGE_HISTORY_SEQ"),
  373. // Msisdn = account.Msisdn,
  374. // VendorPackageId = vendorPackage.Id,
  375. // Status = CommonConstant.StatusSuccess,
  376. // CompletedTime = DateTime.Now,
  377. // AccountId = account.Id
  378. // };
  379. // dbContext.VendorPackageHistories.Add(vendorPackageHistoryNew);
  380. // await dbContext.SaveChangesAsync();
  381. // }
  382. // else
  383. // {
  384. // log.Debug($"User {account.Msisdn} not registered vendor package {vendorPackage.Code}");
  385. // canPlay = false;
  386. // }
  387. // }
  388. // }
  389. // }
  390. // return DotnetLib.Http.HttpResponse.BuildResponse(
  391. // log,
  392. // url,
  393. // json,
  394. // CommonErrorCode.Success,
  395. // canPlay ? ConfigManager.Instance.GetConfigWebValue("NEED_BUY_VENDOR") : "Success",
  396. // new
  397. // {
  398. // token,
  399. // refreshToken,
  400. // account = new
  401. // {
  402. // account.Msisdn,
  403. // account.Username,
  404. // account.Birthday
  405. // },
  406. // canPlay,
  407. // vendorPackageId
  408. // }
  409. // );
  410. // }
  411. // catch (Exception exception)
  412. // {
  413. // log.Error("Exception: ", exception);
  414. // }
  415. // return DotnetLib.Http.HttpResponse.BuildResponse(
  416. // log,
  417. // url,
  418. // json,
  419. // CommonErrorCode.Error,
  420. // ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  421. // new { }
  422. // );
  423. //}
  424. //public async Task<IActionResult> UserInvite(HttpRequest httpRequest, UserInviteReq request)
  425. //{
  426. // var url = httpRequest.Path;
  427. // var json = JsonConvert.SerializeObject(request);
  428. // log.Debug("URL: " + url + " => Request: " + json);
  429. // try
  430. // {
  431. // var msisdn = CommonLogic.GetDataFromToken(configuration, httpRequest, "Msisdn");
  432. // var msisdnInvited = DotnetLib.Logic.ReuseLogic.TelemorValidateMsisdn(GetParameter("CountryCode"), request.receiver);
  433. // if (msisdnInvited == null)
  434. // {
  435. // return DotnetLib.Http.HttpResponse.BuildResponse(
  436. // log,
  437. // url,
  438. // json,
  439. // CommonErrorCode.Error,
  440. // "Invalid msisdn",
  441. // new { }
  442. // );
  443. // }
  444. // log.Debug("msisdn: " + msisdn);
  445. // log.Debug("msisdnInvited: " + msisdnInvited);
  446. // // check time inviting
  447. // var inviting = dbContext
  448. // .InvitingHistories.Where(x => x.Receiver == msisdnInvited)
  449. // .OrderByDescending(x => x.InvitedTime)
  450. // .ToList();
  451. // if (inviting.Count > 0)
  452. // {
  453. // if (inviting.Any(x => x.Status == CommonConstant.StatusClaimed))
  454. // {
  455. // return DotnetLib.Http.HttpResponse.BuildResponse(
  456. // log,
  457. // url,
  458. // json,
  459. // CommonErrorCode.Error,
  460. // ConfigManager.Instance.GetConfigWebValue("INVITE_BEFORE"),
  461. // new { }
  462. // );
  463. // }
  464. // else if (inviting.Any(x => x.InvitedTime.AddHours(24) >= DateTime.Now))
  465. // {
  466. // return DotnetLib.Http.HttpResponse.BuildResponse(
  467. // log,
  468. // url,
  469. // json,
  470. // CommonErrorCode.Error,
  471. // ConfigManager.Instance.GetConfigWebValue("INVITE_BEFORE"),
  472. // new { }
  473. // );
  474. // }
  475. // }
  476. // // this user is valid for inviting
  477. // var getInvitingHis = inviting.FindAll(
  478. // x => x.Msisdn == msisdn && x.Receiver == msisdnInvited
  479. // );
  480. // if (getInvitingHis.Count() > 0)
  481. // {
  482. // getInvitingHis[0].InvitedTime = DateTime.Now;
  483. // getInvitingHis[0].Status = CommonConstant.StatusSuccess;
  484. // dbContext.InvitingHistories.Update(getInvitingHis[0]);
  485. // }
  486. // else
  487. // {
  488. // var invitingCreate = new InvitingHistory
  489. // {
  490. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "INVITING_HISTORY_SEQ"),
  491. // Msisdn = msisdn!,
  492. // Receiver = msisdnInvited,
  493. // InvitedTime = DateTime.Now,
  494. // Status = CommonConstant.StatusSuccess,
  495. // AccountId = decimal.Parse(CommonLogic.GetDataFromToken(configuration, httpRequest, "AccountId")!)
  496. // };
  497. // dbContext.InvitingHistories.Add(invitingCreate);
  498. // // send mt to owner
  499. // await MtLogic.SendMt(
  500. // dbContext,
  501. // msisdnInvited,
  502. // ConfigManager.Instance.GetConfigSmsValue("PARTNER_INVITE_SUCCESS")
  503. // );
  504. // }
  505. // await dbContext.SaveChangesAsync();
  506. // return DotnetLib.Http.HttpResponse.BuildResponse(
  507. // log,
  508. // url,
  509. // json,
  510. // CommonErrorCode.Success,
  511. // ConfigManager.Instance.GetConfigWebValue("INVITE_SUCCESS"),
  512. // new { }
  513. // );
  514. // }
  515. // catch (Exception exception)
  516. // {
  517. // log.Error("Exception: ", exception);
  518. // }
  519. // return DotnetLib.Http.HttpResponse.BuildResponse(
  520. // log,
  521. // url,
  522. // json,
  523. // CommonErrorCode.Error,
  524. // ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  525. // new { }
  526. // );
  527. //}
  528. //public async Task<IActionResult> VendorPackageRegister(
  529. // HttpRequest httpRequest,
  530. // VendorPackageRegisterReq request
  531. //)
  532. //{
  533. // var url = httpRequest.Path;
  534. // var json = JsonConvert.SerializeObject(request);
  535. // log.Debug("URL: " + url + " => Request: " + json);
  536. // try
  537. // {
  538. // var msisdn = CommonLogic.GetDataFromToken(configuration, httpRequest, "Msisdn");
  539. // if (msisdn == null)
  540. // {
  541. // return DotnetLib.Http.HttpResponse.BuildResponse(
  542. // log,
  543. // url,
  544. // json,
  545. // CommonErrorCode.Error,
  546. // ConfigManager.Instance.GetConfigWebValue("MSISDN_INVALID"),
  547. // new { }
  548. // );
  549. // }
  550. // log.Debug("msisdn: " + msisdn);
  551. // // call soap to register
  552. // var webService = dbContext
  553. // .Webservices.Where(x => x.WsCode == "SUBSCRIBE")
  554. // .FirstOrDefault();
  555. // if (webService == null)
  556. // {
  557. // log.Error("Not found webservice SUBSCRIBE");
  558. // return DotnetLib.Http.HttpResponse.BuildResponse(
  559. // log,
  560. // url,
  561. // json,
  562. // CommonErrorCode.Error,
  563. // "Not found webservice SUBSCRIBE",
  564. // new { }
  565. // );
  566. // }
  567. // // check vendor package
  568. // var vendorPackage = dbContext
  569. // .VendorPackages.Where(
  570. // x =>
  571. // x.Id == request.vendorPackageId
  572. // && x.Status == CommonConstant.StatusActive
  573. // )
  574. // .FirstOrDefault();
  575. // if (vendorPackage == null)
  576. // {
  577. // log.Error("Not found vendor package");
  578. // return DotnetLib.Http.HttpResponse.BuildResponse(
  579. // log,
  580. // url,
  581. // json,
  582. // CommonErrorCode.Error,
  583. // "Not found vendor package",
  584. // new { }
  585. // );
  586. // }
  587. // // check payment channel
  588. // var paymentChannel = dbContext
  589. // .PaymentChannels.Where(
  590. // x =>
  591. // x.Id == request.paymentChannelId
  592. // && x.Status == CommonConstant.StatusActive
  593. // )
  594. // .FirstOrDefault();
  595. // if (paymentChannel == null)
  596. // {
  597. // log.Error("Not found payment channel");
  598. // return DotnetLib.Http.HttpResponse.BuildResponse(
  599. // log,
  600. // url,
  601. // json,
  602. // CommonErrorCode.Error,
  603. // "Not found payment channel",
  604. // new { }
  605. // );
  606. // }
  607. // string transactionId = DotnetLib.Logic.ReuseLogic.GenerateUniqueNumber();
  608. // string body = webService
  609. // .MsgTemplate!.Replace("#MSISDN#", msisdn)
  610. // .Replace("#SERVICE_ID#", vendorPackage.Code)
  611. // .Replace("#PARAM#", "0")
  612. // .Replace("#TRANS_ID#", transactionId);
  613. // var (errorCode, envelope) = await QuestLogic.RegisterServiceForUserAsync(
  614. // dbContext,
  615. // webService.Wsdl!,
  616. // msisdn,
  617. // body,
  618. // vendorPackage.Code,
  619. // transactionId
  620. // );
  621. // if (errorCode != CommonErrorCode.Success || envelope == null)
  622. // {
  623. // return DotnetLib.Http.HttpResponse.BuildResponse(
  624. // log,
  625. // url,
  626. // json,
  627. // CommonErrorCode.Error,
  628. // ConfigManager.Instance.GetConfigWebValue("REGISTER_FAILED"),
  629. // new { }
  630. // );
  631. // }
  632. // // Lấy danh sách gói:
  633. // var subscriberResponse = envelope.Body!.SubscriberResponse;
  634. // if (subscriberResponse != null && subscriberResponse.ResponseCode == "0")
  635. // {
  636. // log.Debug("Register vendor package successfully");
  637. // // save vendor package register to db
  638. // var vendorPackageHistory = new VendorPackageHistory
  639. // {
  640. // Id = (decimal)await DbLogic.GenIdAsync(dbContext, "VENDOR_PACKAGE_HISTORY_SEQ"),
  641. // Msisdn = msisdn!,
  642. // VendorPackageId = vendorPackage.Id,
  643. // Status = CommonConstant.StatusSuccess,
  644. // CompletedTime = DateTime.Now,
  645. // AccountId = decimal.Parse(CommonLogic.GetDataFromToken(configuration, httpRequest, "AccountId")!)
  646. // };
  647. // // send mt
  648. // await MtLogic.SendMt(
  649. // dbContext,
  650. // msisdn!,
  651. // ConfigManager.Instance.GetConfigSmsValue("VENDOR_BUYING_SUCCESS").Replace("%MONEY%", vendorPackage.Price.ToString())
  652. // );
  653. // return DotnetLib.Http.HttpResponse.BuildResponse(
  654. // log,
  655. // url,
  656. // json,
  657. // CommonErrorCode.Success,
  658. // ConfigManager.Instance.GetConfigWebValue("REGISTER_SUCCESS").Replace("%SERVICE%", vendorPackage.Code),
  659. // new { }
  660. // );
  661. // }
  662. // else
  663. // {
  664. // log.Error("Register vendor package failed");
  665. // return DotnetLib.Http.HttpResponse.BuildResponse(
  666. // log,
  667. // url,
  668. // json,
  669. // CommonErrorCode.Error,
  670. // ConfigManager.Instance.GetConfigWebValue("REGISTER_FAILED"),
  671. // new { }
  672. // );
  673. // }
  674. // }
  675. // catch (Exception exception)
  676. // {
  677. // log.Error("Exception: ", exception);
  678. // }
  679. // return DotnetLib.Http.HttpResponse.BuildResponse(
  680. // log,
  681. // url,
  682. // json,
  683. // CommonErrorCode.Error,
  684. // ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  685. // new { }
  686. // );
  687. //}
  688. //public async Task<IActionResult> LoadVendorPackage(HttpRequest httpRequest, LoadVendorPackageReq request)
  689. //{
  690. // var url = httpRequest.Path;
  691. // var json = JsonConvert.SerializeObject(request);
  692. // log.Debug("URL: " + url + " => Request: " + json);
  693. // try
  694. // {
  695. // // check if user completed vendor package
  696. // var campaignOpening = dbContext
  697. // .Campaigns.Where(
  698. // x =>
  699. // x.Status == CommonConstant.StatusActive
  700. // && x.FromTime <= DateTime.Now
  701. // && x.ToTime >= DateTime.Now
  702. // )
  703. // .FirstOrDefault();
  704. // if (campaignOpening == null)
  705. // {
  706. // return DotnetLib.Http.HttpResponse.BuildResponse(
  707. // log,
  708. // url,
  709. // json,
  710. // CommonErrorCode.Error,
  711. // "No active campaign",
  712. // new { }
  713. // );
  714. // }
  715. // // load vendor package
  716. // var vendorPackage = dbContext
  717. // .VendorPackages
  718. // .Where(x => x.Status == CommonConstant.StatusActive && x.Id == campaignOpening.VendorPackageId)
  719. // .Select(x => new
  720. // {
  721. // x.Id,
  722. // x.Name,
  723. // x.Code,
  724. // x.Description,
  725. // x.Price,
  726. // x.Type,
  727. // x.Period,
  728. // x.MoneyType,
  729. // x.Introduction,
  730. // })
  731. // .FirstOrDefault();
  732. // if (vendorPackage == null)
  733. // {
  734. // return DotnetLib.Http.HttpResponse.BuildResponse(
  735. // log,
  736. // url,
  737. // json,
  738. // CommonErrorCode.Error,
  739. // "No vendor package found",
  740. // new { }
  741. // );
  742. // }
  743. // return DotnetLib.Http.HttpResponse.BuildResponse(
  744. // log,
  745. // url,
  746. // json,
  747. // CommonErrorCode.Success,
  748. // "Load vendor package successfully",
  749. // new
  750. // {
  751. // vendorPackage
  752. // }
  753. // );
  754. // }
  755. // catch (Exception exception)
  756. // {
  757. // log.Error("Exception: ", exception);
  758. // }
  759. // return DotnetLib.Http.HttpResponse.BuildResponse(
  760. // log,
  761. // url,
  762. // json,
  763. // CommonErrorCode.Error,
  764. // ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  765. // new { }
  766. // );
  767. //}
  768. #region Auth Methods - OTP Login
  769. /// <summary>
  770. /// Request OTP to be sent to email
  771. /// </summary>
  772. public async Task<IActionResult> RequestOtp(HttpRequest httpRequest, RequestOtpReq request)
  773. {
  774. var url = httpRequest.Path;
  775. var json = JsonConvert.SerializeObject(request);
  776. log.Debug("URL: " + url + " => Request: " + json);
  777. try
  778. {
  779. if (string.IsNullOrEmpty(request.email))
  780. {
  781. return DotnetLib.Http.HttpResponse.BuildResponse(
  782. log,
  783. url,
  784. json,
  785. CommonErrorCode.RequiredFieldMissing,
  786. "Email is required",
  787. new { }
  788. );
  789. }
  790. // Generate 6-digit OTP
  791. string otpCode = GenerateOtp();
  792. // Check if customer exists, if not create new
  793. var customer = dbContext.CustomerInfos
  794. .Where(c => c.Email == request.email)
  795. .FirstOrDefault();
  796. int? customerId = customer?.Id;
  797. if (customer == null)
  798. {
  799. // Create new customer record
  800. var newCustomerId = (int)await Database.DbLogic.GenIdAsync(dbContext, "CUSTOMER_INFO_SEQ");
  801. var newCustomer = new CustomerInfo
  802. {
  803. Id = newCustomerId,
  804. Email = request.email,
  805. Status = true,
  806. IsVerified = false,
  807. CreatedDate = DateTime.Now,
  808. LastUpdate = DateTime.Now
  809. };
  810. dbContext.CustomerInfos.Add(newCustomer);
  811. await dbContext.SaveChangesAsync();
  812. customerId = newCustomerId;
  813. }
  814. // Invalidate previous unused OTPs for this email
  815. var oldOtps = dbContext.OtpVerifications
  816. .Where(o => o.UserEmail == request.email && o.IsUsed == false)
  817. .ToList();
  818. foreach (var oldOtp in oldOtps)
  819. {
  820. oldOtp.IsUsed = true;
  821. }
  822. // Create new OTP record
  823. int otpExpireMinutes = 5;
  824. var otpId = (int)await Database.DbLogic.GenIdAsync(dbContext, "OTP_VERIFICATION_SEQ");
  825. var otpVerification = new OtpVerification
  826. {
  827. Id = otpId,
  828. CustomerId = customerId,
  829. UserEmail = request.email,
  830. OtpCode = otpCode,
  831. OtpType = 1, // Login OTP
  832. ExpiredAt = DateTime.Now.AddMinutes(otpExpireMinutes),
  833. IsUsed = false,
  834. AttemptCount = 0,
  835. CreatedDate = DateTime.Now
  836. };
  837. dbContext.OtpVerifications.Add(otpVerification);
  838. await dbContext.SaveChangesAsync();
  839. // Add to MESSAGE_QUEUE for background email sending using template
  840. var messageId = (int)await Database.DbLogic.GenIdAsync(dbContext, "MESSAGE_QUEUE_SEQ");
  841. // Determine template code based on language
  842. // TemplateCode format: OTP_LOGIN (default Vietnamese), OTP_LOGIN_EN, OTP_LOGIN_LO
  843. string lang = (request.lang ?? "vi").ToLower();
  844. string templateCode = lang switch
  845. {
  846. "en" => "OTP_LOGIN_EN",
  847. "lo" => "OTP_LOGIN_LO",
  848. _ => "OTP_LOGIN" // Default Vietnamese
  849. };
  850. // Prepare template data as JSON
  851. var templateData = System.Text.Json.JsonSerializer.Serialize(new
  852. {
  853. OTP_CODE = otpCode,
  854. EXPIRE_MINUTES = otpExpireMinutes.ToString()
  855. });
  856. var emailMessage = new MessageQueue
  857. {
  858. Id = messageId,
  859. MessageType = 1, // Email
  860. Recipient = request.email,
  861. TemplateCode = templateCode, // Use template based on language
  862. TemplateData = templateData,
  863. Priority = true, // High priority
  864. Status = 0, // Pending
  865. ScheduledAt = DateTime.Now,
  866. RetryCount = 0,
  867. MaxRetry = 3,
  868. CreatedBy = customerId,
  869. CreatedDate = DateTime.Now
  870. };
  871. dbContext.MessageQueues.Add(emailMessage);
  872. await dbContext.SaveChangesAsync();
  873. log.Info($"OTP generated for {request.email}: {otpCode} - Email queued");
  874. return DotnetLib.Http.HttpResponse.BuildResponse(
  875. log,
  876. url,
  877. json,
  878. CommonErrorCode.Success,
  879. "OTP sent successfully",
  880. new
  881. {
  882. email = request.email,
  883. expireInSeconds = otpExpireMinutes * 60
  884. }
  885. );
  886. }
  887. catch (Exception exception)
  888. {
  889. log.Error("Exception: ", exception);
  890. }
  891. return DotnetLib.Http.HttpResponse.BuildResponse(
  892. log,
  893. url,
  894. json,
  895. CommonErrorCode.SystemError,
  896. ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  897. new { }
  898. );
  899. }
  900. /// <summary>
  901. /// Verify OTP and complete login - return JWT token
  902. /// </summary>
  903. public async Task<IActionResult> VerifyOtp(HttpRequest httpRequest, VerifyOtpReq request)
  904. {
  905. var url = httpRequest.Path;
  906. var json = JsonConvert.SerializeObject(request);
  907. log.Debug("URL: " + url + " => Request: " + json);
  908. try
  909. {
  910. if (string.IsNullOrEmpty(request.email) || string.IsNullOrEmpty(request.otpCode))
  911. {
  912. return DotnetLib.Http.HttpResponse.BuildResponse(
  913. log,
  914. url,
  915. json,
  916. CommonErrorCode.RequiredFieldMissing,
  917. "Email and OTP are required",
  918. new { }
  919. );
  920. }
  921. // Find valid OTP
  922. var otpRecord = dbContext.OtpVerifications
  923. .Where(o => o.UserEmail == request.email
  924. && o.OtpCode == request.otpCode
  925. && o.IsUsed == false
  926. && o.ExpiredAt > DateTime.Now)
  927. .OrderByDescending(o => o.CreatedDate)
  928. .FirstOrDefault();
  929. if (otpRecord == null)
  930. {
  931. // Check if OTP exists but expired or used
  932. var anyOtp = dbContext.OtpVerifications
  933. .Where(o => o.UserEmail == request.email && o.OtpCode == request.otpCode)
  934. .FirstOrDefault();
  935. if (anyOtp != null)
  936. {
  937. if (anyOtp.IsUsed == true)
  938. {
  939. return DotnetLib.Http.HttpResponse.BuildResponse(
  940. log,
  941. url,
  942. json,
  943. CommonErrorCode.OtpAlreadyUsed,
  944. "OTP has already been used",
  945. new { }
  946. );
  947. }
  948. if (anyOtp.ExpiredAt <= DateTime.Now)
  949. {
  950. return DotnetLib.Http.HttpResponse.BuildResponse(
  951. log,
  952. url,
  953. json,
  954. CommonErrorCode.OtpExpired,
  955. "OTP has expired",
  956. new { }
  957. );
  958. }
  959. }
  960. return DotnetLib.Http.HttpResponse.BuildResponse(
  961. log,
  962. url,
  963. json,
  964. CommonErrorCode.OtpInvalid,
  965. "Invalid OTP",
  966. new { }
  967. );
  968. }
  969. // Mark OTP as used
  970. otpRecord.IsUsed = true;
  971. // Get customer info
  972. var customer = dbContext.CustomerInfos
  973. .Where(c => c.Email == request.email)
  974. .FirstOrDefault();
  975. if (customer == null)
  976. {
  977. return DotnetLib.Http.HttpResponse.BuildResponse(
  978. log,
  979. url,
  980. json,
  981. CommonErrorCode.UserNotFound,
  982. "Customer not found",
  983. new { }
  984. );
  985. }
  986. // Update customer verification status
  987. customer.IsVerified = true;
  988. customer.LastLoginDate = DateTime.Now;
  989. customer.LastUpdate = DateTime.Now;
  990. // Generate JWT tokens
  991. int tokenExpireHours = 24;
  992. int refreshTokenExpireDays = 30;
  993. string accessToken = CommonLogic.GenToken(configuration, customer.Email ?? "", customer.Id.ToString() ?? "");
  994. string refreshToken = CommonLogic.GenRefreshToken(configuration, customer.Email ?? "");
  995. var expiresAt = DateTime.Now.AddHours(tokenExpireHours);
  996. var refreshExpiresAt = DateTime.Now.AddDays(refreshTokenExpireDays);
  997. // Revoke old tokens
  998. var oldTokens = dbContext.UserTokens
  999. .Where(t => t.CustomerId == customer.Id && t.IsRevoked == false)
  1000. .ToList();
  1001. foreach (var oldToken in oldTokens)
  1002. {
  1003. oldToken.IsRevoked = true;
  1004. }
  1005. // Save new token
  1006. var tokenId = (int)await Database.DbLogic.GenIdAsync(dbContext, "USER_TOKEN_SEQ");
  1007. var userToken = new UserToken
  1008. {
  1009. Id = tokenId,
  1010. CustomerId = customer.Id.Value,
  1011. AccessToken = accessToken,
  1012. RefreshToken = refreshToken,
  1013. TokenType = "Bearer",
  1014. DeviceInfo = httpRequest.Headers["User-Agent"].ToString(),
  1015. IpAddress = GetClientIpAddress(httpRequest),
  1016. ExpiredAt = expiresAt,
  1017. RefreshExpiredAt = refreshExpiresAt,
  1018. IsRevoked = false,
  1019. CreatedDate = DateTime.Now,
  1020. LastUsed = DateTime.Now
  1021. };
  1022. dbContext.UserTokens.Add(userToken);
  1023. await dbContext.SaveChangesAsync();
  1024. return DotnetLib.Http.HttpResponse.BuildResponse(
  1025. log,
  1026. url,
  1027. json,
  1028. CommonErrorCode.Success,
  1029. "Login successful",
  1030. new
  1031. {
  1032. userId = customer.Id.Value,
  1033. email = customer.Email ?? "",
  1034. fullName = $"{customer.SurName} {customer.LastName}".Trim(),
  1035. avatarUrl = customer.AvatarUrl,
  1036. accessToken,
  1037. refreshToken,
  1038. expiresAt
  1039. }
  1040. );
  1041. }
  1042. catch (Exception exception)
  1043. {
  1044. log.Error("Exception: ", exception);
  1045. }
  1046. return DotnetLib.Http.HttpResponse.BuildResponse(
  1047. log,
  1048. url,
  1049. json,
  1050. CommonErrorCode.SystemError,
  1051. ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
  1052. new { }
  1053. );
  1054. }
  1055. /// <summary>
  1056. /// Generate 6-digit OTP code
  1057. /// </summary>
  1058. private string GenerateOtp()
  1059. {
  1060. using (var rng = System.Security.Cryptography.RandomNumberGenerator.Create())
  1061. {
  1062. var bytes = new byte[4];
  1063. rng.GetBytes(bytes);
  1064. var number = Math.Abs(BitConverter.ToInt32(bytes, 0)) % 1000000;
  1065. return number.ToString("D6");
  1066. }
  1067. }
  1068. /// <summary>
  1069. /// Get client IP address
  1070. /// </summary>
  1071. private string GetClientIpAddress(HttpRequest httpRequest)
  1072. {
  1073. var ipAddress = httpRequest.Headers["X-Forwarded-For"].FirstOrDefault();
  1074. if (string.IsNullOrEmpty(ipAddress))
  1075. {
  1076. ipAddress = httpRequest.HttpContext.Connection.RemoteIpAddress?.ToString();
  1077. }
  1078. return ipAddress ?? "Unknown";
  1079. }
  1080. #endregion
  1081. }
  1082. }