Ver código fonte

update code mới liên quan bổ sung nút mua lượt
tôi ưu css

student 12 horas atrás
pai
commit
81fadf192f
20 arquivos alterados com 129 adições e 64 exclusões
  1. 18 5
      KittyFallWs/KittyFallWs/src/com/vas/kittyfallwsvas/wsfw/database/WsProcessUtils.java
  2. 0 4
      Kitty_Fall/Kitty_Fall/Common/CommonConstants.cs
  3. 4 0
      Kitty_Fall/Kitty_Fall/Common/CommonLogic.cs
  4. 1 0
      Kitty_Fall/Kitty_Fall/Common/Http/Apis/Request/UserGameLevelResult.cs
  5. 6 2
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Apis/Business/Game/GameBusinessImpl.cs
  6. 26 23
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Apis/Business/User/UserBusinessImpl.cs
  7. 3 3
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Cms/Views/Shared/_Layout.cshtml
  8. 2 6
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/BaseController.cs
  9. 7 1
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/GameController.cs
  10. 0 1
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/HistoryController.cs
  11. 3 2
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/HomeController.cs
  12. 0 5
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Helpers/PackagesCacheHelper.cs
  13. 2 2
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/Home/Index.cshtml
  14. 4 4
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/Play/Index.cshtml
  15. 5 0
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/all.min.css
  16. 5 0
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/input.css
  17. 11 0
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/all.min.js
  18. 11 0
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/input.js
  19. 19 4
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Woker/Services/GameRewardPayoutWorker.cs
  20. 2 2
      Kitty_Fall/Kitty_Fall/Kitty_Fall.Woker/appsettings.json

+ 18 - 5
KittyFallWs/KittyFallWs/src/com/vas/kittyfallwsvas/wsfw/database/WsProcessUtils.java

@@ -204,13 +204,26 @@ public class WsProcessUtils extends DbProcessorAbstract {
                             + "FROM RESULT_REQUEST_INBOX WHERE EVENT_ID=?");
                     checkDuplicate.setString(1, event.getEventId());
                     duplicateRs = checkDuplicate.executeQuery();
-                    if (duplicateRs.next()
-                            && event.getPayloadHash().equals(duplicateRs.getString(1))) {
-                        logger.info("Skip duplicate resultRequest eventId=" + event.getEventId());
+                    if (duplicateRs.next()) {
+                        String existingPayloadHash = duplicateRs.getString(1);
+                        if (event.getPayloadHash().equals(existingPayloadHash)) {
+                            logger.info("Skip duplicate resultRequest eventId=" + event.getEventId());
+                            return 1;
+                        }
+                        // The original event has already claimed this transaction identity.
+                        // Do not retry or process the conflicting payload because doing so may
+                        // charge/renew the subscriber a second time. The spool source is retained
+                        // in the done archive for reconciliation.
+                        logger.error("Skip EVENT_ID collision with different payload"
+                                + ", eventId=" + event.getEventId()
+                                + ", incomingPayloadHash=" + event.getPayloadHash()
+                                + ", existingPayloadHash=" + existingPayloadHash
+                                + ", sourceFile=" + sourceFile
+                                + ", sourceLine=" + sourceLine);
                         return 1;
                     }
-                    throw new SQLException("EVENT_ID collision with different payload: "
-                            + event.getEventId(), ex);
+                    throw new SQLException("Duplicate EVENT_ID was reported but the existing row "
+                            + "could not be found: " + event.getEventId(), ex);
                 }
                 throw ex;
             }

+ 0 - 4
Kitty_Fall/Kitty_Fall/Common/CommonConstants.cs

@@ -199,10 +199,6 @@ namespace Common
 
     public static class CommonErrorCode
     {
-        public const int AddPointSuccess = 0;
-        public const int AddPointFailure = -1;
-        public const int AddPointWaiting = 100;
-
         // http code
         public const string WAITING_OTP = "100";
         public const int USER_EXISTED = 2;

+ 4 - 0
Kitty_Fall/Kitty_Fall/Common/CommonLogic.cs

@@ -20,6 +20,10 @@ namespace Common;
 
 public static class CommonLogic
 {
+    public const int AddPointSuccess = 0;
+    public const int AddPointFailure = -1;
+    public const int AddPointWaiting = 100;
+
     private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CommonLogic));
 
 

+ 1 - 0
Kitty_Fall/Kitty_Fall/Common/Http/Apis/Request/UserGameLevelResult.cs

@@ -27,6 +27,7 @@ namespace Common.Http.Apis.Request
         public string reason { get; set; } = "";
         public decimal totalDataMb { get; set; }
         public decimal totalLoyalty { get; set; }
+        public int totalTurn { get; set; }
     }
 
     public class UserGameLevelResultRes : CommonResponse

+ 6 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Apis/Business/Game/GameBusinessImpl.cs

@@ -708,6 +708,7 @@ namespace Kitty_Fall.Apis.Business.Game
                 session.LastActionTime = now;
                 session.UpdatedTime = now;
                 await dbContext.SaveChangesAsync();
+                var totalTurn = await GetAvailableTurnAsync(msisdn, now);
 
                 return CommonLogic.BuildResponse(
                     url,
@@ -719,7 +720,8 @@ namespace Kitty_Fall.Apis.Business.Game
                         point = "0",
                         data = "",
                         score = session.TotalScore.ToString(CultureInfo.InvariantCulture),
-                        transId = request.transId
+                        transId = request.transId,
+                        totalTurn = totalTurn
                     });
             }
             catch (Exception exception)
@@ -783,6 +785,7 @@ namespace Kitty_Fall.Apis.Business.Game
                     session.LastActionTime = now;
                     session.UpdatedTime = now;
                     await dbContext.SaveChangesAsync();
+                    var totalTurn = await GetAvailableTurnAsync(msisdn, now);
 
                     return CommonLogic.BuildResponse(
                         url,
@@ -796,7 +799,8 @@ namespace Kitty_Fall.Apis.Business.Game
                             score = session.TotalScore.ToString(CultureInfo.InvariantCulture),
                             transId = request.transId,
                             totalDataMb = session.TotalDataMb,
-                            totalLoyalty = session.TotalLoyalty
+                            totalLoyalty = session.TotalLoyalty,
+                            totalTurn = totalTurn
                         });
                 }
 

+ 26 - 23
Kitty_Fall/Kitty_Fall/Kitty_Fall.Apis/Business/User/UserBusinessImpl.cs

@@ -467,14 +467,7 @@ namespace Kitty_Fall.Apis.Business.User
                 {
                     // VAS trả "2" (SUCCESS_FOR_THE_FIRST_TIME_REGISTER) khi user đăng ký lần đầu -> vẫn là thành công.
                     // Đăng ký thẳng (không cần OTP) -> trả kèm danh sách gói để client cập nhật ngay trạng thái thuê bao.
-                    List<RegInfo> userPackage = await dbContext
-                        .RegInfos.Where(x => x.Msisdn == msisdn
-                            && x.Status == true
-                            && x.Renew == 1
-                            )
-                        .OrderByDescending(x => x.RegisterTime)
-                        .ThenByDescending(x => x.RegisterId)
-                        .ToListAsync();
+                    List<RegInfo> userPackage = await TryLoadActiveRegistrationsAfterSuccessfulCharge(msisdn);
                     return CommonLogic.BuildResponse(
                         url,
                         json,
@@ -579,14 +572,7 @@ namespace Kitty_Fall.Apis.Business.User
                 {
                     // VAS trả "2" (SUCCESS_FOR_THE_FIRST_TIME_REGISTER) khi user đăng ký lần đầu -> vẫn là thành công.
                     // Trả kèm danh sách gói đang dùng để client cập nhật ngay trạng thái thuê bao (không phải gọi lại GetProfileInfo).
-                    List<RegInfo> userPackage = await dbContext
-                        .RegInfos.Where(x => x.Msisdn == msisdn
-                            && x.Status == true
-                            && x.Renew == 1
-                         )
-                        .OrderByDescending(x => x.RegisterTime)
-                        .ThenByDescending(x => x.RegisterId)
-                        .ToListAsync();
+                    List<RegInfo> userPackage = await TryLoadActiveRegistrationsAfterSuccessfulCharge(msisdn);
                     return CommonLogic.BuildResponse(
                         url,
                         json,
@@ -675,13 +661,7 @@ namespace Kitty_Fall.Apis.Business.User
                 if (wsRegisterSubQuickResponse.@return.errorCode == CommonErrorCode.Success
                     || wsRegisterSubQuickResponse.@return.errorCode == CommonErrorCode.SuccessFirstRegister)
                 {
-                    List<RegInfo> userPackage = await dbContext
-                        .RegInfos.Where(x => x.Msisdn == msisdn
-                            && x.Status == true
-                            && x.Renew == 1)
-                        .OrderByDescending(x => x.RegisterTime)
-                        .ThenByDescending(x => x.RegisterId)
-                        .ToListAsync();
+                    List<RegInfo> userPackage = await TryLoadActiveRegistrationsAfterSuccessfulCharge(msisdn);
 
                     return CommonLogic.BuildResponse(
                         url,
@@ -1475,6 +1455,29 @@ namespace Kitty_Fall.Apis.Business.User
                 new BadRequestObjectResult(new { message = Lang.badRequest })
             );
         }
+        private async Task<List<RegInfo>> TryLoadActiveRegistrationsAfterSuccessfulCharge(string msisdn)
+        {
+            try
+            {
+                return await dbContext.RegInfos
+                    .Where(x => x.Msisdn == msisdn
+                        && x.Status == true
+                        && x.Renew == 1)
+                    .OrderByDescending(x => x.RegisterTime)
+                    .ThenByDescending(x => x.RegisterId)
+                    .ToListAsync();
+            }
+            catch (Exception exception)
+            {
+                // Charging/registration was already confirmed by VAS. A profile refresh
+                // failure must not turn that completed transaction into a client-visible
+                // failure, which could also encourage a duplicate purchase attempt.
+                log.Warn("VAS registration succeeded, but active package refresh failed. "
+                    + "Returning the confirmed success response without regInfos.", exception);
+                return new List<RegInfo>();
+            }
+        }
+
         private static object GetHttpSendRequest()
         {
             return GetHttpSendRequest;

+ 3 - 3
Kitty_Fall/Kitty_Fall/Kitty_Fall.Cms/Views/Shared/_Layout.cshtml

@@ -84,7 +84,7 @@
                     <div class="bg-admin-active p-1.5 rounded-lg">
                         <i class="fas fa-rocket text-white"></i>
                     </div>
-                    <span>MYJOB CMS</span>
+                    <span>KITTY_FALL CMS</span>
                 </a>
                 <button type="button" onclick="closeMobileSidebar()" class="flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white">
                     <i class="fas fa-times"></i>
@@ -287,7 +287,7 @@
                     <div class="bg-admin-active p-1.5 rounded-lg">
                         <i class="fas fa-rocket text-white"></i>
                     </div>
-                    <span>MYJOB CMS</span>
+                    <span>KITTY_FALL CMS</span>
                 </a>
                 <ul class="mt-8">
                     @if (canViewDashboard)
@@ -485,7 +485,7 @@
                             <i class="fas fa-bars"></i>
                         </button>
                         <div class="min-w-0">
-                            <div class="text-xs font-bold uppercase tracking-[0.2em] text-gray-400 md:hidden">MYJOB CMS</div>
+                            <div class="text-xs font-bold uppercase tracking-[0.2em] text-gray-400 md:hidden">KITTY_FALL CMS</div>
                             <div class="truncate text-lg font-bold text-gray-800">@ViewData["Title"]</div>
                         </div>
                     </div>

+ 2 - 6
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/BaseController.cs

@@ -1,17 +1,13 @@
 
 using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.Rendering;
-using Microsoft.AspNetCore.Mvc.ViewEngines;
-using Microsoft.AspNetCore.Mvc.ViewFeatures;
 using System.Security.Cryptography;
-using System.ServiceModel;
 
 namespace Kitty_Fall.Website.Controllers;
 
 public class BaseController : Controller
 {
 
-    
+
     private string GenerateAuthId()
     {
 #pragma warning disable SYSLIB0023 // Type or member is obsolete
@@ -88,6 +84,6 @@ public class BaseController : Controller
     }
 
 
-    
+
 
 }

+ 7 - 1
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/GameController.cs

@@ -1,4 +1,3 @@
-using Common;
 using Common.Extension;
 using Common.Http.Apis.Request;
 using Microsoft.AspNetCore.Mvc;
@@ -25,6 +24,7 @@ namespace Kitty_Fall.Website.Controllers
                 if (apiResult.errorCode == "0" && apiResult.data != null)
                 {
                     var maxLevel = await GetTodayMaxLevelAsync(request);
+                    HttpContext.Session.SetComplexData("totalTurn", (long)apiResult.data.totalTurn);
 
                     return Json(new
                     {
@@ -33,6 +33,7 @@ namespace Kitty_Fall.Website.Controllers
                         data = apiResult.data.data,
                         score = apiResult.data.score,
                         transId = apiResult.data.transId,
+                        totalTurn = apiResult.data.totalTurn,
                         max_level = maxLevel
                     });
                 }
@@ -101,6 +102,10 @@ namespace Kitty_Fall.Website.Controllers
                 log.Info($"ExitGame msisdn={request.msisdn}, transId={request.transId}, level={request.level}, score={request.score}, gameType={request.gameType}, gameOver={request.gameOver}");
                 request.gameOver = request.gameOver == 0 ? 1 : request.gameOver;
                 var apiResult = await SendGameApiAsync(request, UrlConstant.GameSaveLevelResultUrl);
+                if (apiResult.errorCode == "0" && apiResult.data != null)
+                {
+                    HttpContext.Session.SetComplexData("totalTurn", (long)apiResult.data.totalTurn);
+                }
                 var payload = JsonSerializer.Serialize(new
                 {
                     type = "EXIT_GAME_RESULT",
@@ -108,6 +113,7 @@ namespace Kitty_Fall.Website.Controllers
                     score = apiResult.data?.score ?? request.score.ToString(),
                     data = apiResult.data?.totalDataMb ?? 0,
                     loyalty = apiResult.data?.totalLoyalty ?? 0,
+                    totalTurn = apiResult.data?.totalTurn,
                     level = request.level,
                     message = apiResult.message ?? ""
                 });

+ 0 - 1
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/HistoryController.cs

@@ -2,7 +2,6 @@ using Common;
 using Common.Extension;
 using Common.Http.Apis.Request;
 using Microsoft.AspNetCore.Mvc;
-using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 
 namespace Kitty_Fall.Website.Controllers

+ 3 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Controllers/HomeController.cs

@@ -8,7 +8,6 @@ using Newtonsoft.Json;
 using Newtonsoft.Json.Linq;
 using System.Diagnostics;
 using System.Net.Http.Headers;
-using System.Security.Policy;
 using System.Text;
 using static DotnetLib.Http.HttpObject;
 
@@ -76,7 +75,9 @@ namespace Kitty_Fall.Website.Controllers
 
                 var allowedTypes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
                 {
-                    ["image/jpeg"] = ".jpg", ["image/png"] = ".png", ["image/webp"] = ".webp"
+                    ["image/jpeg"] = ".jpg",
+                    ["image/png"] = ".png",
+                    ["image/webp"] = ".webp"
                 };
                 if (!allowedTypes.TryGetValue(avatar.ContentType, out var extension))
                     return BadRequest(new { success = false, message = "Only JPG, PNG or WEBP images are supported." });

+ 0 - 5
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Helpers/PackagesCacheHelper.cs

@@ -1,11 +1,6 @@
-using Common;
 using Common.Extension;
 using Common.Http.Apis.Request;
-using Microsoft.AspNetCore.Http;
 using Newtonsoft.Json.Linq;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
 
 namespace Kitty_Fall.Website.Helpers
 {

+ 2 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/Home/Index.cshtml

@@ -346,8 +346,8 @@
                 url: "/Login/LogoutBackAction",
                 type: "POST",
                 complete: function () {
-                    //window.location.href = "mytel://back";
-                    window.location.href = "Login/index";
+                    window.location.href = "mytel://back";
+                    // window.location.href = "Login/index";
                 }
             });
         }

+ 4 - 4
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/Views/Play/Index.cshtml

@@ -26,11 +26,11 @@
                 <img src="~/kitty/assets/kitty-fall/coin.png" alt="">
                 <strong>@Model.TotalPoint.ToString("N0")</strong>
             </span>
-            <span class="play-top-chip">
+            <a class="play-top-chip play-turn-chip" href="@Url.Action("Index", "Home", new { buyturn = true })" aria-label="@Lang.BuyTurn">
                 <img src="~/kitty/assets/kitty-fall/ticket.png" alt="">
-                <strong>@Model.TotalTurn.ToString("N0")</strong>
+                <strong data-play-total-turn>@Model.TotalTurn.ToString("N0")</strong>
                 <b>+</b>
-            </span>
+            </a>
         </div>
         <button class="menu-button" aria-label="@Lang.OpenMenu">
             <span></span>
@@ -96,7 +96,7 @@
     </section>
 
     <div class="play-action-bar">
-        <a class="play-back-button" href="/">
+        <a class="play-back-button" href="@Url.Action("Index", "Home")">
             <span aria-hidden="true"></span>
             <strong>@Lang.Back</strong>
         </a>

+ 5 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/all.min.css

@@ -203,6 +203,11 @@ button {
     line-height: 1;
     font-weight: 900;
     text-shadow: 0 1px 1px rgba(65, 68, 147, 0.2);
+    text-decoration: none;
+}
+
+.play-turn-chip {
+    cursor: pointer;
 }
 
 .play-top-chip img {

+ 5 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/css/input.css

@@ -203,6 +203,11 @@ button {
     line-height: 1;
     font-weight: 900;
     text-shadow: 0 1px 1px rgba(65, 68, 147, 0.2);
+    text-decoration: none;
+}
+
+.play-turn-chip {
+    cursor: pointer;
 }
 
 .play-top-chip img {

+ 11 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/all.min.js

@@ -260,6 +260,7 @@ const initKittyFall = () => {
         const gameOverScore = playGameRoot.querySelector("[data-game-over-score]");
         const gameOverData = playGameRoot.querySelector("[data-game-over-data]");
         const gameOverLoyalty = playGameRoot.querySelector("[data-game-over-loyalty]");
+        const totalTurnElement = playGameRoot.querySelector("[data-play-total-turn]");
         let selectedLevel = playGameRoot.querySelector("[data-level].is-selected")?.dataset.level
             || levelButtons[0]?.dataset.level
             || "Easy";
@@ -311,6 +312,14 @@ const initKittyFall = () => {
 
         const formatNumber = (value) => Math.max(0, Math.round(value)).toLocaleString("en-US");
 
+        const updateTotalTurn = (value) => {
+            if (value === null || value === undefined || value === "") return;
+            const totalTurn = Number(value);
+            if (!totalTurnElement || !Number.isFinite(totalTurn)) return;
+            totalTurnElement.textContent = formatNumber(totalTurn);
+            playGameRoot.dataset.totalTurn = String(Math.max(0, Math.round(totalTurn)));
+        };
+
         const addLevelReward = (data) => {
             const rewardType = String(data?.rewardType || "").toUpperCase();
             const rewardValue = toNumber(data?.rewardValue);
@@ -409,6 +418,7 @@ const initKittyFall = () => {
             }
             if (event.data?.type === "EXIT_GAME_RESULT") {
                 setRunSummary(event.data);
+                updateTotalTurn(event.data.totalTurn);
                 closeEmbeddedGame();
                 showGameOverSummary();
             }
@@ -453,6 +463,7 @@ const initKittyFall = () => {
                     return;
                 }
 
+                updateTotalTurn(result.totalTurn);
                 resetRunRewards();
                 gameStarted = true;
                 playGameRoot.classList.add("is-game-running");

+ 11 - 0
Kitty_Fall/Kitty_Fall/Kitty_Fall.Website/wwwroot/kitty/js/input.js

@@ -260,6 +260,7 @@ const initKittyFall = () => {
         const gameOverScore = playGameRoot.querySelector("[data-game-over-score]");
         const gameOverData = playGameRoot.querySelector("[data-game-over-data]");
         const gameOverLoyalty = playGameRoot.querySelector("[data-game-over-loyalty]");
+        const totalTurnElement = playGameRoot.querySelector("[data-play-total-turn]");
         let selectedLevel = playGameRoot.querySelector("[data-level].is-selected")?.dataset.level
             || levelButtons[0]?.dataset.level
             || "Easy";
@@ -311,6 +312,14 @@ const initKittyFall = () => {
 
         const formatNumber = (value) => Math.max(0, Math.round(value)).toLocaleString("en-US");
 
+        const updateTotalTurn = (value) => {
+            if (value === null || value === undefined || value === "") return;
+            const totalTurn = Number(value);
+            if (!totalTurnElement || !Number.isFinite(totalTurn)) return;
+            totalTurnElement.textContent = formatNumber(totalTurn);
+            playGameRoot.dataset.totalTurn = String(Math.max(0, Math.round(totalTurn)));
+        };
+
         const addLevelReward = (data) => {
             const rewardType = String(data?.rewardType || "").toUpperCase();
             const rewardValue = toNumber(data?.rewardValue);
@@ -409,6 +418,7 @@ const initKittyFall = () => {
             }
             if (event.data?.type === "EXIT_GAME_RESULT") {
                 setRunSummary(event.data);
+                updateTotalTurn(event.data.totalTurn);
                 closeEmbeddedGame();
                 showGameOverSummary();
             }
@@ -453,6 +463,7 @@ const initKittyFall = () => {
                     return;
                 }
 
+                updateTotalTurn(result.totalTurn);
                 resetRunRewards();
                 gameStarted = true;
                 playGameRoot.classList.add("is-game-running");

+ 19 - 4
Kitty_Fall/Kitty_Fall/Kitty_Fall.Woker/Services/GameRewardPayoutWorker.cs

@@ -120,14 +120,23 @@ namespace Kitty_Fall.Woker.Services
                     rewardLog.Msisdn,
                     rewardLog.RewardLogId.ToString(CultureInfo.InvariantCulture),
                     GetPackageName(rewardLog));
-                var isSuccess = addPointRes?.success == true;
+                var responseStatus = addPointRes?.result?.status;
+                var hasResponseCode = int.TryParse(
+                    responseStatus,
+                    NumberStyles.Integer,
+                    CultureInfo.InvariantCulture,
+                    out var responseCode);
+                var isSuccess = addPointRes?.success == true
+                    || (hasResponseCode && responseCode == CommonLogic.AddPointSuccess);
+                var isWaiting = hasResponseCode
+                    && responseCode == CommonLogic.AddPointWaiting;
 
                 rewardLog.ResponseTime = DateTime.Now;
                 // DotnetLib tra ma/trang thai cua doi tac trong result.status.
-                rewardLog.ResponseCode = addPointRes?.result?.status
+                rewardLog.ResponseCode = responseStatus
                     ?? (isSuccess
-                        ? CommonErrorCode.AddPointSuccess.ToString(CultureInfo.InvariantCulture)
-                        : CommonErrorCode.AddPointFailure.ToString(CultureInfo.InvariantCulture));
+                        ? CommonLogic.AddPointSuccess.ToString(CultureInfo.InvariantCulture)
+                        : CommonLogic.AddPointFailure.ToString(CultureInfo.InvariantCulture));
                 rewardLog.ResponseMessage = Truncate(addPointRes?.message, 500);
                 rewardLog.ExternalTransId = rewardLog.RewardLogId.ToString(CultureInfo.InvariantCulture);
                 rewardLog.UpdatedTime = DateTime.Now;
@@ -140,6 +149,12 @@ namespace Kitty_Fall.Woker.Services
                     await SendSuccessMtAsync(dbContext, rewardLog, cancellationToken);
                     return;
                 }
+                else if (isWaiting)
+                {
+                    // Doi tac da nhan giao dich va dang xu ly. Giu PROCESSING de doi soat,
+                    // khong danh dau FAILED va khong tu dong gui lai giao dich.
+                    rewardLog.Status = StatusProcessing;
+                }
                 else
                 {
                     rewardLog.RetryCount++;

+ 2 - 2
Kitty_Fall/Kitty_Fall/Kitty_Fall.Woker/appsettings.json

@@ -18,8 +18,8 @@
     "IntervalSeconds": 10,
     "BatchSize": 20,
     "ServiceId": "Kitty_Fall_DAYLY",
-    "DataPackageName": "GAME_DATA",
-    "LoyaltyPackageName": "GAME_LOYALTY",
+    "DataPackageName": "DATA_",
+    "LoyaltyPackageName": "LOYALTY_",
     "DefaultPackageName": "GAME_REWARD"
   },
   "MonthlyWinner": {