Procházet zdrojové kódy

Update full luồng

vuDUng před 2 týdny
rodič
revize
a10c7ae77f
96 změnil soubory, kde provedl 16194 přidání a 732 odebrání
  1. 23 0
      SicboSub/Common/Common.csproj
  2. 326 0
      SicboSub/Common/CommonLogic.cs
  3. 254 0
      SicboSub/Common/Constant/CommonConstant.cs
  4. 26 0
      SicboSub/Common/Global/DbHelper.cs
  5. 8 0
      SicboSub/Common/Global/GlobalConfig.cs
  6. 19 0
      SicboSub/Database/Database/ConfigMessage.cs
  7. 1 1
      SicboSub/Database/Database/ExchangeConfig.cs
  8. 80 0
      SicboSub/Database/Database/ExchangeOtp.cs
  9. 23 0
      SicboSub/Database/Database/JobLog.cs
  10. 137 6
      SicboSub/Database/Database/ModelContext.cs
  11. 1 1
      SicboSub/Database/Database/MtHi.cs
  12. 1 1
      SicboSub/Database/Database/RankingRewardLog.cs
  13. 1 1
      SicboSub/Database/Database/RegInfo.cs
  14. 13 0
      SicboSub/SicboSub.Api/.config/dotnet-tools.json
  15. 229 0
      SicboSub/SicboSub.Api/Business/AuthBusinessImpl.cs
  16. 150 0
      SicboSub/SicboSub.Api/Business/AuthServiceImpl.cs
  17. 633 0
      SicboSub/SicboSub.Api/Business/ExchangeBusinessImpl.cs
  18. 354 0
      SicboSub/SicboSub.Api/Business/GameBusinessImpl.cs
  19. 39 0
      SicboSub/SicboSub.Api/Business/IAuthService.cs
  20. 26 0
      SicboSub/SicboSub.Api/Business/IExchangeBusiness.cs
  21. 23 0
      SicboSub/SicboSub.Api/Business/IGameBusiness.cs
  22. 18 0
      SicboSub/SicboSub.Api/Business/IPackageBusiness.cs
  23. 18 0
      SicboSub/SicboSub.Api/Business/ISubscriptionBusiness.cs
  24. 13 0
      SicboSub/SicboSub.Api/Business/IUserBusiness.cs
  25. 157 0
      SicboSub/SicboSub.Api/Business/PackageBusinessImpl.cs
  26. 196 0
      SicboSub/SicboSub.Api/Business/SubscriptionBusinessImpl.cs
  27. 113 0
      SicboSub/SicboSub.Api/Business/UserBusinessImpl.cs
  28. 16 0
      SicboSub/SicboSub.Api/Connected Services/SicboSubWss/ConnectedService.json
  29. 3725 0
      SicboSub/SicboSub.Api/Connected Services/SicboSubWss/Reference.cs
  30. 78 0
      SicboSub/SicboSub.Api/Controllers/AuthController.cs
  31. 56 0
      SicboSub/SicboSub.Api/Controllers/ExchangeController.cs
  32. 48 0
      SicboSub/SicboSub.Api/Controllers/GameController.cs
  33. 44 0
      SicboSub/SicboSub.Api/Controllers/PackageController.cs
  34. 44 0
      SicboSub/SicboSub.Api/Controllers/SubscriptionController.cs
  35. 31 0
      SicboSub/SicboSub.Api/Controllers/UserController.cs
  36. 71 0
      SicboSub/SicboSub.Api/DTO/AuthDto.cs
  37. 96 0
      SicboSub/SicboSub.Api/DTO/ExchangeDto.cs
  38. 121 0
      SicboSub/SicboSub.Api/DTO/GameDto.cs
  39. 64 0
      SicboSub/SicboSub.Api/DTO/PackageDto.cs
  40. 30 0
      SicboSub/SicboSub.Api/DTO/UserDto.cs
  41. 74 7
      SicboSub/SicboSub.Api/Program.cs
  42. 20 0
      SicboSub/SicboSub.Api/Properties/PublishProfiles/FolderProfile.pubxml
  43. 29 5
      SicboSub/SicboSub.Api/SicboSub.Api.csproj
  44. 115 0
      SicboSub/SicboSub.Api/Singleton/ConfigManager.cs
  45. 4 1
      SicboSub/SicboSub.Api/appsettings.json
  46. 25 0
      SicboSub/SicboSub.Api/log4net.config
  47. 16 0
      SicboSub/SicboSub.StartProcedure/Connected Services/SicboSubWss/ConnectedService.json
  48. 3725 0
      SicboSub/SicboSub.StartProcedure/Connected Services/SicboSubWss/Reference.cs
  49. 154 0
      SicboSub/SicboSub.StartProcedure/ExchangeService.cs
  50. 76 16
      SicboSub/SicboSub.StartProcedure/Program.cs
  51. 16 0
      SicboSub/SicboSub.StartProcedure/Properties/PublishProfiles/FolderProfile.pubxml
  52. 67 16
      SicboSub/SicboSub.StartProcedure/RankingService.cs
  53. 16 4
      SicboSub/SicboSub.StartProcedure/SicboSub.StartProcedure.csproj
  54. 32 0
      SicboSub/SicboSub.StartProcedure/SicboSub.StartProcedure.csproj.Backup.tmp
  55. 4 3
      SicboSub/SicboSub.StartProcedure/appsettings.json
  56. 22 0
      SicboSub/SicboSub.StartProcedure/log4net.config
  57. 13 0
      SicboSub/SicboSub.Web/.config/dotnet-tools.json
  58. 56 0
      SicboSub/SicboSub.Web/Constants/WebConstants.cs
  59. 149 0
      SicboSub/SicboSub.Web/Controllers/BaseController.cs
  60. 742 12
      SicboSub/SicboSub.Web/Controllers/HomeController.cs
  61. 52 0
      SicboSub/SicboSub.Web/Helpers/SessionExtensions.cs
  62. 729 0
      SicboSub/SicboSub.Web/Language/Language.Designer.cs
  63. 342 0
      SicboSub/SicboSub.Web/Language/Language.resx
  64. 342 0
      SicboSub/SicboSub.Web/Language/Language.vi.resx
  65. 70 0
      SicboSub/SicboSub.Web/Models/AuthModels.cs
  66. 23 0
      SicboSub/SicboSub.Web/Models/CommonResponse.cs
  67. 179 0
      SicboSub/SicboSub.Web/Models/HistoryModels.cs
  68. 11 0
      SicboSub/SicboSub.Web/Models/HistoryViewModel.cs
  69. 50 0
      SicboSub/SicboSub.Web/Models/RankingModels.cs
  70. 113 0
      SicboSub/SicboSub.Web/Models/SubscriptionModels.cs
  71. 21 0
      SicboSub/SicboSub.Web/Program.cs
  72. 20 0
      SicboSub/SicboSub.Web/Properties/PublishProfiles/FolderProfile.pubxml
  73. 36 0
      SicboSub/SicboSub.Web/SicboSub.Web.csproj
  74. 29 14
      SicboSub/SicboSub.Web/Views/Home/Account.cshtml
  75. 37 48
      SicboSub/SicboSub.Web/Views/Home/DailyRanking.cshtml
  76. 86 120
      SicboSub/SicboSub.Web/Views/Home/History.cshtml
  77. 587 200
      SicboSub/SicboSub.Web/Views/Home/Index.cshtml
  78. 37 48
      SicboSub/SicboSub.Web/Views/Home/MonthlyRanking.cshtml
  79. 5 5
      SicboSub/SicboSub.Web/Views/Home/Winner.cshtml
  80. 9 1
      SicboSub/SicboSub.Web/Views/Shared/_GameLayout.cshtml
  81. 5 5
      SicboSub/SicboSub.Web/Views/Shared/_GameMenu.cshtml
  82. 0 49
      SicboSub/SicboSub.Web/Views/Shared/_Layout.cshtml
  83. 0 48
      SicboSub/SicboSub.Web/Views/Shared/_Layout.cshtml.css
  84. 1 1
      SicboSub/SicboSub.Web/Views/_ViewStart.cshtml
  85. 18 1
      SicboSub/SicboSub.Web/appsettings.json
  86. 25 0
      SicboSub/SicboSub.Web/log4net.config
  87. 58 1
      SicboSub/SicboSub.Web/wwwroot/css/sicbo-account.css
  88. 271 7
      SicboSub/SicboSub.Web/wwwroot/css/sicbo-popup.css
  89. binární
      SicboSub/SicboSub.Web/wwwroot/img/exchange_success_bg.png
  90. 198 3
      SicboSub/SicboSub.Web/wwwroot/js/site.js
  91. 1 1
      SicboSubWs/SicboSubWs/src/com/vas/sicbosubnc/wsfw/common/Common.java
  92. 113 8
      SicboSubWs/SicboSubWs/src/com/vas/sicbosubnc/wsfw/database/WsProcessUtils.java
  93. 61 94
      SicboSubWs/SicboSubWs/src/com/vas/webservices/SicboSubWs.java
  94. 1 1
      SicboSubWs/etc/app.conf
  95. 2 2
      SicboSubWs/etc/database.xml
  96. 1 1
      SicboSubWs/etc/webservices.xml

+ 23 - 0
SicboSub/Common/Common.csproj

@@ -5,5 +5,28 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
   </PropertyGroup>
+	<ItemGroup>
+		<PackageReference Include="log4net" Version="2.0.15" />
+		<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
+		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+		<PackageReference Include="Quartz" Version="3.11.0" />
+		<PackageReference Include="Quartz.Extensions.Hosting" Version="3.11.0" />
+		<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
 
+		<PackageReference Include="System.ServiceModel.Http" Version="6.0.0" />
+		<PackageReference Include="System.ServiceModel.NetTcp" Version="6.0.0" />
+		<PackageReference Include="System.ServiceModel.Federation" Version="6.0.0" />
+		<PackageReference Include="System.ServiceModel.Duplex" Version="6.0.0" />
+
+		<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
+		<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
+	</ItemGroup>
+	<ItemGroup>
+		<ProjectReference Include="..\Database\Database.csproj" />
+	</ItemGroup>
+	<ItemGroup>
+		<Reference Include="DotnetLib">
+			<HintPath>..\lib\DotnetLib.dll</HintPath>
+		</Reference>
+	</ItemGroup>
 </Project>

+ 326 - 0
SicboSub/Common/CommonLogic.cs

@@ -0,0 +1,326 @@
+using Common.Constant;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.Configuration;
+using Microsoft.IdentityModel.Tokens;
+using Newtonsoft.Json;
+using System.Globalization;
+using System.IdentityModel.Tokens.Jwt;
+using System.Net;
+using System.Security.Claims;
+using System.Text;
+using System.Xml.Linq;
+using System.Xml.Serialization;
+
+namespace Common.Logic;
+
+public class CommonLogic
+{
+    private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(CommonLogic));
+
+    public static String GenToken(IConfiguration configuration, String Email, String accountId)
+    {
+        var issuer = configuration["Jwt:Issuer"];
+        var audience = configuration["Jwt:Audience"];
+        var key = Encoding.ASCII.GetBytes(configuration["Jwt:Key"]!);
+        var tokenDescriptor = new SecurityTokenDescriptor
+        {
+            Subject = new ClaimsIdentity(
+                new[]
+                {
+                    new Claim("Id", Guid.NewGuid().ToString()),
+                    new Claim("Msisdn", Email),
+                    new Claim("AccountId", accountId),
+                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
+                }
+            ),
+            Expires = DateTime.UtcNow.AddMinutes(int.Parse(configuration["Jwt:Time"] ?? "900")),
+            Issuer = issuer,
+            Audience = audience,
+            SigningCredentials = new SigningCredentials(
+                new SymmetricSecurityKey(key),
+                SecurityAlgorithms.HmacSha512Signature
+            )
+        };
+        var tokenHandler = new JwtSecurityTokenHandler();
+        var token = tokenHandler.CreateToken(tokenDescriptor);
+        var jwtToken = tokenHandler.WriteToken(token);
+        var stringToken = tokenHandler.WriteToken(token);
+        return stringToken;
+    }
+
+    public static string GenRefreshToken(IConfiguration configuration, string msisdn)
+    {
+        var issuer = configuration["Jwt:Issuer"];
+        var audience = configuration["Jwt:Audience"];
+        var key = Encoding.ASCII.GetBytes(configuration["Jwt:Key"]);
+        var tokenDescriptor = new SecurityTokenDescriptor
+        {
+            Subject = new ClaimsIdentity(
+                new[]
+                {
+                    new Claim("Id", Guid.NewGuid().ToString()),
+                    new Claim("Msisdn", msisdn),
+                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
+                }
+            ),
+            Expires = DateTime.UtcNow.AddMinutes(int.Parse(configuration["Jwt:Time"] ?? "900")),
+            Issuer = issuer,
+            Audience = audience,
+            SigningCredentials = new SigningCredentials(
+                new SymmetricSecurityKey(key),
+                SecurityAlgorithms.HmacSha512Signature
+            )
+        };
+        var tokenHandler = new JwtSecurityTokenHandler();
+        var token = tokenHandler.CreateToken(tokenDescriptor);
+        var jwtToken = tokenHandler.WriteToken(token);
+        var stringToken = tokenHandler.WriteToken(token);
+        return stringToken;
+    }
+
+    public static string? GetDataFromToken(
+        IConfiguration configuration,
+        HttpRequest httpRequest,
+        string nameKey
+    )
+    {
+        string realToken = "";
+        var token = httpRequest.Headers["Authorization"];
+        if (token.Count == 0)
+        {
+            return null;
+        }
+        realToken = token[0];
+
+        // Trim 'Bearer ' from the start since its just a prefix for the token
+        var jwtEncodedString = realToken.Substring(7);
+
+        string? value = GetPath(configuration, jwtEncodedString, nameKey);
+        if (value == null)
+        {
+            return null;
+        }
+        string url = httpRequest.Path;
+        log.Info("url: " + url + " || nameKey: " + nameKey + " value: " + value);
+        return value;
+    }
+
+    public static string? GetPath(IConfiguration configuration, string token, string nameKey)
+    {
+        var key = Encoding.ASCII.GetBytes(configuration["Jwt:Key"] ?? "");
+        var handler = new JwtSecurityTokenHandler();
+        var validations = new TokenValidationParameters
+        {
+            ValidateIssuerSigningKey = true,
+            IssuerSigningKey = new SymmetricSecurityKey(key),
+            ValidateIssuer = false,
+            ValidateAudience = false,
+            ValidateLifetime = true
+        };
+        var claims = handler.ValidateToken(token, validations, out var tokenSecure);
+        var data = claims.Claims.First(x => x.Type == nameKey).Value;
+        return data;
+    }
+
+    public static string? ValidateMsisdn(string? input)
+    {
+        if (input == null || input.Length == 0 || !long.TryParse(input, out long temp))
+        {
+            return null;
+        }
+        else if (input.StartsWith("255") && input.Length == 12)
+        {
+            return input.Trim();
+        }
+        else if (input.StartsWith("0") && input.Length == 10)
+        {
+            input = "255" + input.Substring(1);
+            return input.Trim();
+        }
+        return null;
+    }
+    
+
+    public static string GenPassword(int length)
+    {
+        const string chars = "0123456789";
+        var random = new Random();
+        var password = new StringBuilder();
+        for (int i = 0; i < length; i++)
+        {
+            password.Append(chars[random.Next(chars.Length)]);
+        }
+        return password.ToString();
+    }
+
+    /// <summary>
+    /// Get language from request header or body
+    /// Priority: header Lang > header Accept-Language > body lang > default "lo"
+    /// </summary>
+    /// <param name="httpRequest">HTTP request</param>
+    /// <param name="bodyLang">Language from request body (optional)</param>
+    /// <returns>Language code: "lo" or "en"</returns>
+    public static string GetLanguage(HttpRequest httpRequest, string? bodyLang = null)
+    {
+        // Check custom Lang header first (highest priority)
+        var langHeader = httpRequest.Headers["Lang"].FirstOrDefault();
+        if (!string.IsNullOrEmpty(langHeader))
+        {
+            var lang = langHeader.ToLower();
+            if (lang == "en" || lang == "lo")
+                return lang;
+        }
+
+        // Check Accept-Language header
+        var acceptLangHeader = httpRequest.Headers["Accept-Language"].FirstOrDefault();
+        if (!string.IsNullOrEmpty(acceptLangHeader))
+        {
+            // Accept-Language can be "en", "lo", "en-US,en;q=0.9", etc.
+            var lang = acceptLangHeader.Split(',')[0].Split('-')[0].ToLower();
+            if (lang == "en" || lang == "lo")
+                return lang;
+        }
+
+        // Then check body
+        if (!string.IsNullOrEmpty(bodyLang))
+            return bodyLang.ToLower();
+
+        return "lo"; // Default
+    }
+
+    public static DateTime ConvertStringToTime(string? time)
+    {
+        return DateTime.ParseExact(
+            time!,
+            CommonConstant.ListDateTimeFormat,
+            System.Globalization.CultureInfo.InvariantCulture,
+            DateTimeStyles.None
+        );
+    }
+
+    public static string? SendPostWithAuthen(ILog log, string Url, dynamic data, string authenToken,string lang = "tu")
+    {
+        var json = JsonConvert.SerializeObject(data);
+        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
+        request.Method = "POST";
+        request.ContentType = "application/json";
+        request.ContentLength = json.Length;
+        request.Headers.Add("Authorization", "Bearer " + authenToken);
+        request.Headers.Add("Accept-Language", lang);
+        log.Info("request: " + Url + " data: " + json);
+
+        using (Stream webStream = request.GetRequestStream())
+        using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
+        {
+            requestWriter.Write(json);
+        }
+        try
+        {
+            WebResponse webResponse = request.GetResponse();
+            using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
+            using (StreamReader responseReader = new StreamReader(webStream))
+            {
+                string response = responseReader.ReadToEnd();
+                log.Info("request: " + Url + " /nData: " + json + " /n response: " + response);
+                return response;
+            }
+        }
+        catch (Exception e)
+        {
+            log.Info("-----------------");
+            log.Info(e.Message);
+        }
+        return null;
+    }
+
+    public static string? SendPost(ILog log, string Url, dynamic data)
+    {
+        var json = JsonConvert.SerializeObject(data);
+
+        log.Info("request: " + Url + " data: " + json);
+
+        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
+        request.Method = "POST";
+        request.ContentType = "application/json";
+        request.ContentLength = json.Length;
+
+        // CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
+        // log.Debug("Lang: " + currentCulture.Name);
+        // request.Headers.Add("Lang", currentCulture.Name);
+
+        using (Stream webStream = request.GetRequestStream())
+        using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
+        {
+            requestWriter.Write(json);
+        }
+        try
+        {
+            WebResponse webResponse = request.GetResponse();
+            using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
+            using (StreamReader responseReader = new StreamReader(webStream))
+            {
+                string response = responseReader.ReadToEnd();
+                log.Info("request: " + Url + " /nData: " + json + " /n response: " + response);
+                return response;
+            }
+        }
+        catch (Exception e)
+        {
+            log.Info("-----------------");
+            log.Info(e.Message);
+        }
+        return null;
+    }
+
+    public static string GetErrorDescription(string code)
+    {
+        switch (code)
+        {
+            case "0":
+                return "SUBSCRIBER put to queue Success";
+            case "1":
+                return "SUBSCRIBER put to Queue failed";
+            case "2":
+                return "Unauthentic";
+            case "15":
+                return "Missing value (Input params null) / Invalid Parameter(s)";
+            case "200":
+                return "Invalid username or password";
+            case "201":
+                return "Invalid Request Type";
+            case "202":
+                return "Invalid Request";
+            case "203":
+                return "Invalid package";
+            case "204":
+                return "Server too busy";
+            case "400":
+                return "Not register";
+            case "401":
+                return "Not enough money";
+            case "403":
+                return "Already register";
+            case "408":
+                return "Get price charge error";
+            case "411":
+                return "Subscriber was cancel service";
+            case "412":
+                return "Subscriber not use service";
+            case "413":
+                return "Conflict package. Subscriber is using other package in same service";
+            case "418":
+                return "MO command not support";
+            case "419":
+                return "3rd Party is incorrect";
+            case "420":
+                return "Wrong format datetime: yyyy-MM-dd";
+            case "504":
+                return "Unknown error";
+            default:
+                return "Unknown error code";
+        }
+    }
+
+}

+ 254 - 0
SicboSub/Common/Constant/CommonConstant.cs

@@ -0,0 +1,254 @@
+namespace Common.Constant;
+
+public static class CommonConstant
+{
+    public const string ShowResult = "1";
+    public const string NextQuestion = "2";
+
+    public const string Channel = "1542";
+    public const string CountryCode = "258";
+
+    public const string Success = "0";
+    public const string Error = "-1";
+    public const string WrongAnswer = "-7";
+
+    public const string LoginFails = "-2";
+    public const string MsisdnInvalid = "-3";
+    public const string TransactionInvalid = "-4";
+    public const string NoTimeLeftToSendOtp = "-5";
+    public const string NeedLogin = "-7";
+    public const string NextQuestionFail = "-8";
+    public const string OtpWrong = "-9";
+
+
+    public const string Unauthorized = "-401";
+    public const string BadRequest = "-402";
+
+    public const string DateTimeFormat = "dd/MM/yyyy HH:mm:ss";
+
+    public const int PageNumber = 10;
+    public const string NoQuestionExisted = "-6";
+
+    public const string ANSWER_RIGHT = "RIGHT";
+    public const string ANSWER_WRONG = "WRONG";
+
+
+    public const String PathImage = "/outside";
+
+    public const String MissitonTypeLOGIN = "LOGIN";
+    public const String MissitonTypeREGISTER = "REGISTER";
+    public const String MissitonTypeREGISTERS = "REGISTERS";
+    public const String MissitonTypeINVITING = "INVITING";
+
+
+    public const int StatusActive = 1;
+    public const int StatusInactive = 0;
+    public const int StatusNotClaimed = 2;
+    public const int StatusClaimed = 3;
+
+    public const int StatusPending = 100;
+    public const int StatusSuccess = 0;
+    public const int StatusFailed = -1;
+    public const int UserNotRegistered = 0;
+    public const int UserRegistered = 1;
+
+    public const string Waiting = "WAITING";
+    public const int Request = 1;
+    public const int Response = 2;
+
+    public const string TypeRegisterService = "REGISTER";
+    public const string TypeLogin = "LOGIN";
+    public const string TypeInviting = "INVITING";
+    public const string TypeRenewService = "RENEW";
+
+
+    public const string PathOutside = "PathOutside";
+
+    public const string CheckSub = "CHECKSUB";
+    public const string Subscribe = "SUBSCRIBE";
+
+
+    public static readonly List<int> ListStatusInt = new List<int> { StatusActive, StatusInactive };
+
+    public const string DateTimeFormar1 = "dd/MM/yyyy HH:mm:ss";
+    public const string DateTimeFormar2 = "MMMM yyyy";
+    public const string DateTimeFormar3 = "dd/MM";
+    public const string DateTimeFormar4 = "HH:mm";
+    public const string DateTimeFormar7 = "dd/MM/yyyy HH:mm";
+
+    public const string DateTimeFormar5 = "yyyy-MM-dd";
+    public const string DateTimeFormar6 = "yyyyMMddHHmmss";
+    public const string DateTimeFormar8 = "yyyy-MM-ddTHH:mm:ss";
+    public const string DateTimeFormar9 = "yyyy-MM-ddTHH:mm";
+    public const string DateTimeFormar10 = "yyyy_MM_dd";
+    public const string DateTimeFormar11 = "yyyy_MM";
+    public const string DateTimeFormar12 = "dd/MM/yyyy";
+    public const string DateTimeFormar13 = "dd/MM/yyyy HH:mm:ss";
+    public const string DateTimeFormar14 = "d/M/yyyy HH:mm:sstt";
+    public const string DateTimeFormar15 = "d/MM/yyyy HH:mm:sstt";
+    public const string DateTimeFormar16 = "dd/MM/yyyy HH:mm:sstt";
+
+    public static readonly string[] ListDateTimeFormat =
+    {
+        DateTimeFormar1,
+        DateTimeFormar2,
+        DateTimeFormar3,
+        DateTimeFormar4,
+        DateTimeFormar5,
+        DateTimeFormar6,
+        DateTimeFormar7,
+        DateTimeFormar8,
+        DateTimeFormar9,
+        DateTimeFormar10,
+        DateTimeFormar11,
+        DateTimeFormar12,
+        DateTimeFormar13,
+        DateTimeFormar14,
+        DateTimeFormar15,
+        DateTimeFormar16
+    };
+}
+
+public static class ApiUrlConstant
+{
+    // Package URLs
+    public const String PackageLoadUrl = "/apis/package/load";
+    public const String ExchangeConfigLoadUrl = "/apis/package/exchange";
+    public const String RegisterUrl = "/apis/package/register";
+    public const String BuyMoreUrl = "/apis/package/buymore";
+    public const String PlayHistoryUrl = "/apis/game/play_history";
+    public const String RankingHistoryUrl = "/apis/game/ranking_history";
+    public const String UserInfoUrl = "/apis/user/info";
+    public const String PurchaseHistoryUrl = "/apis/game/purchase_history";
+
+    // Exchange OTP URLs
+    public const String ExchangeRequestOtpUrl = "/apis/exchange/request-otp";
+    public const String ExchangeVerifyOtpUrl = "/apis/exchange/verify-otp";
+    public const String ExchangeResendOtpUrl = "/apis/exchange/resend-otp";
+
+    // Auth URLs
+    public const String AuthLoginUrl = "/apis/auth/login";
+    public const String AuthGetMsisdnUrl = "/apis/auth/get-msisdn";
+}
+
+public static class CommonErrorCode
+{
+    // ============================================
+    // SUCCESS CODES (0 - 99)
+    // ============================================
+    public const string Success = "0";
+    public const string LoginCompleted = "1";
+    public const string RegistrationCompleted = "2";
+    public const string OtpSentSuccessfully = "3";
+    public const string OtpVerifiedSuccessfully = "4";
+    public const string EmailSentSuccessfully = "5";
+
+    // ============================================
+    // GENERAL ERRORS (-1 to -99)
+    // ============================================
+    public const string Error = "-1";
+    public const string InvalidRequest = "-2";
+    public const string InvalidParameter = "-3";
+    public const string DataNotFound = "-4";
+    public const string DatabaseError = "-5";
+    public const string SystemError = "-6";
+    public const string ServiceUnavailable = "-7";
+    public const string RateLimitExceeded = "-8";
+    public const string OperationFailed = "-9";
+
+    // ============================================
+    // AUTHENTICATION ERRORS (-100 to -199)
+    // ============================================
+    public const string LoginFails = "-100";
+    public const string LoginRequired = "-101";
+    public const string SessionExpired = "-102";
+    public const string InvalidCredentials = "-103";
+    public const string AccountLocked = "-104";
+    public const string AccountDisabled = "-105";
+    public const string TokenExpired = "-106";
+    public const string TokenInvalid = "-107";
+    public const string RefreshTokenExpired = "-108";
+    public const string RefreshTokenInvalid = "-109";
+    public const string UnauthorizedAccess = "-110";
+    public const string PermissionDenied = "-111";
+
+    // ============================================
+    // OTP ERRORS (-200 to -299)
+    // ============================================
+    public const string OtpRequired = "-200";
+    public const string OtpInvalid = "-201";
+    public const string OtpExpired = "-202";
+    public const string OtpAlreadyUsed = "-203";
+    public const string OtpMaxAttemptsExceeded = "-204";
+    public const string OtpSendFailed = "-205";
+    public const string OtpTooManyRequests = "-206";
+    public const string OtpNotFound = "-207";
+    public const string OtpNotRequested = "-208"; // User hasn't requested OTP yet (for resend scenario)
+
+    // ============================================
+    // USER/CUSTOMER ERRORS (-300 to -399)
+    // ============================================
+    public const string UserNotFound = "-300";
+    public const string UserAlreadyExists = "-301";
+    public const string UserNotVerified = "-302";
+    public const string UserDisabled = "-303";
+    public const string InvalidEmail = "-304";
+    public const string InvalidPhone = "-305";
+    public const string ProfileUpdateFailed = "-306";
+    public const string PasswordTooWeak = "-307";
+    public const string PasswordMismatch = "-308";
+
+    // ============================================
+    // EMAIL ERRORS (-400 to -499)
+    // ============================================
+    public const string EmailNotConfigured = "-400";
+    public const string EmailSendFailed = "-401";
+    public const string EmailTemplateNotFound = "-402";
+    public const string EmailInvalidRecipient = "-403";
+    public const string EmailQueueFailed = "-404";
+    public const string SmtpConnectionFailed = "-405";
+
+    // ============================================
+    // CAMPAIGN/MISSION ERRORS (-500 to -599)
+    // ============================================
+    public const string NoCampaignAvailable = "-500";
+    public const string CampaignExpired = "-501";
+    public const string CampaignNotStarted = "-502";
+    public const string MissionCompleted = "-503";
+    public const string MissionNotFound = "-504";
+    public const string NeedCompleteQuest = "-505";
+    public const string PrizeAlreadyClaimed = "-506";
+    public const string PrizeClaimFailed = "-507";
+
+    // ============================================
+    // PACKAGE/SUBSCRIPTION ERRORS (-600 to -699)
+    // ============================================
+    public const string VendorPackageRequired = "-600";
+    public const string PackageNotFound = "-601";
+    public const string PackageExpired = "-602";
+    public const string PackageAlreadyActive = "-603";
+    public const string InsufficientBalance = "-604";
+    public const string PaymentFailed = "-605";
+    public const string SubscriptionFailed = "-606";
+
+    // ============================================
+    // EXTERNAL SERVICE ERRORS (-700 to -799)
+    // ============================================
+    public const string ExternalServiceError = "-700";
+    public const string ExternalServiceTimeout = "-701";
+    public const string ExternalServiceUnavailable = "-702";
+    public const string MpsRegistered = "-703";
+    public const string MpsError = "-704";
+    public const string SmsGatewayError = "-705";
+
+    // ============================================
+    // VALIDATION ERRORS (-800 to -899)
+    // ============================================
+    public const string ValidationFailed = "-800";
+    public const string RequiredFieldMissing = "-801";
+    public const string InvalidFormat = "-802";
+    public const string ValueOutOfRange = "-803";
+    public const string DuplicateEntry = "-804";
+    public const string LimitExceeded = "-805";
+
+}

+ 26 - 0
SicboSub/Common/Global/DbHelper.cs

@@ -0,0 +1,26 @@
+using System;
+using Database.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+
+namespace Common.Global;
+
+public class DbHelper
+{
+    private DbContextOptions<ModelContext> GetAllOptions(IConfiguration configuration)
+    {
+        DbContextOptionsBuilder<ModelContext> optionsBuilder =
+            new DbContextOptionsBuilder<ModelContext>();
+
+        string connectionString = configuration.GetSection("Connection").Value!;
+
+        optionsBuilder.UseOracle(connectionString);
+
+        return optionsBuilder.Options;
+    }
+
+    public ModelContext GetDbContext(IConfiguration configuration)
+    {
+        return new ModelContext(GetAllOptions(configuration));
+    }
+}

+ 8 - 0
SicboSub/Common/Global/GlobalConfig.cs

@@ -0,0 +1,8 @@
+using Microsoft.Extensions.Configuration;
+
+namespace Common.Global;
+
+public static class GlobalConfig
+{
+    public static IConfiguration? Configuration { get; set; }
+}

+ 19 - 0
SicboSub/Database/Database/ConfigMessage.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+namespace Database.Database;
+
+public partial class ConfigMessage
+{
+    public decimal Id { get; set; }
+
+    public string Name { get; set; } = null!;
+
+    public string ValueLocal { get; set; } = null!;
+
+    public string ValueGlobal { get; set; } = null!;
+
+    public string Type { get; set; } = null!;
+
+    public string? Value { get; set; }
+}

+ 1 - 1
SicboSub/Database/Database/ExchangeConfig.cs

@@ -17,5 +17,5 @@ public partial class ExchangeConfig
 
     public string? Description { get; set; }
 
-    public bool? IsActive { get; set; }
+    public byte? IsActive { get; set; }
 }

+ 80 - 0
SicboSub/Database/Database/ExchangeOtp.cs

@@ -0,0 +1,80 @@
+using System;
+
+namespace Database.Database;
+
+/// <summary>
+/// Entity cho bảng EXCHANGE_OTP - Lưu mã OTP cho xác thực rút thưởng
+/// </summary>
+public partial class ExchangeOtp
+{
+    /// <summary>
+    /// Primary Key - ID OTP
+    /// </summary>
+    public decimal Id { get; set; }
+
+    /// <summary>
+    /// Số điện thoại nhận OTP
+    /// </summary>
+    public string Msisdn { get; set; } = null!;
+
+    /// <summary>
+    /// Mã OTP 6 số
+    /// </summary>
+    public string OtpCode { get; set; } = null!;
+
+    /// <summary>
+    /// ID gói đổi thưởng (tham chiếu EXCHANGE_CONFIG.ID)
+    /// </summary>
+    public decimal? ConfigId { get; set; }
+
+    /// <summary>
+    /// Số Coin yêu cầu đổi (snapshot lúc tạo OTP)
+    /// </summary>
+    public decimal? CoinAmount { get; set; }
+
+    /// <summary>
+    /// Số tiền HTG sẽ nhận (snapshot)
+    /// </summary>
+    public decimal? MoneyAmount { get; set; }
+
+    /// <summary>
+    /// Thời điểm tạo mã OTP
+    /// </summary>
+    public DateTime CreatedTime { get; set; }
+
+    /// <summary>
+    /// Thời điểm hết hạn OTP (default +5 phút)
+    /// </summary>
+    public DateTime? ExpiredTime { get; set; }
+
+    /// <summary>
+    /// Thời điểm OTP được verify thành công
+    /// </summary>
+    public DateTime? VerifiedTime { get; set; }
+
+    /// <summary>
+    /// Trạng thái: 0-Pending, 1-Verified, 2-Expired, 3-Failed (sai quá nhiều)
+    /// </summary>
+    public byte? Status { get; set; }
+
+    /// <summary>
+    /// Số lần nhập sai OTP (max 3 lần)
+    /// </summary>
+    public byte? AttemptCount { get; set; }
+
+    /// <summary>
+    /// IP address để audit/chống fraud
+    /// </summary>
+    public string? IpAddress { get; set; }
+}
+
+/// <summary>
+/// Enum trạng thái OTP
+/// </summary>
+public static class ExchangeOtpStatus
+{
+    public const byte Pending = 0;      // Đang chờ xác thực
+    public const byte Verified = 1;     // Đã xác thực thành công
+    public const byte Expired = 2;      // Đã hết hạn
+    public const byte Failed = 3;       // Bị khóa do sai quá nhiều
+}

+ 23 - 0
SicboSub/Database/Database/JobLog.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+
+namespace Database.Database;
+
+public partial class JobLog
+{
+    public decimal Id { get; set; }
+
+    public string? JobName { get; set; }
+
+    public string? JobType { get; set; }
+
+    public DateTime? TargetDate { get; set; }
+
+    public DateTime? StartTime { get; set; }
+
+    public DateTime? EndTime { get; set; }
+
+    public string? Status { get; set; }
+
+    public string? ErrorMsg { get; set; }
+}

+ 137 - 6
SicboSub/Database/Database/ModelContext.cs

@@ -31,10 +31,16 @@ public partial class ModelContext : DbContext
 
     public virtual DbSet<Config> Configs { get; set; }
 
+    public virtual DbSet<ConfigMessage> ConfigMessages { get; set; }
+
     public virtual DbSet<ExchangeConfig> ExchangeConfigs { get; set; }
 
     public virtual DbSet<ExchangeHistory> ExchangeHistories { get; set; }
 
+    public virtual DbSet<ExchangeOtp> ExchangeOtps { get; set; }
+
+    public virtual DbSet<JobLog> JobLogs { get; set; }
+
     public virtual DbSet<LogChat> LogChats { get; set; }
 
     public virtual DbSet<MpsConfig> MpsConfigs { get; set; }
@@ -85,7 +91,6 @@ public partial class ModelContext : DbContext
 
     public virtual DbSet<WsUser> WsUsers { get; set; }
 
-   
     protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
         modelBuilder
@@ -380,6 +385,38 @@ public partial class ModelContext : DbContext
                 .HasColumnName("PARAM_VALUE_FR");
         });
 
+        modelBuilder.Entity<ConfigMessage>(entity =>
+        {
+            entity.HasKey(e => e.Id).HasName("CONFIG_PK");
+
+            entity.ToTable("CONFIG_MESSAGE");
+
+            entity.Property(e => e.Id)
+                .HasColumnType("NUMBER(38)")
+                .HasColumnName("ID");
+            entity.Property(e => e.Name)
+                .HasMaxLength(100)
+                .IsUnicode(false)
+                .HasColumnName("NAME");
+            entity.Property(e => e.Type)
+                .HasMaxLength(20)
+                .IsUnicode(false)
+                .HasDefaultValueSql("'WEB' ")
+                .HasColumnName("TYPE");
+            entity.Property(e => e.Value)
+                .HasMaxLength(1000)
+                .IsUnicode(false)
+                .HasColumnName("VALUE");
+            entity.Property(e => e.ValueGlobal)
+                .HasMaxLength(1000)
+                .IsUnicode(false)
+                .HasColumnName("VALUE_GLOBAL");
+            entity.Property(e => e.ValueLocal)
+                .HasMaxLength(1000)
+                .IsUnicode(false)
+                .HasColumnName("VALUE_LOCAL");
+        });
+
         modelBuilder.Entity<ExchangeConfig>(entity =>
         {
             entity.HasKey(e => e.Id).HasName("EXCHANGE_CONFIG_PK");
@@ -413,11 +450,11 @@ public partial class ModelContext : DbContext
                 .HasColumnName("PRODUCT_NAME");
         });
 
-        modelBuilder.Entity<ExchangeHistory>(entity =>
-        {
-            entity
-                .HasNoKey()
-                .ToTable("EXCHANGE_HISTORY");
+            modelBuilder.Entity<ExchangeHistory>(entity =>
+            {
+                entity.HasKey(e => e.Id).HasName("EXCHANGE_HISTORY_PK");
+
+                entity.ToTable("EXCHANGE_HISTORY");
 
             entity.HasIndex(e => new { e.Msisdn, e.ExchangeTime }, "EXCHANGE_HISTORY_IDX_DATE");
 
@@ -447,6 +484,98 @@ public partial class ModelContext : DbContext
                 .HasColumnName("STATUS");
         });
 
+        modelBuilder.Entity<ExchangeOtp>(entity =>
+        {
+            entity.HasKey(e => e.Id).HasName("EXCHANGE_OTP_PK");
+
+            entity.ToTable("EXCHANGE_OTP");
+
+            entity.HasIndex(e => new { e.Msisdn, e.Status, e.ExpiredTime }, "EXCHANGE_OTP_IDX_LOOKUP");
+            entity.HasIndex(e => new { e.Status, e.CreatedTime }, "EXCHANGE_OTP_IDX_CLEANUP");
+
+            entity.Property(e => e.Id)
+                .HasColumnType("NUMBER")
+                .HasColumnName("ID");
+            entity.Property(e => e.Msisdn)
+                .HasMaxLength(20)
+                .IsUnicode(false)
+                .HasColumnName("MSISDN");
+            entity.Property(e => e.OtpCode)
+                .HasMaxLength(10)
+                .IsUnicode(false)
+                .HasColumnName("OTP_CODE");
+            entity.Property(e => e.ConfigId)
+                .HasColumnType("NUMBER")
+                .HasColumnName("CONFIG_ID");
+            entity.Property(e => e.CoinAmount)
+                .HasColumnType("NUMBER")
+                .HasColumnName("COIN_AMOUNT");
+            entity.Property(e => e.MoneyAmount)
+                .HasColumnType("NUMBER")
+                .HasColumnName("MONEY_AMOUNT");
+            entity.Property(e => e.CreatedTime)
+                .HasDefaultValueSql("sysdate")
+                .HasColumnType("DATE")
+                .HasColumnName("CREATED_TIME");
+            entity.Property(e => e.ExpiredTime)
+                .HasColumnType("DATE")
+                .HasColumnName("EXPIRED_TIME");
+            entity.Property(e => e.VerifiedTime)
+                .HasColumnType("DATE")
+                .HasColumnName("VERIFIED_TIME");
+            entity.Property(e => e.Status)
+                .HasPrecision(1)
+                .HasDefaultValueSql("0")
+                .HasColumnName("STATUS");
+            entity.Property(e => e.AttemptCount)
+                .HasPrecision(1)
+                .HasDefaultValueSql("0")
+                .HasColumnName("ATTEMPT_COUNT");
+            entity.Property(e => e.IpAddress)
+                .HasMaxLength(50)
+                .IsUnicode(false)
+                .HasColumnName("IP_ADDRESS");
+        });
+
+        modelBuilder.Entity<JobLog>(entity =>
+        {
+            entity.HasKey(e => e.Id).HasName("JOB_LOG_PK");
+
+            entity.ToTable("JOB_LOG");
+
+            entity.HasIndex(e => new { e.JobName, e.TargetDate, e.Status }, "JOB_LOG_IDX_CHECK");
+
+            entity.Property(e => e.Id)
+                .HasColumnType("NUMBER")
+                .HasColumnName("ID");
+            entity.Property(e => e.EndTime)
+                .HasColumnType("DATE")
+                .HasColumnName("END_TIME");
+            entity.Property(e => e.ErrorMsg)
+                .HasMaxLength(2000)
+                .IsUnicode(false)
+                .HasColumnName("ERROR_MSG");
+            entity.Property(e => e.JobName)
+                .HasMaxLength(100)
+                .IsUnicode(false)
+                .HasColumnName("JOB_NAME");
+            entity.Property(e => e.JobType)
+                .HasMaxLength(50)
+                .IsUnicode(false)
+                .HasColumnName("JOB_TYPE");
+            entity.Property(e => e.StartTime)
+                .HasDefaultValueSql("sysdate")
+                .HasColumnType("DATE")
+                .HasColumnName("START_TIME");
+            entity.Property(e => e.Status)
+                .HasMaxLength(20)
+                .IsUnicode(false)
+                .HasColumnName("STATUS");
+            entity.Property(e => e.TargetDate)
+                .HasColumnType("DATE")
+                .HasColumnName("TARGET_DATE");
+        });
+
         modelBuilder.Entity<LogChat>(entity =>
         {
             entity.HasKey(e => e.Id).HasName("LOG_CHAT_PK");
@@ -1381,6 +1510,7 @@ public partial class ModelContext : DbContext
         });
         modelBuilder.HasSequence("EXCHANGE_CONFIG_SEQ");
         modelBuilder.HasSequence("EXCHANGE_HISTORY_SEQ");
+        modelBuilder.HasSequence("JOB_LOG_SEQ");
         modelBuilder.HasSequence("RANKING_CONFIG_SEQ");
         modelBuilder.HasSequence("RANKING_HISTORY_SEQ");
         modelBuilder.HasSequence("RANKING_REWARD_SEQ");
@@ -1388,6 +1518,7 @@ public partial class ModelContext : DbContext
         modelBuilder.HasSequence("TOOL_PLAY_HISTORY_SEQ");
         modelBuilder.HasSequence("TOOL_SCHEDULER_SEQ");
         modelBuilder.HasSequence("TOOL_SIM_SEQ");
+        modelBuilder.HasSequence("MT_SEQ"); 
 
         OnModelCreatingPartial(modelBuilder);
     }

+ 1 - 1
SicboSub/Database/Database/MtHi.cs

@@ -19,7 +19,7 @@ public partial class MtHi
 
     public string? ClusterName { get; set; }
 
-    public int? Status { get; set; }
+    public byte? Status { get; set; }
 
     public string? Channel { get; set; }
 

+ 1 - 1
SicboSub/Database/Database/RankingRewardLog.cs

@@ -17,7 +17,7 @@ public partial class RankingRewardLog
 
     public DateTime? RewardDate { get; set; }
 
-    public int? Status { get; set; }
+    public byte? Status { get; set; }
 
     public string? Note { get; set; }
 

+ 1 - 1
SicboSub/Database/Database/RegInfo.cs

@@ -19,7 +19,7 @@ public partial class RegInfo
 
     public bool? ExtendStatus { get; set; }
 
-    public bool? Status { get; set; }
+    public byte Status { get; set; }
 
     public DateTime? ExpireTime { get; set; }
 

+ 13 - 0
SicboSub/SicboSub.Api/.config/dotnet-tools.json

@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "isRoot": true,
+  "tools": {
+    "dotnet-ef": {
+      "version": "10.0.2",
+      "commands": [
+        "dotnet-ef"
+      ],
+      "rollForward": false
+    }
+  }
+}

+ 229 - 0
SicboSub/SicboSub.Api/Business/AuthBusinessImpl.cs

@@ -0,0 +1,229 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+
+namespace SicboSub.Api.Business
+{
+    /// <summary>
+    /// Business logic cho Authentication
+    /// Xử lý đăng nhập website qua URL token
+    /// </summary>
+    public interface IAuthBusiness
+    {
+        /// <summary>
+        /// Đăng nhập bằng token từ URL
+        /// Website gọi API này khi user truy cập qua URL có ?token=xxx
+        /// </summary>
+        Task<IActionResult> LoginByToken(HttpRequest httpRequest, TokenLoginReq request);
+
+        /// <summary>
+        /// Lấy MSISDN từ token (API nhẹ)
+        /// </summary>
+        Task<IActionResult> GetMsisdnFromToken(HttpRequest httpRequest, GetMsisdnFromTokenReq request);
+    }
+
+    public class AuthBusinessImpl : IAuthBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(AuthBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IAuthService authService;
+        private readonly IConfiguration configuration;
+
+        public AuthBusinessImpl(ModelContext _dbContext, IAuthService _authService, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            authService = _authService;
+            configuration = _configuration;
+        }
+
+        /// <summary>
+        /// Đăng nhập bằng token từ URL
+        /// Flow: 
+        ///   1. User truy cập website qua URL: https://domain.com?token=abc123
+        ///   2. Frontend lấy token từ URL và gọi API này
+        ///   3. API xác thực token và trả về thông tin user
+        ///   4. Frontend lưu token vào localStorage để dùng cho các request sau
+        /// </summary>
+        public async Task<IActionResult> LoginByToken(HttpRequest httpRequest, TokenLoginReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(new { token = "***" }); // Ẩn token trong log
+            log.Debug("URL: " + url + " => Request: LoginByToken");
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                // 1. Validate request
+                if (string.IsNullOrEmpty(request.token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("TOKEN_REQUIRED", lang),
+                        new { }
+                    );
+                }
+
+                // 2. Validate token và lấy thông tin user
+                var validationResult = await authService.ValidateTokenWithDetails(request.token);
+
+                if (!validationResult.IsValid)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        validationResult.ErrorCode ?? CommonErrorCode.TokenInvalid,
+                        ConfigManager.Instance.GetConfigWebValue("TOKEN_INVALID", lang),
+                        new { }
+                    );
+                }
+
+                var user = validationResult.User!;
+
+                // 3. Update last login time
+                var userToUpdate = await dbContext.AccountUsers
+                    .FirstOrDefaultAsync(u => u.Id == user.Id);
+                
+                if (userToUpdate != null)
+                {
+                    userToUpdate.LastLogin = DateTime.Now;
+                    await dbContext.SaveChangesAsync();
+                }
+
+                log.Info($"LoginByToken success: MSISDN={user.Msisdn}");
+
+                // 4. Check Registration Status
+                bool isRegistered = false;
+                RegInfoDto? regPkg = null;
+                
+                string productCode = "SICBO_DAY"; // Default
+                // Try to get from config if available (assuming ConfigManager has it, or just use default)
+                // var cfgCode = ConfigManager.Instance.GetConfigWebValue("PackageCodeDaily");
+                // if(!string.IsNullOrEmpty(cfgCode)) productCode = cfgCode;
+
+                var regInfo = await dbContext.RegInfos
+                    .Where(r => r.Msisdn == user.Msisdn 
+                             && r.ProductName == productCode
+                             && r.Renew == 1 
+                             && r.Status == 1 
+                             && r.ExpireTime > DateTime.Now)
+                    .OrderByDescending(r => r.RegisterTime)
+                    .FirstOrDefaultAsync();
+
+                if (regInfo != null)
+                {
+                    isRegistered = true;
+                    regPkg = new RegInfoDto
+                    {
+                        RegisterId = regInfo.RegisterId,
+                        Msisdn = regInfo.Msisdn,
+                        ProductName = regInfo.ProductName,
+                        RegisterTime = regInfo.RegisterTime,
+                        NumberSpin = regInfo.NumberSpin,
+                        Status = regInfo.Status,
+                        ExpireTime = regInfo.ExpireTime,
+                        Renew = regInfo.Renew
+                    };
+                }
+
+                // 5. Return user info
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOGIN_SUCCESS", lang),
+                    new TokenLoginRes
+                    {
+                        id = user.Id,
+                        msisdn = user.Msisdn,
+                        username = user.Username,
+                        fullname = user.Fullname,
+                        picture = user.Picture,
+                        winCoin = user.WinCoin,
+                        betCoin = user.BetCoin,
+                        point = user.Point,
+                        freeSpin = user.FreeSpin,
+                        status = user.Status,
+                        lastLogin = DateTime.Now,
+                        isRegistered = isRegistered,
+                        regPkg = regPkg
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("LoginByToken exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Lấy MSISDN từ token (API nhẹ cho các tác vụ đơn giản)
+        /// </summary>
+        public async Task<IActionResult> GetMsisdnFromToken(HttpRequest httpRequest, GetMsisdnFromTokenReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(new { token = "***" });
+            log.Debug("URL: " + url + " => Request: GetMsisdnFromToken");
+
+            try
+            {
+                if (string.IsNullOrEmpty(request.token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        "Token is required",
+                        new GetMsisdnFromTokenRes { isValid = false }
+                    );
+                }
+
+                var msisdn = await authService.GetMsisdnFromToken(request.token);
+
+                if (string.IsNullOrEmpty(msisdn))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.TokenInvalid,
+                        "Token invalid",
+                        new GetMsisdnFromTokenRes { isValid = false }
+                    );
+                }
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    "Success",
+                    new GetMsisdnFromTokenRes 
+                    { 
+                        msisdn = msisdn,
+                        isValid = true 
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("GetMsisdnFromToken exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                "System error",
+                new GetMsisdnFromTokenRes { isValid = false }
+            );
+        }
+    }
+}

+ 150 - 0
SicboSub/SicboSub.Api/Business/AuthServiceImpl.cs

@@ -0,0 +1,150 @@
+using Common.Constant;
+using Database.Database;
+using log4net;
+using Microsoft.EntityFrameworkCore;
+
+namespace SicboSub.Api.Business
+{
+    /// <summary>
+    /// Implementation cho Authentication Service
+    /// Xác thực token và lấy thông tin thuê bao từ database
+    /// 
+    /// Token được lưu trong bảng ACCOUNT_USER.TOKEN
+    /// User truy cập website qua URL: https://...?token=xxx
+    /// </summary>
+    public class AuthServiceImpl : IAuthService
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(AuthServiceImpl));
+
+        private readonly ModelContext dbContext;
+
+        public AuthServiceImpl(ModelContext _dbContext)
+        {
+            dbContext = _dbContext;
+        }
+
+        /// <summary>
+        /// Xác thực token và trả về thông tin user
+        /// Token được so sánh với trường TOKEN trong bảng ACCOUNT_USER
+        /// </summary>
+        public async Task<AccountUser?> ValidateToken(string token)
+        {
+            if (string.IsNullOrEmpty(token))
+            {
+                log.Warn("ValidateToken: Token is null or empty");
+                return null;
+            }
+
+            try
+            {
+                // Tìm user có token khớp
+                var user = await dbContext.AccountUsers.AsNoTracking()
+                    .FirstOrDefaultAsync(u => u.Token == token);
+
+                if (user == null)
+                {
+                    log.Warn($"ValidateToken: Token not found in database");
+                    return null;
+                }
+
+                // Check user status
+                if (user.IsActive != 1)
+                {
+                    log.Warn($"ValidateToken: User {user.Msisdn} is not active");
+                    return null;
+                }
+
+                if (user.IsLock == 1)
+                {
+                    log.Warn($"ValidateToken: User {user.Msisdn} is locked");
+                    return null;
+                }
+
+                log.Debug($"ValidateToken: Token valid for MSISDN {user.Msisdn}");
+                return user;
+            }
+            catch (Exception ex)
+            {
+                log.Error("ValidateToken exception: ", ex);
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Lấy MSISDN từ token
+        /// </summary>
+        public async Task<string?> GetMsisdnFromToken(string token)
+        {
+            var user = await ValidateToken(token);
+            return user?.Msisdn;
+        }
+
+        /// <summary>
+        /// Validate token và trả về kết quả chi tiết với error code
+        /// </summary>
+        public async Task<TokenValidationResult> ValidateTokenWithDetails(string token)
+        {
+            var result = new TokenValidationResult();
+
+            if (string.IsNullOrEmpty(token))
+            {
+                result.IsValid = false;
+                result.ErrorCode = CommonErrorCode.TokenInvalid;
+                result.ErrorMessage = "Token is required";
+                return result;
+            }
+
+            try
+            {
+                // Tìm user có token khớp
+                var user = await dbContext.AccountUsers.AsNoTracking()
+                    .FirstOrDefaultAsync(u => u.Token == token);
+
+                if (user == null)
+                {
+                    result.IsValid = false;
+                    result.ErrorCode = CommonErrorCode.TokenInvalid;
+                    result.ErrorMessage = "Token không hợp lệ hoặc đã hết hạn";
+                    log.Warn($"ValidateTokenWithDetails: Token not found");
+                    return result;
+                }
+
+                // Check user is active
+                if (user.IsActive != 1)
+                {
+                    result.IsValid = false;
+                    result.ErrorCode = CommonErrorCode.AccountDisabled;
+                    result.ErrorMessage = "Tài khoản đã bị vô hiệu hóa";
+                    log.Warn($"ValidateTokenWithDetails: User {user.Msisdn} is not active");
+                    return result;
+                }
+
+                // Check user is locked
+                if (user.IsLock == 1)
+                {
+                    result.IsValid = false;
+                    result.ErrorCode = CommonErrorCode.AccountLocked;
+                    result.ErrorMessage = "Tài khoản đã bị khóa";
+                    log.Warn($"ValidateTokenWithDetails: User {user.Msisdn} is locked");
+                    return result;
+                }
+
+                // Token is valid
+                result.IsValid = true;
+                result.Msisdn = user.Msisdn;
+                result.User = user;
+                log.Debug($"ValidateTokenWithDetails: Token valid for MSISDN {user.Msisdn}");
+
+                return result;
+            }
+            catch (Exception ex)
+            {
+                log.Error("ValidateTokenWithDetails exception: ", ex);
+                result.IsValid = false;
+                result.ErrorCode = CommonErrorCode.SystemError;
+                result.ErrorMessage = "Lỗi hệ thống khi xác thực token";
+                return result;
+            }
+        }
+    }
+}

+ 633 - 0
SicboSub/SicboSub.Api/Business/ExchangeBusinessImpl.cs

@@ -0,0 +1,633 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+
+namespace SicboSub.Api.Business
+{
+    /// <summary>
+    /// Implementation cho Exchange Business Logic với OTP verification
+    /// </summary>
+    public class ExchangeBusinessImpl : IExchangeBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(ExchangeBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IConfiguration configuration;
+
+        // OTP Configuration
+        private const int OTP_LENGTH = 6;
+        private const int OTP_EXPIRE_MINUTES = 1;
+        private const int MAX_ATTEMPT_PER_OTP = 3;
+        private const int MAX_OTP_PER_DAY = 10;
+        private const int RESEND_COOLDOWN_SECONDS = 60;
+
+        public ExchangeBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            configuration = _configuration;
+        }
+
+        /// <summary>
+        /// Yêu cầu OTP để thực hiện Exchange
+        /// Flow: Validate -> Check pending OTP -> Check rate limit -> Create OTP -> Send SMS via MT table
+        /// </summary>
+        public async Task<IActionResult> RequestOtp(HttpRequest httpRequest, ExchangeRequestOtpReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                // 1. Validate token
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+
+                // 2. Validate request
+                if (string.IsNullOrEmpty(request.msisdn) || request.configId <= 0)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                // 3. Check user exists
+                var user = await dbContext.AccountUsers.AsNoTracking()
+                    .FirstOrDefaultAsync(u => u.Msisdn == request.msisdn);
+
+                if (user == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UserNotFound,
+                        ConfigManager.Instance.GetConfigWebValue("USER_NOT_FOUND", lang),
+                        new { }
+                    );
+                }
+
+                // 4. Get Exchange Config
+                var exchangeConfig = await dbContext.ExchangeConfigs.AsNoTracking()
+                    .FirstOrDefaultAsync(e => e.Id == request.configId && e.IsActive == 1);
+
+                if (exchangeConfig == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.PackageNotFound,
+                        ConfigManager.Instance.GetConfigWebValue("EXCHANGE_CONFIG_NOT_FOUND", lang),
+                        new { }
+                    );
+                }
+
+                // 5. Check user has enough coins
+                if (user.WinCoin < exchangeConfig.CoinCost)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InsufficientBalance,
+                        ConfigManager.Instance.GetConfigWebValue("INSUFFICIENT_COIN", lang),
+                        new { currentBalance = user.WinCoin, required = exchangeConfig.CoinCost }
+                    );
+                }
+
+                // 6. Check pending OTP (chưa hết hạn)
+                var pendingOtp = await dbContext.ExchangeOtps.AsNoTracking()
+                    .FirstOrDefaultAsync(o => o.Msisdn == request.msisdn 
+                        && o.Status == ExchangeOtpStatus.Pending 
+                        && o.ExpiredTime > DateTime.Now);
+
+                if (pendingOtp != null)
+                {
+                    var remainingSeconds = (int)(pendingOtp.ExpiredTime!.Value - DateTime.Now).TotalSeconds;
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.OtpTooManyRequests,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_PENDING_EXISTS", lang),
+                        new { expiresInSeconds = remainingSeconds }
+                    );
+                }
+
+                // 7. Check rate limit (max OTP per day)
+                var today = DateTime.Today;
+                var todayOtpCount = await dbContext.ExchangeOtps.AsNoTracking()
+                    .CountAsync(o => o.Msisdn == request.msisdn && o.CreatedTime >= today);
+
+                if (todayOtpCount >= MAX_OTP_PER_DAY)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.RateLimitExceeded,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_RATE_LIMIT_EXCEEDED", lang),
+                        new { maxPerDay = MAX_OTP_PER_DAY }
+                    );
+                }
+
+                // CHECK: Max withdrawal < 100 HTG/day
+                var totalWithdrawnToday = await dbContext.ExchangeHistories.AsNoTracking()
+                    .Where(h => h.Msisdn == request.msisdn && h.ExchangeTime >= today && h.Status >= 0)
+                    .SumAsync(h => h.MoneyAdded ?? 0);
+
+                if (totalWithdrawnToday + (exchangeConfig.MoneyReceived ?? 0) >= 100)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.LimitExceeded, 
+                        ConfigManager.Instance.GetConfigWebValue("EXCHANGE_DAILY_LIMIT_EXCEEDED", lang),
+                        new { currentDailyTotal = totalWithdrawnToday, limit = 100 }
+                    );
+                }
+
+                // 8. Expire any old pending OTPs
+                var oldPendingOtps = await dbContext.ExchangeOtps
+                    .Where(o => o.Msisdn == request.msisdn && o.Status == ExchangeOtpStatus.Pending)
+                    .ToListAsync();
+
+                foreach (var oldOtp in oldPendingOtps)
+                {
+                    oldOtp.Status = ExchangeOtpStatus.Expired;
+                }
+
+                // 9. Generate new OTP
+                string otpCode = GenerateOtpCode();
+                var now = DateTime.Now;
+                var expiredTime = now.AddMinutes(OTP_EXPIRE_MINUTES);
+
+                // Get next sequence value
+                var otpId = await GetNextSequenceValue("EXCHANGE_OTP_SEQ");
+
+                var newOtp = new ExchangeOtp
+                {
+                    Id = otpId,
+                    Msisdn = request.msisdn,
+                    OtpCode = otpCode,
+                    ConfigId = request.configId,
+                    CoinAmount = exchangeConfig.CoinCost,
+                    MoneyAmount = exchangeConfig.MoneyReceived,
+                    CreatedTime = now,
+                    ExpiredTime = expiredTime,
+                    Status = ExchangeOtpStatus.Pending,
+                    AttemptCount = 0,
+                    IpAddress = GetClientIpAddress(httpRequest)
+                };
+
+                dbContext.ExchangeOtps.Add(newOtp);
+
+                // 10. Insert vào bảng MT để gửi SMS
+                var mtId = await GetNextSequenceValue("MT_SEQ");
+                var smsMessage = GetOtpSmsMessage(otpCode, OTP_EXPIRE_MINUTES);
+
+                var mt = new Mt
+                {
+                    MtId = mtId,
+                    MoHisId = (int)mtId,
+                    Msisdn = request.msisdn,
+                    Message = smsMessage,
+                    ReceiveTime = now,
+                    RetryNum = 0,
+                    Channel = CommonConstant.Channel
+                };
+                dbContext.Mts.Add(mt);
+
+                await dbContext.SaveChangesAsync();
+
+                log.Info($"OTP created successfully: msisdn={request.msisdn}, otpId={otpId}");
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("OTP_SENT_SUCCESS", lang),
+                    new ExchangeRequestOtpRes
+                    {
+                        otpId = otpId,
+                        expiresInSeconds = OTP_EXPIRE_MINUTES * 60,
+                        coinAmount = exchangeConfig.CoinCost ?? 0,
+                        moneyAmount = exchangeConfig.MoneyReceived ?? 0
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Xác thực OTP và tạo yêu cầu Exchange (Pending)
+        /// Flow: Validate OTP -> Check attempts -> Verify code -> Deduct coins -> Save to EXCHANGE_HISTORY (status=0)
+        /// Trình tự động sẽ quét bảng này để gọi API cộng thưởng và cập nhật status
+        /// </summary>
+        public async Task<IActionResult> VerifyOtp(HttpRequest httpRequest, ExchangeVerifyOtpReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                // 1. Validate token
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+
+                // 2. Validate request
+                if (string.IsNullOrEmpty(request.msisdn) || string.IsNullOrEmpty(request.otpCode))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                // 3. Find pending OTP
+                var otp = await dbContext.ExchangeOtps
+                    .FirstOrDefaultAsync(o => o.Msisdn == request.msisdn 
+                        && o.Status == ExchangeOtpStatus.Pending 
+                        && o.ExpiredTime > DateTime.Now);
+
+                if (otp == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.OtpExpired,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_NOT_FOUND_OR_EXPIRED", lang),
+                        new { }
+                    );
+                }
+
+                // 4. Check max attempts
+                if (otp.AttemptCount >= MAX_ATTEMPT_PER_OTP)
+                {
+                    otp.Status = ExchangeOtpStatus.Failed;
+                    await dbContext.SaveChangesAsync();
+
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.OtpMaxAttemptsExceeded,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_MAX_ATTEMPTS_EXCEEDED", lang),
+                        new { }
+                    );
+                }
+
+                // 5. Verify OTP code
+                if (otp.OtpCode != request.otpCode)
+                {
+                    otp.AttemptCount = (byte?)((otp.AttemptCount ?? 0) + 1);
+
+                    // Lock if max attempts reached
+                    if (otp.AttemptCount >= MAX_ATTEMPT_PER_OTP)
+                    {
+                        otp.Status = ExchangeOtpStatus.Failed;
+                    }
+
+                    await dbContext.SaveChangesAsync();
+
+                    int attemptsRemaining = MAX_ATTEMPT_PER_OTP - (otp.AttemptCount ?? 0);
+
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.OtpInvalid,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_INVALID", lang),
+                        new ExchangeVerifyOtpErrorRes { attemptsRemaining = attemptsRemaining }
+                    );
+                }
+
+                // 6. OTP is valid - Mark as verified
+                otp.Status = ExchangeOtpStatus.Verified;
+                otp.VerifiedTime = DateTime.Now;
+
+                // 7. Get user and check balance
+                var user = await dbContext.AccountUsers
+                    .FirstOrDefaultAsync(u => u.Msisdn == request.msisdn);
+
+                if (user == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UserNotFound,
+                        ConfigManager.Instance.GetConfigWebValue("USER_NOT_FOUND", lang),
+                        new { }
+                    );
+                }
+
+                // Double check balance
+                if (user.WinCoin < otp.CoinAmount)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InsufficientBalance,
+                        ConfigManager.Instance.GetConfigWebValue("INSUFFICIENT_COIN", lang),
+                        new { currentBalance = user.WinCoin, required = otp.CoinAmount }
+                    );
+                }
+
+                // 8. Deduct coins from user
+                user.WinCoin -= otp.CoinAmount ?? 0;
+
+                // 9. Create Exchange History record với STATUS = 0 (Pending)
+                // Trình tự động sẽ quét bảng này để gọi API cộng thưởng
+                var exchangeId = await GetNextSequenceValue("EXCHANGE_HISTORY_SEQ");
+                
+                var exchangeHistory = new ExchangeHistory
+                {
+                    Id = exchangeId,
+                    Msisdn = request.msisdn,
+                    ConfigId = otp.ConfigId,
+                    CoinDeducted = otp.CoinAmount,
+                    MoneyAdded = otp.MoneyAmount,
+                    ExchangeTime = DateTime.Now,
+                    Status = 0  // PENDING - Chờ trình tự động xử lý cộng thưởng
+                };
+
+                dbContext.ExchangeHistories.Add(exchangeHistory);
+
+                await dbContext.SaveChangesAsync();
+
+                log.Info($"Exchange request created: msisdn={request.msisdn}, exchangeId={exchangeId}, coinDeducted={otp.CoinAmount}, moneyToAdd={otp.MoneyAmount}, status=PENDING");
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("EXCHANGE_REQUEST_SUCCESS", lang),
+                    new ExchangeVerifyOtpRes
+                    {
+                        exchangeId = exchangeId,
+                        coinDeducted = otp.CoinAmount ?? 0,
+                        moneyAdded = otp.MoneyAmount ?? 0,
+                        newBalance = user.WinCoin
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Gửi lại OTP (resend)
+        /// Flow: Check cooldown -> Find last pending OTP -> Create new OTP -> Send SMS
+        /// </summary>
+        public async Task<IActionResult> ResendOtp(HttpRequest httpRequest, ExchangeResendOtpReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                // 1. Validate token
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+
+                // 2. Validate request
+                if (string.IsNullOrEmpty(request.msisdn))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                // 3. Find last OTP (pending or recently expired)
+                var lastOtp = await dbContext.ExchangeOtps.AsNoTracking()
+                    .Where(o => o.Msisdn == request.msisdn)
+                    .OrderByDescending(o => o.CreatedTime)
+                    .FirstOrDefaultAsync();
+
+                if (lastOtp == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.OtpNotRequested,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_NOT_REQUESTED", lang),
+                        new { }
+                    );
+                }
+
+                // 4. Check cooldown (60 seconds between resends)
+                var secondsSinceLastOtp = (DateTime.Now - lastOtp.CreatedTime).TotalSeconds;
+                if (secondsSinceLastOtp < RESEND_COOLDOWN_SECONDS)
+                {
+                    int waitSeconds = RESEND_COOLDOWN_SECONDS - (int)secondsSinceLastOtp;
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.RateLimitExceeded,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_RESEND_COOLDOWN", lang),
+                        new { waitSeconds = waitSeconds }
+                    );
+                }
+
+                // 5. Check rate limit
+                var today = DateTime.Today;
+                var todayOtpCount = await dbContext.ExchangeOtps.AsNoTracking()
+                    .CountAsync(o => o.Msisdn == request.msisdn && o.CreatedTime >= today);
+
+                if (todayOtpCount >= MAX_OTP_PER_DAY)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.RateLimitExceeded,
+                        ConfigManager.Instance.GetConfigWebValue("OTP_RATE_LIMIT_EXCEEDED", lang),
+                        new { maxPerDay = MAX_OTP_PER_DAY }
+                    );
+                }
+
+                // 6. Expire old pending OTPs
+                var oldPendingOtps = await dbContext.ExchangeOtps
+                    .Where(o => o.Msisdn == request.msisdn && o.Status == ExchangeOtpStatus.Pending)
+                    .ToListAsync();
+
+                foreach (var oldOtp in oldPendingOtps)
+                {
+                    oldOtp.Status = ExchangeOtpStatus.Expired;
+                }
+
+                // 7. Generate new OTP with same config
+                string otpCode = GenerateOtpCode();
+                var now = DateTime.Now;
+                var expiredTime = now.AddMinutes(OTP_EXPIRE_MINUTES);
+
+                var otpId = await GetNextSequenceValue("EXCHANGE_OTP_SEQ");
+
+                var newOtp = new ExchangeOtp
+                {
+                    Id = otpId,
+                    Msisdn = request.msisdn,
+                    OtpCode = otpCode,
+                    ConfigId = lastOtp.ConfigId,
+                    CoinAmount = lastOtp.CoinAmount,
+                    MoneyAmount = lastOtp.MoneyAmount,
+                    CreatedTime = now,
+                    ExpiredTime = expiredTime,
+                    Status = ExchangeOtpStatus.Pending,
+                    AttemptCount = 0,
+                    IpAddress = GetClientIpAddress(httpRequest)
+                };
+
+                dbContext.ExchangeOtps.Add(newOtp);
+
+                // 8. Insert vào bảng MT để gửi SMS
+                var mtId = await GetNextSequenceValue("MT_SEQ");
+                var smsMessage = GetOtpSmsMessage(otpCode, OTP_EXPIRE_MINUTES);
+
+                var mt = new Mt
+                {
+                    MtId = mtId,
+                    MoHisId = null,
+                    Msisdn = request.msisdn,
+                    Message = smsMessage,
+                    ReceiveTime = now,
+                    RetryNum = 0,
+                    Channel = "API"
+                };
+
+                dbContext.Mts.Add(mt);
+
+                await dbContext.SaveChangesAsync();
+
+                log.Info($"OTP resent successfully: msisdn={request.msisdn}, otpId={otpId}");
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("OTP_RESENT_SUCCESS", lang),
+                    new ExchangeRequestOtpRes
+                    {
+                        otpId = otpId,
+                        expiresInSeconds = OTP_EXPIRE_MINUTES * 60,
+                        coinAmount = lastOtp.CoinAmount ?? 0,
+                        moneyAmount = lastOtp.MoneyAmount ?? 0
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        #region Private Helper Methods
+
+        /// <summary>
+        /// Generate random 6-digit OTP code
+        /// </summary>
+        private string GenerateOtpCode()
+        {
+            var random = new Random();
+            int otp = random.Next(0, 999999);
+            return otp.ToString().PadLeft(OTP_LENGTH, '0');
+        }
+
+        /// <summary>
+        /// Get next value from Oracle sequence
+        /// </summary>
+        private async Task<decimal> GetNextSequenceValue(string sequenceName)
+        {
+            var connection = dbContext.Database.GetDbConnection();
+            if (connection.State != System.Data.ConnectionState.Open)
+            {
+                await connection.OpenAsync();
+            }
+
+            using var command = connection.CreateCommand();
+            command.CommandText = $"SELECT {sequenceName}.NEXTVAL FROM DUAL";
+            var result = await command.ExecuteScalarAsync();
+
+            return Convert.ToDecimal(result);
+        }
+
+        /// <summary>
+        /// Get client IP address from request
+        /// </summary>
+        private string? GetClientIpAddress(HttpRequest httpRequest)
+        {
+            // Check for forwarded IP (if behind proxy/load balancer)
+            var forwardedFor = httpRequest.Headers["X-Forwarded-For"].FirstOrDefault();
+            if (!string.IsNullOrEmpty(forwardedFor))
+            {
+                return forwardedFor.Split(',').FirstOrDefault()?.Trim();
+            }
+
+            return httpRequest.HttpContext.Connection.RemoteIpAddress?.ToString();
+        }
+
+        /// <summary>
+        /// Generate SMS message for OTP
+        /// </summary>
+        private string GetOtpSmsMessage(string otpCode, int expireMinutes)
+        {
+            // Lấy template từ config hoặc dùng mặc định
+            var template = ConfigManager.Instance.GetConfig("OTP_SMS_TEMPLATE") 
+                ?? "Ma xac thuc rut thuong cua ban la: {OTP}. Ma co hieu luc trong {EXPIRE} phut.";
+
+            return template
+                .Replace("{OTP}", otpCode)
+                .Replace("{EXPIRE}", expireMinutes.ToString());
+        }
+
+        #endregion
+    }
+}

+ 354 - 0
SicboSub/SicboSub.Api/Business/GameBusinessImpl.cs

@@ -0,0 +1,354 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+
+namespace SicboSub.Api.Business
+{
+    public class GameBusinessImpl : IGameBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(GameBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IConfiguration configuration;
+
+        public GameBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            configuration = _configuration;
+        }
+
+        public async Task<IActionResult> PlayHistory(HttpRequest httpRequest, PlayHistoryReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
+                int pageSize = request.pageSize <= 0 ? 20 : request.pageSize;
+
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+                token = token.Replace("Bearer ", "");
+
+                if (string.IsNullOrEmpty(request.msisdn))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                // Query BettingHistory
+                var query = dbContext.BettingHistories.AsNoTracking()
+                    .Where(b => b.Msisdn == request.msisdn);
+                
+                if (!string.IsNullOrEmpty(request.fromDate))
+                {
+                    if (DateTime.TryParseExact(request.fromDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime from))
+                    {
+                        query = query.Where(b => b.BettingTime >= from);
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(request.toDate))
+                {
+                    if (DateTime.TryParseExact(request.toDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime to))
+                    {
+                        query = query.Where(b => b.BettingTime <= to);
+                    }
+                }
+                
+                int totalCount = await query.CountAsync();
+                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+                // Fetch bets
+                var bets = await query
+                    .OrderByDescending(b => b.BettingTime)
+                    .Skip(pageNumber * pageSize)
+                    .Take(pageSize)
+                    .ToListAsync();
+                
+                // Get Room Ids from bets
+                var roomIds = bets.Select(b => b.RoomId).Distinct().ToList();
+
+                // Query RoomPrize for these rooms and user
+                var prizes = await dbContext.RoomPrizes.AsNoTracking()
+                    .Where(p => p.Msisdn == request.msisdn && roomIds.Contains(p.RoomId))
+                    .ToListAsync();
+
+                // Merge
+                var history = bets.Select(b => {
+                    // Match prize by RoomId and Type == BettingType
+                    var prize = prizes.FirstOrDefault(p => p.RoomId == b.RoomId && p.Type == b.BettingType);
+                    
+                    return new PlayHistoryItem
+                    {
+                        id = b.Id,
+                        roomId = b.RoomId,
+                        bettingType = b.BettingType,
+                        bettingValue = b.BettingValue,
+                        bettingTime = b.BettingTime,
+                        winCoin = prize?.WinCoin ?? 0,
+                        backCoin = prize?.BackCoin ?? 0,
+                        isWin = prize != null && prize.WinCoin > 0
+                    };
+                }).ToList();
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new
+                    {
+                        history = history,
+                        pagination = new
+                        {
+                            pageNumber,
+                            pageSize,
+                            totalCount,
+                            totalPages
+                        }
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+        public async Task<IActionResult> RankingHistory(HttpRequest httpRequest, RankingHistoryReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
+                int pageSize = request.pageSize <= 0 ? 20 : request.pageSize;
+
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+                token = token.Replace("Bearer ", "");
+
+
+                // Query RankingRewardLog joined with RankingHistory
+                var query = from reward in dbContext.RankingRewardLogs.AsNoTracking()
+                            join ranking in dbContext.RankingHistories.AsNoTracking() on reward.RankingHistoryId equals ranking.Id
+                            select new { reward, ranking };
+
+                if (!string.IsNullOrEmpty(request.rankType))
+                {
+                    query = query.Where(x => x.ranking.RankType == request.rankType);
+                }
+                if (!string.IsNullOrEmpty(request.msisdn))
+                {
+                    query = query.Where(x => x.ranking.Msisdn == request.msisdn);
+                }
+
+                if (!string.IsNullOrEmpty(request.fromDate))
+                {
+                    if (DateTime.TryParseExact(request.fromDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime from))
+                    {
+                        query = query.Where(x => x.reward.RewardDate >= from);
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(request.toDate))
+                {
+                    if (DateTime.TryParseExact(request.toDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime to))
+                    {
+                        query = query.Where(x => x.reward.RewardDate <= to);
+                    }
+                }
+
+                int totalCount = await query.CountAsync();
+                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+                var items = await query
+                    .OrderByDescending(x => x.reward.RewardDate)
+                    .Skip(pageNumber * pageSize)
+                    .Take(pageSize)
+                    .Select(x => new RankingHistoryItem
+                    {
+                        id = x.reward.Id,
+                        msisdn = x.reward.Msisdn,
+                        rankType = x.ranking.RankType ?? "",
+                        rankDate = x.ranking.RankDate ?? DateTime.MinValue,
+                        rankPosition = x.ranking.RankPosition ?? 0,
+                        rewardValue = x.reward.RewardValue ?? 0,
+                        rewardUnit = x.reward.RewardUnit ?? "",
+                        rewardDate = x.reward.RewardDate ?? DateTime.MinValue,
+                        totalBetValue = x.ranking.TotalBetValue ?? 0
+                    })
+                    .ToListAsync();
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new
+                    {
+                        history = items,
+                        pagination = new
+                        {
+                            pageNumber,
+                            pageSize,
+                            totalCount,
+                            totalPages
+                        }
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+        public async Task<IActionResult> PurchaseHistory(HttpRequest httpRequest, PurchaseHistoryReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
+                int pageSize = request.pageSize <= 0 ? 20 : request.pageSize;
+
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+                token = token.Replace("Bearer ", "");
+
+                if (string.IsNullOrEmpty(request.msisdn))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                // Query REGINFO
+                var query = dbContext.RegInfos.AsNoTracking()
+                    .Where(r => r.Msisdn == request.msisdn);
+                
+                if (!string.IsNullOrEmpty(request.fromDate))
+                {
+                    if (DateTime.TryParseExact(request.fromDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime from))
+                    {
+                        query = query.Where(r => r.RegisterTime >= from);
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(request.toDate))
+                {
+                    if (DateTime.TryParseExact(request.toDate, "dd/MM/yyyy HH:mm:ss", null, System.Globalization.DateTimeStyles.None, out DateTime to))
+                    {
+                        query = query.Where(r => r.RegisterTime <= to);
+                    }
+                }
+
+                int totalCount = await query.CountAsync();
+                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+                var items = await query
+                    .OrderByDescending(r => r.RegisterTime)
+                    .Skip(pageNumber * pageSize)
+                    .Take(pageSize)
+                    .Select(r => new PurchaseHistoryItem
+                    {
+                        id = r.RegisterId,
+                        productName = r.ProductName ?? "",
+                        registerTime = r.RegisterTime ?? DateTime.MinValue,
+                        expireTime = r.ExpireTime ?? DateTime.MinValue,
+                        serviceId = r.ServiceId ?? 0, // Using ServiceId column which seems to store Fee based on model (NUMBER(10,2))
+                        channel = r.Channel ?? "",
+                        status = r.Status ,
+                        renew = r.Renew ?? 0
+                    })
+                    .ToListAsync();
+                
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new
+                    {
+                        history = items,
+                        pagination = new
+                        {
+                            pageNumber,
+                            pageSize,
+                            totalCount,
+                            totalPages
+                        }
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("PurchaseHistory: Exception", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+    }
+}

+ 39 - 0
SicboSub/SicboSub.Api/Business/IAuthService.cs

@@ -0,0 +1,39 @@
+using Database.Database;
+
+namespace SicboSub.Api.Business
+{
+    /// <summary>
+    /// Interface cho Authentication Service
+    /// Xác thực token và lấy thông tin thuê bao
+    /// </summary>
+    public interface IAuthService
+    {
+        /// <summary>
+        /// Xác thực token từ URL query parameter hoặc header
+        /// Trả về thông tin user nếu token hợp lệ
+        /// </summary>
+        Task<AccountUser?> ValidateToken(string token);
+
+        /// <summary>
+        /// Lấy MSISDN từ token
+        /// </summary>
+        Task<string?> GetMsisdnFromToken(string token);
+
+        /// <summary>
+        /// Validate token và trả về kết quả chi tiết
+        /// </summary>
+        Task<TokenValidationResult> ValidateTokenWithDetails(string token);
+    }
+
+    /// <summary>
+    /// Kết quả xác thực token
+    /// </summary>
+    public class TokenValidationResult
+    {
+        public bool IsValid { get; set; }
+        public string? Msisdn { get; set; }
+        public AccountUser? User { get; set; }
+        public string? ErrorCode { get; set; }
+        public string? ErrorMessage { get; set; }
+    }
+}

+ 26 - 0
SicboSub/SicboSub.Api/Business/IExchangeBusiness.cs

@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Business
+{
+    /// <summary>
+    /// Interface cho Exchange Business Logic
+    /// </summary>
+    public interface IExchangeBusiness
+    {
+        /// <summary>
+        /// Yêu cầu OTP để thực hiện Exchange
+        /// </summary>
+        Task<IActionResult> RequestOtp(HttpRequest httpRequest, ExchangeRequestOtpReq request);
+
+        /// <summary>
+        /// Xác thực OTP và thực hiện Exchange
+        /// </summary>
+        Task<IActionResult> VerifyOtp(HttpRequest httpRequest, ExchangeVerifyOtpReq request);
+
+        /// <summary>
+        /// Gửi lại OTP (resend)
+        /// </summary>
+        Task<IActionResult> ResendOtp(HttpRequest httpRequest, ExchangeResendOtpReq request);
+    }
+}

+ 23 - 0
SicboSub/SicboSub.Api/Business/IGameBusiness.cs

@@ -0,0 +1,23 @@
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Business
+{
+    public interface IGameBusiness
+    {
+        /// <summary>
+        /// Get play history (betting and winning info)
+        /// </summary>
+        Task<IActionResult> PlayHistory(HttpRequest httpRequest, PlayHistoryReq request);
+
+        /// <summary>
+        /// Get ranking prize history
+        /// </summary>
+        Task<IActionResult> RankingHistory(HttpRequest httpRequest, RankingHistoryReq request);
+
+        /// <summary>
+        /// Get purchase history (reg/buymore logs)
+        /// </summary>
+        Task<IActionResult> PurchaseHistory(HttpRequest httpRequest, PurchaseHistoryReq request);
+    }
+}

+ 18 - 0
SicboSub/SicboSub.Api/Business/IPackageBusiness.cs

@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Business
+{
+    public interface IPackageBusiness
+    {
+        /// <summary>
+        /// Load coin packages for purchase
+        /// </summary>
+        Task<IActionResult> PackageLoad(HttpRequest httpRequest, PackageLoadReq request);
+
+        /// <summary>
+        /// Load exchange/withdraw configurations
+        /// </summary>
+        Task<IActionResult> ExchangeConfigLoad(HttpRequest httpRequest, ExchangeConfigLoadReq request);
+    }
+}

+ 18 - 0
SicboSub/SicboSub.Api/Business/ISubscriptionBusiness.cs

@@ -0,0 +1,18 @@
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Business
+{
+    public interface ISubscriptionBusiness
+    {
+        /// <summary>
+        /// Register package
+        /// </summary>
+        Task<IActionResult> Register(HttpRequest httpRequest, RegisterReq request);
+
+        /// <summary>
+        /// Buy more package
+        /// </summary>
+        Task<IActionResult> BuyMore(HttpRequest httpRequest, BuyMoreReq request);
+    }
+}

+ 13 - 0
SicboSub/SicboSub.Api/Business/IUserBusiness.cs

@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Business
+{
+    public interface IUserBusiness
+    {
+        /// <summary>
+        /// Get account information
+        /// </summary>
+        Task<IActionResult> GetAccountInfo(HttpRequest httpRequest, AccountInfoReq request);
+    }
+}

+ 157 - 0
SicboSub/SicboSub.Api/Business/PackageBusinessImpl.cs

@@ -0,0 +1,157 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+
+namespace SicboSub.Api.Business
+{
+    public class PackageBusinessImpl : IPackageBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(PackageBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IConfiguration configuration;
+
+        public PackageBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            configuration = _configuration;
+        }
+
+        /// <summary>
+        /// Load coin packages for purchase
+        /// </summary>
+        public async Task<IActionResult> PackageLoad(HttpRequest httpRequest, PackageLoadReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
+                int pageSize = request.pageSize <= 0 ? 20 : request.pageSize;
+
+                // Query packages
+                var query = dbContext.Packgs.AsQueryable();
+
+                int totalCount = query.Count();
+                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+                var packages = query
+                    .Skip(pageNumber * pageSize)
+                    .Take(pageSize)
+                    .Select(p => new
+                    {
+                        productId = p.ProductId,
+                        productName = p.ProductName,
+                        fee = p.Fee,
+                        numberSpin = p.NumberSpin,
+                        expireDays = p.ExpireDays,
+                        smsSyntax = p.SmsSyntax
+                    })
+                    .ToList();
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new
+                    {
+                        packages = packages,
+                        pagination = new
+                        {
+                            pageNumber,
+                            pageSize,
+                            totalCount,
+                            totalPages
+                        }
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Load exchange/withdraw configurations
+        /// </summary>
+        public async Task<IActionResult> ExchangeConfigLoad(HttpRequest httpRequest, ExchangeConfigLoadReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+                int pageNumber = request.pageNumber < 0 ? 0 : request.pageNumber;
+                int pageSize = request.pageSize <= 0 ? 20 : request.pageSize;
+
+                // Query exchange configs - only active ones
+                var query = dbContext.ExchangeConfigs
+                    .Where(e => e.IsActive.HasValue && e.IsActive == 1);
+
+                int totalCount = query.Count();
+                int totalPages = (int)Math.Ceiling((double)totalCount / pageSize);
+
+                var exchangeConfigs = query
+                    .OrderBy(e => e.CoinCost)
+                    .Skip(pageNumber * pageSize)
+                    .Take(pageSize)
+                    .Select(e => new
+                    {
+                        id = e.Id,
+                        productName = e.ProductName,
+                        coinCost = e.CoinCost,
+                        moneyReceived = e.MoneyReceived,
+                        feeCoin = e.FeeCoin,
+                        description = e.Description
+                    })
+                    .ToList();
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    new
+                    {
+                        exchangeConfigs = exchangeConfigs,
+                        pagination = new
+                        {
+                            pageNumber,
+                            pageSize,
+                            totalCount,
+                            totalPages
+                        }
+                    }
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+    }
+}

+ 196 - 0
SicboSub/SicboSub.Api/Business/SubscriptionBusinessImpl.cs

@@ -0,0 +1,196 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+using SicboSubWss;
+using System.Drawing.Printing;
+using System.Net;
+using System.ServiceModel;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace SicboSub.Api.Business
+{
+    public class SubscriptionBusinessImpl : ISubscriptionBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(SubscriptionBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IConfiguration configuration;
+        SicboSubWss.SicboSubWsClient wsClient;
+
+        string wsUser;
+        string wsPass;
+        protected void SetWsClient(ref SicboSubWss.SicboSubWsClient wsClient, IConfiguration configuration)
+        {
+            wsClient.Endpoint.Address = new EndpointAddress(configuration.GetSection("wsUrl").Value);
+            log.Info("gds:" + configuration.GetSection("wsUrl").Value);
+        }
+        public SubscriptionBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            configuration = _configuration;
+            wsClient = new SicboSubWss.SicboSubWsClient();
+            SetWsClient(ref wsClient, configuration);
+            wsUser = GetParameter("wsUser");
+            wsPass = GetParameter("wsPass");
+        }
+        private string GetParameter(string key)
+        {
+            return configuration.GetSection(key).Value ?? "";
+        }
+        /// <summary>
+        /// Register package
+        /// </summary>
+        public async Task<IActionResult> Register(HttpRequest httpRequest, RegisterReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+            string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+            try
+            {
+                if (string.IsNullOrEmpty(request.msisdn) || string.IsNullOrEmpty(request.packageCode))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(log, url, json, CommonErrorCode.InvalidParameter, "Missing parameters", new { });
+                }
+
+                // Get WS Configs
+                
+                string serviceId = ConfigManager.Instance.GetConfig("SERVICE_ID");
+
+                string requestId = DateTime.Now.ToString("yyyyMMddHHmmssfff");
+
+                SicboSubWss.wsRegisterSubOtpResponse wsRegisterSubOtpResponse =
+                await wsClient.wsRegisterSubOtpAsync(
+                       wsUser,
+                       wsPass,
+                       request.msisdn,
+                       request.packageCode,
+                       request.packageCode
+                );
+
+                var jsonData = JsonConvert.SerializeObject(wsRegisterSubOtpResponse);
+                log.Info("request: wsRegisterSubOtpAsync => data: " + jsonData);
+
+                if (wsRegisterSubOtpResponse.@return.errorCode == CommonErrorCode.Success)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.Success,
+                        ConfigManager.Instance.GetConfigWebValue("REGISTER_SUCCESS", lang),
+                        new
+                        {
+                        }
+                    );
+                  
+                }
+                else
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.Error,
+                        wsRegisterSubOtpResponse.@return.content,
+                        new
+                        {
+                        }
+                    );
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+
+        /// <summary>
+        /// Buy more package
+        /// </summary>
+        public async Task<IActionResult> BuyMore(HttpRequest httpRequest, BuyMoreReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+            string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+            try
+            {
+                if (string.IsNullOrEmpty(request.msisdn) || string.IsNullOrEmpty(request.packageCode))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(log, url, json, CommonErrorCode.InvalidParameter, "Missing parameters", new { });
+                }
+
+                // Get package fee
+                var package = dbContext.Packgs.FirstOrDefault(p => p.ProductName == request.packageCode);
+                if (package == null)
+                {
+                     return DotnetLib.Http.HttpResponse.BuildResponse(log, url, json, CommonErrorCode.DataNotFound, "Package not found", new { });
+                }
+                string fee = package.Fee.ToString();
+
+                // Get WS Configs
+
+                string serviceId = ConfigManager.Instance.GetConfig("SERVICE_ID");
+
+                string requestId = DateTime.Now.ToString("yyyyMMddHHmmssfff");
+
+                SicboSubWss.wsChargeFeeOtpResponse requestRegister =
+                    await wsClient.wsChargeFeeOtpAsync(
+                        wsUser,
+                        wsPass,
+                        request.msisdn,
+                        package.ProductName,
+                        fee,
+                        serviceId
+                    );
+
+                var jsonData = JsonConvert.SerializeObject(requestRegister);
+                log.Info("request: wsChargeFeeOtpAsync => data: " + jsonData);
+
+                if (requestRegister.@return.errorCode == CommonErrorCode.Success)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.Success,
+                        requestRegister.@return.content,
+                        new
+                        {
+                        }
+                    );
+                }else
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                       log, url, json,
+                       CommonErrorCode.Success,
+                       requestRegister.@return.content,
+                       new
+                       {
+                       }
+                   );
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+    }
+}

+ 113 - 0
SicboSub/SicboSub.Api/Business/UserBusinessImpl.cs

@@ -0,0 +1,113 @@
+using Common.Constant;
+using Common.Logic;
+using Database.Database;
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using SicboSub.Api.DTO;
+using SicboSub.Api.Singleton;
+
+namespace SicboSub.Api.Business
+{
+    public class UserBusinessImpl : IUserBusiness
+    {
+        private static readonly ILog log = LogManager.GetLogger(typeof(UserBusinessImpl));
+
+        private readonly ModelContext dbContext;
+        private readonly IConfiguration configuration;
+
+        public UserBusinessImpl(ModelContext _dbContext, IConfiguration _configuration)
+        {
+            dbContext = _dbContext;
+            configuration = _configuration;
+        }
+
+        public async Task<IActionResult> GetAccountInfo(HttpRequest httpRequest, AccountInfoReq request)
+        {
+            var url = httpRequest.Path;
+            var json = JsonConvert.SerializeObject(request);
+            log.Debug("URL: " + url + " => Request: " + json);
+
+            try
+            {
+                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);
+
+                string token = httpRequest.Headers["Authorization"].ToString();
+                if (string.IsNullOrEmpty(token))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UnauthorizedAccess,
+                        ConfigManager.Instance.GetConfigWebValue("UNAUTHORIZED", lang),
+                        new { }
+                    );
+                }
+                token = token.Replace("Bearer ", "");
+
+                if (string.IsNullOrEmpty(request.msisdn))
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.InvalidParameter,
+                        ConfigManager.Instance.GetConfigWebValue("INVALID_PARAM", lang),
+                        new { }
+                    );
+                }
+
+                var user = await dbContext.AccountUsers.AsNoTracking()
+                    .FirstOrDefaultAsync(u => u.Msisdn == request.msisdn);
+
+                if (user == null)
+                {
+                    return DotnetLib.Http.HttpResponse.BuildResponse(
+                        log, url, json,
+                        CommonErrorCode.UserNotFound,
+                        ConfigManager.Instance.GetConfigWebValue("USER_NOT_FOUND", lang),
+                        new { }
+                    );
+                }
+
+                var result = new AccountInfoRes
+                {
+                    id = user.Id,
+                    msisdn = user.Msisdn,
+                    username = user.Username,
+                    fullname = user.Fullname,
+                    picture = user.Picture,
+                    email = user.Email,
+                    address = user.Address,
+                    gender = user.Gender,
+                    birthday = user.Birthday,
+                    winCoin = user.WinCoin,
+                    point = user.Point,
+                    freeSpin = user.FreeSpin,
+                    totalSpin = user.TotalSpin,
+                    status = user.Status,
+                    isActive = user.IsActive,
+                    createdDate = user.CreatedDate,
+                    lastLogin = user.LastLogin,
+                    betCoin = user.BetCoin
+                };
+
+                return DotnetLib.Http.HttpResponse.BuildResponse(
+                    log, url, json,
+                    CommonErrorCode.Success,
+                    ConfigManager.Instance.GetConfigWebValue("LOAD_SUCCESS", lang),
+                    result
+                );
+            }
+            catch (Exception ex)
+            {
+                log.Error("Exception: ", ex);
+            }
+
+            return DotnetLib.Http.HttpResponse.BuildResponse(
+                log, url, json,
+                CommonErrorCode.SystemError,
+                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
+                new { }
+            );
+        }
+    }
+}

+ 16 - 0
SicboSub/SicboSub.Api/Connected Services/SicboSubWss/ConnectedService.json

@@ -0,0 +1,16 @@
+{
+  "ExtendedData": {
+    "inputs": [
+      "http://127.0.0.1:8199/SicboSubWs?wsdl"
+    ],
+    "collectionTypes": [
+      "System.Array",
+      "System.Collections.Generic.Dictionary`2"
+    ],
+    "namespaceMappings": [
+      "*, SicboSubWss"
+    ],
+    "targetFramework": "net8.0",
+    "typeReuseMode": "All"
+  }
+}

+ 3725 - 0
SicboSub/SicboSub.Api/Connected Services/SicboSubWss/Reference.cs

@@ -0,0 +1,3725 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SicboSubWss
+{
+    
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ServiceModel.ServiceContractAttribute(Namespace="http://webservices.vas.com/", ConfigurationName="SicboSubWss.SicboSubWs")]
+    public interface SicboSubWs
+    {
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> wsRegisterSubConfirmAsync(SicboSubWss.wsRegisterSubConfirmRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> wsDisableRegisterAsync(SicboSubWss.wsDisableRegisterRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> wsGetUserServicesAsync(SicboSubWss.wsGetUserServicesRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> wsChargeFeeConfirmAsync(SicboSubWss.wsChargeFeeConfirmRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> wsLoadPrizeAsync(SicboSubWss.wsLoadPrizeRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> wsGetListWinnerAsync(SicboSubWss.wsGetListWinnerRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> wsDoSpinTAsync(SicboSubWss.wsDoSpinTRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> wsAddDataAsync(SicboSubWss.wsAddDataRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> wsDoSpinAsync(SicboSubWss.wsDoSpinRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> receiveresultAsync(SicboSubWss.receiveresultRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> wsRegisterSubOtpAsync(SicboSubWss.wsRegisterSubOtpRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> wsAddMoneyAsync(SicboSubWss.wsAddMoneyRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> wsAddEmolaAsync(SicboSubWss.wsAddEmolaRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> wsChargeFeeOtpAsync(SicboSubWss.wsChargeFeeOtpRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> subRequestAsync(SicboSubWss.subRequestRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> heartbeatAsync(SicboSubWss.heartbeatRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.pairResponse> pairAsync(SicboSubWss.pairRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> getIpClientAsync(SicboSubWss.getIpClientRequest request);
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class response
+    {
+        
+        private string contentField;
+        
+        private string errorCodeField;
+        
+        private accountInfo[] listAccountsField;
+        
+        private configuration[] listConfigurationsField;
+        
+        private game[] listGamesField;
+        
+        private string[] listPackgField;
+        
+        private prizeObj[] listPrizeField;
+        
+        private string[] listServicesField;
+        
+        private prizeWinner[] listWinnerField;
+        
+        private int moneyDeductedField;
+        
+        private string msisdnField;
+        
+        private string positionField;
+        
+        private int remainSpinField;
+        
+        private string resultCodeField;
+        
+        private spinResultObj spinResultField;
+        
+        private string statusField;
+        
+        private accountInfo[] topPlayedTimeField;
+        
+        private accountInfo[] topWonMiniGameField;
+        
+        private string totalPageField;
+        
+        private int totalSpinField;
+        
+        private int totalSpinAddField;
+        
+        private topPlayer[] userRankField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string content
+        {
+            get
+            {
+                return this.contentField;
+            }
+            set
+            {
+                this.contentField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string errorCode
+        {
+            get
+            {
+                return this.errorCodeField;
+            }
+            set
+            {
+                this.errorCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listAccounts", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=2)]
+        public accountInfo[] listAccounts
+        {
+            get
+            {
+                return this.listAccountsField;
+            }
+            set
+            {
+                this.listAccountsField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listConfigurations", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=3)]
+        public configuration[] listConfigurations
+        {
+            get
+            {
+                return this.listConfigurationsField;
+            }
+            set
+            {
+                this.listConfigurationsField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listGames", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=4)]
+        public game[] listGames
+        {
+            get
+            {
+                return this.listGamesField;
+            }
+            set
+            {
+                this.listGamesField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listPackg", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=5)]
+        public string[] listPackg
+        {
+            get
+            {
+                return this.listPackgField;
+            }
+            set
+            {
+                this.listPackgField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listPrize", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=6)]
+        public prizeObj[] listPrize
+        {
+            get
+            {
+                return this.listPrizeField;
+            }
+            set
+            {
+                this.listPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listServices", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=7)]
+        public string[] listServices
+        {
+            get
+            {
+                return this.listServicesField;
+            }
+            set
+            {
+                this.listServicesField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listWinner", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=8)]
+        public prizeWinner[] listWinner
+        {
+            get
+            {
+                return this.listWinnerField;
+            }
+            set
+            {
+                this.listWinnerField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public int moneyDeducted
+        {
+            get
+            {
+                return this.moneyDeductedField;
+            }
+            set
+            {
+                this.moneyDeductedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string position
+        {
+            get
+            {
+                return this.positionField;
+            }
+            set
+            {
+                this.positionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public int remainSpin
+        {
+            get
+            {
+                return this.remainSpinField;
+            }
+            set
+            {
+                this.remainSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string resultCode
+        {
+            get
+            {
+                return this.resultCodeField;
+            }
+            set
+            {
+                this.resultCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public spinResultObj spinResult
+        {
+            get
+            {
+                return this.spinResultField;
+            }
+            set
+            {
+                this.spinResultField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("topPlayedTime", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=16)]
+        public accountInfo[] topPlayedTime
+        {
+            get
+            {
+                return this.topPlayedTimeField;
+            }
+            set
+            {
+                this.topPlayedTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("topWonMiniGame", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=17)]
+        public accountInfo[] topWonMiniGame
+        {
+            get
+            {
+                return this.topWonMiniGameField;
+            }
+            set
+            {
+                this.topWonMiniGameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string totalPage
+        {
+            get
+            {
+                return this.totalPageField;
+            }
+            set
+            {
+                this.totalPageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public int totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public int totalSpinAdd
+        {
+            get
+            {
+                return this.totalSpinAddField;
+            }
+            set
+            {
+                this.totalSpinAddField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("userRank", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=21)]
+        public topPlayer[] userRank
+        {
+            get
+            {
+                return this.userRankField;
+            }
+            set
+            {
+                this.userRankField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class accountInfo
+    {
+        
+        private string accountIdField;
+        
+        private string betcoinField;
+        
+        private string birthdayField;
+        
+        private string channelField;
+        
+        private string createDateField;
+        
+        private string emailField;
+        
+        private string freeSpinField;
+        
+        private string fullNameField;
+        
+        private string isActiveField;
+        
+        private string isLockField;
+        
+        private string languageField;
+        
+        private string lastLoginField;
+        
+        private string lastUpdateField;
+        
+        private string msisdnField;
+        
+        private string passwordField;
+        
+        private string pictureField;
+        
+        private string pointField;
+        
+        private string rankingField;
+        
+        private string roleField;
+        
+        private string serviceIdField;
+        
+        private string statusField;
+        
+        private string timeLockField;
+        
+        private string totalFalseField;
+        
+        private string totalSpinField;
+        
+        private string updateDateField;
+        
+        private string usersField;
+        
+        private string wincoinField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string accountId
+        {
+            get
+            {
+                return this.accountIdField;
+            }
+            set
+            {
+                this.accountIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string betcoin
+        {
+            get
+            {
+                return this.betcoinField;
+            }
+            set
+            {
+                this.betcoinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string birthday
+        {
+            get
+            {
+                return this.birthdayField;
+            }
+            set
+            {
+                this.birthdayField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string channel
+        {
+            get
+            {
+                return this.channelField;
+            }
+            set
+            {
+                this.channelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string createDate
+        {
+            get
+            {
+                return this.createDateField;
+            }
+            set
+            {
+                this.createDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string email
+        {
+            get
+            {
+                return this.emailField;
+            }
+            set
+            {
+                this.emailField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string freeSpin
+        {
+            get
+            {
+                return this.freeSpinField;
+            }
+            set
+            {
+                this.freeSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public string fullName
+        {
+            get
+            {
+                return this.fullNameField;
+            }
+            set
+            {
+                this.fullNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public string isActive
+        {
+            get
+            {
+                return this.isActiveField;
+            }
+            set
+            {
+                this.isActiveField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string isLock
+        {
+            get
+            {
+                return this.isLockField;
+            }
+            set
+            {
+                this.isLockField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string language
+        {
+            get
+            {
+                return this.languageField;
+            }
+            set
+            {
+                this.languageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string lastLogin
+        {
+            get
+            {
+                return this.lastLoginField;
+            }
+            set
+            {
+                this.lastLoginField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string lastUpdate
+        {
+            get
+            {
+                return this.lastUpdateField;
+            }
+            set
+            {
+                this.lastUpdateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string password
+        {
+            get
+            {
+                return this.passwordField;
+            }
+            set
+            {
+                this.passwordField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string picture
+        {
+            get
+            {
+                return this.pictureField;
+            }
+            set
+            {
+                this.pictureField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string point
+        {
+            get
+            {
+                return this.pointField;
+            }
+            set
+            {
+                this.pointField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public string ranking
+        {
+            get
+            {
+                return this.rankingField;
+            }
+            set
+            {
+                this.rankingField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string role
+        {
+            get
+            {
+                return this.roleField;
+            }
+            set
+            {
+                this.roleField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public string serviceId
+        {
+            get
+            {
+                return this.serviceIdField;
+            }
+            set
+            {
+                this.serviceIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=21)]
+        public string timeLock
+        {
+            get
+            {
+                return this.timeLockField;
+            }
+            set
+            {
+                this.timeLockField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=22)]
+        public string totalFalse
+        {
+            get
+            {
+                return this.totalFalseField;
+            }
+            set
+            {
+                this.totalFalseField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=23)]
+        public string totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=24)]
+        public string updateDate
+        {
+            get
+            {
+                return this.updateDateField;
+            }
+            set
+            {
+                this.updateDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=25)]
+        public string users
+        {
+            get
+            {
+                return this.usersField;
+            }
+            set
+            {
+                this.usersField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=26)]
+        public string wincoin
+        {
+            get
+            {
+                return this.wincoinField;
+            }
+            set
+            {
+                this.wincoinField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class topPlayer
+    {
+        
+        private string msisdnField;
+        
+        private int rankField;
+        
+        private int spinCountField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public int rank
+        {
+            get
+            {
+                return this.rankField;
+            }
+            set
+            {
+                this.rankField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public int spinCount
+        {
+            get
+            {
+                return this.spinCountField;
+            }
+            set
+            {
+                this.spinCountField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class spinResultObj
+    {
+        
+        private long luckySpinIdField;
+        
+        private int prizeIdField;
+        
+        private int prizeWinnerIdField;
+        
+        private int remainSpinField;
+        
+        private int totalCoinField;
+        
+        private int totalSpinField;
+        
+        private int usedSpinField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public long luckySpinId
+        {
+            get
+            {
+                return this.luckySpinIdField;
+            }
+            set
+            {
+                this.luckySpinIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public int prizeId
+        {
+            get
+            {
+                return this.prizeIdField;
+            }
+            set
+            {
+                this.prizeIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public int prizeWinnerId
+        {
+            get
+            {
+                return this.prizeWinnerIdField;
+            }
+            set
+            {
+                this.prizeWinnerIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public int remainSpin
+        {
+            get
+            {
+                return this.remainSpinField;
+            }
+            set
+            {
+                this.remainSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public int totalCoin
+        {
+            get
+            {
+                return this.totalCoinField;
+            }
+            set
+            {
+                this.totalCoinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public int totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public int usedSpin
+        {
+            get
+            {
+                return this.usedSpinField;
+            }
+            set
+            {
+                this.usedSpinField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class prizeWinner
+    {
+        
+        private string channelField;
+        
+        private string codeField;
+        
+        private string codeTimeField;
+        
+        private string expireTimeField;
+        
+        private int idField;
+        
+        private string msisdnField;
+        
+        private int pageField;
+        
+        private int periodField;
+        
+        private int pointWinField;
+        
+        private string prizeDescriptionField;
+        
+        private string prizeDescription1Field;
+        
+        private string prizeDescription2Field;
+        
+        private int prizeIdField;
+        
+        private string prizeNameField;
+        
+        private string prizeName1Field;
+        
+        private string prizeName2Field;
+        
+        private string processTimeField;
+        
+        private int topField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string channel
+        {
+            get
+            {
+                return this.channelField;
+            }
+            set
+            {
+                this.channelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string code
+        {
+            get
+            {
+                return this.codeField;
+            }
+            set
+            {
+                this.codeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string codeTime
+        {
+            get
+            {
+                return this.codeTimeField;
+            }
+            set
+            {
+                this.codeTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string expireTime
+        {
+            get
+            {
+                return this.expireTimeField;
+            }
+            set
+            {
+                this.expireTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public int id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public int page
+        {
+            get
+            {
+                return this.pageField;
+            }
+            set
+            {
+                this.pageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public int period
+        {
+            get
+            {
+                return this.periodField;
+            }
+            set
+            {
+                this.periodField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public int pointWin
+        {
+            get
+            {
+                return this.pointWinField;
+            }
+            set
+            {
+                this.pointWinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string prizeDescription
+        {
+            get
+            {
+                return this.prizeDescriptionField;
+            }
+            set
+            {
+                this.prizeDescriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string prizeDescription1
+        {
+            get
+            {
+                return this.prizeDescription1Field;
+            }
+            set
+            {
+                this.prizeDescription1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string prizeDescription2
+        {
+            get
+            {
+                return this.prizeDescription2Field;
+            }
+            set
+            {
+                this.prizeDescription2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public int prizeId
+        {
+            get
+            {
+                return this.prizeIdField;
+            }
+            set
+            {
+                this.prizeIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string prizeName
+        {
+            get
+            {
+                return this.prizeNameField;
+            }
+            set
+            {
+                this.prizeNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string prizeName1
+        {
+            get
+            {
+                return this.prizeName1Field;
+            }
+            set
+            {
+                this.prizeName1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string prizeName2
+        {
+            get
+            {
+                return this.prizeName2Field;
+            }
+            set
+            {
+                this.prizeName2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string processTime
+        {
+            get
+            {
+                return this.processTimeField;
+            }
+            set
+            {
+                this.processTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public int top
+        {
+            get
+            {
+                return this.topField;
+            }
+            set
+            {
+                this.topField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class prizeObj
+    {
+        
+        private string actionCodeField;
+        
+        private string actionTypeField;
+        
+        private string descriptionField;
+        
+        private string description1Field;
+        
+        private string description2Field;
+        
+        private long idField;
+        
+        private string imgPrizeField;
+        
+        private int isPadField;
+        
+        private int isTopField;
+        
+        private double moneyConvertedField;
+        
+        private int periodField;
+        
+        private string prefixMsisdnField;
+        
+        private string prizeNameField;
+        
+        private string prizeName1Field;
+        
+        private string prizeName2Field;
+        
+        private int statusField;
+        
+        private int subGroupPrizeField;
+        
+        private int valuePrizeField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string actionCode
+        {
+            get
+            {
+                return this.actionCodeField;
+            }
+            set
+            {
+                this.actionCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string actionType
+        {
+            get
+            {
+                return this.actionTypeField;
+            }
+            set
+            {
+                this.actionTypeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string description
+        {
+            get
+            {
+                return this.descriptionField;
+            }
+            set
+            {
+                this.descriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string description1
+        {
+            get
+            {
+                return this.description1Field;
+            }
+            set
+            {
+                this.description1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string description2
+        {
+            get
+            {
+                return this.description2Field;
+            }
+            set
+            {
+                this.description2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public long id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string imgPrize
+        {
+            get
+            {
+                return this.imgPrizeField;
+            }
+            set
+            {
+                this.imgPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public int isPad
+        {
+            get
+            {
+                return this.isPadField;
+            }
+            set
+            {
+                this.isPadField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public int isTop
+        {
+            get
+            {
+                return this.isTopField;
+            }
+            set
+            {
+                this.isTopField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public double moneyConverted
+        {
+            get
+            {
+                return this.moneyConvertedField;
+            }
+            set
+            {
+                this.moneyConvertedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public int period
+        {
+            get
+            {
+                return this.periodField;
+            }
+            set
+            {
+                this.periodField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string prefixMsisdn
+        {
+            get
+            {
+                return this.prefixMsisdnField;
+            }
+            set
+            {
+                this.prefixMsisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string prizeName
+        {
+            get
+            {
+                return this.prizeNameField;
+            }
+            set
+            {
+                this.prizeNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string prizeName1
+        {
+            get
+            {
+                return this.prizeName1Field;
+            }
+            set
+            {
+                this.prizeName1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string prizeName2
+        {
+            get
+            {
+                return this.prizeName2Field;
+            }
+            set
+            {
+                this.prizeName2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public int status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public int subGroupPrize
+        {
+            get
+            {
+                return this.subGroupPrizeField;
+            }
+            set
+            {
+                this.subGroupPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public int valuePrize
+        {
+            get
+            {
+                return this.valuePrizeField;
+            }
+            set
+            {
+                this.valuePrizeField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class game
+    {
+        
+        private string codeField;
+        
+        private string contentField;
+        
+        private string contentTypeField;
+        
+        private string createdDateField;
+        
+        private string descriptionField;
+        
+        private string descriptionGlobalField;
+        
+        private string descriptionLocalField;
+        
+        private string fromDateField;
+        
+        private string iconField;
+        
+        private string idField;
+        
+        private string introductionField;
+        
+        private string introductionGlobalField;
+        
+        private string introductionLocalField;
+        
+        private string isPlayedField;
+        
+        private string levelField;
+        
+        private string logoField;
+        
+        private string nameField;
+        
+        private string nameGlobalField;
+        
+        private string nameLocalField;
+        
+        private string noteField;
+        
+        private string parentIdField;
+        
+        private string serviceIdField;
+        
+        private string statusField;
+        
+        private string toDateField;
+        
+        private string typeOfField;
+        
+        private string updateDateField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string code
+        {
+            get
+            {
+                return this.codeField;
+            }
+            set
+            {
+                this.codeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string content
+        {
+            get
+            {
+                return this.contentField;
+            }
+            set
+            {
+                this.contentField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string contentType
+        {
+            get
+            {
+                return this.contentTypeField;
+            }
+            set
+            {
+                this.contentTypeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string createdDate
+        {
+            get
+            {
+                return this.createdDateField;
+            }
+            set
+            {
+                this.createdDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string description
+        {
+            get
+            {
+                return this.descriptionField;
+            }
+            set
+            {
+                this.descriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string descriptionGlobal
+        {
+            get
+            {
+                return this.descriptionGlobalField;
+            }
+            set
+            {
+                this.descriptionGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string descriptionLocal
+        {
+            get
+            {
+                return this.descriptionLocalField;
+            }
+            set
+            {
+                this.descriptionLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public string fromDate
+        {
+            get
+            {
+                return this.fromDateField;
+            }
+            set
+            {
+                this.fromDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public string icon
+        {
+            get
+            {
+                return this.iconField;
+            }
+            set
+            {
+                this.iconField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string introduction
+        {
+            get
+            {
+                return this.introductionField;
+            }
+            set
+            {
+                this.introductionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string introductionGlobal
+        {
+            get
+            {
+                return this.introductionGlobalField;
+            }
+            set
+            {
+                this.introductionGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string introductionLocal
+        {
+            get
+            {
+                return this.introductionLocalField;
+            }
+            set
+            {
+                this.introductionLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string isPlayed
+        {
+            get
+            {
+                return this.isPlayedField;
+            }
+            set
+            {
+                this.isPlayedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string level
+        {
+            get
+            {
+                return this.levelField;
+            }
+            set
+            {
+                this.levelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string logo
+        {
+            get
+            {
+                return this.logoField;
+            }
+            set
+            {
+                this.logoField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string name
+        {
+            get
+            {
+                return this.nameField;
+            }
+            set
+            {
+                this.nameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public string nameGlobal
+        {
+            get
+            {
+                return this.nameGlobalField;
+            }
+            set
+            {
+                this.nameGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string nameLocal
+        {
+            get
+            {
+                return this.nameLocalField;
+            }
+            set
+            {
+                this.nameLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public string note
+        {
+            get
+            {
+                return this.noteField;
+            }
+            set
+            {
+                this.noteField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public string parentId
+        {
+            get
+            {
+                return this.parentIdField;
+            }
+            set
+            {
+                this.parentIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=21)]
+        public string serviceId
+        {
+            get
+            {
+                return this.serviceIdField;
+            }
+            set
+            {
+                this.serviceIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=22)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=23)]
+        public string toDate
+        {
+            get
+            {
+                return this.toDateField;
+            }
+            set
+            {
+                this.toDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=24)]
+        public string typeOf
+        {
+            get
+            {
+                return this.typeOfField;
+            }
+            set
+            {
+                this.typeOfField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=25)]
+        public string updateDate
+        {
+            get
+            {
+                return this.updateDateField;
+            }
+            set
+            {
+                this.updateDateField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class configuration
+    {
+        
+        private string idField;
+        
+        private string para_keyField;
+        
+        private string para_valueField;
+        
+        private string service_idField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string para_key
+        {
+            get
+            {
+                return this.para_keyField;
+            }
+            set
+            {
+                this.para_keyField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string para_value
+        {
+            get
+            {
+                return this.para_valueField;
+            }
+            set
+            {
+                this.para_valueField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string service_id
+        {
+            get
+            {
+                return this.service_idField;
+            }
+            set
+            {
+                this.service_idField = value;
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubConfirm", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubConfirmRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string RequestId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Otp;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsRegisterSubConfirmRequest()
+        {
+        }
+        
+        public wsRegisterSubConfirmRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string RequestId, string Otp, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.RequestId = RequestId;
+            this.Otp = Otp;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubConfirmResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubConfirmResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsRegisterSubConfirmResponse()
+        {
+        }
+        
+        public wsRegisterSubConfirmResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDisableRegister", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDisableRegisterRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string packName;
+        
+        public wsDisableRegisterRequest()
+        {
+        }
+        
+        public wsDisableRegisterRequest(string WsUser, string WsPass, string msisdn, string packName)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.msisdn = msisdn;
+            this.packName = packName;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDisableRegisterResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDisableRegisterResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDisableRegisterResponse()
+        {
+        }
+        
+        public wsDisableRegisterResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetUserServices", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetUserServicesRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsGetUserServicesRequest()
+        {
+        }
+        
+        public wsGetUserServicesRequest(string WsUser, string WsPass, string Msisdn, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetUserServicesResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetUserServicesResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsGetUserServicesResponse()
+        {
+        }
+        
+        public wsGetUserServicesResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeConfirm", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeConfirmRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string RequestId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Otp;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsChargeFeeConfirmRequest()
+        {
+        }
+        
+        public wsChargeFeeConfirmRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string RequestId, string Otp, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.RequestId = RequestId;
+            this.Otp = Otp;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeConfirmResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeConfirmResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsChargeFeeConfirmResponse()
+        {
+        }
+        
+        public wsChargeFeeConfirmResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsLoadPrize", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsLoadPrizeRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        public wsLoadPrizeRequest()
+        {
+        }
+        
+        public wsLoadPrizeRequest(string WsUser, string WsPass)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsLoadPrizeResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsLoadPrizeResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsLoadPrizeResponse()
+        {
+        }
+        
+        public wsLoadPrizeResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetListWinner", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetListWinnerRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string period;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string page;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string pageSize;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string isTop;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string codeType;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string startDate;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=9)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string endDate;
+        
+        public wsGetListWinnerRequest()
+        {
+        }
+        
+        public wsGetListWinnerRequest(string WsUser, string WsPass, string msisdn, string period, string page, string pageSize, string isTop, string codeType, string startDate, string endDate)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.msisdn = msisdn;
+            this.period = period;
+            this.page = page;
+            this.pageSize = pageSize;
+            this.isTop = isTop;
+            this.codeType = codeType;
+            this.startDate = startDate;
+            this.endDate = endDate;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetListWinnerResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetListWinnerResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsGetListWinnerResponse()
+        {
+        }
+        
+        public wsGetListWinnerResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinT", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinTRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeID;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeWinnerID;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PartnerTransId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string TransId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Channel;
+        
+        public wsDoSpinTRequest()
+        {
+        }
+        
+        public wsDoSpinTRequest(string WsUser, string WsPass, string Msisdn, string PrizeID, string PrizeWinnerID, string PartnerTransId, string TransId, string Channel)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PrizeID = PrizeID;
+            this.PrizeWinnerID = PrizeWinnerID;
+            this.PartnerTransId = PartnerTransId;
+            this.TransId = TransId;
+            this.Channel = Channel;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinTResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinTResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDoSpinTResponse()
+        {
+        }
+        
+        public wsDoSpinTResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddData", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddDataRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string data;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsAddDataRequest()
+        {
+        }
+        
+        public wsAddDataRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string data, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.data = data;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddDataResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddDataResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddDataResponse()
+        {
+        }
+        
+        public wsAddDataResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpin", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Channel;
+        
+        public wsDoSpinRequest()
+        {
+        }
+        
+        public wsDoSpinRequest(string WsUser, string WsPass, string Msisdn, string Channel)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.Channel = Channel;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDoSpinResponse()
+        {
+        }
+        
+        public wsDoSpinResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="receiveresult", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class receiveresultRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string username;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string password;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string serviceid;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string chargetime;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @params;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string mode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string amount;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string transid;
+        
+        public receiveresultRequest()
+        {
+        }
+        
+        public receiveresultRequest(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            this.username = username;
+            this.password = password;
+            this.serviceid = serviceid;
+            this.msisdn = msisdn;
+            this.chargetime = chargetime;
+            this.@params = @params;
+            this.mode = mode;
+            this.amount = amount;
+            this.transid = transid;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="receiveresultResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class receiveresultResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public receiveresultResponse()
+        {
+        }
+        
+        public receiveresultResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubOtp", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubOtpRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsRegisterSubOtpRequest()
+        {
+        }
+        
+        public wsRegisterSubOtpRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubOtpResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubOtpResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsRegisterSubOtpResponse()
+        {
+        }
+        
+        public wsRegisterSubOtpResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddMoney", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddMoneyRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string top;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string type;
+        
+        public wsAddMoneyRequest()
+        {
+        }
+        
+        public wsAddMoneyRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId, string top, string type)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.ServiceId = ServiceId;
+            this.top = top;
+            this.type = type;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddMoneyResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddMoneyResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddMoneyResponse()
+        {
+        }
+        
+        public wsAddMoneyResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddEmola", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddEmolaRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeCode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeType;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string top;
+        
+        public wsAddEmolaRequest()
+        {
+        }
+        
+        public wsAddEmolaRequest(string WsUser, string WsPass, string Msisdn, string PrizeCode, string PrizeType, string ServiceId, string top)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PrizeCode = PrizeCode;
+            this.PrizeType = PrizeType;
+            this.ServiceId = ServiceId;
+            this.top = top;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddEmolaResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddEmolaResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddEmolaResponse()
+        {
+        }
+        
+        public wsAddEmolaResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeOtp", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeOtpRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsChargeFeeOtpRequest()
+        {
+        }
+        
+        public wsChargeFeeOtpRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeOtpResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeOtpResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsChargeFeeOtpResponse()
+        {
+        }
+        
+        public wsChargeFeeOtpResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="subRequest", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class subRequestRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string username;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string password;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string serviceid;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string chargetime;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @params;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string mode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string amount;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string transid;
+        
+        public subRequestRequest()
+        {
+        }
+        
+        public subRequestRequest(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            this.username = username;
+            this.password = password;
+            this.serviceid = serviceid;
+            this.msisdn = msisdn;
+            this.chargetime = chargetime;
+            this.@params = @params;
+            this.mode = mode;
+            this.amount = amount;
+            this.transid = transid;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="subRequestResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class subRequestResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public subRequestResponse()
+        {
+        }
+        
+        public subRequestResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="heartbeat", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class heartbeatRequest
+    {
+        
+        public heartbeatRequest()
+        {
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="heartbeatResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class heartbeatResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public heartbeatResponse()
+        {
+        }
+        
+        public heartbeatResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="pair", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class pairRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string arg0;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string arg1;
+        
+        public pairRequest()
+        {
+        }
+        
+        public pairRequest(string arg0, string arg1)
+        {
+            this.arg0 = arg0;
+            this.arg1 = arg1;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="pairResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class pairResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public bool @return;
+        
+        public pairResponse()
+        {
+        }
+        
+        public pairResponse(bool @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="getIpClient", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class getIpClientRequest
+    {
+        
+        public getIpClientRequest()
+        {
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="getIpClientResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class getIpClientResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public getIpClientResponse()
+        {
+        }
+        
+        public getIpClientResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    public interface SicboSubWsChannel : SicboSubWss.SicboSubWs, System.ServiceModel.IClientChannel
+    {
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    public partial class SicboSubWsClient : System.ServiceModel.ClientBase<SicboSubWss.SicboSubWs>, SicboSubWss.SicboSubWs
+    {
+        
+        /// <summary>
+        /// Implement this partial method to configure the service endpoint.
+        /// </summary>
+        /// <param name="serviceEndpoint">The endpoint to configure</param>
+        /// <param name="clientCredentials">The client credentials</param>
+        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
+        
+        public SicboSubWsClient() : 
+                base(SicboSubWsClient.GetDefaultBinding(), SicboSubWsClient.GetDefaultEndpointAddress())
+        {
+            this.Endpoint.Name = EndpointConfiguration.SicboSubWsPort.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), SicboSubWsClient.GetEndpointAddress(endpointConfiguration))
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration, string remoteAddress) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
+                base(binding, remoteAddress)
+        {
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> SicboSubWss.SicboSubWs.wsRegisterSubConfirmAsync(SicboSubWss.wsRegisterSubConfirmRequest request)
+        {
+            return base.Channel.wsRegisterSubConfirmAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> wsRegisterSubConfirmAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string RequestId, string Otp, string ServiceId)
+        {
+            SicboSubWss.wsRegisterSubConfirmRequest inValue = new SicboSubWss.wsRegisterSubConfirmRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.RequestId = RequestId;
+            inValue.Otp = Otp;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsRegisterSubConfirmAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> SicboSubWss.SicboSubWs.wsDisableRegisterAsync(SicboSubWss.wsDisableRegisterRequest request)
+        {
+            return base.Channel.wsDisableRegisterAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> wsDisableRegisterAsync(string WsUser, string WsPass, string msisdn, string packName)
+        {
+            SicboSubWss.wsDisableRegisterRequest inValue = new SicboSubWss.wsDisableRegisterRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.msisdn = msisdn;
+            inValue.packName = packName;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDisableRegisterAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> SicboSubWss.SicboSubWs.wsGetUserServicesAsync(SicboSubWss.wsGetUserServicesRequest request)
+        {
+            return base.Channel.wsGetUserServicesAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> wsGetUserServicesAsync(string WsUser, string WsPass, string Msisdn, string ServiceId)
+        {
+            SicboSubWss.wsGetUserServicesRequest inValue = new SicboSubWss.wsGetUserServicesRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsGetUserServicesAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> SicboSubWss.SicboSubWs.wsChargeFeeConfirmAsync(SicboSubWss.wsChargeFeeConfirmRequest request)
+        {
+            return base.Channel.wsChargeFeeConfirmAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> wsChargeFeeConfirmAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string RequestId, string Otp, string ServiceId)
+        {
+            SicboSubWss.wsChargeFeeConfirmRequest inValue = new SicboSubWss.wsChargeFeeConfirmRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.RequestId = RequestId;
+            inValue.Otp = Otp;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsChargeFeeConfirmAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> SicboSubWss.SicboSubWs.wsLoadPrizeAsync(SicboSubWss.wsLoadPrizeRequest request)
+        {
+            return base.Channel.wsLoadPrizeAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> wsLoadPrizeAsync(string WsUser, string WsPass)
+        {
+            SicboSubWss.wsLoadPrizeRequest inValue = new SicboSubWss.wsLoadPrizeRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            return ((SicboSubWss.SicboSubWs)(this)).wsLoadPrizeAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> SicboSubWss.SicboSubWs.wsGetListWinnerAsync(SicboSubWss.wsGetListWinnerRequest request)
+        {
+            return base.Channel.wsGetListWinnerAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> wsGetListWinnerAsync(string WsUser, string WsPass, string msisdn, string period, string page, string pageSize, string isTop, string codeType, string startDate, string endDate)
+        {
+            SicboSubWss.wsGetListWinnerRequest inValue = new SicboSubWss.wsGetListWinnerRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.msisdn = msisdn;
+            inValue.period = period;
+            inValue.page = page;
+            inValue.pageSize = pageSize;
+            inValue.isTop = isTop;
+            inValue.codeType = codeType;
+            inValue.startDate = startDate;
+            inValue.endDate = endDate;
+            return ((SicboSubWss.SicboSubWs)(this)).wsGetListWinnerAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> SicboSubWss.SicboSubWs.wsDoSpinTAsync(SicboSubWss.wsDoSpinTRequest request)
+        {
+            return base.Channel.wsDoSpinTAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> wsDoSpinTAsync(string WsUser, string WsPass, string Msisdn, string PrizeID, string PrizeWinnerID, string PartnerTransId, string TransId, string Channel)
+        {
+            SicboSubWss.wsDoSpinTRequest inValue = new SicboSubWss.wsDoSpinTRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PrizeID = PrizeID;
+            inValue.PrizeWinnerID = PrizeWinnerID;
+            inValue.PartnerTransId = PartnerTransId;
+            inValue.TransId = TransId;
+            inValue.Channel = Channel;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDoSpinTAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> SicboSubWss.SicboSubWs.wsAddDataAsync(SicboSubWss.wsAddDataRequest request)
+        {
+            return base.Channel.wsAddDataAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> wsAddDataAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string data, string ServiceId)
+        {
+            SicboSubWss.wsAddDataRequest inValue = new SicboSubWss.wsAddDataRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.data = data;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddDataAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> SicboSubWss.SicboSubWs.wsDoSpinAsync(SicboSubWss.wsDoSpinRequest request)
+        {
+            return base.Channel.wsDoSpinAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> wsDoSpinAsync(string WsUser, string WsPass, string Msisdn, string Channel)
+        {
+            SicboSubWss.wsDoSpinRequest inValue = new SicboSubWss.wsDoSpinRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.Channel = Channel;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDoSpinAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> SicboSubWss.SicboSubWs.receiveresultAsync(SicboSubWss.receiveresultRequest request)
+        {
+            return base.Channel.receiveresultAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> receiveresultAsync(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            SicboSubWss.receiveresultRequest inValue = new SicboSubWss.receiveresultRequest();
+            inValue.username = username;
+            inValue.password = password;
+            inValue.serviceid = serviceid;
+            inValue.msisdn = msisdn;
+            inValue.chargetime = chargetime;
+            inValue.@params = @params;
+            inValue.mode = mode;
+            inValue.amount = amount;
+            inValue.transid = transid;
+            return ((SicboSubWss.SicboSubWs)(this)).receiveresultAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> SicboSubWss.SicboSubWs.wsRegisterSubOtpAsync(SicboSubWss.wsRegisterSubOtpRequest request)
+        {
+            return base.Channel.wsRegisterSubOtpAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> wsRegisterSubOtpAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string ServiceId)
+        {
+            SicboSubWss.wsRegisterSubOtpRequest inValue = new SicboSubWss.wsRegisterSubOtpRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsRegisterSubOtpAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> SicboSubWss.SicboSubWs.wsAddMoneyAsync(SicboSubWss.wsAddMoneyRequest request)
+        {
+            return base.Channel.wsAddMoneyAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> wsAddMoneyAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId, string top, string type)
+        {
+            SicboSubWss.wsAddMoneyRequest inValue = new SicboSubWss.wsAddMoneyRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.ServiceId = ServiceId;
+            inValue.top = top;
+            inValue.type = type;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddMoneyAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> SicboSubWss.SicboSubWs.wsAddEmolaAsync(SicboSubWss.wsAddEmolaRequest request)
+        {
+            return base.Channel.wsAddEmolaAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> wsAddEmolaAsync(string WsUser, string WsPass, string Msisdn, string PrizeCode, string PrizeType, string ServiceId, string top)
+        {
+            SicboSubWss.wsAddEmolaRequest inValue = new SicboSubWss.wsAddEmolaRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PrizeCode = PrizeCode;
+            inValue.PrizeType = PrizeType;
+            inValue.ServiceId = ServiceId;
+            inValue.top = top;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddEmolaAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> SicboSubWss.SicboSubWs.wsChargeFeeOtpAsync(SicboSubWss.wsChargeFeeOtpRequest request)
+        {
+            return base.Channel.wsChargeFeeOtpAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> wsChargeFeeOtpAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId)
+        {
+            SicboSubWss.wsChargeFeeOtpRequest inValue = new SicboSubWss.wsChargeFeeOtpRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsChargeFeeOtpAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> SicboSubWss.SicboSubWs.subRequestAsync(SicboSubWss.subRequestRequest request)
+        {
+            return base.Channel.subRequestAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> subRequestAsync(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            SicboSubWss.subRequestRequest inValue = new SicboSubWss.subRequestRequest();
+            inValue.username = username;
+            inValue.password = password;
+            inValue.serviceid = serviceid;
+            inValue.msisdn = msisdn;
+            inValue.chargetime = chargetime;
+            inValue.@params = @params;
+            inValue.mode = mode;
+            inValue.amount = amount;
+            inValue.transid = transid;
+            return ((SicboSubWss.SicboSubWs)(this)).subRequestAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> SicboSubWss.SicboSubWs.heartbeatAsync(SicboSubWss.heartbeatRequest request)
+        {
+            return base.Channel.heartbeatAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> heartbeatAsync()
+        {
+            SicboSubWss.heartbeatRequest inValue = new SicboSubWss.heartbeatRequest();
+            return ((SicboSubWss.SicboSubWs)(this)).heartbeatAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.pairResponse> SicboSubWss.SicboSubWs.pairAsync(SicboSubWss.pairRequest request)
+        {
+            return base.Channel.pairAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.pairResponse> pairAsync(string arg0, string arg1)
+        {
+            SicboSubWss.pairRequest inValue = new SicboSubWss.pairRequest();
+            inValue.arg0 = arg0;
+            inValue.arg1 = arg1;
+            return ((SicboSubWss.SicboSubWs)(this)).pairAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> SicboSubWss.SicboSubWs.getIpClientAsync(SicboSubWss.getIpClientRequest request)
+        {
+            return base.Channel.getIpClientAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> getIpClientAsync()
+        {
+            SicboSubWss.getIpClientRequest inValue = new SicboSubWss.getIpClientRequest();
+            return ((SicboSubWss.SicboSubWs)(this)).getIpClientAsync(inValue);
+        }
+        
+        public virtual System.Threading.Tasks.Task OpenAsync()
+        {
+            return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
+        }
+        
+        #if !NET6_0_OR_GREATER
+        public virtual System.Threading.Tasks.Task CloseAsync()
+        {
+            return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
+        }
+        #endif
+        
+        private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
+        {
+            if ((endpointConfiguration == EndpointConfiguration.SicboSubWsPort))
+            {
+                System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
+                result.MaxBufferSize = int.MaxValue;
+                result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
+                result.MaxReceivedMessageSize = int.MaxValue;
+                result.AllowCookies = true;
+                return result;
+            }
+            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
+        }
+        
+        private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
+        {
+            if ((endpointConfiguration == EndpointConfiguration.SicboSubWsPort))
+            {
+                return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8199/SicboSubWs");
+            }
+            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
+        }
+        
+        private static System.ServiceModel.Channels.Binding GetDefaultBinding()
+        {
+            return SicboSubWsClient.GetBindingForEndpoint(EndpointConfiguration.SicboSubWsPort);
+        }
+        
+        private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
+        {
+            return SicboSubWsClient.GetEndpointAddress(EndpointConfiguration.SicboSubWsPort);
+        }
+        
+        public enum EndpointConfiguration
+        {
+            
+            SicboSubWsPort,
+        }
+    }
+}

+ 78 - 0
SicboSub/SicboSub.Api/Controllers/AuthController.cs

@@ -0,0 +1,78 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    /// <summary>
+    /// Controller cho Authentication APIs
+    /// Xử lý đăng nhập website qua URL token
+    /// 
+    /// Flow:
+    ///   1. User nhận link từ SMS/App: https://domain.com?token=abc123
+    ///   2. Frontend lấy token từ URL query parameter
+    ///   3. Frontend gọi POST /apis/auth/login với token
+    ///   4. API xác thực, trả về thông tin user
+    ///   5. Frontend lưu token và user info, cho phép truy cập
+    /// </summary>
+    [ApiController]
+    public class AuthController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(AuthController));
+
+        private readonly IAuthBusiness authBusiness;
+
+        public AuthController(IAuthBusiness authBusiness)
+        {
+            this.authBusiness = authBusiness;
+        }
+
+        /// <summary>
+        /// Đăng nhập bằng token từ URL
+        /// POST /apis/auth/login
+        /// 
+        /// Body: { "token": "abc123xyz..." }
+        /// 
+        /// Response success:
+        /// {
+        ///   "errorCode": "0",
+        ///   "data": {
+        ///     "id": 1,
+        ///     "msisdn": "509xxxxxxxx",
+        ///     "username": "user1",
+        ///     "winCoin": 1000,
+        ///     ...
+        ///   }
+        /// }
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.AuthLoginUrl)]
+        public async Task<IActionResult> LoginByToken([FromBody] TokenLoginReq request)
+        {
+            return await authBusiness.LoginByToken(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Lấy MSISDN từ token (API nhẹ)
+        /// POST /apis/auth/get-msisdn
+        /// 
+        /// Body: { "token": "abc123xyz..." }
+        /// 
+        /// Response:
+        /// {
+        ///   "errorCode": "0",
+        ///   "data": {
+        ///     "msisdn": "509xxxxxxxx",
+        ///     "isValid": true
+        ///   }
+        /// }
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.AuthGetMsisdnUrl)]
+        public async Task<IActionResult> GetMsisdnFromToken([FromBody] GetMsisdnFromTokenReq request)
+        {
+            return await authBusiness.GetMsisdnFromToken(HttpContext.Request, request);
+        }
+    }
+}

+ 56 - 0
SicboSub/SicboSub.Api/Controllers/ExchangeController.cs

@@ -0,0 +1,56 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    /// <summary>
+    /// Controller cho Exchange APIs (Rút thưởng với xác thực OTP)
+    /// </summary>
+    [ApiController]
+    public class ExchangeController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ExchangeController));
+
+        private readonly IExchangeBusiness exchangeBusiness;
+
+        public ExchangeController(IExchangeBusiness exchangeBusiness)
+        {
+            this.exchangeBusiness = exchangeBusiness;
+        }
+
+        /// <summary>
+        /// Yêu cầu OTP để thực hiện rút thưởng
+        /// POST /apis/exchange/request-otp
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ExchangeRequestOtpUrl)]
+        public async Task<IActionResult> RequestOtp([FromBody] ExchangeRequestOtpReq request)
+        {
+            return await exchangeBusiness.RequestOtp(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Xác thực OTP và thực hiện rút thưởng
+        /// POST /apis/exchange/verify-otp
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ExchangeVerifyOtpUrl)]
+        public async Task<IActionResult> VerifyOtp([FromBody] ExchangeVerifyOtpReq request)
+        {
+            return await exchangeBusiness.VerifyOtp(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Gửi lại OTP
+        /// POST /apis/exchange/resend-otp
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ExchangeResendOtpUrl)]
+        public async Task<IActionResult> ResendOtp([FromBody] ExchangeResendOtpReq request)
+        {
+            return await exchangeBusiness.ResendOtp(HttpContext.Request, request);
+        }
+    }
+}

+ 48 - 0
SicboSub/SicboSub.Api/Controllers/GameController.cs

@@ -0,0 +1,48 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    [ApiController]
+    public class GameController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(GameController));
+
+        IGameBusiness gameBusiness;
+
+        public GameController(IGameBusiness gameBusiness)
+        {
+            this.gameBusiness = gameBusiness;
+        }
+
+        /// <summary>
+        /// Get play history (betting + winning)
+        /// POST /apis/game/play_history
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.PlayHistoryUrl)]
+        public async Task<IActionResult> PlayHistory([FromBody] PlayHistoryReq request)
+        {
+            return await gameBusiness.PlayHistory(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Get ranking prize history (daily/monthly)
+        /// POST /apis/game/ranking_history
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.RankingHistoryUrl)]
+        public async Task<IActionResult> RankingHistory([FromBody] RankingHistoryReq request)
+        {
+            return await gameBusiness.RankingHistory(HttpContext.Request, request);
+        }
+        [HttpPost]
+        [Route(ApiUrlConstant.PurchaseHistoryUrl)]
+        public async Task<IActionResult> PurchaseHistory([FromBody] PurchaseHistoryReq request)
+        {
+            return await gameBusiness.PurchaseHistory(HttpContext.Request, request);
+        }
+    }
+}

+ 44 - 0
SicboSub/SicboSub.Api/Controllers/PackageController.cs

@@ -0,0 +1,44 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    [ApiController]
+    public class PackageController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
+            typeof(PackageController)
+        );
+
+        IPackageBusiness packageBusiness;
+
+        public PackageController(IPackageBusiness packageBusiness)
+        {
+            this.packageBusiness = packageBusiness;
+        }
+
+        /// <summary>
+        /// Load coin packages for purchase
+        /// POST /apis/package/load
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.PackageLoadUrl)]
+        public async Task<IActionResult> PackageLoad([FromBody] PackageLoadReq request)
+        {
+            return await packageBusiness.PackageLoad(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Load exchange/withdraw configurations
+        /// POST /apis/package/exchange
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.ExchangeConfigLoadUrl)]
+        public async Task<IActionResult> ExchangeConfigLoad([FromBody] ExchangeConfigLoadReq request)
+        {
+            return await packageBusiness.ExchangeConfigLoad(HttpContext.Request, request);
+        }
+    }
+}

+ 44 - 0
SicboSub/SicboSub.Api/Controllers/SubscriptionController.cs

@@ -0,0 +1,44 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    [ApiController]
+    public class SubscriptionController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
+            typeof(SubscriptionController)
+        );
+
+        ISubscriptionBusiness subscriptionBusiness;
+
+        public SubscriptionController(ISubscriptionBusiness subscriptionBusiness)
+        {
+            this.subscriptionBusiness = subscriptionBusiness;
+        }
+
+        /// <summary>
+        /// Register package
+        /// POST /apis/package/register
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.RegisterUrl)]
+        public async Task<IActionResult> Register([FromBody] RegisterReq request)
+        {
+            return await subscriptionBusiness.Register(HttpContext.Request, request);
+        }
+
+        /// <summary>
+        /// Buy more package
+        /// POST /apis/package/buymore
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.BuyMoreUrl)]
+        public async Task<IActionResult> BuyMore([FromBody] BuyMoreReq request)
+        {
+            return await subscriptionBusiness.BuyMore(HttpContext.Request, request);
+        }
+    }
+}

+ 31 - 0
SicboSub/SicboSub.Api/Controllers/UserController.cs

@@ -0,0 +1,31 @@
+using Common.Constant;
+using Microsoft.AspNetCore.Mvc;
+using SicboSub.Api.Business;
+using SicboSub.Api.DTO;
+
+namespace SicboSub.Api.Controllers
+{
+    [ApiController]
+    public class UserController : Controller
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(UserController));
+
+        IUserBusiness userBusiness;
+
+        public UserController(IUserBusiness userBusiness)
+        {
+            this.userBusiness = userBusiness;
+        }
+
+        /// <summary>
+        /// Get account information by msisdn
+        /// POST /apis/user/info
+        /// </summary>
+        [HttpPost]
+        [Route(ApiUrlConstant.UserInfoUrl)]
+        public async Task<IActionResult> GetAccountInfo([FromBody] AccountInfoReq request)
+        {
+            return await userBusiness.GetAccountInfo(HttpContext.Request, request);
+        }
+    }
+}

+ 71 - 0
SicboSub/SicboSub.Api/DTO/AuthDto.cs

@@ -0,0 +1,71 @@
+namespace SicboSub.Api.DTO
+{
+    #region Auth Request/Response DTOs
+
+    /// <summary>
+    /// Request đăng nhập bằng token từ URL
+    /// </summary>
+    public class TokenLoginReq
+    {
+        /// <summary>
+        /// Token từ URL query parameter
+        /// </summary>
+        public string token { get; set; } = null!;
+        
+        /// <summary>
+        /// Ngôn ngữ (optional)
+        /// </summary>
+        public string? lang { get; set; }
+    }
+
+    /// <summary>
+    /// Response sau khi đăng nhập thành công
+    /// </summary>
+    public class TokenLoginRes
+    {
+        public decimal id { get; set; }
+        public string msisdn { get; set; } = null!;
+        public string? username { get; set; }
+        public string? fullname { get; set; }
+        public string? picture { get; set; }
+        public decimal winCoin { get; set; }
+        public decimal betCoin { get; set; }
+        public int? point { get; set; }
+        public int? freeSpin { get; set; }
+        public byte? status { get; set; }
+        public DateTime? lastLogin { get; set; }
+        public bool isRegistered { get; set; }
+        public RegInfoDto? regPkg { get; set; }
+    }
+
+    public class RegInfoDto
+    {
+        public decimal RegisterId { get; set; }
+        public string? Msisdn { get; set; }
+        public string? ProductName { get; set; }
+        public DateTime? RegisterTime { get; set; }
+        public short? NumberSpin { get; set; }
+        public byte Status { get; set; }
+        public DateTime? ExpireTime { get; set; }
+        public byte? Renew { get; set; }
+    }
+
+    /// <summary>
+    /// Request lấy thông tin thuê bao từ token
+    /// </summary>
+    public class GetMsisdnFromTokenReq
+    {
+        public string token { get; set; } = null!;
+    }
+
+    /// <summary>
+    /// Response thông tin thuê bao
+    /// </summary>
+    public class GetMsisdnFromTokenRes
+    {
+        public string msisdn { get; set; } = null!;
+        public bool isValid { get; set; }
+    }
+
+    #endregion
+}

+ 96 - 0
SicboSub/SicboSub.Api/DTO/ExchangeDto.cs

@@ -0,0 +1,96 @@
+namespace SicboSub.Api.DTO
+{
+    #region Request DTOs
+
+    /// <summary>
+    /// Request yêu cầu OTP cho Exchange
+    /// </summary>
+    public class ExchangeRequestOtpReq
+    {
+        public string msisdn { get; set; } = null!;
+        public decimal configId { get; set; }
+        public string? lang { get; set; }
+    }
+
+    /// <summary>
+    /// Request xác thực OTP
+    /// </summary>
+    public class ExchangeVerifyOtpReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string otpCode { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+
+    /// <summary>
+    /// Request gửi lại OTP
+    /// </summary>
+    public class ExchangeResendOtpReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+
+    #endregion
+
+    #region Response DTOs
+
+    /// <summary>
+    /// Response sau khi request OTP thành công
+    /// </summary>
+    public class ExchangeRequestOtpRes
+    {
+        public decimal otpId { get; set; }
+        public int expiresInSeconds { get; set; }
+        public decimal coinAmount { get; set; }
+        public decimal moneyAmount { get; set; }
+    }
+
+    /// <summary>
+    /// Response sau khi verify OTP thành công
+    /// </summary>
+    public class ExchangeVerifyOtpRes
+    {
+        public decimal exchangeId { get; set; }
+        public decimal coinDeducted { get; set; }
+        public decimal moneyAdded { get; set; }
+        public decimal newBalance { get; set; }
+    }
+
+    /// <summary>
+    /// Response khi OTP verify thất bại
+    /// </summary>
+    public class ExchangeVerifyOtpErrorRes
+    {
+        public int attemptsRemaining { get; set; }
+    }
+
+    /// <summary>
+    /// Response thông tin chi tiết gói Exchange
+    /// </summary>
+    public class ExchangeConfigRes
+    {
+        public decimal id { get; set; }
+        public string productName { get; set; } = null!;
+        public decimal coinCost { get; set; }
+        public decimal moneyReceived { get; set; }
+        public decimal feeCoin { get; set; }
+        public string? description { get; set; }
+    }
+
+    /// <summary>
+    /// Response lịch sử Exchange
+    /// </summary>
+    public class ExchangeHistoryRes
+    {
+        public decimal id { get; set; }
+        public string msisdn { get; set; } = null!;
+        public decimal coinDeducted { get; set; }
+        public decimal moneyAdded { get; set; }
+        public DateTime exchangeTime { get; set; }
+        public byte status { get; set; }
+        public string? statusName { get; set; }
+    }
+
+    #endregion
+}

+ 121 - 0
SicboSub/SicboSub.Api/DTO/GameDto.cs

@@ -0,0 +1,121 @@
+namespace SicboSub.Api.DTO
+{
+    /// <summary>
+    /// Request model for loading play history
+    /// </summary>
+    public class PlayHistoryReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+        // Token passed in header
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    /// <summary>
+    /// Response model for play history item
+    /// </summary>
+    public class PlayHistoryItem
+    {
+        // From BettingHistory
+        public decimal id { get; set; }
+        public decimal roomId { get; set; }
+        public decimal bettingType { get; set; }
+        public decimal bettingValue { get; set; }
+        public DateTime bettingTime { get; set; }
+
+        // From RoomPrize
+        public decimal winCoin { get; set; }
+        public decimal backCoin { get; set; }
+        
+        // Calculated
+        public bool isWin { get; set; }
+    }
+
+    /// <summary>
+    /// Request model for loading ranking prize history
+    /// </summary>
+    public class RankingHistoryReq
+    {
+        public string? msisdn { get; set; }
+        public string? lang { get; set; }
+        // Token passed in header
+        
+        /// <summary>
+        /// Optional: DAILY or MONTHLY. If null, return both.
+        /// </summary>
+        public string? rankType { get; set; } 
+        
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    /// <summary>
+    /// Response model for ranking prize history
+    /// </summary>
+    public class RankingHistoryItem
+    {
+        public decimal id { get; set; }
+        public string msisdn { get; set; } // Added field
+        public string rankType { get; set; } = null!; // DAILY, MONTHLY
+        public DateTime rankDate { get; set; }
+        public decimal rankPosition { get; set; }
+        public decimal rewardValue { get; set; }
+        public string rewardUnit { get; set; } = null!;
+        public DateTime rewardDate { get; set; }
+        public decimal totalBetValue { get; set; }
+    }
+
+    /// <summary>
+    /// Request model for loading purchase history
+    /// </summary>
+    public class PurchaseHistoryReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    /// <summary>
+    /// Response model for purchase history item (from REGINFO)
+    /// </summary>
+    public class PurchaseHistoryItem
+    {
+        public decimal id { get; set; }
+        public string productName { get; set; } = null!;
+        public DateTime registerTime { get; set; }
+        public DateTime expireTime { get; set; }
+        public decimal serviceId { get; set; } // Fee
+        public string channel { get; set; } = null!;
+        public byte status { get; set; }
+        public int renew { get; set; }
+    }
+
+    /// <summary>
+    /// Request model for loading exchange configuration
+    /// </summary>
+    public class ExchangeConfigReq
+    {
+        public string? lang { get; set; }
+    }
+
+    /// <summary>
+    /// Response model for exchange configuration item
+    /// </summary>
+    public class ExchangeConfigItem
+    {
+        public decimal id { get; set; }
+        public string productName { get; set; } = null!; // PRODUCT_NAME
+        public decimal? coinCost { get; set; } // COIN_COST
+        public decimal? moneyReceived { get; set; } // MONEY_RECEIVED
+        public decimal? feeCoin { get; set; } // FEE_COIN
+        public string description { get; set; } = null!; // DESCRIPTION
+    }
+}

+ 64 - 0
SicboSub/SicboSub.Api/DTO/PackageDto.cs

@@ -0,0 +1,64 @@
+namespace SicboSub.Api.DTO
+{
+    /// <summary>
+    /// Request model for loading coin packages
+    /// </summary>
+    public class PackageLoadReq
+    {
+        /// <summary>
+        /// Language code (en, vi, lo)
+        /// </summary>
+        public string? lang { get; set; }
+
+        /// <summary>
+        /// Page number for pagination (0-based)
+        /// </summary>
+        public int pageNumber { get; set; } = 0;
+
+        /// <summary>
+        /// Number of items per page
+        /// </summary>
+        public int pageSize { get; set; } = 20;
+    }
+
+    /// <summary>
+    /// Request model for loading exchange configurations
+    /// </summary>
+    public class ExchangeConfigLoadReq
+    {
+        /// <summary>
+        /// Language code (en, vi, lo)
+        /// </summary>
+        public string? lang { get; set; }
+
+        /// <summary>
+        /// Page number for pagination (0-based)
+        /// </summary>
+        public int pageNumber { get; set; } = 0;
+
+        /// <summary>
+        /// Number of items per page
+        /// </summary>
+        public int pageSize { get; set; } = 20;
+    }
+
+    /// <summary>
+    /// Request model for registration
+    /// </summary>
+    public class RegisterReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string packageCode { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+
+    /// <summary>
+    /// Request model for buying more coins/packages
+    /// </summary>
+    public class BuyMoreReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string packageCode { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+}

+ 30 - 0
SicboSub/SicboSub.Api/DTO/UserDto.cs

@@ -0,0 +1,30 @@
+namespace SicboSub.Api.DTO
+{
+    public class AccountInfoReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+
+    public class AccountInfoRes
+    {
+        public decimal id { get; set; }
+        public string msisdn { get; set; } = null!;
+        public string? username { get; set; }
+        public string? fullname { get; set; }
+        public string? picture { get; set; }
+        public string? email { get; set; }
+        public string? address { get; set; }
+        public decimal? gender { get; set; }
+        public DateTime? birthday { get; set; }
+        public decimal winCoin { get; set; }
+        public decimal betCoin { get; set; }
+        public int? point { get; set; }
+        public int? freeSpin { get; set; }
+        public int? totalSpin { get; set; }
+        public byte? status { get; set; }
+        public byte? isActive { get; set; }
+        public DateTime createdDate { get; set; }
+        public DateTime? lastLogin { get; set; }
+    }
+}

+ 74 - 7
SicboSub/SicboSub.Api/Program.cs

@@ -1,23 +1,90 @@
+using System.Text.Json;
+using Common.Global;
+using Database.Database;
+using log4net;
+using log4net.Config;
+using Microsoft.EntityFrameworkCore;
+using SicboSub.Api.Business;
+using SicboSub.Api.Singleton;
+
 var builder = WebApplication.CreateBuilder(args);
 
+// Initialize log4net
+XmlConfigurator.Configure(new FileInfo(Path.Combine(builder.Environment.ContentRootPath, "log4net.config")));
+
+// Set global configuration for use by singletons like ConfigManager
+GlobalConfig.Configuration = builder.Configuration;
+
 // Add services to the container.
+builder.Services.AddControllersWithViews()
+    .AddJsonOptions(options =>
+    {
+        // Use camelCase for JSON property names
+        options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
+    });
+
+// Add DbContext with Oracle provider
+var connectionString = builder.Configuration.GetSection("Connection").Value;
+builder.Services.AddDbContext<ModelContext>(options =>
+    options.UseOracle(connectionString));
+
+// Add Business Services
+builder.Services.AddScoped<IPackageBusiness, PackageBusinessImpl>();
+builder.Services.AddScoped<ISubscriptionBusiness, SubscriptionBusinessImpl>();
+builder.Services.AddScoped<IGameBusiness, GameBusinessImpl>();
+builder.Services.AddScoped<IUserBusiness, UserBusinessImpl>();
+builder.Services.AddScoped<IExchangeBusiness, ExchangeBusinessImpl>();
+
+// Add Auth Services
+builder.Services.AddScoped<IAuthService, AuthServiceImpl>();
+builder.Services.AddScoped<IAuthBusiness, AuthBusinessImpl>();
+
+// Configure CORS
+builder.Services.AddCors(options =>
+{
+    options.AddPolicy("AllowAll", policy =>
+    {
+        policy.AllowAnyOrigin()
+            .AllowAnyMethod()
+            .AllowAnyHeader();
+    });
+});
 
-builder.Services.AddControllers();
-// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
 builder.Services.AddEndpointsApiExplorer();
 builder.Services.AddSwaggerGen();
 
 var app = builder.Build();
 
-// Configure the HTTP request pipeline.
-if (app.Environment.IsDevelopment())
+// Initialize ConfigManager to load configs from database
+using (var scope = app.Services.CreateScope())
 {
-    app.UseSwagger();
-    app.UseSwaggerUI();
+    var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
+    try
+    {
+        logger.LogInformation("Initializing ConfigManager...");
+        ConfigManager.Instance.Initialize();
+        logger.LogInformation("ConfigManager initialized successfully");
+        
+        // Start background refresh task
+        Task.Run(() => ConfigManager.Instance.RefreshConfigs());
+    }
+    catch (Exception ex)
+    {
+        logger.LogError(ex, "Failed to initialize ConfigManager");
+    }
 }
 
-app.UseHttpsRedirection();
+// Configure the HTTP request pipeline.
+app.UseSwagger();
+app.UseSwaggerUI();
+
+if (!app.Environment.IsDevelopment())
+{
+    app.UseHttpsRedirection();
+}
 
+app.UseRouting();
+app.UseCors("AllowAll");
 app.UseAuthorization();
 
 app.MapControllers();

+ 20 - 0
SicboSub/SicboSub.Api/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
+<Project>
+  <PropertyGroup>
+    <DeleteExistingFiles>true</DeleteExistingFiles>
+    <ExcludeApp_Data>false</ExcludeApp_Data>
+    <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
+    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
+    <LastUsedPlatform>Any CPU</LastUsedPlatform>
+    <PublishProvider>FileSystem</PublishProvider>
+    <PublishUrl>D:\Code\Ex_publish\Natcom_SicboSub\apis</PublishUrl>
+    <WebPublishMethod>FileSystem</WebPublishMethod>
+    <_TargetId>Folder</_TargetId>
+    <SiteUrlToLaunchAfterPublish />
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <ProjectGuid>cbf3997b-fd6f-4b3a-bf85-ab39fe7a18aa</ProjectGuid>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 29 - 5
SicboSub/SicboSub.Api/SicboSub.Api.csproj

@@ -1,17 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk.Web">
-
   <PropertyGroup>
     <TargetFramework>net8.0</TargetFramework>
     <Nullable>enable</Nullable>
     <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
-
   <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.15" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
   </ItemGroup>
-
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.7" />
+    <PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.1" />
+    <PackageReference Include="System.ServiceModel.Security" Version="6.0.0" />
+    <PackageReference Include="System.ServiceModel.Duplex" Version="6.0.0" />
+    <PackageReference Include="System.ServiceModel.NetTcp" Version="6.0.0" />
+    <PackageReference Include="System.ServiceModel.Http" Version="6.0.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+    <PackageReference Include="Dapper" Version="2.0.143" />
+    <PackageReference Include="Nancy" Version="2.0.0" />
+    <PackageReference Include="NCrontab" Version="3.3.3" />
+  </ItemGroup>
   <ItemGroup>
     <Folder Include="Controllers\" />
   </ItemGroup>
-
-</Project>
+  <ItemGroup>
+    <ProjectReference Include="..\Common\Common.csproj" />
+    <ProjectReference Include="..\Database\Database.csproj" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="DotnetLib">
+      <HintPath>..\lib\DotnetLib.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="System.ServiceModel.Primitives" Version="8.*" />
+  </ItemGroup>
+</Project>

+ 115 - 0
SicboSub/SicboSub.Api/Singleton/ConfigManager.cs

@@ -0,0 +1,115 @@
+using Common.Global;
+using Database.Database;
+
+namespace SicboSub.Api.Singleton
+{
+    public class ConfigManager
+    {
+
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ConfigManager));
+
+        private ModelContext dbContext;
+        private List<ConfigMessage> appConfigs = new List<ConfigMessage>();
+        private List<Config> systemConfigs = new List<Config>();
+
+        private ConfigManager()
+        {
+            dbContext = new DbHelper().GetDbContext(GlobalConfig.Configuration!);
+            log.Debug("ConfigManager initialized");
+        }
+
+        private static readonly object lockObj = new object();
+
+        private static ConfigManager? instance;
+        public static ConfigManager Instance => instance ??= new ConfigManager();
+
+        public void Initialize()
+        {
+            appConfigs = dbContext.ConfigMessages.ToList();
+            systemConfigs = dbContext.Configs.ToList();
+            log.Debug($"ConfigManager initialized with {appConfigs.Count} messages and {systemConfigs.Count} configs");
+        }
+
+        /// <summary>
+        /// Get system config value (from CONFIGS table)
+        /// </summary>
+        public string GetConfig(string paramName)
+        {
+             var config = systemConfigs.FirstOrDefault(c => c.ParamName == paramName);
+             if (config != null)
+             {
+                 return config.ParamValue ?? "";
+             }
+             return "";
+        }
+
+        public string GetConfigWebValue(string configName, string lang = "lo")
+        {
+            var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "WEB");
+            if (config != null)
+            {
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
+            }
+            log.Warn($"Config not found: {configName}");
+            return string.Empty;
+        }
+
+        public string GetConfigSmsValue(string configName, string lang = "lo")
+        {
+            var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "SMS");
+            if (config != null)
+            {
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
+            }
+            log.Warn($"Config not found: {configName}");
+            return string.Empty;
+        }
+
+        public string GetConfigAppValue(string configName, string lang = "lo")
+        {
+            var config = appConfigs.FirstOrDefault(c => c.Name == configName && c.Type == "APP");
+            if (config != null)
+            {
+                log.Debug($"Config found: {configName} = {config.ValueLocal}");
+                return GetValueByLang(config, lang);
+            }
+            log.Warn($"Config not found: {configName}");
+            return string.Empty;
+        }
+
+        /// <summary>
+        /// Get config value by language: vi=Vietnamese, en=English, lo=Lao (default)
+        /// </summary>
+        private string GetValueByLang(ConfigMessage config, string lang)
+        {
+            return lang switch
+            {
+                "vi" => config.Value ?? config.ValueLocal ?? "",
+                "en" => config.ValueGlobal ?? config.ValueLocal ?? "",
+                _ => config.ValueLocal ?? ""  // Default: Lao
+            };
+        }
+
+        // loop 5p to refresh
+        public void RefreshConfigs()
+        {
+            while (true)
+            {
+                try
+                {
+                    log.Debug($"ConfigManager refreshing...");
+                    appConfigs = dbContext.ConfigMessages.ToList();
+                    systemConfigs = dbContext.Configs.ToList();
+                    log.Debug("ConfigManager refreshed");
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Error refreshing configs", ex);
+                }
+                Thread.Sleep(5 * 60 * 1000); // 5 minutes
+            }
+        }
+    }
+}

+ 4 - 1
SicboSub/SicboSub.Api/appsettings.json

@@ -1,9 +1,12 @@
 {
   "Connection": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1539))(CONNECT_DATA=(SERVICE_NAME=ORA12C)));User Id=sicbo;Password=qwK99QfuhEmcFE;Connection Timeout=120;",
+  "wsUrl": "http://127.0.0.1:8199/SicboSubWs?wsdl",
+  "wsUser": "sicboSub",
+  "wsPass": "123456a@",
   "Kestrel": {
     "EndPoints": {
       "Http": {
-        "Url": "http://0.0.0.0:9106"
+        "Url": "http://127.0.0.1:9106"
       }
       //"Https": {
       //  "Url": "https://0.0.0.0:9107",

+ 25 - 0
SicboSub/SicboSub.Api/log4net.config

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<log4net>
+  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
+    <file value="logs/sicbo-api.log" />
+    <appendToFile value="true" />
+    <rollingStyle value="Date" />
+    <datePattern value="yyyyMMdd" />
+    <staticLogFileName value="true" />
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+
+  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+
+  <root>
+    <level value="DEBUG" />
+    <appender-ref ref="RollingFileAppender" />
+    <appender-ref ref="ConsoleAppender" />
+  </root>
+</log4net>

+ 16 - 0
SicboSub/SicboSub.StartProcedure/Connected Services/SicboSubWss/ConnectedService.json

@@ -0,0 +1,16 @@
+{
+  "ExtendedData": {
+    "inputs": [
+      "http://127.0.0.1:8199/SicboSubWs?wsdl"
+    ],
+    "collectionTypes": [
+      "System.Array",
+      "System.Collections.Generic.Dictionary`2"
+    ],
+    "namespaceMappings": [
+      "*, SicboSubWss"
+    ],
+    "targetFramework": "net8.0",
+    "typeReuseMode": "All"
+  }
+}

+ 3725 - 0
SicboSub/SicboSub.StartProcedure/Connected Services/SicboSubWss/Reference.cs

@@ -0,0 +1,3725 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SicboSubWss
+{
+    
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ServiceModel.ServiceContractAttribute(Namespace="http://webservices.vas.com/", ConfigurationName="SicboSubWss.SicboSubWs")]
+    public interface SicboSubWs
+    {
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> receiveresultAsync(SicboSubWss.receiveresultRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> wsRegisterSubOtpAsync(SicboSubWss.wsRegisterSubOtpRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> subRequestAsync(SicboSubWss.subRequestRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> heartbeatAsync(SicboSubWss.heartbeatRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> wsGetListWinnerAsync(SicboSubWss.wsGetListWinnerRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> wsAddMoneyAsync(SicboSubWss.wsAddMoneyRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> wsDoSpinTAsync(SicboSubWss.wsDoSpinTRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> wsChargeFeeOtpAsync(SicboSubWss.wsChargeFeeOtpRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> wsDoSpinAsync(SicboSubWss.wsDoSpinRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> wsAddDataAsync(SicboSubWss.wsAddDataRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> wsLoadPrizeAsync(SicboSubWss.wsLoadPrizeRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> wsAddEmolaAsync(SicboSubWss.wsAddEmolaRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> wsDisableRegisterAsync(SicboSubWss.wsDisableRegisterRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> wsRegisterSubConfirmAsync(SicboSubWss.wsRegisterSubConfirmRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> wsChargeFeeConfirmAsync(SicboSubWss.wsChargeFeeConfirmRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> wsGetUserServicesAsync(SicboSubWss.wsGetUserServicesRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.pairResponse> pairAsync(SicboSubWss.pairRequest request);
+        
+        [System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]
+        [System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
+        System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> getIpClientAsync(SicboSubWss.getIpClientRequest request);
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="receiveresult", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class receiveresultRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string username;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string password;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string serviceid;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string chargetime;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @params;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string mode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string amount;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string transid;
+        
+        public receiveresultRequest()
+        {
+        }
+        
+        public receiveresultRequest(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            this.username = username;
+            this.password = password;
+            this.serviceid = serviceid;
+            this.msisdn = msisdn;
+            this.chargetime = chargetime;
+            this.@params = @params;
+            this.mode = mode;
+            this.amount = amount;
+            this.transid = transid;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="receiveresultResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class receiveresultResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public receiveresultResponse()
+        {
+        }
+        
+        public receiveresultResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class response
+    {
+        
+        private string contentField;
+        
+        private string errorCodeField;
+        
+        private accountInfo[] listAccountsField;
+        
+        private configuration[] listConfigurationsField;
+        
+        private game[] listGamesField;
+        
+        private string[] listPackgField;
+        
+        private prizeObj[] listPrizeField;
+        
+        private string[] listServicesField;
+        
+        private prizeWinner[] listWinnerField;
+        
+        private int moneyDeductedField;
+        
+        private string msisdnField;
+        
+        private string positionField;
+        
+        private int remainSpinField;
+        
+        private string resultCodeField;
+        
+        private spinResultObj spinResultField;
+        
+        private string statusField;
+        
+        private accountInfo[] topPlayedTimeField;
+        
+        private accountInfo[] topWonMiniGameField;
+        
+        private string totalPageField;
+        
+        private int totalSpinField;
+        
+        private int totalSpinAddField;
+        
+        private topPlayer[] userRankField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string content
+        {
+            get
+            {
+                return this.contentField;
+            }
+            set
+            {
+                this.contentField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string errorCode
+        {
+            get
+            {
+                return this.errorCodeField;
+            }
+            set
+            {
+                this.errorCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listAccounts", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=2)]
+        public accountInfo[] listAccounts
+        {
+            get
+            {
+                return this.listAccountsField;
+            }
+            set
+            {
+                this.listAccountsField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listConfigurations", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=3)]
+        public configuration[] listConfigurations
+        {
+            get
+            {
+                return this.listConfigurationsField;
+            }
+            set
+            {
+                this.listConfigurationsField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listGames", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=4)]
+        public game[] listGames
+        {
+            get
+            {
+                return this.listGamesField;
+            }
+            set
+            {
+                this.listGamesField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listPackg", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=5)]
+        public string[] listPackg
+        {
+            get
+            {
+                return this.listPackgField;
+            }
+            set
+            {
+                this.listPackgField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listPrize", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=6)]
+        public prizeObj[] listPrize
+        {
+            get
+            {
+                return this.listPrizeField;
+            }
+            set
+            {
+                this.listPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listServices", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=7)]
+        public string[] listServices
+        {
+            get
+            {
+                return this.listServicesField;
+            }
+            set
+            {
+                this.listServicesField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("listWinner", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=8)]
+        public prizeWinner[] listWinner
+        {
+            get
+            {
+                return this.listWinnerField;
+            }
+            set
+            {
+                this.listWinnerField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public int moneyDeducted
+        {
+            get
+            {
+                return this.moneyDeductedField;
+            }
+            set
+            {
+                this.moneyDeductedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string position
+        {
+            get
+            {
+                return this.positionField;
+            }
+            set
+            {
+                this.positionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public int remainSpin
+        {
+            get
+            {
+                return this.remainSpinField;
+            }
+            set
+            {
+                this.remainSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string resultCode
+        {
+            get
+            {
+                return this.resultCodeField;
+            }
+            set
+            {
+                this.resultCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public spinResultObj spinResult
+        {
+            get
+            {
+                return this.spinResultField;
+            }
+            set
+            {
+                this.spinResultField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("topPlayedTime", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=16)]
+        public accountInfo[] topPlayedTime
+        {
+            get
+            {
+                return this.topPlayedTimeField;
+            }
+            set
+            {
+                this.topPlayedTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("topWonMiniGame", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=17)]
+        public accountInfo[] topWonMiniGame
+        {
+            get
+            {
+                return this.topWonMiniGameField;
+            }
+            set
+            {
+                this.topWonMiniGameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string totalPage
+        {
+            get
+            {
+                return this.totalPageField;
+            }
+            set
+            {
+                this.totalPageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public int totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public int totalSpinAdd
+        {
+            get
+            {
+                return this.totalSpinAddField;
+            }
+            set
+            {
+                this.totalSpinAddField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute("userRank", Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true, Order=21)]
+        public topPlayer[] userRank
+        {
+            get
+            {
+                return this.userRankField;
+            }
+            set
+            {
+                this.userRankField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class accountInfo
+    {
+        
+        private string accountIdField;
+        
+        private string betcoinField;
+        
+        private string birthdayField;
+        
+        private string channelField;
+        
+        private string createDateField;
+        
+        private string emailField;
+        
+        private string freeSpinField;
+        
+        private string fullNameField;
+        
+        private string isActiveField;
+        
+        private string isLockField;
+        
+        private string languageField;
+        
+        private string lastLoginField;
+        
+        private string lastUpdateField;
+        
+        private string msisdnField;
+        
+        private string passwordField;
+        
+        private string pictureField;
+        
+        private string pointField;
+        
+        private string rankingField;
+        
+        private string roleField;
+        
+        private string serviceIdField;
+        
+        private string statusField;
+        
+        private string timeLockField;
+        
+        private string totalFalseField;
+        
+        private string totalSpinField;
+        
+        private string updateDateField;
+        
+        private string usersField;
+        
+        private string wincoinField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string accountId
+        {
+            get
+            {
+                return this.accountIdField;
+            }
+            set
+            {
+                this.accountIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string betcoin
+        {
+            get
+            {
+                return this.betcoinField;
+            }
+            set
+            {
+                this.betcoinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string birthday
+        {
+            get
+            {
+                return this.birthdayField;
+            }
+            set
+            {
+                this.birthdayField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string channel
+        {
+            get
+            {
+                return this.channelField;
+            }
+            set
+            {
+                this.channelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string createDate
+        {
+            get
+            {
+                return this.createDateField;
+            }
+            set
+            {
+                this.createDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string email
+        {
+            get
+            {
+                return this.emailField;
+            }
+            set
+            {
+                this.emailField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string freeSpin
+        {
+            get
+            {
+                return this.freeSpinField;
+            }
+            set
+            {
+                this.freeSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public string fullName
+        {
+            get
+            {
+                return this.fullNameField;
+            }
+            set
+            {
+                this.fullNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public string isActive
+        {
+            get
+            {
+                return this.isActiveField;
+            }
+            set
+            {
+                this.isActiveField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string isLock
+        {
+            get
+            {
+                return this.isLockField;
+            }
+            set
+            {
+                this.isLockField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string language
+        {
+            get
+            {
+                return this.languageField;
+            }
+            set
+            {
+                this.languageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string lastLogin
+        {
+            get
+            {
+                return this.lastLoginField;
+            }
+            set
+            {
+                this.lastLoginField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string lastUpdate
+        {
+            get
+            {
+                return this.lastUpdateField;
+            }
+            set
+            {
+                this.lastUpdateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string password
+        {
+            get
+            {
+                return this.passwordField;
+            }
+            set
+            {
+                this.passwordField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string picture
+        {
+            get
+            {
+                return this.pictureField;
+            }
+            set
+            {
+                this.pictureField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string point
+        {
+            get
+            {
+                return this.pointField;
+            }
+            set
+            {
+                this.pointField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public string ranking
+        {
+            get
+            {
+                return this.rankingField;
+            }
+            set
+            {
+                this.rankingField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string role
+        {
+            get
+            {
+                return this.roleField;
+            }
+            set
+            {
+                this.roleField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public string serviceId
+        {
+            get
+            {
+                return this.serviceIdField;
+            }
+            set
+            {
+                this.serviceIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=21)]
+        public string timeLock
+        {
+            get
+            {
+                return this.timeLockField;
+            }
+            set
+            {
+                this.timeLockField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=22)]
+        public string totalFalse
+        {
+            get
+            {
+                return this.totalFalseField;
+            }
+            set
+            {
+                this.totalFalseField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=23)]
+        public string totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=24)]
+        public string updateDate
+        {
+            get
+            {
+                return this.updateDateField;
+            }
+            set
+            {
+                this.updateDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=25)]
+        public string users
+        {
+            get
+            {
+                return this.usersField;
+            }
+            set
+            {
+                this.usersField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=26)]
+        public string wincoin
+        {
+            get
+            {
+                return this.wincoinField;
+            }
+            set
+            {
+                this.wincoinField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class topPlayer
+    {
+        
+        private string msisdnField;
+        
+        private int rankField;
+        
+        private int spinCountField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public int rank
+        {
+            get
+            {
+                return this.rankField;
+            }
+            set
+            {
+                this.rankField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public int spinCount
+        {
+            get
+            {
+                return this.spinCountField;
+            }
+            set
+            {
+                this.spinCountField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class spinResultObj
+    {
+        
+        private long luckySpinIdField;
+        
+        private int prizeIdField;
+        
+        private int prizeWinnerIdField;
+        
+        private int remainSpinField;
+        
+        private int totalCoinField;
+        
+        private int totalSpinField;
+        
+        private int usedSpinField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public long luckySpinId
+        {
+            get
+            {
+                return this.luckySpinIdField;
+            }
+            set
+            {
+                this.luckySpinIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public int prizeId
+        {
+            get
+            {
+                return this.prizeIdField;
+            }
+            set
+            {
+                this.prizeIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public int prizeWinnerId
+        {
+            get
+            {
+                return this.prizeWinnerIdField;
+            }
+            set
+            {
+                this.prizeWinnerIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public int remainSpin
+        {
+            get
+            {
+                return this.remainSpinField;
+            }
+            set
+            {
+                this.remainSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public int totalCoin
+        {
+            get
+            {
+                return this.totalCoinField;
+            }
+            set
+            {
+                this.totalCoinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public int totalSpin
+        {
+            get
+            {
+                return this.totalSpinField;
+            }
+            set
+            {
+                this.totalSpinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public int usedSpin
+        {
+            get
+            {
+                return this.usedSpinField;
+            }
+            set
+            {
+                this.usedSpinField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class prizeWinner
+    {
+        
+        private string channelField;
+        
+        private string codeField;
+        
+        private string codeTimeField;
+        
+        private string expireTimeField;
+        
+        private int idField;
+        
+        private string msisdnField;
+        
+        private int pageField;
+        
+        private int periodField;
+        
+        private int pointWinField;
+        
+        private string prizeDescriptionField;
+        
+        private string prizeDescription1Field;
+        
+        private string prizeDescription2Field;
+        
+        private int prizeIdField;
+        
+        private string prizeNameField;
+        
+        private string prizeName1Field;
+        
+        private string prizeName2Field;
+        
+        private string processTimeField;
+        
+        private int topField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string channel
+        {
+            get
+            {
+                return this.channelField;
+            }
+            set
+            {
+                this.channelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string code
+        {
+            get
+            {
+                return this.codeField;
+            }
+            set
+            {
+                this.codeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string codeTime
+        {
+            get
+            {
+                return this.codeTimeField;
+            }
+            set
+            {
+                this.codeTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string expireTime
+        {
+            get
+            {
+                return this.expireTimeField;
+            }
+            set
+            {
+                this.expireTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public int id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string msisdn
+        {
+            get
+            {
+                return this.msisdnField;
+            }
+            set
+            {
+                this.msisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public int page
+        {
+            get
+            {
+                return this.pageField;
+            }
+            set
+            {
+                this.pageField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public int period
+        {
+            get
+            {
+                return this.periodField;
+            }
+            set
+            {
+                this.periodField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public int pointWin
+        {
+            get
+            {
+                return this.pointWinField;
+            }
+            set
+            {
+                this.pointWinField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string prizeDescription
+        {
+            get
+            {
+                return this.prizeDescriptionField;
+            }
+            set
+            {
+                this.prizeDescriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string prizeDescription1
+        {
+            get
+            {
+                return this.prizeDescription1Field;
+            }
+            set
+            {
+                this.prizeDescription1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string prizeDescription2
+        {
+            get
+            {
+                return this.prizeDescription2Field;
+            }
+            set
+            {
+                this.prizeDescription2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public int prizeId
+        {
+            get
+            {
+                return this.prizeIdField;
+            }
+            set
+            {
+                this.prizeIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string prizeName
+        {
+            get
+            {
+                return this.prizeNameField;
+            }
+            set
+            {
+                this.prizeNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string prizeName1
+        {
+            get
+            {
+                return this.prizeName1Field;
+            }
+            set
+            {
+                this.prizeName1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string prizeName2
+        {
+            get
+            {
+                return this.prizeName2Field;
+            }
+            set
+            {
+                this.prizeName2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string processTime
+        {
+            get
+            {
+                return this.processTimeField;
+            }
+            set
+            {
+                this.processTimeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public int top
+        {
+            get
+            {
+                return this.topField;
+            }
+            set
+            {
+                this.topField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class prizeObj
+    {
+        
+        private string actionCodeField;
+        
+        private string actionTypeField;
+        
+        private string descriptionField;
+        
+        private string description1Field;
+        
+        private string description2Field;
+        
+        private long idField;
+        
+        private string imgPrizeField;
+        
+        private int isPadField;
+        
+        private int isTopField;
+        
+        private double moneyConvertedField;
+        
+        private int periodField;
+        
+        private string prefixMsisdnField;
+        
+        private string prizeNameField;
+        
+        private string prizeName1Field;
+        
+        private string prizeName2Field;
+        
+        private int statusField;
+        
+        private int subGroupPrizeField;
+        
+        private int valuePrizeField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string actionCode
+        {
+            get
+            {
+                return this.actionCodeField;
+            }
+            set
+            {
+                this.actionCodeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string actionType
+        {
+            get
+            {
+                return this.actionTypeField;
+            }
+            set
+            {
+                this.actionTypeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string description
+        {
+            get
+            {
+                return this.descriptionField;
+            }
+            set
+            {
+                this.descriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string description1
+        {
+            get
+            {
+                return this.description1Field;
+            }
+            set
+            {
+                this.description1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string description2
+        {
+            get
+            {
+                return this.description2Field;
+            }
+            set
+            {
+                this.description2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public long id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string imgPrize
+        {
+            get
+            {
+                return this.imgPrizeField;
+            }
+            set
+            {
+                this.imgPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public int isPad
+        {
+            get
+            {
+                return this.isPadField;
+            }
+            set
+            {
+                this.isPadField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public int isTop
+        {
+            get
+            {
+                return this.isTopField;
+            }
+            set
+            {
+                this.isTopField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public double moneyConverted
+        {
+            get
+            {
+                return this.moneyConvertedField;
+            }
+            set
+            {
+                this.moneyConvertedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public int period
+        {
+            get
+            {
+                return this.periodField;
+            }
+            set
+            {
+                this.periodField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string prefixMsisdn
+        {
+            get
+            {
+                return this.prefixMsisdnField;
+            }
+            set
+            {
+                this.prefixMsisdnField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string prizeName
+        {
+            get
+            {
+                return this.prizeNameField;
+            }
+            set
+            {
+                this.prizeNameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string prizeName1
+        {
+            get
+            {
+                return this.prizeName1Field;
+            }
+            set
+            {
+                this.prizeName1Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string prizeName2
+        {
+            get
+            {
+                return this.prizeName2Field;
+            }
+            set
+            {
+                this.prizeName2Field = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public int status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public int subGroupPrize
+        {
+            get
+            {
+                return this.subGroupPrizeField;
+            }
+            set
+            {
+                this.subGroupPrizeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public int valuePrize
+        {
+            get
+            {
+                return this.valuePrizeField;
+            }
+            set
+            {
+                this.valuePrizeField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class game
+    {
+        
+        private string codeField;
+        
+        private string contentField;
+        
+        private string contentTypeField;
+        
+        private string createdDateField;
+        
+        private string descriptionField;
+        
+        private string descriptionGlobalField;
+        
+        private string descriptionLocalField;
+        
+        private string fromDateField;
+        
+        private string iconField;
+        
+        private string idField;
+        
+        private string introductionField;
+        
+        private string introductionGlobalField;
+        
+        private string introductionLocalField;
+        
+        private string isPlayedField;
+        
+        private string levelField;
+        
+        private string logoField;
+        
+        private string nameField;
+        
+        private string nameGlobalField;
+        
+        private string nameLocalField;
+        
+        private string noteField;
+        
+        private string parentIdField;
+        
+        private string serviceIdField;
+        
+        private string statusField;
+        
+        private string toDateField;
+        
+        private string typeOfField;
+        
+        private string updateDateField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string code
+        {
+            get
+            {
+                return this.codeField;
+            }
+            set
+            {
+                this.codeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string content
+        {
+            get
+            {
+                return this.contentField;
+            }
+            set
+            {
+                this.contentField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string contentType
+        {
+            get
+            {
+                return this.contentTypeField;
+            }
+            set
+            {
+                this.contentTypeField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string createdDate
+        {
+            get
+            {
+                return this.createdDateField;
+            }
+            set
+            {
+                this.createdDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=4)]
+        public string description
+        {
+            get
+            {
+                return this.descriptionField;
+            }
+            set
+            {
+                this.descriptionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=5)]
+        public string descriptionGlobal
+        {
+            get
+            {
+                return this.descriptionGlobalField;
+            }
+            set
+            {
+                this.descriptionGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=6)]
+        public string descriptionLocal
+        {
+            get
+            {
+                return this.descriptionLocalField;
+            }
+            set
+            {
+                this.descriptionLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=7)]
+        public string fromDate
+        {
+            get
+            {
+                return this.fromDateField;
+            }
+            set
+            {
+                this.fromDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=8)]
+        public string icon
+        {
+            get
+            {
+                return this.iconField;
+            }
+            set
+            {
+                this.iconField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=9)]
+        public string id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=10)]
+        public string introduction
+        {
+            get
+            {
+                return this.introductionField;
+            }
+            set
+            {
+                this.introductionField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=11)]
+        public string introductionGlobal
+        {
+            get
+            {
+                return this.introductionGlobalField;
+            }
+            set
+            {
+                this.introductionGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=12)]
+        public string introductionLocal
+        {
+            get
+            {
+                return this.introductionLocalField;
+            }
+            set
+            {
+                this.introductionLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=13)]
+        public string isPlayed
+        {
+            get
+            {
+                return this.isPlayedField;
+            }
+            set
+            {
+                this.isPlayedField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=14)]
+        public string level
+        {
+            get
+            {
+                return this.levelField;
+            }
+            set
+            {
+                this.levelField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=15)]
+        public string logo
+        {
+            get
+            {
+                return this.logoField;
+            }
+            set
+            {
+                this.logoField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=16)]
+        public string name
+        {
+            get
+            {
+                return this.nameField;
+            }
+            set
+            {
+                this.nameField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=17)]
+        public string nameGlobal
+        {
+            get
+            {
+                return this.nameGlobalField;
+            }
+            set
+            {
+                this.nameGlobalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=18)]
+        public string nameLocal
+        {
+            get
+            {
+                return this.nameLocalField;
+            }
+            set
+            {
+                this.nameLocalField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=19)]
+        public string note
+        {
+            get
+            {
+                return this.noteField;
+            }
+            set
+            {
+                this.noteField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=20)]
+        public string parentId
+        {
+            get
+            {
+                return this.parentIdField;
+            }
+            set
+            {
+                this.parentIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=21)]
+        public string serviceId
+        {
+            get
+            {
+                return this.serviceIdField;
+            }
+            set
+            {
+                this.serviceIdField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=22)]
+        public string status
+        {
+            get
+            {
+                return this.statusField;
+            }
+            set
+            {
+                this.statusField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=23)]
+        public string toDate
+        {
+            get
+            {
+                return this.toDateField;
+            }
+            set
+            {
+                this.toDateField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=24)]
+        public string typeOf
+        {
+            get
+            {
+                return this.typeOfField;
+            }
+            set
+            {
+                this.typeOfField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=25)]
+        public string updateDate
+        {
+            get
+            {
+                return this.updateDateField;
+            }
+            set
+            {
+                this.updateDateField = value;
+            }
+        }
+    }
+    
+    /// <remarks/>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://webservices.vas.com/")]
+    public partial class configuration
+    {
+        
+        private string idField;
+        
+        private string para_keyField;
+        
+        private string para_valueField;
+        
+        private string service_idField;
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=0)]
+        public string id
+        {
+            get
+            {
+                return this.idField;
+            }
+            set
+            {
+                this.idField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=1)]
+        public string para_key
+        {
+            get
+            {
+                return this.para_keyField;
+            }
+            set
+            {
+                this.para_keyField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=2)]
+        public string para_value
+        {
+            get
+            {
+                return this.para_valueField;
+            }
+            set
+            {
+                this.para_valueField = value;
+            }
+        }
+        
+        /// <remarks/>
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, Order=3)]
+        public string service_id
+        {
+            get
+            {
+                return this.service_idField;
+            }
+            set
+            {
+                this.service_idField = value;
+            }
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubOtp", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubOtpRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsRegisterSubOtpRequest()
+        {
+        }
+        
+        public wsRegisterSubOtpRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubOtpResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubOtpResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsRegisterSubOtpResponse()
+        {
+        }
+        
+        public wsRegisterSubOtpResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="subRequest", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class subRequestRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string username;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string password;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string serviceid;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string chargetime;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @params;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string mode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string amount;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string transid;
+        
+        public subRequestRequest()
+        {
+        }
+        
+        public subRequestRequest(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            this.username = username;
+            this.password = password;
+            this.serviceid = serviceid;
+            this.msisdn = msisdn;
+            this.chargetime = chargetime;
+            this.@params = @params;
+            this.mode = mode;
+            this.amount = amount;
+            this.transid = transid;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="subRequestResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class subRequestResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public subRequestResponse()
+        {
+        }
+        
+        public subRequestResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="heartbeat", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class heartbeatRequest
+    {
+        
+        public heartbeatRequest()
+        {
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="heartbeatResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class heartbeatResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public heartbeatResponse()
+        {
+        }
+        
+        public heartbeatResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetListWinner", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetListWinnerRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string period;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string page;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string pageSize;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string isTop;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string codeType;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=8)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string startDate;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=9)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string endDate;
+        
+        public wsGetListWinnerRequest()
+        {
+        }
+        
+        public wsGetListWinnerRequest(string WsUser, string WsPass, string msisdn, string period, string page, string pageSize, string isTop, string codeType, string startDate, string endDate)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.msisdn = msisdn;
+            this.period = period;
+            this.page = page;
+            this.pageSize = pageSize;
+            this.isTop = isTop;
+            this.codeType = codeType;
+            this.startDate = startDate;
+            this.endDate = endDate;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetListWinnerResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetListWinnerResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsGetListWinnerResponse()
+        {
+        }
+        
+        public wsGetListWinnerResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddMoney", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddMoneyRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string top;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string type;
+        
+        public wsAddMoneyRequest()
+        {
+        }
+        
+        public wsAddMoneyRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId, string top, string type)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.ServiceId = ServiceId;
+            this.top = top;
+            this.type = type;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddMoneyResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddMoneyResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddMoneyResponse()
+        {
+        }
+        
+        public wsAddMoneyResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinT", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinTRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeID;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeWinnerID;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PartnerTransId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string TransId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Channel;
+        
+        public wsDoSpinTRequest()
+        {
+        }
+        
+        public wsDoSpinTRequest(string WsUser, string WsPass, string Msisdn, string PrizeID, string PrizeWinnerID, string PartnerTransId, string TransId, string Channel)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PrizeID = PrizeID;
+            this.PrizeWinnerID = PrizeWinnerID;
+            this.PartnerTransId = PartnerTransId;
+            this.TransId = TransId;
+            this.Channel = Channel;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinTResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinTResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDoSpinTResponse()
+        {
+        }
+        
+        public wsDoSpinTResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeOtp", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeOtpRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsChargeFeeOtpRequest()
+        {
+        }
+        
+        public wsChargeFeeOtpRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeOtpResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeOtpResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsChargeFeeOtpResponse()
+        {
+        }
+        
+        public wsChargeFeeOtpResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpin", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Channel;
+        
+        public wsDoSpinRequest()
+        {
+        }
+        
+        public wsDoSpinRequest(string WsUser, string WsPass, string Msisdn, string Channel)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.Channel = Channel;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDoSpinResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDoSpinResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDoSpinResponse()
+        {
+        }
+        
+        public wsDoSpinResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddData", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddDataRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string data;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsAddDataRequest()
+        {
+        }
+        
+        public wsAddDataRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string data, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.data = data;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddDataResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddDataResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddDataResponse()
+        {
+        }
+        
+        public wsAddDataResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsLoadPrize", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsLoadPrizeRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        public wsLoadPrizeRequest()
+        {
+        }
+        
+        public wsLoadPrizeRequest(string WsUser, string WsPass)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsLoadPrizeResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsLoadPrizeResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsLoadPrizeResponse()
+        {
+        }
+        
+        public wsLoadPrizeResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddEmola", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddEmolaRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeCode;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PrizeType;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string top;
+        
+        public wsAddEmolaRequest()
+        {
+        }
+        
+        public wsAddEmolaRequest(string WsUser, string WsPass, string Msisdn, string PrizeCode, string PrizeType, string ServiceId, string top)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PrizeCode = PrizeCode;
+            this.PrizeType = PrizeType;
+            this.ServiceId = ServiceId;
+            this.top = top;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsAddEmolaResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsAddEmolaResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsAddEmolaResponse()
+        {
+        }
+        
+        public wsAddEmolaResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDisableRegister", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDisableRegisterRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string packName;
+        
+        public wsDisableRegisterRequest()
+        {
+        }
+        
+        public wsDisableRegisterRequest(string WsUser, string WsPass, string msisdn, string packName)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.msisdn = msisdn;
+            this.packName = packName;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsDisableRegisterResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsDisableRegisterResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsDisableRegisterResponse()
+        {
+        }
+        
+        public wsDisableRegisterResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubConfirm", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubConfirmRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string RequestId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Otp;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsRegisterSubConfirmRequest()
+        {
+        }
+        
+        public wsRegisterSubConfirmRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string RequestId, string Otp, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.RequestId = RequestId;
+            this.Otp = Otp;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsRegisterSubConfirmResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsRegisterSubConfirmResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsRegisterSubConfirmResponse()
+        {
+        }
+        
+        public wsRegisterSubConfirmResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeConfirm", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeConfirmRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string PackageName;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=4)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Fee;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=5)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string RequestId;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=6)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Otp;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=7)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsChargeFeeConfirmRequest()
+        {
+        }
+        
+        public wsChargeFeeConfirmRequest(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string RequestId, string Otp, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.PackageName = PackageName;
+            this.Fee = Fee;
+            this.RequestId = RequestId;
+            this.Otp = Otp;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsChargeFeeConfirmResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsChargeFeeConfirmResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsChargeFeeConfirmResponse()
+        {
+        }
+        
+        public wsChargeFeeConfirmResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetUserServices", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetUserServicesRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsUser;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string WsPass;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=2)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string Msisdn;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=3)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string ServiceId;
+        
+        public wsGetUserServicesRequest()
+        {
+        }
+        
+        public wsGetUserServicesRequest(string WsUser, string WsPass, string Msisdn, string ServiceId)
+        {
+            this.WsUser = WsUser;
+            this.WsPass = WsPass;
+            this.Msisdn = Msisdn;
+            this.ServiceId = ServiceId;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="wsGetUserServicesResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class wsGetUserServicesResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public SicboSubWss.response @return;
+        
+        public wsGetUserServicesResponse()
+        {
+        }
+        
+        public wsGetUserServicesResponse(SicboSubWss.response @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="pair", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class pairRequest
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string arg0;
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=1)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string arg1;
+        
+        public pairRequest()
+        {
+        }
+        
+        public pairRequest(string arg0, string arg1)
+        {
+            this.arg0 = arg0;
+            this.arg1 = arg1;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="pairResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class pairResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public bool @return;
+        
+        public pairResponse()
+        {
+        }
+        
+        public pairResponse(bool @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="getIpClient", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class getIpClientRequest
+    {
+        
+        public getIpClientRequest()
+        {
+        }
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+    [System.ServiceModel.MessageContractAttribute(WrapperName="getIpClientResponse", WrapperNamespace="http://webservices.vas.com/", IsWrapped=true)]
+    public partial class getIpClientResponse
+    {
+        
+        [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://webservices.vas.com/", Order=0)]
+        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
+        public string @return;
+        
+        public getIpClientResponse()
+        {
+        }
+        
+        public getIpClientResponse(string @return)
+        {
+            this.@return = @return;
+        }
+    }
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    public interface SicboSubWsChannel : SicboSubWss.SicboSubWs, System.ServiceModel.IClientChannel
+    {
+    }
+    
+    [System.Diagnostics.DebuggerStepThroughAttribute()]
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "8.0.0")]
+    public partial class SicboSubWsClient : System.ServiceModel.ClientBase<SicboSubWss.SicboSubWs>, SicboSubWss.SicboSubWs
+    {
+        
+        /// <summary>
+        /// Implement this partial method to configure the service endpoint.
+        /// </summary>
+        /// <param name="serviceEndpoint">The endpoint to configure</param>
+        /// <param name="clientCredentials">The client credentials</param>
+        static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
+        
+        public SicboSubWsClient() : 
+                base(SicboSubWsClient.GetDefaultBinding(), SicboSubWsClient.GetDefaultEndpointAddress())
+        {
+            this.Endpoint.Name = EndpointConfiguration.SicboSubWsPort.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), SicboSubWsClient.GetEndpointAddress(endpointConfiguration))
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration, string remoteAddress) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) : 
+                base(SicboSubWsClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
+        {
+            this.Endpoint.Name = endpointConfiguration.ToString();
+            ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+        }
+        
+        public SicboSubWsClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
+                base(binding, remoteAddress)
+        {
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> SicboSubWss.SicboSubWs.receiveresultAsync(SicboSubWss.receiveresultRequest request)
+        {
+            return base.Channel.receiveresultAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.receiveresultResponse> receiveresultAsync(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            SicboSubWss.receiveresultRequest inValue = new SicboSubWss.receiveresultRequest();
+            inValue.username = username;
+            inValue.password = password;
+            inValue.serviceid = serviceid;
+            inValue.msisdn = msisdn;
+            inValue.chargetime = chargetime;
+            inValue.@params = @params;
+            inValue.mode = mode;
+            inValue.amount = amount;
+            inValue.transid = transid;
+            return ((SicboSubWss.SicboSubWs)(this)).receiveresultAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> SicboSubWss.SicboSubWs.wsRegisterSubOtpAsync(SicboSubWss.wsRegisterSubOtpRequest request)
+        {
+            return base.Channel.wsRegisterSubOtpAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubOtpResponse> wsRegisterSubOtpAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string ServiceId)
+        {
+            SicboSubWss.wsRegisterSubOtpRequest inValue = new SicboSubWss.wsRegisterSubOtpRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsRegisterSubOtpAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> SicboSubWss.SicboSubWs.subRequestAsync(SicboSubWss.subRequestRequest request)
+        {
+            return base.Channel.subRequestAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.subRequestResponse> subRequestAsync(string username, string password, string serviceid, string msisdn, string chargetime, string @params, string mode, string amount, string transid)
+        {
+            SicboSubWss.subRequestRequest inValue = new SicboSubWss.subRequestRequest();
+            inValue.username = username;
+            inValue.password = password;
+            inValue.serviceid = serviceid;
+            inValue.msisdn = msisdn;
+            inValue.chargetime = chargetime;
+            inValue.@params = @params;
+            inValue.mode = mode;
+            inValue.amount = amount;
+            inValue.transid = transid;
+            return ((SicboSubWss.SicboSubWs)(this)).subRequestAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> SicboSubWss.SicboSubWs.heartbeatAsync(SicboSubWss.heartbeatRequest request)
+        {
+            return base.Channel.heartbeatAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.heartbeatResponse> heartbeatAsync()
+        {
+            SicboSubWss.heartbeatRequest inValue = new SicboSubWss.heartbeatRequest();
+            return ((SicboSubWss.SicboSubWs)(this)).heartbeatAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> SicboSubWss.SicboSubWs.wsGetListWinnerAsync(SicboSubWss.wsGetListWinnerRequest request)
+        {
+            return base.Channel.wsGetListWinnerAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsGetListWinnerResponse> wsGetListWinnerAsync(string WsUser, string WsPass, string msisdn, string period, string page, string pageSize, string isTop, string codeType, string startDate, string endDate)
+        {
+            SicboSubWss.wsGetListWinnerRequest inValue = new SicboSubWss.wsGetListWinnerRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.msisdn = msisdn;
+            inValue.period = period;
+            inValue.page = page;
+            inValue.pageSize = pageSize;
+            inValue.isTop = isTop;
+            inValue.codeType = codeType;
+            inValue.startDate = startDate;
+            inValue.endDate = endDate;
+            return ((SicboSubWss.SicboSubWs)(this)).wsGetListWinnerAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> SicboSubWss.SicboSubWs.wsAddMoneyAsync(SicboSubWss.wsAddMoneyRequest request)
+        {
+            return base.Channel.wsAddMoneyAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddMoneyResponse> wsAddMoneyAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId, string top, string type)
+        {
+            SicboSubWss.wsAddMoneyRequest inValue = new SicboSubWss.wsAddMoneyRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.ServiceId = ServiceId;
+            inValue.top = top;
+            inValue.type = type;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddMoneyAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> SicboSubWss.SicboSubWs.wsDoSpinTAsync(SicboSubWss.wsDoSpinTRequest request)
+        {
+            return base.Channel.wsDoSpinTAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDoSpinTResponse> wsDoSpinTAsync(string WsUser, string WsPass, string Msisdn, string PrizeID, string PrizeWinnerID, string PartnerTransId, string TransId, string Channel)
+        {
+            SicboSubWss.wsDoSpinTRequest inValue = new SicboSubWss.wsDoSpinTRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PrizeID = PrizeID;
+            inValue.PrizeWinnerID = PrizeWinnerID;
+            inValue.PartnerTransId = PartnerTransId;
+            inValue.TransId = TransId;
+            inValue.Channel = Channel;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDoSpinTAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> SicboSubWss.SicboSubWs.wsChargeFeeOtpAsync(SicboSubWss.wsChargeFeeOtpRequest request)
+        {
+            return base.Channel.wsChargeFeeOtpAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeOtpResponse> wsChargeFeeOtpAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string ServiceId)
+        {
+            SicboSubWss.wsChargeFeeOtpRequest inValue = new SicboSubWss.wsChargeFeeOtpRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsChargeFeeOtpAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> SicboSubWss.SicboSubWs.wsDoSpinAsync(SicboSubWss.wsDoSpinRequest request)
+        {
+            return base.Channel.wsDoSpinAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDoSpinResponse> wsDoSpinAsync(string WsUser, string WsPass, string Msisdn, string Channel)
+        {
+            SicboSubWss.wsDoSpinRequest inValue = new SicboSubWss.wsDoSpinRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.Channel = Channel;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDoSpinAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> SicboSubWss.SicboSubWs.wsAddDataAsync(SicboSubWss.wsAddDataRequest request)
+        {
+            return base.Channel.wsAddDataAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddDataResponse> wsAddDataAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string data, string ServiceId)
+        {
+            SicboSubWss.wsAddDataRequest inValue = new SicboSubWss.wsAddDataRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.data = data;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddDataAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> SicboSubWss.SicboSubWs.wsLoadPrizeAsync(SicboSubWss.wsLoadPrizeRequest request)
+        {
+            return base.Channel.wsLoadPrizeAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsLoadPrizeResponse> wsLoadPrizeAsync(string WsUser, string WsPass)
+        {
+            SicboSubWss.wsLoadPrizeRequest inValue = new SicboSubWss.wsLoadPrizeRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            return ((SicboSubWss.SicboSubWs)(this)).wsLoadPrizeAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> SicboSubWss.SicboSubWs.wsAddEmolaAsync(SicboSubWss.wsAddEmolaRequest request)
+        {
+            return base.Channel.wsAddEmolaAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsAddEmolaResponse> wsAddEmolaAsync(string WsUser, string WsPass, string Msisdn, string PrizeCode, string PrizeType, string ServiceId, string top)
+        {
+            SicboSubWss.wsAddEmolaRequest inValue = new SicboSubWss.wsAddEmolaRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PrizeCode = PrizeCode;
+            inValue.PrizeType = PrizeType;
+            inValue.ServiceId = ServiceId;
+            inValue.top = top;
+            return ((SicboSubWss.SicboSubWs)(this)).wsAddEmolaAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> SicboSubWss.SicboSubWs.wsDisableRegisterAsync(SicboSubWss.wsDisableRegisterRequest request)
+        {
+            return base.Channel.wsDisableRegisterAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsDisableRegisterResponse> wsDisableRegisterAsync(string WsUser, string WsPass, string msisdn, string packName)
+        {
+            SicboSubWss.wsDisableRegisterRequest inValue = new SicboSubWss.wsDisableRegisterRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.msisdn = msisdn;
+            inValue.packName = packName;
+            return ((SicboSubWss.SicboSubWs)(this)).wsDisableRegisterAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> SicboSubWss.SicboSubWs.wsRegisterSubConfirmAsync(SicboSubWss.wsRegisterSubConfirmRequest request)
+        {
+            return base.Channel.wsRegisterSubConfirmAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsRegisterSubConfirmResponse> wsRegisterSubConfirmAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string RequestId, string Otp, string ServiceId)
+        {
+            SicboSubWss.wsRegisterSubConfirmRequest inValue = new SicboSubWss.wsRegisterSubConfirmRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.RequestId = RequestId;
+            inValue.Otp = Otp;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsRegisterSubConfirmAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> SicboSubWss.SicboSubWs.wsChargeFeeConfirmAsync(SicboSubWss.wsChargeFeeConfirmRequest request)
+        {
+            return base.Channel.wsChargeFeeConfirmAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsChargeFeeConfirmResponse> wsChargeFeeConfirmAsync(string WsUser, string WsPass, string Msisdn, string PackageName, string Fee, string RequestId, string Otp, string ServiceId)
+        {
+            SicboSubWss.wsChargeFeeConfirmRequest inValue = new SicboSubWss.wsChargeFeeConfirmRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.PackageName = PackageName;
+            inValue.Fee = Fee;
+            inValue.RequestId = RequestId;
+            inValue.Otp = Otp;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsChargeFeeConfirmAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> SicboSubWss.SicboSubWs.wsGetUserServicesAsync(SicboSubWss.wsGetUserServicesRequest request)
+        {
+            return base.Channel.wsGetUserServicesAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.wsGetUserServicesResponse> wsGetUserServicesAsync(string WsUser, string WsPass, string Msisdn, string ServiceId)
+        {
+            SicboSubWss.wsGetUserServicesRequest inValue = new SicboSubWss.wsGetUserServicesRequest();
+            inValue.WsUser = WsUser;
+            inValue.WsPass = WsPass;
+            inValue.Msisdn = Msisdn;
+            inValue.ServiceId = ServiceId;
+            return ((SicboSubWss.SicboSubWs)(this)).wsGetUserServicesAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.pairResponse> SicboSubWss.SicboSubWs.pairAsync(SicboSubWss.pairRequest request)
+        {
+            return base.Channel.pairAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.pairResponse> pairAsync(string arg0, string arg1)
+        {
+            SicboSubWss.pairRequest inValue = new SicboSubWss.pairRequest();
+            inValue.arg0 = arg0;
+            inValue.arg1 = arg1;
+            return ((SicboSubWss.SicboSubWs)(this)).pairAsync(inValue);
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> SicboSubWss.SicboSubWs.getIpClientAsync(SicboSubWss.getIpClientRequest request)
+        {
+            return base.Channel.getIpClientAsync(request);
+        }
+        
+        public System.Threading.Tasks.Task<SicboSubWss.getIpClientResponse> getIpClientAsync()
+        {
+            SicboSubWss.getIpClientRequest inValue = new SicboSubWss.getIpClientRequest();
+            return ((SicboSubWss.SicboSubWs)(this)).getIpClientAsync(inValue);
+        }
+        
+        public virtual System.Threading.Tasks.Task OpenAsync()
+        {
+            return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
+        }
+        
+        #if !NET6_0_OR_GREATER
+        public virtual System.Threading.Tasks.Task CloseAsync()
+        {
+            return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
+        }
+        #endif
+        
+        private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
+        {
+            if ((endpointConfiguration == EndpointConfiguration.SicboSubWsPort))
+            {
+                System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
+                result.MaxBufferSize = int.MaxValue;
+                result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
+                result.MaxReceivedMessageSize = int.MaxValue;
+                result.AllowCookies = true;
+                return result;
+            }
+            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
+        }
+        
+        private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
+        {
+            if ((endpointConfiguration == EndpointConfiguration.SicboSubWsPort))
+            {
+                return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8199/SicboSubWs");
+            }
+            throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
+        }
+        
+        private static System.ServiceModel.Channels.Binding GetDefaultBinding()
+        {
+            return SicboSubWsClient.GetBindingForEndpoint(EndpointConfiguration.SicboSubWsPort);
+        }
+        
+        private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
+        {
+            return SicboSubWsClient.GetEndpointAddress(EndpointConfiguration.SicboSubWsPort);
+        }
+        
+        public enum EndpointConfiguration
+        {
+            
+            SicboSubWsPort,
+        }
+    }
+}

+ 154 - 0
SicboSub/SicboSub.StartProcedure/ExchangeService.cs

@@ -0,0 +1,154 @@
+using Dapper;
+using Microsoft.Extensions.Configuration;
+using Oracle.ManagedDataAccess.Client;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.ServiceModel;
+using System.Threading.Tasks;
+
+namespace SicboSub.StartProcedure
+{
+    public class ExchangeService
+    {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(ExchangeService));
+        private readonly string _connectionString;
+        SicboSubWss.SicboSubWsClient wsClient;
+
+        string wsUser;
+        string wsPass;
+        string wsPackage;
+        protected void SetWsClient(ref SicboSubWss.SicboSubWsClient wsClient, IConfiguration configuration)
+        {
+            wsClient.Endpoint.Address = new EndpointAddress(configuration.GetSection("wsUrl").Value);
+        }
+        public ExchangeService(string connectionString, IConfiguration configuration)
+        {
+            _connectionString = connectionString;
+            wsUser = configuration["wsUser"];
+            wsPass = configuration["wsPass"];
+            wsPackage = configuration["SERVICE_ID"];
+            wsClient = new SicboSubWss.SicboSubWsClient();
+            SetWsClient(ref wsClient, configuration);
+        }
+
+        public async Task ExecuteExchangeProcessingAsync()
+        {
+            log.Info($"[BẮT ĐẦU] Quét trả thưởng đổi quà (ExchangeHistory)...");
+
+            using (var conn = new OracleConnection(_connectionString))
+            {
+                await conn.OpenAsync();
+
+                try
+                {
+                    // 1. QUÉT ALL PENDING (Status=0)
+                    string sqlGetPending = @"
+                        SELECT ID, MSISDN, MONEY_ADDED, COIN_DEDUCTED
+                        FROM EXCHANGE_HISTORY 
+                        WHERE STATUS = 0
+                        ORDER BY ID ASC"; // FIFO
+
+                    var pendingExchanges = await conn.QueryAsync<ExchangeHistoryDto>(sqlGetPending);
+                    var exchangeList = pendingExchanges.ToList();
+                    
+                    if (exchangeList.Count == 0)
+                    {
+                        log.Info(" -> Không có yêu cầu đổi thưởng nào cần xử lý.");
+                        return;
+                    }
+
+                    log.Info($" -> Tìm thấy {exchangeList.Count} yêu cầu đang chờ (Status=0).");
+
+                    // 2. XỬ LÝ AN TOÀN (Claim -> Process -> Finish)
+                    foreach (var item in exchangeList)
+                    {
+                        await ProcessSingleExchangeSafe(conn, item);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error($"[LỖI NGHIÊM TRỌNG] {ex.Message}");
+                }
+            }
+            log.Info("[HOÀN TẤT] Quá trình đổi thưởng kết thúc.\n");
+        }
+
+        /// <summary>
+        /// Xử lý từng giao dịch với cơ chế 'Chiếm quyền' (Optimistic Locking) tránh tranh chấp.
+        /// </summary>
+        private async Task ProcessSingleExchangeSafe(OracleConnection conn, ExchangeHistoryDto item)
+        {
+            // BƯỚC 1: CHIẾM QUYỀN (Mark as Processing - 3)
+            // Chỉ update được nếu Status vẫn đang là 0.
+            string sqlClaim = "UPDATE EXCHANGE_HISTORY SET STATUS = 3 WHERE ID = :id AND STATUS = 0";
+            int rowsAffected = await conn.ExecuteAsync(sqlClaim, new { id = item.ID });
+
+            if (rowsAffected == 0)
+            {
+                // Ai đó đã xử lý rồi, hoặc trạng thái đã thay đổi -> Bỏ qua
+                log.Warn($"    ! Bỏ qua ID {item.ID} (User {item.MSISDN}) - Đã bị chiếm bởi tiến trình khác.");
+                return;
+            }
+
+            // BƯỚC 2: THỰC HIỆN TRẢ THƯỞNG (Payment Logic)
+            log.Info($"    -> Đang xử lý ID {item.ID} (User {item.MSISDN}): Topup {item.MONEY_ADDED}...");
+            bool isSuccess = await DistributeMoney(item);
+
+            // BƯỚC 3: CHỐT TRẠNG THÁI
+            // Nếu thành công -> 1, Nếu thất bại -> 2
+            // Đảm bảo không retry lại nếu status = 2.
+            int finalStatus = isSuccess ? 1 : 2; 
+
+            // Cập nhật lại Status
+            string sqlFinalize = "UPDATE EXCHANGE_HISTORY SET STATUS = :s WHERE ID = :id";
+            await conn.ExecuteAsync(sqlFinalize, new { s = finalStatus, id = item.ID });
+
+            log.Info($"       -> KẾT QUẢ: {(isSuccess ? "THÀNH CÔNG" : "THẤT BẠI (Đã set status=2 để không retry)")}");
+        }
+
+        private async Task<bool> DistributeMoney(ExchangeHistoryDto item)
+        {
+            try
+            {
+                if (item.MONEY_ADDED <= 0) return true;
+
+                // Gọi web service AddMoney
+                SicboSubWss.wsAddMoneyResponse response = await wsClient.wsAddMoneyAsync(
+                    wsUser,
+                    wsPass,
+                    item.MSISDN,
+                    wsPackage,
+                    item.MONEY_ADDED.ToString(),
+                    wsPackage,
+                    null, // Transaction/Service info
+                    "Exchange" // Additional info if needed
+                );
+
+                // Kiểm tra kết quả trả về
+                // Giả sử errorCode = "0" là thành công, cần verify với định nghĩa WSDL/Class sinh ra
+                if (response != null && response.@return != null && response.@return.errorCode == "0")
+                {
+                    return true;
+                }
+                
+                log.Error($"       [API ERROR] ErrorCode: {response?.@return?.errorCode}, Message: {response?.@return?.content}");
+                return false;
+            }
+            catch (Exception ex)
+            {
+                log.Error($"       [LỖI API] {ex.Message}");
+                return false;
+            }
+        }
+    }
+
+    public class ExchangeHistoryDto
+    {
+        public decimal ID { get; set; }
+        public string MSISDN { get; set; } = "";
+        public decimal MONEY_ADDED { get; set; }
+        public decimal COIN_DEDUCTED { get; set; }
+    }
+}

+ 76 - 16
SicboSub/SicboSub.StartProcedure/Program.cs

@@ -1,25 +1,48 @@
 using System;
+using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Configuration;
+using log4net;
+using log4net.Config;
+using System.IO;
+using Microsoft.Extensions.Configuration;
 
 namespace SicboSub.StartProcedure
 {
     class Program
     {
+        private static readonly ILog log = LogManager.GetLogger(typeof(Program));
+
         static async Task Main(string[] args)
         {
+            // Load log4net config
+            var logRepository = LogManager.GetRepository(System.Reflection.Assembly.GetEntryAssembly());
+            XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
+
             Console.OutputEncoding = System.Text.Encoding.UTF8; // Hỗ trợ hiển thị tiếng Việt
-            Console.WriteLine("=== TIẾN TRÌNH TÍNH TOÁN BXH SICBO ===");
+            log.Info("=== TIẾN TRÌNH TÍNH TOÁN BXH SICBO ===");
 
             // 1. Cấu hình (Configuration)
             IConfiguration config = new ConfigurationBuilder()
                 .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                 .Build();
 
-            string connectionString = config.GetConnectionString("DefaultConnection") 
-                                   ?? "Data Source=YOUR_DB_HOST:1521/YOUR_SERVICE_NAME;User Id=YOUR_USER;Password=YOUR_PASSWORD;";
+            string connectionString = config["Connection"];
 
-            var service = new RankingService(connectionString);
+            if (string.IsNullOrEmpty(connectionString) || connectionString.Contains("YOUR_DB_HOST"))
+            {
+                 log.Warn("[CẢNH BÁO] Không đọc được Connection String từ appsettings.json. Vui lòng kiểm tra file config.");
+                 // Fallback or explicit error if needed
+                 connectionString = "Data Source=YOUR_DB_HOST:1521/YOUR_SERVICE_NAME;User Id=YOUR_USER;Password=YOUR_PASSWORD;";
+            }
+            else
+            {
+                 log.Info($"[INFO] Đã load Connection String: {connectionString.Substring(0, 30)}...");
+                 // Set current directory base to ensure Oracle driver finds dependencies if needed
+                 log.Info($"[INFO] BaseDirectory: {AppContext.BaseDirectory}");
+            }
+
+            var service = new RankingService(connectionString, config);
 
             // 2. Phân tích tham số đầu vào hoặc Chạy mặc định
             // Cách dùng: 
@@ -34,33 +57,70 @@ namespace SicboSub.StartProcedure
             {
                 if (args[0].ToUpper() == "DAILY") mode = "DAILY";
                 else if (args[0].ToUpper() == "MONTHLY") mode = "MONTHLY";
+                else if (args[0].ToUpper() == "EXCHANGE") mode = "EXCHANGE";
                 else if (DateTime.TryParse(args[0], out DateTime parsedDate)) targetDate = parsedDate;
 
                 if (args.Length > 1)
                 {
                    if (args[1].ToUpper() == "DAILY") mode = "DAILY";
                    else if (args[1].ToUpper() == "MONTHLY") mode = "MONTHLY";
+                   else if (args[1].ToUpper() == "EXCHANGE") mode = "EXCHANGE";
                 }
             }
 
-            Console.WriteLine($"Chế độ chạy: {(mode == "DAILY" ? "Hàng Ngày" : "Hàng Tháng")}");
-            Console.WriteLine($"Ngày mục tiêu: {targetDate:yyyy-MM-dd}");
+            log.Info($"Chế độ chạy: {mode}");
+            log.Info($"Ngày mục tiêu: {targetDate:yyyy-MM-dd}");
 
             // 3. Thực thi
-            if (mode == "DAILY")
+            log.Info("Press Ctrl+C to stop...");
+            
+            // Create a cancellation token source to handle manual stop
+            var cts = new CancellationTokenSource();
+            Console.CancelKeyPress += (s, e) =>
             {
-                await service.ExecuteDailyRankingAsync(targetDate);
-            }
-            else if (mode == "MONTHLY")
+                e.Cancel = true;
+                cts.Cancel();
+                log.Info("Stop request received...");
+            };
+
+            while (!cts.Token.IsCancellationRequested)
             {
-                // Đối với chạy Tháng, Procedure sẽ lấy ngày truyền vào để xác định tháng.
-                // VD: 14/01/2026 -> Sẽ tính cho Tháng 1/2026.
-                // Nếu muốn tính tháng trước, cần đảm bảo targetDate thuộc về tháng trước.
-                await service.ExecuteMonthlyRankingAsync(targetDate);
+                try 
+                {
+                    // 3. Thực thi
+                    if (mode == "DAILY")
+                    {
+                        await service.ExecuteDailyRankingAsync(targetDate);
+                    }
+                    else if (mode == "MONTHLY")
+                    {
+                         // Đối với chạy Tháng, Procedure sẽ lấy ngày truyền vào để xác định tháng.
+                         // VD: 14/01/2026 -> Sẽ tính cho Tháng 1/2026.
+                         // Nếu muốn tính tháng trước, cần đảm bảo targetDate thuộc về tháng trước.
+                        await service.ExecuteMonthlyRankingAsync(targetDate);
+                    }
+                    else if (mode == "EXCHANGE")
+                    {
+                        var exchangeService = new ExchangeService(connectionString, config);
+                        await exchangeService.ExecuteExchangeProcessingAsync();
+                    }
+
+                    // Wait 5 seconds before next run
+                    log.Info("Waiting 5s before next run...");
+                    await Task.Delay(5000, cts.Token);
+                }
+                catch (TaskCanceledException)
+                {
+                    break;
+                }
+                catch (Exception ex)
+                {
+                     log.Error("Unexpected error in main loop:", ex);
+                     await Task.Delay(5000); // Wait on error too
+                }
             }
 
-            Console.WriteLine("Nhấn phím bất kỳ để thoát...");
-            // Console.ReadKey(); // Bỏ comment nếu chạy bằng tay để xem kết quả
+            log.Info("Program stopped.");
         }
     }
 }

+ 16 - 0
SicboSub/SicboSub.StartProcedure/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>D:\Code\Ex_publish\Natcom_SicboSub\procedure</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+    <PublishSingleFile>false</PublishSingleFile>
+    <PublishTrimmed>false</PublishTrimmed>
+  </PropertyGroup>
+</Project>

+ 67 - 16
SicboSub/SicboSub.StartProcedure/RankingService.cs

@@ -5,16 +5,33 @@ using Oracle.ManagedDataAccess.Client;
 using System.Threading.Tasks;
 using System.Linq;
 using System.Collections.Generic;
+using Microsoft.Extensions.Configuration;
+using System.ServiceModel;
 
 namespace SicboSub.StartProcedure
 {
     public class RankingService
     {
+        private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(RankingService));
         private readonly string _connectionString;
+        SicboSubWss.SicboSubWsClient wsClient;
+        string wsUser;
+        string wsPass;
+        string wsPackage;
 
-        public RankingService(string connectionString)
+        public RankingService(string connectionString, IConfiguration configuration)
         {
             _connectionString = connectionString;
+            wsUser = configuration["wsUser"];
+            wsPass = configuration["wsPass"];
+            wsPackage = configuration["SERVICE_ID"];
+            wsClient = new SicboSubWss.SicboSubWsClient();
+            SetWsClient(ref wsClient, configuration);
+        }
+
+        protected void SetWsClient(ref SicboSubWss.SicboSubWsClient wsClient, IConfiguration configuration)
+        {
+            wsClient.Endpoint.Address = new EndpointAddress(configuration.GetSection("wsUrl").Value);
         }
 
         public async Task ExecuteDailyRankingAsync(DateTime reportDate)
@@ -30,7 +47,7 @@ namespace SicboSub.StartProcedure
         private async Task RunRankingProcess(DateTime reportDate, string type)
         {
             string typeVN = type == "DAILY" ? "NGÀY" : "THÁNG";
-            Console.WriteLine($"[BẮT ĐẦU] Tính toán BXH {typeVN} cho ngày {reportDate:yyyy-MM-dd}...");
+            log.Info($"[BẮT ĐẦU] Tính toán BXH {typeVN} cho ngày {reportDate:yyyy-MM-dd}...");
 
             using (var conn = new OracleConnection(_connectionString))
             {
@@ -44,7 +61,7 @@ namespace SicboSub.StartProcedure
                     p.Add("p_type", type, DbType.String, ParameterDirection.Input);
 
                     await conn.ExecuteAsync("PRC_CALCULATE_RANKING", p, commandType: CommandType.StoredProcedure);
-                    Console.WriteLine(" -> Kiểm tra/Chạy Procedure hoàn tất.");
+                    log.Info(" -> Kiểm tra/Chạy Procedure hoàn tất.");
 
                     // 2. QUÉT ALL PENDING (Kể cả những cái bị treo từ lần chạy cũ bị crash)
                     // Không chỉ lấy của ngày hôm nay mà lấy tất cả status=0 để xử lý triệt để
@@ -59,11 +76,11 @@ namespace SicboSub.StartProcedure
                     
                     if (rewardList.Count == 0)
                     {
-                        Console.WriteLine(" -> Không có phần thưởng nào cần xử lý.");
+                        log.Info(" -> Không có phần thưởng nào cần xử lý.");
                         return;
                     }
 
-                    Console.WriteLine($" -> Tìm thấy {rewardList.Count} lệnh thưởng đang chờ (Status=0).");
+                    log.Info($" -> Tìm thấy {rewardList.Count} lệnh thưởng đang chờ (Status=0).");
 
                     // 3. XỬ LÝ AN TOÀN (Claim -> Process -> Finish)
                     foreach (var reward in rewardList)
@@ -73,10 +90,10 @@ namespace SicboSub.StartProcedure
                 }
                 catch (Exception ex)
                 {
-                    Console.WriteLine($"[LỖI NGHIÊM TRỌNG] {ex.Message}");
+                    log.Error($"[LỖI NGHIÊM TRỌNG] {ex.Message}");
                 }
             }
-            Console.WriteLine("[HOÀN TẤT] Quá trình kết thúc.\n");
+            log.Info("[HOÀN TẤT] Quá trình kết thúc.\n");
         }
 
         /// <summary>
@@ -92,13 +109,13 @@ namespace SicboSub.StartProcedure
             if (rowsAffected == 0)
             {
                 // Ai đó đã xử lý rồi, hoặc trạng thái đã thay đổi -> Bỏ qua
-                Console.WriteLine($"    ! Bỏ qua ID {reward.ID} (User {reward.MSISDN}) - Đã bị chiếm bởi tiến trình khác.");
+                log.Warn($"    ! Bỏ qua ID {reward.ID} (User {reward.MSISDN}) - Đã bị chiếm bởi tiến trình khác.");
                 return;
             }
 
             // BƯỚC 2: THỰC HIỆN TRẢ THƯỞNG (Payment Logic)
-            Console.WriteLine($"    -> Đang xử lý ID {reward.ID} (User {reward.MSISDN}): {reward.REWARD_VALUE} {reward.REWARD_UNIT}...");
-            bool isSuccess = await DistributeReward(reward);
+            log.Info($"    -> Đang xử lý ID {reward.ID} (User {reward.MSISDN}): {reward.REWARD_VALUE} {reward.REWARD_UNIT}...");
+            bool isSuccess = await DistributeReward(conn, reward);
 
             // BƯỚC 3: CHỐT TRẠNG THÁI (1: Success, 2: Failed)
             // Nếu thất bại, set về 2 (Failed) để admin check, hoặc set về 0 (Pending) để retry tự động tùy nghiệp vụ.
@@ -108,31 +125,65 @@ namespace SicboSub.StartProcedure
             string sqlFinalize = "UPDATE RANKING_REWARD_LOG SET STATUS = :s, CREATED_DATE = SYSDATE WHERE ID = :id";
             await conn.ExecuteAsync(sqlFinalize, new { s = finalStatus, id = reward.ID });
 
-            Console.WriteLine($"       -> KẾT QUẢ: {(isSuccess ? "THÀNH CÔNG" : "THẤT BẠI")}");
+            log.Info($"       -> KẾT QUẢ: {(isSuccess ? "THÀNH CÔNG" : "THẤT BẠI")}");
         }
 
-        private async Task<bool> DistributeReward(RankingRewardLog reward)
+        private async Task<bool> DistributeReward(OracleConnection conn, RankingRewardLog reward)
         {
             try
             {
-                // TODO: Gọi API, Cộng tiền thật ở đây
                 // Giả lập độ trễ mạng
                 await Task.Delay(50); 
                 
                 if (reward.REWARD_UNIT == "COIN")
                 {
                     // Call Service Add Coin
+                    return await AddCoin(conn, reward.MSISDN, reward.REWARD_VALUE);
                 }
                 else if (reward.REWARD_UNIT == "MONEY")
                 {
-                    // Call Service Add Money
+                    // Call Service Add Money (WS)
+                    if (reward.REWARD_VALUE <= 0) return true;
+
+                    SicboSubWss.wsAddMoneyResponse response = await wsClient.wsAddMoneyAsync(
+                        wsUser,
+                        wsPass,
+                        reward.MSISDN,
+                        wsPackage,
+                        reward.REWARD_VALUE.ToString(),
+                        wsPackage,
+                        null, 
+                        "Ranking Reward"
+                    );
+
+                     if (response != null && response.@return != null && response.@return.errorCode == "0")
+                    {
+                        return true;
+                    }
+                    log.Error($"       [API ERROR] ErrorCode: {response?.@return?.errorCode}, Message: {response?.@return?.content}");
+                    return false;
                 }
 
-                return true; // Giả sử luôn thành công
+                return true; 
             }
             catch (Exception ex)
             {
-                Console.WriteLine($"       [LỖI API] {ex.Message}");
+                log.Error($"       [LỖI API] {ex.Message}");
+                return false;
+            }
+        }
+
+        private async Task<bool> AddCoin(OracleConnection conn, string msisdn, decimal amount)
+        {
+            try 
+            {
+                string sql = "UPDATE ACCOUNT_USER SET WIN_COIN = WIN_COIN + :amount WHERE MSISDN = :msisdn";
+                int rows = await conn.ExecuteAsync(sql, new { amount = amount, msisdn = msisdn });
+                return rows > 0;
+            }
+            catch(Exception ex)
+            {
+                log.Error($"       [DB ERROR] AddCoin: {ex.Message}");
                 return false;
             }
         }

+ 16 - 4
SicboSub/SicboSub.StartProcedure/SicboSub.StartProcedure.csproj

@@ -1,17 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
 <Project Sdk="Microsoft.NET.Sdk">
-
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>net8.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
   </PropertyGroup>
-
   <ItemGroup>
+    <PackageReference Include="log4net" Version="3.2.0" />
     <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.140" />
     <PackageReference Include="Dapper" Version="2.1.35" />
     <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
     <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
   </ItemGroup>
-
-</Project>
+  <ItemGroup>
+    <None Update="appsettings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+    <None Update="log4net.config">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="System.ServiceModel.Http" Version="8.*" />
+    <PackageReference Include="System.ServiceModel.NetTcp" Version="8.*" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="8.*" />
+  </ItemGroup>
+</Project>

+ 32 - 0
SicboSub/SicboSub.StartProcedure/SicboSub.StartProcedure.csproj.Backup.tmp

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+  <ItemGroup>
+    <Content Include="log4net.config">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
+      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Oracle.ManagedDataAccess.Core" Version="3.21.140" />
+    <PackageReference Include="Dapper" Version="2.1.35" />
+    <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Update="appsettings.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="System.ServiceModel.Http" Version="8.*" />
+    <PackageReference Include="System.ServiceModel.NetTcp" Version="8.*" />
+    <PackageReference Include="System.ServiceModel.Primitives" Version="8.*" />
+  </ItemGroup>
+</Project>

+ 4 - 3
SicboSub/SicboSub.StartProcedure/appsettings.json

@@ -1,5 +1,6 @@
 {
-  "ConnectionStrings": {
-    "DefaultConnection": "Data Source=localhost:1521/ORCL;User Id=SICBO_USER;Password=SICBO_PASS;"
-  }
+  "Connection": "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1539))(CONNECT_DATA=(SERVICE_NAME=ORA12C)));User Id=sicbo;Password=qwK99QfuhEmcFE;Connection Timeout=120;",
+  "wsUrl": "http://127.0.0.1:8199/SicboSubWs?wsdl",
+  "wsUser": "sicboSub",
+  "wsPass": "123456a@"
 }

+ 22 - 0
SicboSub/SicboSub.StartProcedure/log4net.config

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<log4net>
+  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
+    <file value="Logs/ExchangeService.log" />
+    <appendToFile value="true" />
+    <rollingStyle value="Date" />
+    <datePattern value="yyyyMMdd" />
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+  <root>
+    <level value="ALL" />
+    <appender-ref ref="RollingLogFileAppender" />
+    <appender-ref ref="ConsoleAppender" />
+  </root>
+</log4net>

+ 13 - 0
SicboSub/SicboSub.Web/.config/dotnet-tools.json

@@ -0,0 +1,13 @@
+{
+  "version": 1,
+  "isRoot": true,
+  "tools": {
+    "dotnet-ef": {
+      "version": "10.0.2",
+      "commands": [
+        "dotnet-ef"
+      ],
+      "rollForward": false
+    }
+  }
+}

+ 56 - 0
SicboSub/SicboSub.Web/Constants/WebConstants.cs

@@ -0,0 +1,56 @@
+namespace SicboSub.Web.Constants
+{
+    /// <summary>
+    /// API URL Constants cho Web gọi API
+    /// </summary>
+    public static class UrlConstant
+    {
+        // Auth
+        public const string AuthLogin = "/apis/auth/login";
+        public const string AuthGetMsisdn = "/apis/auth/get-msisdn";
+
+        // User
+        public const string UserInfo = "/apis/user/info";
+
+        // Package
+        public const string PackageLoad = "/apis/package/load";
+        public const string ExchangeConfigLoad = "/apis/package/exchange";
+        public const string PackageRegister = "/apis/package/register";
+        public const string PackageBuyMore = "/apis/package/buymore";
+
+        // Game
+        public const string PlayHistory = "/apis/game/play_history";
+        public const string RankingHistory = "/apis/game/ranking_history";
+
+        // Exchange OTP
+        public const string ExchangeRequestOtp = "/apis/exchange/request-otp";
+        public const string ExchangeVerifyOtp = "/apis/exchange/verify-otp";
+        public const string ExchangeResendOtp = "/apis/exchange/resend-otp";
+    }
+
+    /// <summary>
+    /// Session Keys
+    /// </summary>
+    public static class SessionKey
+    {
+        public const string Token = "token";
+        public const string Msisdn = "msisdn";
+        public const string UserInfo = "userInfo";
+        public const string Culture = "culture";
+        public const string WinCoin = "winCoin";
+        public const string Point = "point";
+        public const string FreeSpin = "freeSpin";
+    }
+
+    /// <summary>
+    /// Error Codes
+    /// </summary>
+    public static class ErrorCode
+    {
+        public const string Success = "0";
+        public const string Failed = "-1";
+        public const string Unauthorized = "-100";
+        public const string InvalidToken = "-107";
+        public const string SystemError = "-999";
+    }
+}

+ 149 - 0
SicboSub/SicboSub.Web/Controllers/BaseController.cs

@@ -0,0 +1,149 @@
+using log4net;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using SicboSub.Web.Helpers;
+using System.Security.Cryptography;
+
+namespace SicboSub.Web.Controllers
+{
+    public class BaseController : Controller
+    {
+        protected static readonly ILog log = LogManager.GetLogger(typeof(BaseController));
+
+        /// <summary>
+        /// Generate random auth ID
+        /// </summary>
+        private string GenerateAuthId()
+        {
+#pragma warning disable SYSLIB0023
+            using (RandomNumberGenerator rng = new RNGCryptoServiceProvider())
+            {
+                byte[] tokenData = new byte[32];
+                rng.GetBytes(tokenData);
+                return Convert.ToBase64String(tokenData);
+            }
+#pragma warning restore SYSLIB0023
+        }
+
+        /// <summary>
+        /// Tạo auth token và lưu vào Session + Cookie
+        /// </summary>
+        protected void CreateAuthToken()
+        {
+            string authId = GenerateAuthId();
+
+            HttpContext.Session.SetString("AuthorizationCookieId", authId);
+
+            CookieOptions options = new CookieOptions()
+            {
+                Expires = DateTime.Now.AddMinutes(60)
+            };
+            HttpContext.Response.Cookies.Append("AuthorizationCookie", authId, options);
+        }
+
+        /// <summary>
+        /// Kiểm tra auth token hợp lệ
+        /// </summary>
+        protected bool CheckAuthToken()
+        {
+            string? cookieValue = HttpContext.Request.Cookies["AuthorizationCookie"];
+            string? sessionValue = HttpContext.Session.GetString("AuthorizationCookieId");
+
+            if (cookieValue == null || sessionValue == null || cookieValue != sessionValue)
+            {
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Xóa cache/session/cookies
+        /// </summary>
+        protected bool ClearCache()
+        {
+            HttpContext.Session.Clear();
+            foreach (var cookieKey in HttpContext.Request.Cookies.Keys)
+            {
+                HttpContext.Response.Cookies.Delete(cookieKey);
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Check đã đăng nhập chưa (dựa vào token trong Session)
+        /// </summary>
+        protected bool IsAuthenticated()
+        {
+            var token = HttpContext.Session.GetComplexData<string>("token");
+            return !string.IsNullOrEmpty(token);
+        }
+
+        /// <summary>
+        /// Lấy MSISDN từ Session
+        /// </summary>
+        protected string? GetMsisdn()
+        {
+            return HttpContext.Session.GetComplexData<string>("msisdn");
+        }
+
+        /// <summary>
+        /// Lấy token từ Session
+        /// </summary>
+        protected string? GetToken()
+        {
+            return HttpContext.Session.GetComplexData<string>("token");
+        }
+
+        /// <summary>
+        /// Lấy ngôn ngữ từ Session
+        /// </summary>
+        protected string GetLanguage()
+        {
+            var lang = HttpContext.Session.GetComplexData<string>("culture") ?? "ht";
+            HttpContext.Session.SetComplexData("culture", lang);
+            return lang;
+        }
+
+        /// <summary>
+        /// Set ngôn ngữ
+        /// </summary>
+        protected void SetLanguage(string lang)
+        {
+            HttpContext.Session.SetComplexData("culture", lang);
+        }
+
+        /// <summary>
+        /// Redirect đến URL khi chưa đăng nhập
+        /// Nếu không có RedirectUrl trong config thì về trang chủ Index
+        /// </summary>
+        protected IActionResult RedirectToLogin(IConfiguration configuration)
+        {
+            var redirectUrl = configuration.GetSection("RedirectUrl").Value;
+            
+            if (!string.IsNullOrEmpty(redirectUrl))
+            {
+                // Redirect ra URL external
+                return Redirect(redirectUrl);
+            }
+            else
+            {
+                // Redirect về Index
+                return RedirectToAction("Index", "Home");
+            }
+        }
+
+        /// <summary>
+        /// Check authentication - nếu chưa login thì redirect
+        /// Dùng trong các action yêu cầu đăng nhập
+        /// </summary>
+        protected IActionResult? CheckAndRedirectIfNotAuthenticated(IConfiguration configuration)
+        {
+            if (!IsAuthenticated())
+            {
+                log.Warn("User not authenticated, redirecting...");
+                return RedirectToLogin(configuration);
+            }
+            return null; // Đã đăng nhập, tiếp tục
+        }
+    }
+}

+ 742 - 12
SicboSub/SicboSub.Web/Controllers/HomeController.cs

@@ -1,57 +1,787 @@
-using System.Diagnostics;
+using Common.Constant;
+using log4net;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using SicboSub.Web.Helpers;
 using SicboSub.Web.Models;
+using System.Configuration;
+using System.Diagnostics;
 
 namespace SicboSub.Web.Controllers
 {
-    public class HomeController : Controller
+    public class HomeController : BaseController
     {
+        private static readonly ILog log = LogManager.GetLogger(typeof(HomeController));
         private readonly ILogger<HomeController> _logger;
+        private readonly IConfiguration _configuration;
+       
 
-        public HomeController(ILogger<HomeController> logger)
+        public HomeController(ILogger<HomeController> logger, IConfiguration configuration)
         {
             _logger = logger;
+            _configuration = configuration;
+        }
+        public String GetParameter(String key)
+        {
+            return _configuration.GetSection(key).Value ?? "";
         }
+        /// <summary>
+        /// Lấy config value
+        /// </summary>
+        /// <summary>
+        /// Trang chủ - Yêu cầu Token để truy cập
+        /// Nếu chưa login và không có token URL -> Redirect về trang chủ Sicbo (RedirectUrl)
+        /// Nếu có token -> Login -> Success: load trang, Fail: Redirect
+        /// </summary>
+        /// <summary>
+        /// Helper to load exchange config server-side
+        /// </summary>
+        private async Task<List<ExchangeConfigItem>> LoadExchangeConfigInternal()
+        {
+            try
+            {
+                string token = GetToken();
+                var request = new ExchangeConfigReq
+                {
+                    lang = GetLanguage()
+                };
+                var url = GetParameter("Url") + ApiUrlConstant.ExchangeConfigLoadUrl;
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
 
-        public IActionResult Index()
+                if (resData != null)
+                {
+                    ExchangeConfigRes response = new ExchangeConfigRes(resData.data);
+                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                    {
+                        return response.data;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("LoadExchangeConfigInternal: Exception", ex);
+            }
+            return new List<ExchangeConfigItem>();
+        }
+
+        /// <summary>
+        /// Helper to load packages server-side
+        /// </summary>
+        private async Task<List<PackageInfo>> LoadPackagesInternal()
         {
-            return View();
+            try
+            {
+                string token = GetToken();
+                var request = new PackageLoadReq
+                {
+                    lang = GetLanguage(),
+                    pageNumber = 0,
+                    pageSize = 100
+                };
+                var url = GetParameter("Url") + ApiUrlConstant.PackageLoadUrl;
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                if (resData != null)
+                {
+                    PackageLoadRes response = new PackageLoadRes(resData.data);
+                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                    {
+                        return response.data
+                            .Where(p => !string.IsNullOrEmpty(p.productName) && p.productName.StartsWith("CHARGE"))
+                            .OrderBy(p => p.fee)
+                            .ToList();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("LoadPackagesInternal: Exception", ex);
+            }
+            return new List<PackageInfo>();
+        }
+
+        /// <summary>
+        /// Helper to reload account info (refresh session data)
+        /// </summary>
+        private async Task ReloadAccountInfo()
+        {
+            try 
+            {
+                var token = GetToken();
+                if (!string.IsNullOrEmpty(token))
+                {
+                   var request = new TokenLoginReq
+                    {
+                        token = token,
+                        language = GetLanguage()
+                    };
+                    var url = GetParameter("Url") + ApiUrlConstant.AuthLoginUrl;
+                    // Gọi API xác thực/lấy thông tin
+                    var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                        log,
+                        url,
+                        request,
+                        token,
+                        token,
+                        "",
+                        GetLanguage()
+                    );
+                    
+                    if (resData != null)
+                    {
+                        TokenLoginRes response = new TokenLoginRes(resData.data);
+                        if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                        {
+                            // Update Session
+                            HttpContext.Session.SetComplexData("winCoin", response.data.winCoin);
+                            HttpContext.Session.SetComplexData("betCoin", response.data.betCoin);
+                            HttpContext.Session.SetComplexData("userInfo", response.data);
+                            HttpContext.Session.SetComplexData("isRegistered", response.data.isRegistered);
+                        }
+                    }
+                }
+            }
+            catch(Exception ex)
+            {
+                log.Error("ReloadAccountInfo: Error", ex);
+            }
+        }
+
+        public async Task<IActionResult> Index()
+        {
+            // 1. Kiểm tra nếu đã đăng nhập từ trước
+            if (IsAuthenticated())
+            {
+                // Refresh account info as requested
+                await ReloadAccountInfo();
+
+                // Setup ViewData và hiển thị
+                ViewData["IsAuthenticated"] = true;
+                ViewData["Msisdn"] = GetMsisdn();
+                ViewData["WinCoin"] = HttpContext.Session.GetComplexData<decimal?>("winCoin") ?? 0;
+                ViewData["BetCoin"] = HttpContext.Session.GetComplexData<decimal?>("betCoin") ?? 0;
+                
+                // Load packages server-side
+                var packages = await LoadPackagesInternal();
+                HttpContext.Session.SetComplexData("Packages", packages); // Store in session as requested
+                
+                // Load exchange config server-side
+                var exchangeConfigs = await LoadExchangeConfigInternal();
+                HttpContext.Session.SetComplexData("ExchangeConfig", exchangeConfigs);
+
+                return View();
+            }
+
+            // 2. Nếu chưa đăng nhập, kiểm tra Token trên URL
+            var token = Request.Query["token"].FirstOrDefault();
+
+            if (!string.IsNullOrEmpty(token))
+            {
+                log.Info($"Index: Token found in URL, attempting login...");
+
+                try
+                {
+                    // Tạo request
+                    var request = new TokenLoginReq
+                    {
+                        token = token,
+                        language = GetLanguage()
+                    };
+                    var url = GetParameter("Url") + ApiUrlConstant.AuthLoginUrl;
+                    // Gọi API xác thực
+                    var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                        log,
+                        url,
+                        request,
+                        token,
+                        token,
+                        "",
+                        GetLanguage()
+                    );
+
+                    // Parse response
+                    if (resData != null)
+                    {
+                        TokenLoginRes response = new TokenLoginRes(resData.data);
+                        
+                        if (response.errorCode == CommonErrorCode.Success)
+                        {
+                            // Login thành công -> Lưu Session
+                            CreateAuthToken();
+                            HttpContext.Session.SetComplexData("token", token);
+                            HttpContext.Session.SetComplexData("msisdn", response.data?.msisdn);
+                            HttpContext.Session.SetComplexData("winCoin", response.data?.winCoin);
+                            HttpContext.Session.SetComplexData("betCoin", response.data?.betCoin);
+                            HttpContext.Session.SetComplexData("userInfo", response.data);
+                            HttpContext.Session.SetComplexData("isRegistered", response.data?.isRegistered);
+
+                            log.Info($"Index: Login success, MSISDN = {response.data?.msisdn}");
+
+                            // Redirect lại Index để xóa token khỏi URL (và để lọt vào check IsAuthenticated ở trên)
+                            return RedirectToAction("Index");
+                        }
+                        else
+                        {
+                            log.Warn($"Index: Login failed - {response.message}");
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    log.Error("Index: Login exception", ex);
+                }
+            }
+
+            // 3. Nếu chạy đến đây nghĩa là: Chưa Login Session VÀ (Không có token HOẶC Login Token thất bại)
+            // ==> Redirect về trang nguồn (sicbo.vn)
+            return RedirectToLogin(_configuration);
         }
 
         public IActionResult Privacy()
         {
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
             return View();
         }
 
-        public IActionResult History()
+        /// <summary>
+        /// Helper to load play history
+        /// </summary>
+        private async Task<List<PlayHistoryItem>> LoadPlayHistoryInternal()
         {
-            return View();
+            try
+            {
+                var token = GetToken();
+                // 3 days ago
+                var fromDate = DateTime.Now.AddDays(-3).ToString("dd/MM/yyyy");
+                var toDate = DateTime.Now.ToString("dd/MM/yyyy");
+
+                var request = new PlayHistoryReq
+                {
+                    msisdn = GetMsisdn(),
+                    lang = GetLanguage(),
+                    fromDate = fromDate,
+                    toDate = toDate,
+                    pageNumber = 0,
+                    pageSize = 100 
+                };
+
+                var url = GetParameter("Url") + ApiUrlConstant.PlayHistoryUrl;
+
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                if (resData != null)
+                {
+                    PlayHistoryRes response = new PlayHistoryRes(resData.data);
+                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                    {
+                        return response.data;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("LoadPlayHistoryInternal: Error", ex);
+            }
+            return new List<PlayHistoryItem>();
+        }
+
+        /// <summary>
+        /// Helper to load purchase history
+        /// </summary>
+        private async Task<List<PurchaseHistoryItem>> LoadPurchaseHistoryInternal()
+        {
+            try
+            {
+                var token = GetToken();
+                // 30 days ago for purchase history
+                var fromDate = DateTime.Now.AddDays(-30).ToString("dd/MM/yyyy");
+                var toDate = DateTime.Now.ToString("dd/MM/yyyy");
+
+                var request = new PurchaseHistoryReq
+                {
+                    msisdn = GetMsisdn(),
+                    lang = GetLanguage(),
+                    fromDate = fromDate,
+                    toDate = toDate,
+                    pageNumber = 0,
+                    pageSize = 20
+                };
+
+                var url = GetParameter("Url") + ApiUrlConstant.PurchaseHistoryUrl;
+
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                if (resData != null)
+                {
+                    PurchaseHistoryRes response = new PurchaseHistoryRes(resData.data);
+                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                    {
+                        return response.data;
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                log.Error("LoadPurchaseHistoryInternal: Error", ex);
+            }
+            return new List<PurchaseHistoryItem>();
+        }
+
+        public async Task<IActionResult> History()
+        {
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
+            
+            var gameHistory = await LoadPlayHistoryInternal();
+            // User requested: "history prize then pass its msisdn and it is Daily prize"
+            var prizeHistory = await LoadRankingInternal("DAILY", GetMsisdn());
+            var purchaseHistory = await LoadPurchaseHistoryInternal();
+            
+            var model = new HistoryViewModel
+            {
+                GameHistory = gameHistory,
+                PrizeHistory = prizeHistory,
+                PurchaseHistory = purchaseHistory
+            };
+            
+            ViewData["Msisdn"] = GetMsisdn();
+            return View(model);
         }
 
         public IActionResult Winner()
         {
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
             return View();
         }
 
-        public IActionResult DailyRanking()
+        /// <summary>
+        /// Helper to load ranking history
+        /// </summary>
+        /// <summary>
+        /// Helper to load ranking history
+        /// </summary>
+        private async Task<List<RankingHistoryItem>> LoadRankingInternal(string rankType, string msisdn = null)
         {
-            return View();
+            try 
+            {
+                var token = GetToken();
+                // Calculate date range based on rankType
+                string fromDate = "";
+                string toDate = DateTime.Now.ToString("dd/MM/yyyy");
+
+                if (rankType == "DAILY")
+                {
+                    // 7 days ago
+                    fromDate = DateTime.Now.AddDays(-7).ToString("dd/MM/yyyy");
+                }
+                else if (rankType == "MONTHLY")
+                {
+                    // 3 months ago
+                    fromDate = DateTime.Now.AddMonths(-3).ToString("dd/MM/yyyy");
+                }
+
+                var request = new RankingHistoryReq
+                {
+                    msisdn = msisdn, // Pass specific msisdn or null/empty
+                    lang = GetLanguage(),
+                    rankType = rankType,
+                    fromDate = fromDate,
+                    toDate = toDate,
+                    pageNumber = 0,
+                    pageSize = 20
+                };
+                
+                var url = GetParameter("Url") + ApiUrlConstant.RankingHistoryUrl;
+                
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+                
+                if (resData != null)
+                {
+                     RankingHistoryRes response = new RankingHistoryRes(resData.data);
+                     if (response.errorCode == CommonErrorCode.Success && response.data != null)
+                     {
+                         return response.data;
+                     }
+                }
+            }
+            catch(Exception ex)
+            {
+                log.Error($"LoadRankingInternal ({rankType}): Error", ex);
+            }
+            return new List<RankingHistoryItem>();
         }
 
-        public IActionResult MonthlyRanking()
+        public async Task<IActionResult> DailyRanking()
         {
-            return View();
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
+            
+            // For Global Daily Ranking, we don't pass MSISDN implies global list
+            var data = await LoadRankingInternal("DAILY", null);
+            ViewData["RankingType"] = "DAILY";
+            return View(data);
         }
 
-        public IActionResult Account()
+        public async Task<IActionResult> MonthlyRanking()
         {
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
+            
+            var data = await LoadRankingInternal("MONTHLY", null);
+            ViewData["RankingType"] = "MONTHLY";
+            return View(data);
+        }
+
+        public async Task<IActionResult> Account()
+        {
+            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
+
+            // Refresh account info to get latest balance
+            await ReloadAccountInfo();
+
+            // Get user info from session
+            var userInfo = HttpContext.Session.GetComplexData<TokenLoginData>("userInfo");
+            
+            ViewData["UserInfo"] = userInfo;
+            ViewData["Msisdn"] = GetMsisdn();
+            ViewData["WinCoin"] = HttpContext.Session.GetComplexData<decimal?>("winCoin") ?? 0;
+            ViewData["BetCoin"] = HttpContext.Session.GetComplexData<decimal?>("betCoin") ?? 0;
+            
+            // TODO: Retrieve actual values for Today/Month from API when available
+            ViewData["TotalValueToday"] = 0;
+            ViewData["TotalValueMonth"] = 0;
+
             return View();
         }
 
+        /// <summary>
+        /// Đăng xuất
+        /// </summary>
+        public IActionResult Logout()
+        {
+            ClearCache();
+            return RedirectToLogin(_configuration);
+        }
+
         [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
         public IActionResult Error()
         {
             return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
         }
+
+
+        /// <summary>
+        /// Đăng ký gói (Register)
+        /// </summary>
+        [HttpPost]
+        public async Task<IActionResult> Register()
+        {
+            // 1. Check Authentication (server-side check)
+            if (!IsAuthenticated())
+            {
+                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
+            }
+
+            try
+            {
+                // 2. Prepare request data
+                string msisdn = GetMsisdn();
+                string token = GetToken();
+                // Default package for daily registration
+                string packageCode = GetParameter("PackageCodeDaily"); 
+                // Default fallback if config missing
+                if (string.IsNullOrEmpty(packageCode)) packageCode = "SICBO_DAY";
+
+                var request = new RegisterReq
+                {
+                    msisdn = msisdn,
+                    packageCode = packageCode,
+                    lang = GetLanguage()
+                };
+
+                // 3. Call API
+                var url = GetParameter("Url") + ApiUrlConstant.RegisterUrl;
+                
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                // 4. Handle Response
+                if (resData != null)
+                {
+                    RegisterRes response = new RegisterRes(resData.data);
+                    
+                    if (response.errorCode == CommonErrorCode.Success)
+                    {
+                        // Refresh info to get latest balance
+                        await ReloadAccountInfo();
+                        
+                        // Update response data with latest session info
+                        if (response.data == null) response.data = new RegisterData();
+                        
+                        response.data.winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
+                        response.data.betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");
+
+                        return Json(response);
+                    }
+                    else
+                    {
+                        return Json(new { errorCode = response.errorCode, message = response.message });
+                    }
+                }
+                
+                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
+            }
+            catch (Exception ex)
+            {
+                log.Error("Register: Exception", ex);
+                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
+            }
+        }
+
+        /// <summary>
+        /// Mua thêm lượt (Buy More)
+        /// </summary>
+        [HttpPost]
+        public async Task<IActionResult> BuyMore([FromBody] BuyMoreReq reqBody)
+        {
+            // 1. Check Authentication
+            if (!IsAuthenticated())
+            {
+                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
+            }
+
+            try
+            {
+                // 2. Prepare Request
+                string msisdn = GetMsisdn();
+                string token = GetToken();
+                
+                var request = new BuyMoreReq
+                {
+                    msisdn = msisdn,
+                    packageCode = reqBody.packageCode,
+                    lang = GetLanguage()
+                };
+
+                // 3. Call API
+                var url = GetParameter("Url") + ApiUrlConstant.BuyMoreUrl;
+                
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                // 4. Handle Response
+                if (resData != null)
+                {
+                    BuyMoreRes response = new BuyMoreRes(resData.data);
+
+                    if (response.errorCode == CommonErrorCode.Success)
+                    {
+                        // Refresh info to get latest balance
+                        await ReloadAccountInfo();
+
+                        // Update response data with latest session info
+                        if (response.data == null) response.data = new BuyMoreData();
+
+                        response.data.winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
+                        response.data.betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");
+                        
+                        return Json(response);
+                    }
+                    else
+                    {
+                        return Json(new { errorCode = response.errorCode, message = response.message });
+                    }
+                }
+
+                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
+            }
+            catch (Exception ex)
+            {
+                log.Error("BuyMore: Exception", ex);
+                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
+            }
+        }
+
+        /// <summary>
+        /// Request Withdraw OTP
+        /// </summary>
+        [HttpPost]
+        public async Task<IActionResult> RequestWithdrawOtp([FromBody] ExchangeRequestOtpReq reqBody)
+        {
+            if (!IsAuthenticated())
+            {
+                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
+            }
+
+            try
+            {
+                
+                string msisdn = GetMsisdn();
+                string token = GetToken();
+                
+                var request = new ExchangeRequestOtpReq
+                {
+                    msisdn = msisdn,
+                    configId = reqBody.configId,
+                    lang = GetLanguage()
+                };
+
+                // Call API
+                var url = GetParameter("Url") + ApiUrlConstant.ExchangeRequestOtpUrl;
+                
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                if (resData != null)
+                {
+                    ExchangeRequestOtpRes response = new ExchangeRequestOtpRes(resData.data);
+                    return Json(new { errorCode = response.errorCode, message = response.message, data = response.data });
+                }
+                
+                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
+            }
+            catch (Exception ex)
+            {
+                log.Error("RequestWithdrawOtp: Exception", ex);
+                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
+            }
+        }
+
+        /// <summary>
+        /// Confirm Withdraw OTP
+        /// </summary>
+        [HttpPost]
+        public async Task<IActionResult> ConfirmWithdrawOtp([FromBody] ExchangeVerifyOtpReq reqBody)
+        {
+             // 1. Check Authentication
+            if (!IsAuthenticated())
+            {
+                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
+            }
+
+            try
+            {
+                string msisdn = GetMsisdn();
+                string token = GetToken();
+                
+                var request = new ExchangeVerifyOtpReq
+                {
+                    msisdn = msisdn,
+                    otpCode = reqBody.otpCode,
+                    lang = GetLanguage()
+                };
+
+                // Call API
+                var url = GetParameter("Url") + ApiUrlConstant.ExchangeVerifyOtpUrl;
+                
+                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
+                    log,
+                    url,
+                    request,
+                    token,
+                    token,
+                    "",
+                    GetLanguage()
+                );
+
+                if (resData != null)
+                {
+                    ExchangeVerifyOtpRes response = new ExchangeVerifyOtpRes(resData.data);
+                    if (response.errorCode == CommonErrorCode.Success)
+                    {
+                        // Refresh Account Info
+                        await ReloadAccountInfo();
+                        
+                        // Get updated fields
+                        var winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
+                        var betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");
+
+                        return Json(new { errorCode = response.errorCode, message = response.message, data = new { winCoin, betCoin } });
+                    }
+                    
+                    return Json(new { errorCode = response.errorCode, message = response.message, data = response.data });
+                }
+                
+                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
+            }
+            catch (Exception ex)
+            {
+                log.Error("ConfirmWithdrawOtp: Exception", ex);
+                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
+            }
+        }
+
+        /// <summary>
+        /// Lấy danh sách gói cước (Packages)
+        /// </summary>
+        [HttpPost]
+        public async Task<IActionResult> GetPackages()
+        {
+            // 1. Check Authentication
+            if (!IsAuthenticated())
+            {
+                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
+            }
+            var packages = await LoadPackagesInternal();
+            return Json(new { errorCode = CommonErrorCode.Success, data = packages });
+        }
     }
 }

+ 52 - 0
SicboSub/SicboSub.Web/Helpers/SessionExtensions.cs

@@ -0,0 +1,52 @@
+using Newtonsoft.Json;
+
+namespace SicboSub.Web.Helpers
+{
+    /// <summary>
+    /// Extension methods cho Session - lưu/đọc object phức tạp
+    /// </summary>
+    public static class SessionExtensions
+    {
+        /// <summary>
+        /// Lưu object vào Session (serialize thành JSON)
+        /// </summary>
+        public static void SetComplexData<T>(this ISession session, string key, T value)
+        {
+            if (value == null)
+            {
+                session.Remove(key);
+                return;
+            }
+            session.SetString(key, JsonConvert.SerializeObject(value));
+        }
+
+        /// <summary>
+        /// Đọc object từ Session (deserialize từ JSON)
+        /// </summary>
+        public static T? GetComplexData<T>(this ISession session, string key)
+        {
+            var value = session.GetString(key);
+            if (string.IsNullOrEmpty(value))
+            {
+                return default;
+            }
+            return JsonConvert.DeserializeObject<T>(value);
+        }
+
+        /// <summary>
+        /// Check xem session có chứa key không
+        /// </summary>
+        public static bool HasKey(this ISession session, string key)
+        {
+            return !string.IsNullOrEmpty(session.GetString(key));
+        }
+
+        /// <summary>
+        /// Xóa tất cả session data
+        /// </summary>
+        public static void ClearAll(this ISession session)
+        {
+            session.Clear();
+        }
+    }
+}

+ 729 - 0
SicboSub/SicboSub.Web/Language/Language.Designer.cs

@@ -0,0 +1,729 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SicboSub.Web.Language {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    public class Language {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Language() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        public static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SicboSub.Web.Language.Language", typeof(Language).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        public static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Account.
+        /// </summary>
+        public static string Account {
+            get {
+                return ResourceManager.GetString("Account", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Buy more.
+        /// </summary>
+        public static string BuyMore {
+            get {
+                return ResourceManager.GetString("BuyMore", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cancel.
+        /// </summary>
+        public static string Cancel {
+            get {
+                return ResourceManager.GetString("Cancel", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Close.
+        /// </summary>
+        public static string Close {
+            get {
+                return ResourceManager.GetString("Close", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Coin Amount.
+        /// </summary>
+        public static string CoinAmount {
+            get {
+                return ResourceManager.GetString("CoinAmount", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Coins.
+        /// </summary>
+        public static string Coins {
+            get {
+                return ResourceManager.GetString("Coins", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Account.
+        /// </summary>
+        public static string ColAccount {
+            get {
+                return ResourceManager.GetString("ColAccount", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Coin.
+        /// </summary>
+        public static string ColCoin {
+            get {
+                return ResourceManager.GetString("ColCoin", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to ID.
+        /// </summary>
+        public static string ColID {
+            get {
+                return ResourceManager.GetString("ColID", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to No.
+        /// </summary>
+        public static string ColNo {
+            get {
+                return ResourceManager.GetString("ColNo", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Player.
+        /// </summary>
+        public static string ColPlayer {
+            get {
+                return ResourceManager.GetString("ColPlayer", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Rewards.
+        /// </summary>
+        public static string ColRewards {
+            get {
+                return ResourceManager.GetString("ColRewards", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Status.
+        /// </summary>
+        public static string ColStatus {
+            get {
+                return ResourceManager.GetString("ColStatus", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Time.
+        /// </summary>
+        public static string ColTime {
+            get {
+                return ResourceManager.GetString("ColTime", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Top.
+        /// </summary>
+        public static string ColTop {
+            get {
+                return ResourceManager.GetString("ColTop", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Type.
+        /// </summary>
+        public static string ColType {
+            get {
+                return ResourceManager.GetString("ColType", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Value.
+        /// </summary>
+        public static string ColValue {
+            get {
+                return ResourceManager.GetString("ColValue", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Confirm.
+        /// </summary>
+        public static string Confirm {
+            get {
+                return ResourceManager.GetString("Confirm", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Confirm buy more.
+        /// </summary>
+        public static string ConfirmBuyMore {
+            get {
+                return ResourceManager.GetString("ConfirmBuyMore", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Do you confirm to buy the Daily Package?.
+        /// </summary>
+        public static string ConfirmDailyPackage {
+            get {
+                return ResourceManager.GetString("ConfirmDailyPackage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Congratulations.
+        /// </summary>
+        public static string Congratulations {
+            get {
+                return ResourceManager.GetString("Congratulations", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Congratulations, you have successfully claimed your prize..
+        /// </summary>
+        public static string Congratulationsyouhave {
+            get {
+                return ResourceManager.GetString("Congratulationsyouhave", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Daily.
+        /// </summary>
+        public static string Daily {
+            get {
+                return ResourceManager.GetString("Daily", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Daily Package.
+        /// </summary>
+        public static string DailyPackage {
+            get {
+                return ResourceManager.GetString("DailyPackage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Data Not Found.
+        /// </summary>
+        public static string DataNotFound {
+            get {
+                return ResourceManager.GetString("DataNotFound", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Do you want to buy.
+        /// </summary>
+        public static string DoYouWantToBuy {
+            get {
+                return ResourceManager.GetString("DoYouWantToBuy", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Game.
+        /// </summary>
+        public static string Game {
+            get {
+                return ResourceManager.GetString("Game", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to History.
+        /// </summary>
+        public static string History {
+            get {
+                return ResourceManager.GetString("History", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Game.
+        /// </summary>
+        public static string HistoryTabGame {
+            get {
+                return ResourceManager.GetString("HistoryTabGame", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Prize.
+        /// </summary>
+        public static string HistoryTabPrize {
+            get {
+                return ResourceManager.GetString("HistoryTabPrize", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Purchase.
+        /// </summary>
+        public static string HistoryTabPurchase {
+            get {
+                return ResourceManager.GetString("HistoryTabPurchase", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Home.
+        /// </summary>
+        public static string Home {
+            get {
+                return ResourceManager.GetString("Home", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to HTG.
+        /// </summary>
+        public static string HTG {
+            get {
+                return ResourceManager.GetString("HTG", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Insufficient coins to withdraw.
+        /// </summary>
+        public static string Insufficient {
+            get {
+                return ResourceManager.GetString("Insufficient", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Main balance.
+        /// </summary>
+        public static string MainBalance {
+            get {
+                return ResourceManager.GetString("MainBalance", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Monthly.
+        /// </summary>
+        public static string Monthly {
+            get {
+                return ResourceManager.GetString("Monthly", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Msisdn.
+        /// </summary>
+        public static string Msisdn {
+            get {
+                return ResourceManager.GetString("Msisdn", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to My coins.
+        /// </summary>
+        public static string MyCoins {
+            get {
+                return ResourceManager.GetString("MyCoins", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to My play.
+        /// </summary>
+        public static string Myplay {
+            get {
+                return ResourceManager.GetString("Myplay", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Next.
+        /// </summary>
+        public static string Next {
+            get {
+                return ResourceManager.GetString("Next", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Package.
+        /// </summary>
+        public static string Package {
+            get {
+                return ResourceManager.GetString("Package", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Phone number.
+        /// </summary>
+        public static string PhoneNumber {
+            get {
+                return ResourceManager.GetString("PhoneNumber", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Play.
+        /// </summary>
+        public static string Play {
+            get {
+                return ResourceManager.GetString("Play", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Player.
+        /// </summary>
+        public static string Player {
+            get {
+                return ResourceManager.GetString("Player", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Price.
+        /// </summary>
+        public static string Price {
+            get {
+                return ResourceManager.GetString("Price", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Prize.
+        /// </summary>
+        public static string Prize {
+            get {
+                return ResourceManager.GetString("Prize", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Purchase.
+        /// </summary>
+        public static string Purchase {
+            get {
+                return ResourceManager.GetString("Purchase", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Ranking.
+        /// </summary>
+        public static string Ranking {
+            get {
+                return ResourceManager.GetString("Ranking", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Ranking coin.
+        /// </summary>
+        public static string Rankingcoin {
+            get {
+                return ResourceManager.GetString("Rankingcoin", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Register.
+        /// </summary>
+        public static string Register {
+            get {
+                return ResourceManager.GetString("Register", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Rewards.
+        /// </summary>
+        public static string Rewards {
+            get {
+                return ResourceManager.GetString("Rewards", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select Package.
+        /// </summary>
+        public static string SelectPackage {
+            get {
+                return ResourceManager.GetString("SelectPackage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Status.
+        /// </summary>
+        public static string Status {
+            get {
+                return ResourceManager.GetString("Status", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Failed.
+        /// </summary>
+        public static string StatusFail {
+            get {
+                return ResourceManager.GetString("StatusFail", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Lost.
+        /// </summary>
+        public static string StatusLost {
+            get {
+                return ResourceManager.GetString("StatusLost", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Pending.
+        /// </summary>
+        public static string StatusPending {
+            get {
+                return ResourceManager.GetString("StatusPending", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Successful.
+        /// </summary>
+        public static string StatusSuccessful {
+            get {
+                return ResourceManager.GetString("StatusSuccessful", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Won.
+        /// </summary>
+        public static string StatusWon {
+            get {
+                return ResourceManager.GetString("StatusWon", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Switch to Daily.
+        /// </summary>
+        public static string SwitchToDaily {
+            get {
+                return ResourceManager.GetString("SwitchToDaily", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Switch to Monthly.
+        /// </summary>
+        public static string SwitchToMonthly {
+            get {
+                return ResourceManager.GetString("SwitchToMonthly", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Time.
+        /// </summary>
+        public static string Time {
+            get {
+                return ResourceManager.GetString("Time", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Top.
+        /// </summary>
+        public static string Top {
+            get {
+                return ResourceManager.GetString("Top", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Total play coins.
+        /// </summary>
+        public static string TotalCoins {
+            get {
+                return ResourceManager.GetString("TotalCoins", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Total value this month.
+        /// </summary>
+        public static string TotalValueThisMonth {
+            get {
+                return ResourceManager.GetString("TotalValueThisMonth", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Total value today.
+        /// </summary>
+        public static string TotalValueToday {
+            get {
+                return ResourceManager.GetString("TotalValueToday", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Total withdraw today.
+        /// </summary>
+        public static string TotalWithdrawToday {
+            get {
+                return ResourceManager.GetString("TotalWithdrawToday", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Tunnel.
+        /// </summary>
+        public static string Tunnel {
+            get {
+                return ResourceManager.GetString("Tunnel", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Buy Turn.
+        /// </summary>
+        public static string TypeBuyTurn {
+            get {
+                return ResourceManager.GetString("TypeBuyTurn", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Unsubscribe.
+        /// </summary>
+        public static string Unsubscribe {
+            get {
+                return ResourceManager.GetString("Unsubscribe", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Verify.
+        /// </summary>
+        public static string Verify {
+            get {
+                return ResourceManager.GetString("Verify", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to View ranking coin tablet 👉.
+        /// </summary>
+        public static string ViewRankingCoin {
+            get {
+                return ResourceManager.GetString("ViewRankingCoin", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Winner.
+        /// </summary>
+        public static string Winner {
+            get {
+                return ResourceManager.GetString("Winner", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Withdraw.
+        /// </summary>
+        public static string Withdraw {
+            get {
+                return ResourceManager.GetString("Withdraw", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Withdraw value.
+        /// </summary>
+        public static string WithdrawValue {
+            get {
+                return ResourceManager.GetString("WithdrawValue", resourceCulture);
+            }
+        }
+    }
+}

+ 342 - 0
SicboSub/SicboSub.Web/Language/Language.resx

@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Myplay" xml:space="preserve">
+    <value>My play</value>
+  </data>
+  <data name="Rankingcoin" xml:space="preserve">
+    <value>Ranking coin</value>
+  </data>
+  <data name="ViewRankingCoin" xml:space="preserve">
+    <value>View ranking coin tablet 👉</value>
+  </data>
+  <data name="MyCoins" xml:space="preserve">
+    <value>My coins</value>
+  </data>
+  <data name="Register" xml:space="preserve">
+    <value>Register</value>
+  </data>
+  <data name="BuyMore" xml:space="preserve">
+    <value>Buy more</value>
+  </data>
+  <data name="Play" xml:space="preserve">
+    <value>Play</value>
+  </data>
+  <data name="SelectPackage" xml:space="preserve">
+    <value>Select Package</value>
+  </data>
+  <data name="Coins" xml:space="preserve">
+    <value>Coins</value>
+  </data>
+  <data name="HTG" xml:space="preserve">
+    <value>HTG</value>
+  </data>
+  <data name="Cancel" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name="Next" xml:space="preserve">
+    <value>Next</value>
+  </data>
+  <data name="ConfirmBuyMore" xml:space="preserve">
+    <value>Confirm buy more</value>
+  </data>
+  <data name="DoYouWantToBuy" xml:space="preserve">
+    <value>Do you want to buy</value>
+  </data>
+  <data name="Price" xml:space="preserve">
+    <value>Price</value>
+  </data>
+  <data name="Confirm" xml:space="preserve">
+    <value>Confirm</value>
+  </data>
+  <data name="ConfirmDailyPackage" xml:space="preserve">
+    <value>Do you confirm to buy the Daily Package?</value>
+  </data>
+  <data name="DailyPackage" xml:space="preserve">
+    <value>Daily Package</value>
+  </data>
+  <data name="PhoneNumber" xml:space="preserve">
+    <value>Phone number</value>
+  </data>
+  <data name="Tunnel" xml:space="preserve">
+    <value>Tunnel</value>
+  </data>
+  <data name="MainBalance" xml:space="preserve">
+    <value>Main balance</value>
+  </data>
+  <data name="TotalWithdrawToday" xml:space="preserve">
+    <value>Total withdraw today</value>
+  </data>
+  <data name="CoinAmount" xml:space="preserve">
+    <value>Coin Amount</value>
+  </data>
+  <data name="WithdrawValue" xml:space="preserve">
+    <value>Withdraw value</value>
+  </data>
+  <data name="Withdraw" xml:space="preserve">
+    <value>Withdraw</value>
+  </data>
+  <data name="TotalCoins" xml:space="preserve">
+    <value>Total play coins</value>
+  </data>
+  <data name="TotalValueToday" xml:space="preserve">
+    <value>Total value today</value>
+  </data>
+  <data name="TotalValueThisMonth" xml:space="preserve">
+    <value>Total value this month</value>
+  </data>
+  <data name="HistoryTabGame" xml:space="preserve">
+    <value>Game</value>
+  </data>
+  <data name="HistoryTabPrize" xml:space="preserve">
+    <value>Prize</value>
+  </data>
+  <data name="HistoryTabPurchase" xml:space="preserve">
+    <value>Purchase</value>
+  </data>
+  <data name="ColID" xml:space="preserve">
+    <value>ID</value>
+  </data>
+  <data name="ColTime" xml:space="preserve">
+    <value>Time</value>
+  </data>
+  <data name="ColStatus" xml:space="preserve">
+    <value>Status</value>
+  </data>
+  <data name="ColAccount" xml:space="preserve">
+    <value>Account</value>
+  </data>
+  <data name="ColValue" xml:space="preserve">
+    <value>Value</value>
+  </data>
+  <data name="ColCoin" xml:space="preserve">
+    <value>Coin</value>
+  </data>
+  <data name="ColNo" xml:space="preserve">
+    <value>No</value>
+  </data>
+  <data name="ColType" xml:space="preserve">
+    <value>Type</value>
+  </data>
+  <data name="StatusWon" xml:space="preserve">
+    <value>Won</value>
+  </data>
+  <data name="StatusLost" xml:space="preserve">
+    <value>Lost</value>
+  </data>
+  <data name="StatusPending" xml:space="preserve">
+    <value>Pending</value>
+  </data>
+  <data name="StatusSuccessful" xml:space="preserve">
+    <value>Successful</value>
+  </data>
+  <data name="StatusFail" xml:space="preserve">
+    <value>Failed</value>
+  </data>
+  <data name="TypeBuyTurn" xml:space="preserve">
+    <value>Buy Turn</value>
+  </data>
+  <data name="SwitchToMonthly" xml:space="preserve">
+    <value>Switch to Monthly</value>
+  </data>
+  <data name="SwitchToDaily" xml:space="preserve">
+    <value>Switch to Daily</value>
+  </data>
+  <data name="Daily" xml:space="preserve">
+    <value>Daily</value>
+  </data>
+  <data name="Monthly" xml:space="preserve">
+    <value>Monthly</value>
+  </data>
+  <data name="Ranking" xml:space="preserve">
+    <value>Ranking</value>
+  </data>
+  <data name="ColTop" xml:space="preserve">
+    <value>Top</value>
+  </data>
+  <data name="ColPlayer" xml:space="preserve">
+    <value>Player</value>
+  </data>
+  <data name="ColRewards" xml:space="preserve">
+    <value>Rewards</value>
+  </data>
+  <data name="Home" xml:space="preserve">
+    <value>Home</value>
+  </data>
+  <data name="History" xml:space="preserve">
+    <value>History</value>
+  </data>
+  <data name="Winner" xml:space="preserve">
+    <value>Winner</value>
+  </data>
+  <data name="Account" xml:space="preserve">
+    <value>Account</value>
+  </data>
+  <data name="Top" xml:space="preserve">
+    <value>Top</value>
+  </data>
+  <data name="Player" xml:space="preserve">
+    <value>Player</value>
+  </data>
+  <data name="Rewards" xml:space="preserve">
+    <value>Rewards</value>
+  </data>
+  <data name="Game" xml:space="preserve">
+    <value>Game</value>
+  </data>
+  <data name="Prize" xml:space="preserve">
+    <value>Prize</value>
+  </data>
+  <data name="Purchase" xml:space="preserve">
+    <value>Purchase</value>
+  </data>
+  <data name="Msisdn" xml:space="preserve">
+    <value>Msisdn</value>
+  </data>
+  <data name="Time" xml:space="preserve">
+    <value>Time</value>
+  </data>
+  <data name="Status" xml:space="preserve">
+    <value>Status</value>
+  </data>
+  <data name="Unsubscribe" xml:space="preserve">
+    <value>Unsubscribe</value>
+  </data>
+  <data name="DataNotFound" xml:space="preserve">
+    <value>Data Not Found</value>
+  </data>
+  <data name="Package" xml:space="preserve">
+    <value>Package</value>
+  </data>
+  <data name="Verify" xml:space="preserve">
+    <value>Verify</value>
+  </data>
+  <data name="Insufficient" xml:space="preserve">
+    <value>Insufficient coins to withdraw</value>
+  </data>
+  <data name="Congratulations" xml:space="preserve">
+    <value>Congratulations</value>
+  </data>
+  <data name="Congratulationsyouhave" xml:space="preserve">
+    <value>Congratulations, you have successfully claimed your prize.</value>
+  </data>
+  <data name="Close" xml:space="preserve">
+    <value>Close</value>
+  </data>
+</root>

+ 342 - 0
SicboSub/SicboSub.Web/Language/Language.vi.resx

@@ -0,0 +1,342 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="Myplay" xml:space="preserve">
+    <value>Lượt chơi của tôi</value>
+  </data>
+  <data name="Rankingcoin" xml:space="preserve">
+    <value>Xếp hạng xu</value>
+  </data>
+  <data name="ViewRankingCoin" xml:space="preserve">
+    <value>Xem bảng xếp hạng xu 👉</value>
+  </data>
+  <data name="MyCoins" xml:space="preserve">
+    <value>Xu của tôi</value>
+  </data>
+  <data name="Register" xml:space="preserve">
+    <value>Đăng ký</value>
+  </data>
+  <data name="BuyMore" xml:space="preserve">
+    <value>Mua thêm</value>
+  </data>
+  <data name="Play" xml:space="preserve">
+    <value>Chơi</value>
+  </data>
+  <data name="SelectPackage" xml:space="preserve">
+    <value>Chọn gói</value>
+  </data>
+  <data name="Coins" xml:space="preserve">
+    <value>Xu</value>
+  </data>
+  <data name="HTG" xml:space="preserve">
+    <value>HTG</value>
+  </data>
+  <data name="Cancel" xml:space="preserve">
+    <value>Hủy</value>
+  </data>
+  <data name="Next" xml:space="preserve">
+    <value>Tiếp tục</value>
+  </data>
+  <data name="ConfirmBuyMore" xml:space="preserve">
+    <value>Xác nhận mua thêm</value>
+  </data>
+  <data name="DoYouWantToBuy" xml:space="preserve">
+    <value>Bạn có muốn mua</value>
+  </data>
+  <data name="Price" xml:space="preserve">
+    <value>Giá</value>
+  </data>
+  <data name="Confirm" xml:space="preserve">
+    <value>Xác nhận</value>
+  </data>
+  <data name="ConfirmDailyPackage" xml:space="preserve">
+    <value>Bạn có xác nhận mua Gói hàng ngày không?</value>
+  </data>
+  <data name="DailyPackage" xml:space="preserve">
+    <value>Gói hàng ngày</value>
+  </data>
+  <data name="PhoneNumber" xml:space="preserve">
+    <value>Số điện thoại</value>
+  </data>
+  <data name="Tunnel" xml:space="preserve">
+    <value>Kênh</value>
+  </data>
+  <data name="MainBalance" xml:space="preserve">
+    <value>Tài khoản chính</value>
+  </data>
+  <data name="TotalWithdrawToday" xml:space="preserve">
+    <value>Tổng rút hôm nay</value>
+  </data>
+  <data name="CoinAmount" xml:space="preserve">
+    <value>Số lượng xu</value>
+  </data>
+  <data name="WithdrawValue" xml:space="preserve">
+    <value>Giá trị rút</value>
+  </data>
+  <data name="Withdraw" xml:space="preserve">
+    <value>Rút tiền</value>
+  </data>
+  <data name="TotalCoins" xml:space="preserve">
+    <value>Tổng số xu</value>
+  </data>
+  <data name="TotalValueToday" xml:space="preserve">
+    <value>Tổng giá trị hôm nay</value>
+  </data>
+  <data name="TotalValueThisMonth" xml:space="preserve">
+    <value>Tổng giá trị tháng này</value>
+  </data>
+  <data name="HistoryTabGame" xml:space="preserve">
+    <value>Trò chơi</value>
+  </data>
+  <data name="HistoryTabPrize" xml:space="preserve">
+    <value>Giải thưởng</value>
+  </data>
+  <data name="HistoryTabPurchase" xml:space="preserve">
+    <value>Mua hàng</value>
+  </data>
+  <data name="ColID" xml:space="preserve">
+    <value>ID</value>
+  </data>
+  <data name="ColTime" xml:space="preserve">
+    <value>Thời gian</value>
+  </data>
+  <data name="ColStatus" xml:space="preserve">
+    <value>Trạng thái</value>
+  </data>
+  <data name="ColAccount" xml:space="preserve">
+    <value>Tài khoản</value>
+  </data>
+  <data name="ColValue" xml:space="preserve">
+    <value>Giá trị</value>
+  </data>
+  <data name="ColCoin" xml:space="preserve">
+    <value>Xu</value>
+  </data>
+  <data name="ColNo" xml:space="preserve">
+    <value>STT</value>
+  </data>
+  <data name="ColType" xml:space="preserve">
+    <value>Loại</value>
+  </data>
+  <data name="StatusWon" xml:space="preserve">
+    <value>Thắng</value>
+  </data>
+  <data name="StatusLost" xml:space="preserve">
+    <value>Thua</value>
+  </data>
+  <data name="StatusPending" xml:space="preserve">
+    <value>Đang xử lý</value>
+  </data>
+  <data name="StatusSuccessful" xml:space="preserve">
+    <value>Thành công</value>
+  </data>
+  <data name="StatusFail" xml:space="preserve">
+    <value>Thất bại</value>
+  </data>
+  <data name="TypeBuyTurn" xml:space="preserve">
+    <value>Mua lượt</value>
+  </data>
+  <data name="SwitchToMonthly" xml:space="preserve">
+    <value>Chuyển sang tháng</value>
+  </data>
+  <data name="SwitchToDaily" xml:space="preserve">
+    <value>Chuyển sang ngày</value>
+  </data>
+  <data name="Daily" xml:space="preserve">
+    <value>Ngày</value>
+  </data>
+  <data name="Monthly" xml:space="preserve">
+    <value>Tháng</value>
+  </data>
+  <data name="Ranking" xml:space="preserve">
+    <value>Xếp hạng</value>
+  </data>
+  <data name="ColTop" xml:space="preserve">
+    <value>Top</value>
+  </data>
+  <data name="ColPlayer" xml:space="preserve">
+    <value>Người chơi</value>
+  </data>
+  <data name="ColRewards" xml:space="preserve">
+    <value>Phần thưởng</value>
+  </data>
+  <data name="Home" xml:space="preserve">
+    <value>Home</value>
+  </data>
+  <data name="History" xml:space="preserve">
+    <value>History</value>
+  </data>
+  <data name="Winner" xml:space="preserve">
+    <value>Winner</value>
+  </data>
+  <data name="Account" xml:space="preserve">
+    <value>Account</value>
+  </data>
+  <data name="Top" xml:space="preserve">
+    <value>Top</value>
+  </data>
+  <data name="Player" xml:space="preserve">
+    <value>Player</value>
+  </data>
+  <data name="Rewards" xml:space="preserve">
+    <value>Rewards</value>
+  </data>
+  <data name="Game" xml:space="preserve">
+    <value>Game</value>
+  </data>
+  <data name="Prize" xml:space="preserve">
+    <value>Prize</value>
+  </data>
+  <data name="Purchase" xml:space="preserve">
+    <value>Purchase</value>
+  </data>
+  <data name="Msisdn" xml:space="preserve">
+    <value>Msisdn</value>
+  </data>
+  <data name="Time" xml:space="preserve">
+    <value>Time</value>
+  </data>
+  <data name="Status" xml:space="preserve">
+    <value>Status</value>
+  </data>
+  <data name="Unsubscribe" xml:space="preserve">
+    <value>Unsubscribe</value>
+  </data>
+  <data name="DataNotFound" xml:space="preserve">
+    <value>Data Not Found</value>
+  </data>
+  <data name="Package" xml:space="preserve">
+    <value>Package</value>
+  </data>
+  <data name="Verify" xml:space="preserve">
+    <value>Verify</value>
+  </data>
+  <data name="Insufficient" xml:space="preserve">
+    <value>Insufficient coins to withdraw</value>
+  </data>
+  <data name="Congratulations" xml:space="preserve">
+    <value>Congratulations</value>
+  </data>
+  <data name="Congratulationsyouhave" xml:space="preserve">
+    <value>Congratulations, you have successfully claimed your prize.</value>
+  </data>
+  <data name="Close" xml:space="preserve">
+    <value>Close</value>
+  </data>
+</root>

+ 70 - 0
SicboSub/SicboSub.Web/Models/AuthModels.cs

@@ -0,0 +1,70 @@
+using System.ComponentModel.DataAnnotations;
+using Newtonsoft.Json.Linq;
+
+namespace SicboSub.Web.Models
+{
+    #region Auth Request/Response
+
+    /// <summary>
+    /// Request đăng nhập bằng token từ URL
+    /// </summary>
+    public class TokenLoginReq
+    {
+        [Required]
+        public string? token { get; set; }
+
+        public string? language { get; set; }
+    }
+
+    /// <summary>
+    /// Data trả về sau khi login thành công
+    /// </summary>
+    public class TokenLoginData
+    {
+        public decimal id { get; set; }
+        public string? msisdn { get; set; }
+        public string? username { get; set; }
+        public string? fullname { get; set; }
+        public string? picture { get; set; }
+        public decimal winCoin { get; set; }
+        public decimal betCoin { get; set; }
+        public int? point { get; set; }
+        public int? freeSpin { get; set; }
+        public byte? status { get; set; }
+        public bool isRegistered { get; set; }
+        public RegInfoData? regPkg { get; set; }
+    }
+
+    public class RegInfoData
+    {
+        public decimal RegisterId { get; set; }
+        public string? Msisdn { get; set; }
+        public string? ProductName { get; set; }
+        public DateTime? RegisterTime { get; set; }
+        public short? NumberSpin { get; set; }
+        public bool? Status { get; set; }
+        public DateTime? ExpireTime { get; set; }
+        public byte? Renew { get; set; }
+    }
+
+    /// <summary>
+    /// Response login - kế thừa CommonResponse
+    /// </summary>
+    public class TokenLoginRes : CommonResponse
+    {
+        public TokenLoginData? data { get; set; }
+
+        public TokenLoginRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                data = jObject["data"]!.ToObject<TokenLoginData>();
+            }
+        }
+    }
+
+    #endregion
+}

+ 23 - 0
SicboSub/SicboSub.Web/Models/CommonResponse.cs

@@ -0,0 +1,23 @@
+using Newtonsoft.Json.Linq;
+
+namespace SicboSub.Web.Models
+{
+    /// <summary>
+    /// Base Response class
+    /// </summary>
+    public class CommonResponse
+    {
+        public string? errorCode { get; set; }
+        public string? message { get; set; }
+
+        public void BuildCommonResponse(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            if (jObject != null)
+            {
+                errorCode = jObject["errorCode"]?.ToString();
+                message = jObject["message"]?.ToString();
+            }
+        }
+    }
+}

+ 179 - 0
SicboSub/SicboSub.Web/Models/HistoryModels.cs

@@ -0,0 +1,179 @@
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+using System;
+
+namespace SicboSub.Web.Models
+{
+    public class PlayHistoryReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    public class PlayHistoryItem
+    {
+        public decimal id { get; set; }
+        public decimal roomId { get; set; }
+        public decimal bettingType { get; set; }
+        public decimal bettingValue { get; set; }
+        public DateTime bettingTime { get; set; }
+        public decimal winCoin { get; set; }
+        public decimal backCoin { get; set; }
+        public bool isWin { get; set; }
+    }
+
+    public class PlayHistoryRes : CommonResponse
+    {
+        public List<PlayHistoryItem>? data { get; set; }
+
+        public PlayHistoryRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                 // The API returns data as an object: { "history": [...], "pagination": {...} }
+                 // Similar to RankingHistory structure
+                var dataObj = jObject["data"];
+                if (dataObj["history"] != null)
+                {
+                    data = dataObj["history"]!.ToObject<List<PlayHistoryItem>>();
+                }
+            }
+        }
+    }
+
+    public class PurchaseHistoryReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    public class PurchaseHistoryItem
+    {
+        public decimal id { get; set; }
+        public string productName { get; set; } = null!;
+        public DateTime registerTime { get; set; }
+        public DateTime expireTime { get; set; }
+        public decimal serviceId { get; set; } // Fee
+        public string channel { get; set; } = null!;
+        public int status { get; set; }
+        public int renew { get; set; }
+    }
+
+    public class PurchaseHistoryRes : CommonResponse
+    {
+        public List<PurchaseHistoryItem>? data { get; set; }
+
+        public PurchaseHistoryRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                var dataObj = jObject["data"];
+                if (dataObj["history"] != null)
+                {
+                    data = dataObj["history"]!.ToObject<List<PurchaseHistoryItem>>();
+                }
+            }
+        }
+    }
+
+    public class ExchangeConfigReq
+    {
+        public string? lang { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    public class ExchangeConfigItem
+    {
+        public decimal id { get; set; }
+        public string productName { get; set; } = null!;
+        public decimal coinCost { get; set; }
+        public decimal moneyReceived { get; set; }
+        public decimal feeCoin { get; set; }
+        public string description { get; set; } = null!;
+    }
+
+    public class ExchangeConfigRes : CommonResponse
+    {
+        public List<ExchangeConfigItem>? data { get; set; }
+
+        public ExchangeConfigRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                var dataObj = jObject["data"]; 
+                // The Package API returns { "exchangeConfigs": [...], "pagination": ... }
+                if (dataObj["exchangeConfigs"] != null)
+                {
+                     data = dataObj["exchangeConfigs"]!.ToObject<List<ExchangeConfigItem>>();
+                }
+                else 
+                {
+                     // Fallback 
+                     try {
+                        data = dataObj.ToObject<List<ExchangeConfigItem>>();
+                     } catch {}
+                }
+            }
+        }
+    }
+    public class ExchangeRequestOtpReq
+    {
+        public decimal configId { get; set; }
+        public string? lang { get; set; }
+        public string msisdn { get; set; }
+    }
+
+    public class ExchangeVerifyOtpReq
+    {
+        public string otpCode { get; set; } = null!;
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+    }
+    public class ExchangeRequestOtpRes : CommonResponse
+    {
+        public dynamic data { get; set; }
+
+        public ExchangeRequestOtpRes(string dataGet)
+        {
+             BuildCommonResponse(dataGet);
+             JObject jObject = JObject.Parse(dataGet);
+             if (jObject != null && jObject["data"] != null)
+             {
+                 data = jObject["data"];
+             }
+        }
+    }
+
+    public class ExchangeVerifyOtpRes : CommonResponse
+    {
+        public dynamic data { get; set; }
+
+        public ExchangeVerifyOtpRes(string dataGet)
+        {
+             BuildCommonResponse(dataGet);
+             JObject jObject = JObject.Parse(dataGet);
+             if (jObject != null && jObject["data"] != null)
+             {
+                 data = jObject["data"];
+             }
+        }
+    }
+}

+ 11 - 0
SicboSub/SicboSub.Web/Models/HistoryViewModel.cs

@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+
+namespace SicboSub.Web.Models
+{
+    public class HistoryViewModel
+    {
+        public List<PlayHistoryItem> GameHistory { get; set; } = new List<PlayHistoryItem>();
+        public List<RankingHistoryItem> PrizeHistory { get; set; } = new List<RankingHistoryItem>();
+        public List<PurchaseHistoryItem> PurchaseHistory { get; set; } = new List<PurchaseHistoryItem>();
+    }
+}

+ 50 - 0
SicboSub/SicboSub.Web/Models/RankingModels.cs

@@ -0,0 +1,50 @@
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+
+namespace SicboSub.Web.Models
+{
+    public class RankingHistoryReq
+    {
+        public string msisdn { get; set; } = null!;
+        public string? lang { get; set; }
+        public string? rankType { get; set; } 
+        public string? fromDate { get; set; }
+        public string? toDate { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    public class RankingHistoryItem
+    {
+        public decimal id { get; set; }
+        public string msisdn { get; set; } 
+        public string rankType { get; set; }
+        public DateTime rankDate { get; set; }
+        public decimal rankPosition { get; set; }
+        public decimal rewardValue { get; set; }
+        public string rewardUnit { get; set; }
+        public DateTime rewardDate { get; set; }
+        public decimal totalBetValue { get; set; }
+    }
+
+    public class RankingHistoryRes : CommonResponse
+    {
+        public List<RankingHistoryItem>? data { get; set; }
+
+        public RankingHistoryRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                // The API returns data as an object: { "history": [...], "pagination": {...} }
+                var dataObj = jObject["data"];
+                if (dataObj["history"] != null)
+                {
+                    data = dataObj["history"]!.ToObject<List<RankingHistoryItem>>();
+                }
+            }
+        }
+    }
+}

+ 113 - 0
SicboSub/SicboSub.Web/Models/SubscriptionModels.cs

@@ -0,0 +1,113 @@
+using Newtonsoft.Json.Linq;
+using System.Collections.Generic;
+
+namespace SicboSub.Web.Models
+{
+    public class RegisterReq
+    {
+        public string msisdn { get; set; }
+        public string packageCode { get; set; }
+        public string lang { get; set; }
+    }
+
+    public class RegisterData
+    {
+        public string msisdn { get; set; }
+        public decimal? winCoin { get; set; }
+        public decimal? betCoin { get; set; }
+        public decimal? coin { get; set; }
+        public string packageCode { get; set; }
+        public string regKey { get; set; }
+    }
+
+    public class RegisterRes : CommonResponse
+    {
+        public RegisterData? data { get; set; }
+
+        public RegisterRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                data = jObject["data"]!.ToObject<RegisterData>();
+            }
+        }
+    }
+
+    public class BuyMoreReq
+    {
+        public string msisdn { get; set; }
+        public string packageCode { get; set; }
+        public string lang { get; set; }
+    }
+
+    public class BuyMoreData
+    {
+        public string msisdn { get; set; }
+        public decimal? winCoin { get; set; }
+        public decimal? betCoin { get; set; }
+        public decimal? coin { get; set; }
+        public string packageCode { get; set; }
+    }
+
+    public class BuyMoreRes : CommonResponse
+    {
+        public BuyMoreData? data { get; set; }
+
+        public BuyMoreRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                data = jObject["data"]!.ToObject<BuyMoreData>();
+            }
+        }
+    }
+
+    public class PackageLoadReq
+    {
+        public string lang { get; set; }
+        public int pageNumber { get; set; } = 0;
+        public int pageSize { get; set; } = 20;
+    }
+
+    public class PackageInfo
+    {
+        public int productId { get; set; }
+        public string productName { get; set; }
+        public decimal fee { get; set; }
+        public decimal numberSpin { get; set; }
+        public int expireDays { get; set; }
+        public string smsSyntax { get; set; }
+    }
+
+    public class PackageLoadData
+    {
+        public List<PackageInfo> packages { get; set; }
+        public object pagination { get; set; }
+    }
+
+    public class PackageLoadRes : CommonResponse
+    {
+        public List<PackageInfo>? data { get; set; }
+
+        public PackageLoadRes(string dataGet)
+        {
+            JObject jObject = JObject.Parse(dataGet);
+            BuildCommonResponse(dataGet);
+
+            if (jObject != null && jObject["data"] != null)
+            {
+                var dataObj = jObject["data"];
+                if (dataObj["packages"] != null)
+                {
+                    data = dataObj["packages"]!.ToObject<List<PackageInfo>>();
+                }
+            }
+        }
+    }
+}

+ 21 - 0
SicboSub/SicboSub.Web/Program.cs

@@ -1,8 +1,26 @@
+using log4net;
+using log4net.Config;
+using System.Reflection;
+
 var builder = WebApplication.CreateBuilder(args);
 
+// Configure log4net
+var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
+XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
+
 // Add services to the container.
 builder.Services.AddControllersWithViews();
 
+// Add Session support
+builder.Services.AddDistributedMemoryCache();
+builder.Services.AddSession(options =>
+{
+    options.IdleTimeout = TimeSpan.FromMinutes(30); // Session timeout 30 phút
+    options.Cookie.HttpOnly = true;
+    options.Cookie.IsEssential = true;
+    options.Cookie.Name = ".Sicbo.Session";
+});
+
 var app = builder.Build();
 
 // Configure the HTTP request pipeline.
@@ -18,6 +36,9 @@ app.UseStaticFiles();
 
 app.UseRouting();
 
+// Enable Session (phải trước UseAuthorization)
+app.UseSession();
+
 app.UseAuthorization();
 
 app.MapControllerRoute(

+ 20 - 0
SicboSub/SicboSub.Web/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
+<Project>
+  <PropertyGroup>
+    <DeleteExistingFiles>false</DeleteExistingFiles>
+    <ExcludeApp_Data>false</ExcludeApp_Data>
+    <LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
+    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
+    <LastUsedPlatform>Any CPU</LastUsedPlatform>
+    <PublishProvider>FileSystem</PublishProvider>
+    <PublishUrl>D:\Code\Ex_publish\Natcom_SicboSub\web</PublishUrl>
+    <WebPublishMethod>FileSystem</WebPublishMethod>
+    <_TargetId>Folder</_TargetId>
+    <SiteUrlToLaunchAfterPublish />
+    <TargetFramework>net8.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <ProjectGuid>81272015-fbbc-41ec-a3b4-0014631f267d</ProjectGuid>
+    <SelfContained>true</SelfContained>
+  </PropertyGroup>
+</Project>

+ 36 - 0
SicboSub/SicboSub.Web/SicboSub.Web.csproj

@@ -6,4 +6,40 @@
     <ImplicitUsings>enable</ImplicitUsings>
   </PropertyGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="..\Common\Common.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="log4net" Version="2.0.15" />
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Reference Include="DotnetLib">
+      <HintPath>..\lib\DotnetLib.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Compile Update="Language\Language.Designer.cs">
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Language.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Update="log4net.config">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+  <ItemGroup>
+    <EmbeddedResource Update="Language\Language.resx">
+      <Generator>PublicResXFileCodeGenerator</Generator>
+      <LastGenOutput>Language.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+
 </Project>

+ 29 - 14
SicboSub/SicboSub.Web/Views/Home/Account.cshtml

@@ -1,5 +1,18 @@
+@using SicboSub.Web.Language;
 @{
     Layout = "_GameLayout";
+    var userInfo = ViewData["UserInfo"] as SicboSub.Web.Models.TokenLoginData;
+    var msisdn = ViewData["Msisdn"] as string;
+    var winCoin = ViewData["WinCoin"] ?? 0;
+    var betCoin = ViewData["BetCoin"] ?? 0;
+    // var totalValueToday = ViewData["TotalValueToday"] ?? 0;
+    // var totalValueMonth = ViewData["TotalValueMonth"] ?? 0;
+
+    // Determine avatar URL - use default if null/empty
+    var avatarUrl = !string.IsNullOrEmpty(userInfo?.picture) ? userInfo.picture : Url.Content("~/img/avatar.png");
+    
+    // Package Name or "Free"
+    var currentPackage = userInfo?.regPkg?.ProductName ?? "";
 }
 
 @section Styles {
@@ -18,39 +31,41 @@
         <!-- Left Side - Avatar -->
         <div class="account-avatar-section">
             <div class="avatar-frame">
-                <img class="avatar-image" src="~/img/avatar.png" alt="Avatar" />
+                <img class="avatar-image" src="@avatarUrl" alt="Avatar" onerror="this.src='@Url.Content("~/img/avatar.png")'" />
             </div>
-            <div class="avatar-name">Rosé Stark</div>
+            <div class="avatar-name">@msisdn</div>
         </div>
 
         <!-- Right Side - Account Info -->
         <div class="account-info-section">
             <!-- Phone Number -->
             <div class="info-row">
-                <span class="info-label">Phone number</span>
-                <span class="info-value">0912 345 678</span>
+                <span class="info-label">@Language.PhoneNumber</span>
+                <span class="info-value">@msisdn</span>
             </div>
 
-            <!-- Total Coins -->
+            <!-- Total Play Coins (My Play) -->
             <div class="info-row with-icon">
                 <div class="info-content">
-                    <span class="info-label">Total coins</span>
-                    <span class="info-value coins">140.000</span>
+                    <span class="info-label">@Language.TotalCoins</span>
+                    <span class="info-value coins">@String.Format("{0:n0}", betCoin)</span>
                 </div>
-                <img class="settings-icon" src="~/img/042-settings.png" alt="Settings" />
+                <img class="settings-icon" src="~/img/042-settings.png" alt="Settings" style="cursor:pointer;" onclick="alert('Settings feature coming soon!')" />
             </div>
 
-            <!-- Total Value Today -->
+            <!-- My Coins (Main Balance) -->
             <div class="info-row">
-                <span class="info-label">Total value today</span>
-                <span class="info-value money">$520.000</span>
+                <span class="info-label">@Language.MyCoins</span>
+                <span class="info-value coins">@String.Format("{0:n0}", winCoin)</span>
             </div>
 
-            <!-- Total Value This Month -->
+            <!-- Daily Package -->
             <div class="info-row">
-                <span class="info-label">Total value this month</span>
-                <span class="info-value money">$28.520.000</span>
+                <span class="info-label">@Language.DailyPackage</span>
+                <span class="info-value text-uppercase">@(string.IsNullOrEmpty(currentPackage) ? Language.Unsubscribe : currentPackage)</span>
             </div>
         </div>
     </div>
 </div>
+
+

+ 37 - 48
SicboSub/SicboSub.Web/Views/Home/DailyRanking.cshtml

@@ -1,7 +1,8 @@
+@model List<SicboSub.Web.Models.RankingHistoryItem>
 @{
     Layout = "_GameLayout";
 }
-
+@using SicboSub.Web.Language;
 @section Styles {
     <link rel="stylesheet" href="~/css/sicbo-ranking.css" />
 }
@@ -28,66 +29,54 @@
             <!-- Switch Button -->
             <a href="@Url.Action("MonthlyRanking", "Home")" class="switch-button">
                 <img class="switch-icon" src="~/img/017-strategy.png" alt="" />
-                <span class="switch-text">Switch to Monthy</span>
+                <span class="switch-text">@Language.SwitchToMonthly</span>
             </a>
             
             <!-- Title -->
             <div class="ranking-title daily">
-                <span class="title-line">Daily</span>
-                <span class="title-line">Ranking</span>
+                <span class="title-line">@Language.Daily</span>
+                <span class="title-line">@Language.Ranking</span>
             </div>
         </div>
 
         <!-- Table Header -->
         <div class="ranking-table-header">
-            <div class="col-top">Top</div>
-            <div class="col-player">Player</div>
-            <div class="col-rewards">Rewards</div>
+            <div class="col-top">@Language.Top</div>
+            <div class="col-player">@Language.Player</div>
+            <div class="col-player">@Language.Time</div>
+            <div class="col-rewards">@Language.Rewards</div>
         </div>
 
         <!-- Table Body -->
         <div class="ranking-table-body">
-            <!-- Row 1 - Gold -->
-            <div class="ranking-row gold">
-                <div class="col-top">1</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+1.500</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 2 - Silver -->
-            <div class="ranking-row silver">
-                <div class="col-top">2</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+500</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 3 - Bronze -->
-            <div class="ranking-row bronze">
-                <div class="col-top">3</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+250</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 4 -->
-            <div class="ranking-row">
-                <div class="col-top">4</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+150</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 5 -->
-            <div class="ranking-row">
-                <div class="col-top">5</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+75</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 6 -->
-            <div class="ranking-row">
-                <div class="col-top">6</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+50</span> <span class="reward-unit">Coins</span></div>
-            </div>
+            @if (Model != null && Model.Count > 0)
+            {
+                int top = 1;
+                foreach (var item in Model)
+                {
+                    var rowClass = "";
+                    if (top == 1) rowClass = "gold";
+                    else if (top == 2) rowClass = "silver";
+                    else if (top == 3) rowClass = "bronze";
+
+                    <div class="ranking-row @rowClass">
+                        <div class="col-top">@item.rankPosition</div>
+                        <div class="col-player">@(string.IsNullOrEmpty(item.msisdn) ? "****" : item.msisdn)</div>
+                        <div class="col-player">@item.rankDate.ToString("dd/MM/yyyy")</div>
+                        <div class="col-rewards">
+                            <span class="reward-value">+@item.rewardValue.ToString("N0")</span> 
+                            <span class="reward-unit">@item.rewardUnit</span>
+                        </div>
+                    </div>
+                    top++;
+                }
+            }
+            else
+            {
+                <div class="ranking-row" style="justify-content:center;">
+                    <span></span>
+                </div>
+            }
         </div>
     </div>
 </div>

+ 86 - 120
SicboSub/SicboSub.Web/Views/Home/History.cshtml

@@ -1,7 +1,9 @@
+@model SicboSub.Web.Models.HistoryViewModel
 @{
     Layout = "_GameLayout";
+    var msisdn = ViewData["Msisdn"] as string;
 }
-
+@using SicboSub.Web.Language;
 @section Styles {
     <link rel="stylesheet" href="~/css/sicbo-history.css" />
 }
@@ -18,13 +20,13 @@
         <!-- Tab Buttons -->
         <div class="history-tabs">
             <div class="tab-button active" data-tab="game">
-                <span class="tab-label">Game</span>
+                <span class="tab-label">@Language.Game</span>
             </div>
             <div class="tab-button" data-tab="prize">
-                <span class="tab-label">Prize</span>
+                <span class="tab-label">@Language.Prize</span>
             </div>
             <div class="tab-button" data-tab="purchase">
-                <span class="tab-label">Purchase</span>
+                <span class="tab-label">@Language.Purchase</span>
             </div>
         </div>
 
@@ -32,49 +34,39 @@
         <div class="history-table" id="game-table">
             <!-- Header Row -->
             <div class="table-header">
-                <div class="col-id">ID</div>
-                <div class="col-time">Time</div>
-                <div class="col-coin">Coin</div>
-                <div class="col-status">Status</div>
+                <div class="col-id">@Language.Msisdn</div>
+                <div class="col-time">@Language.Time</div>
+                <div class="col-coin">@Language.Coins</div>
+                <div class="col-status">@Language.Status</div>
             </div>
 
             <!-- Data Rows -->
-            <div class="table-row">
-                <div class="col-id">AA001</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin positive">+5.000</div>
-                <div class="col-status won">Won</div>
-            </div>
-            <div class="table-row">
-                <div class="col-id">AA002</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin positive">+50.000</div>
-                <div class="col-status won">Won</div>
-            </div>
-            <div class="table-row">
-                <div class="col-id">AA003</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin positive">+50.000</div>
-                <div class="col-status won">Won</div>
-            </div>
-            <div class="table-row">
-                <div class="col-id">AA004</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin positive">+50.000</div>
-                <div class="col-status won">Won</div>
-            </div>
-            <div class="table-row">
-                <div class="col-id">AA005</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin negative">-50.000</div>
-                <div class="col-status lost">Losed</div>
-            </div>
-            <div class="table-row">
-                <div class="col-id">AA006</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-coin negative">-250.000</div>
-                <div class="col-status lost">Losed</div>
-            </div>
+            @if (Model != null && Model.GameHistory != null && Model.GameHistory.Count > 0)
+            {
+                foreach (var item in Model.GameHistory)
+                {
+                    <div class="table-row">
+                        <div class="col-id">@msisdn</div>
+                        <div class="col-time">@item.bettingTime.ToString("dd/MM/yyyy, HH:mm:ss")</div>
+                        @if (item.isWin)
+                        {
+                             <div class="col-coin positive">+@item.winCoin.ToString("N0")</div>
+                             <div class="col-status won">Won</div>
+                        }
+                        else
+                        {
+                             <div class="col-coin negative">-@item.bettingValue.ToString("N0")</div>
+                             <div class="col-status lost">Lost</div>
+                        }
+                    </div>
+                }
+            }
+            else
+            {
+                <div class="table-row" style="justify-content:center;">
+                    <span></span>
+                </div>
+            }
         </div>
 
         <!-- Prize History Table (Hidden by default) -->
@@ -84,46 +76,28 @@
                 <div class="col-account">Account</div>
                 <div class="col-time">Time</div>
                 <div class="col-value">Value</div>
-                <div class="col-status">Status</div>
+                <div class="col-status">Rank</div>
             </div>
 
             <!-- Data Rows -->
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">250.000 <span class="usd">USD</span></div>
-                <div class="col-status pending">Peding</div>
-            </div>
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">25.000 <span class="usd">USD</span></div>
-                <div class="col-status successful">Successful</div>
-            </div>
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">1.000.000 <span class="usd">USD</span></div>
-                <div class="col-status fail">Fail</div>
-            </div>
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">5.000 <span class="usd">USD</span></div>
-                <div class="col-status successful">Successful</div>
-            </div>
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">2.000.000 <span class="usd">USD</span></div>
-                <div class="col-status fail">Fail</div>
-            </div>
-            <div class="table-row">
-                <div class="col-account">0912345678</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">105.000 <span class="usd">USD</span></div>
-                <div class="col-status successful">Successful</div>
-            </div>
+            @if (Model != null && Model.PrizeHistory != null && Model.PrizeHistory.Count > 0)
+            {
+                foreach (var item in Model.PrizeHistory)
+                {
+                    <div class="table-row">
+                        <div class="col-account">@msisdn</div>
+                        <div class="col-time">@item.rewardDate.ToString("dd/MM/yyyy, HH:mm:ss")</div>
+                        <div class="col-value">@item.rewardValue.ToString("N0") <span class="usd">@item.rewardUnit</span></div>
+                        <div class="col-status successful">Top @item.rankPosition</div>
+                    </div>
+                }
+            }
+            else
+            {
+                <div class="table-row" style="justify-content:center;">
+                    <span></span>
+                </div>
+            }
         </div>
 
         <!-- Purchase History Table (Hidden by default) -->
@@ -131,48 +105,40 @@
             <!-- Header Row -->
             <div class="table-header">
                 <div class="col-no">No</div>
-                <div class="col-time">Time</div>
-                <div class="col-value">Value</div>
-                <div class="col-type">Type</div>
+                <div class="col-time">@Language.Time</div>
+                <div class="col-value">@Language.Price</div>
+                <div class="col-type">@Language.Package</div>
+                <div class="col-status">@Language.Status</div>
             </div>
 
             <!-- Data Rows -->
-            <div class="table-row">
-                <div class="col-no">1</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">50 <span class="coins">Coins</span></div>
-                <div class="col-type daily-package">Daily Package</div>
-            </div>
-            <div class="table-row">
-                <div class="col-no">2</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">500 <span class="coins">Coins</span></div>
-                <div class="col-type buy-turn">Buy Turn</div>
-            </div>
-            <div class="table-row">
-                <div class="col-no">3</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">50 <span class="coins">Coins</span></div>
-                <div class="col-type daily-package">Daily Package</div>
-            </div>
-            <div class="table-row">
-                <div class="col-no">4</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">50 <span class="coins">Coins</span></div>
-                <div class="col-type buy-turn">Buy Turn</div>
-            </div>
-            <div class="table-row">
-                <div class="col-no">5</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">250 <span class="coins">Coins</span></div>
-                <div class="col-type buy-turn">Buy Turn</div>
-            </div>
-            <div class="table-row">
-                <div class="col-no">6</div>
-                <div class="col-time">20/12/2026, 18:00:00</div>
-                <div class="col-value">50 <span class="coins">Coins</span></div>
-                <div class="col-type daily-package">Daily Package</div>
-            </div>
+            @if (Model != null && Model.PurchaseHistory != null && Model.PurchaseHistory.Count > 0)
+            {
+                int no = 1;
+                foreach (var item in Model.PurchaseHistory)
+                {
+                    <div class="table-row">
+                        <div class="col-no">@(no++)</div>
+                        <div class="col-time">@item.registerTime.ToString("dd/MM/yyyy HH:mm:ss")</div>
+                        <div class="col-value">@item.serviceId.ToString("N0") <span class="coins">HTG</span></div>
+                        <div class="col-type">@item.productName</div>
+                        @if (item.status == 1) // Assuming 1 is Success
+                        {
+                             <div class="col-status successful">Success</div>
+                        }
+                        else
+                        {
+                             <div class="col-status fail">Failed</div>
+                        }
+                    </div>
+                }
+            }
+            else
+            {
+                <div class="table-row" style="justify-content:center;">
+                    <span></span>
+                </div>
+            }
         </div>
     </div>
 </div>

+ 587 - 200
SicboSub/SicboSub.Web/Views/Home/Index.cshtml

@@ -1,10 +1,15 @@
+@using SicboSub.Web.Helpers;
+@using SicboSub.Web.Language;
 @{
     Layout = "_GameLayout";
+    var packages = Context.Session.GetComplexData<List<SicboSub.Web.Models.PackageInfo>>("Packages");
+    var isRegistered = Context.Session.GetComplexData<bool?>("isRegistered") ?? false;
 }
 
 @section Styles {
-    <link rel="stylesheet" href="~/css/sicbo-popup.css" />
+    <link rel="stylesheet" href="~/css/sicbo-popup.css" asp-append-version="true" />
 }
+<!-- Game User Info Header -->
 
 <div class="home">
     <div class="image-2-parent">
@@ -15,50 +20,54 @@
 
         <partial name="_GameMenu" />
 
+        
+    </div>
+    @if (ViewData["IsAuthenticated"] is bool isAuth && isAuth)
+    {
         <div class="frame-parent">
             <div class="medal-parent">
                 <img class="hourglass-icon" src="~/img/021-medal-2.svg" alt="">
-                <div class="ranking-coin">Ranking coin</div>
-                <b class="view-ranking-coin">View ranking coin tablet 👉</b>
+                <div class="ranking-coin">@Language.Rankingcoin</div>
+                <b class="view-ranking-coin">@Language.ViewRankingCoin</b>
             </div>
             <div class="frame-group">
                 <div class="frame-container">
                     <div class="my-play-parent">
-                        <div class="my-play"> My play</div>
+                        <div class="my-play">@Language.Myplay</div>
                         <div class="frame-item">
                         </div>
                     </div>
                     <div class="sword-parent">
                         <img class="sword-icon" src="~/img/003-sword.svg" alt="">
-                        <div class="my-play">1.400</div>
+                        <div id="betCoinVal" class="my-play">@String.Format("{0:n0}", ViewData["BetCoin"])</div>
                     </div>
                 </div>
                 <div class="frame-container">
                     <div class="my-coins-parent">
-                        <div class="my-play">My coins</div>
+                        <div class="my-play">@Language.MyCoins</div>
                         <div class="frame-item">
                         </div>
                     </div>
                     <div class="sword-parent">
                         <img class="sword-icon" src="~/img/021-medal.svg" alt="">
-                        <div class="my-play">140.000</div>
+                        <div id="winCoinVal" class="my-play">@String.Format("{0:n0}", ViewData["WinCoin"])</div>
                     </div>
                 </div>
             </div>
         </div>
-    </div>
+    
     <div class="frame-parent3">
         <div id="registerBtnContainer" class="rectangle-parent" style="cursor: pointer;" onclick="handleRegisterClick()">
             <div class="rectangle-div">
             </div>
             <!-- Register/Withdraw Button -->
-            <div id="registerBtnLabel" class="button-label">Register</div>
+            <div id="registerBtnLabel" class="button-label">@(isRegistered ? Language.Withdraw : Language.Register)</div>
         </div>
         <div class="rectangle-parent" style="cursor: pointer;" onclick="handleBuyMore()">
             <div class="rectangle-div">
             </div>
             <!-- Buy more Button -->
-            <div class="button-label2">Buy more</div>
+            <div class="button-label2">@Language.BuyMore</div>
         </div>
 
         <!-- PLAY BUTTON COMPLEX -->
@@ -86,13 +95,13 @@
         </div>
     </div>
     <!-- <img class="home-barpro-icon" alt=""> -->
-
+    }
     <!-- Select Package Popup -->
     <div id="selectPackagePopup" class="popup-overlay" style="display: none;">
         <div class="popup-container">
             <!-- Header -->
             <div class="popup-header">
-                <span class="popup-title">Select Package</span>
+                <span class="popup-title">@Language.SelectPackage</span>
             </div>
             
             <!-- Close Button -->
@@ -104,41 +113,30 @@
             
             <!-- Package Options -->
             <div class="package-list">
-                <label class="package-option">
-                    <input type="radio" name="package" value="500" />
-                    <span class="package-coins">500 <span class="coins-text">Coins</span></span>
-                    <span class="package-htg">5 <span class="htg-text">HTG</span></span>
-                </label>
-                
-                <label class="package-option">
-                    <input type="radio" name="package" value="400" />
-                    <span class="package-coins">400 <span class="coins-text">Coins</span></span>
-                    <span class="package-htg">4 <span class="htg-text">HTG</span></span>
-                </label>
-                
-                <label class="package-option">
-                    <input type="radio" name="package" value="300" />
-                    <span class="package-coins">300 <span class="coins-text">Coins</span></span>
-                    <span class="package-htg">3 <span class="htg-text">HTG</span></span>
-                </label>
-                
-                <label class="package-option">
-                    <input type="radio" name="package" value="200" />
-                    <span class="package-coins">200 <span class="coins-text">Coins</span></span>
-                    <span class="package-htg">2 <span class="htg-text">HTG</span></span>
-                </label>
-                
-                <label class="package-option">
-                    <input type="radio" name="package" value="100" checked />
-                    <span class="package-coins">100 <span class="coins-text">Coins</span></span>
-                    <span class="package-htg">1 <span class="htg-text">HTG</span></span>
-                </label>
+                @if (packages != null && packages.Any())
+                {
+                    var isFirst = true;
+                    foreach (var pkg in packages)
+                    {
+                        var checkedAttr = isFirst ? "checked" : "";
+                        isFirst = false;
+                        <label class="package-option">
+                            <input type="radio" name="package" value="@pkg.productName" data-price="@pkg.fee" data-coin="@pkg.numberSpin" @checkedAttr />
+                            <span class="package-coins">@String.Format("{0:n0}", pkg.numberSpin) <span class="coins-text">@Language.Coins</span></span>
+                            <span class="package-htg">@String.Format("{0:n0}", pkg.fee) <span class="htg-text">@Language.HTG</span></span>
+                        </label>
+                    }
+                }
+                else
+                {
+                     <div style="color:white;text-align:center;">No packages available</div>
+                }
             </div>
             
             <!-- Action Buttons -->
             <div class="popup-actions">
-                <button class="popup-btn cancel-btn" onclick="closePackagePopup()">Cancel</button>
-                <button class="popup-btn next-btn" onclick="handlePackageNext()">Next</button>
+                <button class="popup-btn cancel-btn" onclick="closePackagePopup()">@Language.Cancel</button>
+                <button class="popup-btn next-btn" onclick="handlePackageNext()">@Language.Next</button>
             </div>
         </div>
     </div>
@@ -148,7 +146,7 @@
         <div class="popup-container confirm-popup">
             <!-- Header -->
             <div class="popup-header">
-                <span class="popup-title">Confirm buy more</span>
+                <span class="popup-title">@Language.ConfirmBuyMore</span>
             </div>
             
             <!-- Close Button -->
@@ -160,15 +158,15 @@
             
             <!-- Confirm Content -->
             <div class="confirm-content">
-                <p class="confirm-message">Do you want to buy</p>
-                <p class="confirm-coins"><span id="confirmCoinsAmount">100</span> <span class="coins-label">Coins</span></p>
-                <p class="confirm-price">Price <span id="confirmPriceAmount">1</span> <span class="htg-label">HTG</span></p>
+                <p class="confirm-message">@Language.DoYouWantToBuy</p>
+                <p class="confirm-coins"><span id="confirmCoinsAmount">100</span> <span class="coins-label">@Language.Coins</span></p>
+                <p class="confirm-price">Price <span id="confirmPriceAmount">1</span> <span class="htg-label">@Language.HTG</span></p>
             </div>
             
             <!-- Action Buttons -->
             <div class="popup-actions">
-                <button class="popup-btn cancel-btn" onclick="closeConfirmPopup()">Cancel</button>
-                <button class="popup-btn next-btn" onclick="handleConfirmBuy()">Confirm</button>
+                <button class="popup-btn cancel-btn" onclick="closeConfirmPopup()">@Language.Cancel</button>
+                <button class="popup-btn next-btn" onclick="handleConfirmBuy()">@Language.Confirm</button>
             </div>
         </div>
     </div>
@@ -199,11 +197,11 @@
                     
                     <!-- Text Content -->
                     <div class="register-text">
-                        <p class="register-message">Do you confirm<br/>to buy the<br/><span class="highlight-text">Daily Package</span>?</p>
+                        <p class="register-message">Do you confirm<br/>to buy the<br/><span class="highlight-text">@Language.DailyPackage</span>?</p>
                     </div>
                     
                     <!-- Confirm Button -->
-                    <button class="popup-btn next-btn register-confirm-btn" onclick="handleRegisterConfirm()">Confirm</button>
+                    <button class="popup-btn next-btn register-confirm-btn" onclick="handleRegisterConfirm()">@Language.Confirm</button>
                 </div>
             </div>
         </div>
@@ -224,192 +222,581 @@
                 <!-- Left Side - Account Info -->
                 <div class="withdraw-left">
                     <div class="withdraw-phone">
-                        <span class="withdraw-label">Phone number</span>
+                        <span class="withdraw-label">@Language.PhoneNumber</span>
                         <span class="withdraw-phone-number">0912 345 678</span>
                     </div>
                     
-                    <div class="withdraw-tunnel">
-                        <div class="tunnel-icon">T</div>
-                        <span class="tunnel-label">Tunnel</span>
-                    </div>
-                    
-                    <div class="withdraw-balance-badge">Main balance</div>
+                    <div class="withdraw-balance-badge">@Language.MainBalance</div>
                     
                     <div class="withdraw-info">
-                        <span class="withdraw-info-label">Total withdraw today</span>
-                        <span class="withdraw-info-value">100 HTG</span>
+                        <span class="withdraw-info-label">@Language.TotalValueToday</span>
+                        <span class="withdraw-info-value">100 @Language.HTG</span>
                     </div>
                     
                     <div class="withdraw-info">
-                        <span class="withdraw-info-label">Coin Amount</span>
-                        <span class="withdraw-coin-amount">140.000</span>
+                        <span class="withdraw-info-label">@Language.CoinAmount</span>
+                        <span class="withdraw-coin-amount">@String.Format("{0:n0}", ViewData["WinCoin"])</span>
                     </div>
                 </div>
                 
                 <!-- Right Side - Withdraw Options -->
                 <div class="withdraw-right">
-                    <span class="withdraw-options-title">Withdraw value</span>
+                    <span class="withdraw-options-title">@Language.WithdrawValue</span>
                     
                     <div class="withdraw-options">
-                        <label class="withdraw-option">
-                            <input type="radio" name="withdrawValue" value="1050" />
-                            <span class="withdraw-option-coins">1050 <span class="coins-text">Coins</span></span>
-                            <span class="withdraw-option-htg">10 <span class="htg-text">HTG</span></span>
-                        </label>
+                        @{
+                            var exchangeConfigs = Context.Session.GetComplexData<List<SicboSub.Web.Models.ExchangeConfigItem>>("ExchangeConfig");
+                        }
                         
-                        <label class="withdraw-option">
-                            <input type="radio" name="withdrawValue" value="525" />
-                            <span class="withdraw-option-coins">525 <span class="coins-text">Coins</span></span>
-                            <span class="withdraw-option-htg">5 <span class="htg-text">HTG</span></span>
-                        </label>
-                        
-                        <label class="withdraw-option">
-                            <input type="radio" name="withdrawValue" value="210" />
-                            <span class="withdraw-option-coins">210 <span class="coins-text">Coins</span></span>
-                            <span class="withdraw-option-htg">2 <span class="htg-text">HTG</span></span>
-                        </label>
-                        
-                        <label class="withdraw-option">
-                            <input type="radio" name="withdrawValue" value="105" checked />
-                            <span class="withdraw-option-coins">105 <span class="coins-text">Coins</span></span>
-                            <span class="withdraw-option-htg">1 <span class="htg-text">HTG</span></span>
-                        </label>
+                        @if (exchangeConfigs != null && exchangeConfigs.Any())
+                        {
+                            bool isFirst = true;
+                            foreach (var config in exchangeConfigs)
+                            {
+                                var checkedAttr = isFirst ? "checked" : "";
+                                isFirst = false;
+                                <label class="withdraw-option">
+                                    <input type="radio" name="withdrawValue" value="@config.id" data-coins="@config.coinCost" data-money="@config.moneyReceived" @checkedAttr />
+                                    <span class="withdraw-option-coins">@config.coinCost.ToString("N0") <span class="coins-text">@Language.Coins</span></span>
+                                    <span class="withdraw-option-htg">@config.moneyReceived.ToString("N0") <span class="htg-text">@Language.HTG</span></span>
+                                </label>
+                            }
+                        }
+                        else
+                        {
+                            <div style="color:white;text-align:center;">
+                               
+                            </div>
+                        }
                     </div>
                 </div>
             </div>
             
             <!-- Withdraw Button -->
-            <button class="withdraw-btn" onclick="handleWithdrawConfirm()">Withdraw</button>
+            <button class="withdraw-btn" onclick="handleWithdrawConfirm()">@Language.Withdraw</button>
+        </div>
+    </div>
+
+    </div>
+
+    <!-- Confirm Withdraw Popup -->
+    <div id="confirmWithdrawPopup" class="popup-overlay" style="display: none;">
+        <div class="popup-container confirm-popup">
+            <!-- Header -->
+            <div class="popup-header">
+                <span class="popup-title">Confirm withdraw</span>
+            </div>
+            
+            <!-- Close Button -->
+            <button class="popup-close-btn" onclick="closeConfirmWithdrawPopup()">
+                <svg width="24" height="24" viewBox="0 0 24 24" fill="white">
+                    <path d="M18.3 5.71a1 1 0 0 0-1.41 0L12 10.59 7.11 5.7a1 1 0 0 0-1.41 1.41L10.59 12l-4.89 4.89a1 1 0 1 0 1.41 1.41L12 13.41l4.89 4.89a1 1 0 0 0 1.41-1.41L13.41 12l4.89-4.89a1 1 0 0 0 0-1.4z"/>
+                </svg>
+            </button>
+            
+            <!-- Confirm Content -->
+            <div class="confirm-content">
+                <p class="confirm-message">Do you want to withdraw?</p>
+                <p class="withdraw-amount-display"><span id="withdrawAmountHtg" class="amount-highlight">0</span> @Language.HTG</p>
+                
+                <div class="withdraw-details">
+                   <div class="detail-row">
+                       <span class="detail-label">Fee</span>
+                       <span class="detail-value"><span id="withdrawFeePoints">0</span> @Language.Coins</span>
+                   </div>
+                   <div class="detail-row">
+                       <span class="detail-label">Balance</span>
+                       <span class="detail-value"><span id="withdrawBalancePoints">0</span> @Language.Coins</span>
+                   </div>
+                </div>
+            </div>
+            
+            <!-- Action Buttons -->
+            <div class="popup-actions">
+                <button class="popup-btn cancel-btn" onclick="closeConfirmWithdrawPopup()">@Language.Cancel</button>
+                <button class="popup-btn next-btn" onclick="processWithdraw()">@Language.Confirm</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- OTP Popup -->
+    <div id="otpPopup" class="popup-overlay" style="display: none;">
+        <div class="popup-container otp-popup">
+            <div class="popup-header">
+                <span class="popup-title">OTP Verification</span>
+            </div>
+             <button class="popup-close-btn" onclick="closeOtpPopup()">
+                <svg width="24" height="24" viewBox="0 0 24 24" fill="white">
+                    <path d="M18.3 5.71a1 1 0 0 0-1.41 0L12 10.59 7.11 5.7a1 1 0 0 0-1.41 1.41L10.59 12l-4.89 4.89a1 1 0 1 0 1.41 1.41L12 13.41l4.89 4.89a1 1 0 0 0 1.41-1.41L13.41 12l4.89-4.89a1 1 0 0 0 0-1.4z"/>
+                </svg>
+            </button>
+
+            <div class="otp-content">
+                <p>Please enter the OTP sent to your phone</p>
+                <!-- 6 OTP Boxes -->
+                <div class="otp-inputs" id="otpInputContainer">
+                    <input type="text" class="otp-box" maxlength="1" data-index="0" />
+                    <input type="text" class="otp-box" maxlength="1" data-index="1" />
+                    <input type="text" class="otp-box" maxlength="1" data-index="2" />
+                    <input type="text" class="otp-box" maxlength="1" data-index="3" />
+                    <input type="text" class="otp-box" maxlength="1" data-index="4" />
+                    <input type="text" class="otp-box" maxlength="1" data-index="5" />
+                </div>
+                <button class="popup-btn next-btn" onclick="verifyOtp()">@Language.Verify</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- Message Popup (Success/Error) -->
+    <div id="messagePopup" class="popup-overlay" style="display: none;">
+        <div class="popup-container message-popup">
+            <!-- Close Button -->
+            <button class="popup-close-btn" onclick="closeMessagePopup()">
+                <svg width="24" height="24" viewBox="0 0 24 24" fill="white">
+                    <path d="M18.3 5.71a1 1 0 0 0-1.41 0L12 10.59 7.11 5.7a1 1 0 0 0-1.41 1.41L10.59 12l-4.89 4.89a1 1 0 1 0 1.41 1.41L12 13.41l4.89 4.89a1 1 0 0 0 1.41-1.41L13.41 12l4.89-4.89a1 1 0 0 0 0-1.4z"/>
+                </svg>
+            </button>
+            
+            <div class="message-content">
+                <div id="messageIcon" class="message-icon">
+                    <!-- Icon injected via JS -->
+                </div>
+                <div id="messageText" class="message-text">
+                    <!-- Message text injected via JS -->
+                </div>
+                <button class="popup-btn next-btn" onclick="closeMessagePopup()">OK</button>
+            </div>
+        </div>
+    </div>
+
+    <!-- Exchange Success Popup (Redesigned) -->
+    <div id="exchangeSuccessPopup" class="popup-overlay" style="display: none;">
+        <div class="exchange-popup-container-custom">
+            <!-- Top Right Close Button (Red Circle) -->
+            <button class="exchange-close-btn-custom" onclick="closeExchangeSuccessPopup()">
+                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
+                    <line x1="18" y1="6" x2="6" y2="18"></line>
+                    <line x1="6" y1="6" x2="18" y2="18"></line>
+                </svg>
+            </button>
+
+            <!-- Content -->
+            <div class="exchange-success-content-custom">
+                <!-- Title -->
+                <div class="exchange-title-custom">@Language.Congratulations !</div>
+                
+                <!-- Message -->
+                <div id="exchangeSuccessMessage" class="exchange-message-custom">
+                    <!-- Message text injected via JS -->
+                </div>
+
+                <!-- Bottom Action Button -->
+                <button class="exchange-action-btn-custom" onclick="closeExchangeSuccessPopup()">@Language.Close</button>
+            </div>
         </div>
     </div>
 
 </div>
 
-<script>
-    // Track registration state
-    let isRegistered = false;
-    
-    function handleRegisterClick() {
-        if (isRegistered) {
-            // Already registered, show withdraw popup
-            handleWithdraw();
-        } else {
-            // Not registered, show register popup
-            handleRegister();
+@section Scripts {
+    <script>
+        // Message Popup Logic
+        function showMessagePopup(type, message) {
+            const popup = document.getElementById('messagePopup');
+            const iconContainer = document.getElementById('messageIcon');
+            const textContainer = document.getElementById('messageText');
+            
+            // Set message
+            textContainer.textContent = message;
+            
+            // Set icon based on type
+            if (type === 'success') {
+                iconContainer.innerHTML = '✔'; 
+                iconContainer.className = 'message-icon success';
+            } else {
+                iconContainer.innerHTML = '✖'; 
+                iconContainer.className = 'message-icon error';
+            }
+            
+            popup.style.display = 'flex';
         }
-    }
-    
-    function handleRegister() {
-        // Show the register popup
-        document.getElementById('registerPopup').style.display = 'flex';
-    }
-    
-    function closeRegisterPopup() {
-        document.getElementById('registerPopup').style.display = 'none';
-    }
-    
-    function handleRegisterConfirm() {
-        // TODO: Implement actual register/buy daily package logic
-        alert('Daily Package purchased!');
+
+        function closeMessagePopup() {
+            document.getElementById('messagePopup').style.display = 'none';
+        }
+
+        function showExchangeSuccessPopup(message) {
+            const popup = document.getElementById('exchangeSuccessPopup');
+            const textContainer = document.getElementById('exchangeSuccessMessage');
+            if (textContainer) {
+                textContainer.textContent = message;
+            }
+            popup.style.display = 'flex';
+        }
+
+        function closeExchangeSuccessPopup() {
+            document.getElementById('exchangeSuccessPopup').style.display = 'none';
+        }
+
+        // Override Site methods to use our custom popup
+        // Ensure this runs after site.js
+        $(document).ready(function() {
+            if (typeof Site !== 'undefined') {
+                Site.showSuccess = function(message) {
+                    showMessagePopup('success', message);
+                };
+                
+                Site.showError = function(message) {
+                    showMessagePopup('error', message);
+                };
+            }
+            
+            // Setup OTP Input Logic
+            setupOtpInputs();
+        });
         
-        // Mark as registered and change button to Withdraw
-        isRegistered = true;
-        document.getElementById('registerBtnLabel').textContent = 'Withdraw';
+        // OTP Inputs Logic
+        function setupOtpInputs() {
+            const container = document.getElementById('otpInputContainer');
+            if (!container) return;
+            
+            const inputs = container.querySelectorAll('.otp-box');
+            
+            inputs.forEach((input, index) => {
+                // Determine pattern to only allow numbers?
+                input.addEventListener('input', function(e) {
+                     // Ensure primitive validation: only numbers
+                     this.value = this.value.replace(/[^0-9]/g, '');
+                     
+                     if (this.value.length >= 1) {
+                         if (index < inputs.length - 1) {
+                             inputs[index + 1].focus();
+                         }
+                     }
+                });
+                
+                input.addEventListener('keydown', function(e) {
+                    if (e.key === 'Backspace' && this.value === '') {
+                        if (index > 0) {
+                            inputs[index - 1].focus();
+                        }
+                    }
+                });
+                
+                // On paste?
+                 input.addEventListener('paste', function(e) {
+                    e.preventDefault();
+                    const text = (e.clipboardData || window.clipboardData).getData('text');
+                    if (!text) return;
+                    const digits = text.replace(/[^0-9]/g, '').split('');
+                    if (digits.length > 0) {
+                        let currentIndex = index;
+                        for (let i = 0; i < digits.length; i++) {
+                            if (currentIndex < inputs.length) {
+                                inputs[currentIndex].value = digits[i];
+                                currentIndex++;
+                            }
+                        }
+                        // Focus on the next available or last
+                        if (currentIndex < inputs.length) {
+                             inputs[currentIndex].focus();
+                        } else {
+                             inputs[inputs.length - 1].focus();
+                        }
+                    }
+                 });
+            });
+        }
+
+        // Track registration state
+        var isRegistered = @(isRegistered.ToString().ToLower());
         
-        closeRegisterPopup();
-    }
-    
-    function handleWithdraw() {
-        // Show the withdraw popup
-        document.getElementById('withdrawPopup').style.display = 'flex';
-    }
-    
-    function closeWithdrawPopup() {
-        document.getElementById('withdrawPopup').style.display = 'none';
-    }
-    
-    function handleWithdrawConfirm() {
-        const selectedOption = document.querySelector('input[name="withdrawValue"]:checked');
-        if (selectedOption) {
-            const coins = selectedOption.value;
-            const htg = parseInt(coins) / 105; // approximate conversion
-            alert('Withdraw requested: ' + coins + ' Coins');
-            // TODO: Implement actual withdraw logic here
-            closeWithdrawPopup();
-        } else {
-            alert('Please select a withdraw amount');
+        function handleRegisterClick() {
+            if (isRegistered) {
+                // Already registered, show withdraw popup
+                handleWithdraw();
+            } else {
+                // Not registered, show register popup
+                handleRegister();
+            }
         }
-    }
+        
+        function handleRegister() {
+            // Show the register popup
+            document.getElementById('registerPopup').style.display = 'flex';
+        }
+        
+        function closeRegisterPopup() {
+            document.getElementById('registerPopup').style.display = 'none';
+        }
+        
+        function handleRegisterConfirm() {
+            Site.showLoading();
+            
+            $.ajax({
+                url: '/Home/Register',
+                type: 'POST',
+                contentType: 'application/json',
+                data: JSON.stringify({}),
+                success: function(response) {
+                    Site.hideLoading();
+                    
+                    if (response.errorCode === '0' || response.errorCode === 0) {
+                       Site.showSuccess(response.message);
+                       
+                       // Mark as registered and change button to Withdraw
+                       isRegistered = true;
+                       document.getElementById('registerBtnLabel').textContent = 'Withdraw'; 
+                       
+                       // Update coins
+                       if(response.data) {
+                           if(document.getElementById('betCoinVal')) document.getElementById('betCoinVal').textContent = Site.formatNumber(response.data.betCoin);
+                           if(document.getElementById('winCoinVal')) document.getElementById('winCoinVal').textContent = Site.formatNumber(response.data.winCoin);
+                       }
 
-    function handleBuyMore() {
-        // Show the select package popup
-        document.getElementById('selectPackagePopup').style.display = 'flex';
-    }
-    
-    function closePackagePopup() {
-        document.getElementById('selectPackagePopup').style.display = 'none';
-    }
-    
-    function handlePackageNext() {
-        const selectedPackage = document.querySelector('input[name="package"]:checked');
-        if (selectedPackage) {
-            const coins = selectedPackage.value;
-            // Calculate HTG based on coins (100 coins = 1 HTG)
-            const htg = parseInt(coins) / 100;
+                       closeRegisterPopup();
+                       
+                       // No reload needed
+                    } else {
+                       Site.showError(response.message || 'Registration failed');
+                       closeRegisterPopup();
+                    }
+                },
+                error: function(xhr, status, error) {
+                    Site.hideLoading();
+                    console.error('Register error:', error);
+                    Site.showError('Connection error: ' + error);
+                }
+            });
+        }
+        
+        function handleWithdraw() {
+            // Show the withdraw popup
+            document.getElementById('withdrawPopup').style.display = 'flex';
+        }
+        
+        function closeWithdrawPopup() {
+            document.getElementById('withdrawPopup').style.display = 'none';
+        }
+        
+        // Global variables for withdraw flow
+        let selectedWithdrawConfig = null;
+
+        function handleWithdrawConfirm() {
+            const selectedOption = document.querySelector('input[name="withdrawValue"]:checked');
+            if (selectedOption) {
+                const configId = selectedOption.value;
+                const coins = parseFloat(selectedOption.getAttribute('data-coins'));
+                const money = parseFloat(selectedOption.getAttribute('data-money'));
+                const feeRatio = 0; 
+                
+                selectedWithdrawConfig = {
+                    id: configId,
+                    coins: coins,
+                    money: money
+                };
+
+                // Update Confirm Popup UI
+                document.getElementById('withdrawAmountHtg').textContent = Site.formatNumber(money);
+                document.getElementById('withdrawFeePoints').textContent = '-' + Site.formatNumber(coins);
+                
+                // Get current balance from cache/DOM
+                let currentBalance = 0;
+                const balanceEl = document.getElementById('winCoinVal');
+                if(balanceEl) {
+                     // remove commas
+                     currentBalance = parseFloat(balanceEl.textContent.replace(/,/g, '')) || 0;
+                }
+                
+                // CHECK: Insufficient Balance
+                if (currentBalance < coins) {
+                    Site.showError('@Language.Insufficient');
+                    return;
+                }
+
+                const newBalance = currentBalance - coins;
+                document.getElementById('withdrawBalancePoints').textContent = Site.formatNumber(newBalance);
+
+                // Show Confirm Popup, Hide Withdraw Popup
+                closeWithdrawPopup();
+                document.getElementById('confirmWithdrawPopup').style.display = 'flex';
+
+            } else {
+                Site.showError('Please select a withdraw amount'); 
+            }
+        }
+
+        function closeConfirmWithdrawPopup() {
+            document.getElementById('confirmWithdrawPopup').style.display = 'none';
+        }
+
+        function processWithdraw() {
+            if (!selectedWithdrawConfig) return;
             
-            // Update confirm popup with selected values
-            document.getElementById('confirmCoinsAmount').textContent = coins;
-            document.getElementById('confirmPriceAmount').textContent = htg;
+            // Call API to request OTP
+            Site.showLoading();
             
-            // Hide select popup and show confirm popup
-            closePackagePopup();
-            document.getElementById('confirmBuyMorePopup').style.display = 'flex';
-        } else {
-            alert('Please select a package');
+            API.post('/Home/RequestWithdrawOtp', { configId: selectedWithdrawConfig.id }, function(response) {
+                Site.hideLoading();
+                if (response.errorCode === '0' || response.errorCode === 0) {
+                     // Success - Show OTP Popup
+                     closeConfirmWithdrawPopup();
+                     // Clear inputs
+                     const inputs = document.querySelectorAll('.otp-box');
+                     inputs.forEach(i => i.value = '');
+                     
+                     document.getElementById('otpPopup').style.display = 'flex';
+                     // Focus first input
+                     if(inputs.length > 0) inputs[0].focus();
+                     
+                     // Optional: Store otpId if returned
+                } else {
+                     Site.showError(response.message || 'Request failed');
+                }
+            });
+        }
+
+        function closeOtpPopup() {
+            document.getElementById('otpPopup').style.display = 'none';
+        }
+
+        function verifyOtp() {
+            // Gather OTP
+            let otp = '';
+            const inputs = document.querySelectorAll('.otp-box');
+            inputs.forEach(input => {
+                otp += input.value;
+            });
+            
+            if(!otp || otp.length < 6) {
+                Site.showError('Please enter full OTP');
+                return;
+            }
+
+            Site.showLoading();
+            
+            API.post('/Home/ConfirmWithdrawOtp', { otpCode: otp }, function(response) {
+                Site.hideLoading();
+                
+                if (response.errorCode === '0' || response.errorCode === 0) {
+                     closeOtpPopup();
+                     let msg = response.message;
+                     if (!msg || msg === 'EXCHANGE_REQUEST_SUCCESS') {
+                        msg = '@Language.StatusSuccessful'; 
+                     }
+                     showExchangeSuccessPopup(msg);
+                     
+                     // Update balance
+                     if(response.data) {
+                         if(document.getElementById('betCoinVal') && response.data.betCoin !== undefined) 
+                             document.getElementById('betCoinVal').textContent = Site.formatNumber(response.data.betCoin);
+                         if(document.getElementById('winCoinVal') && response.data.winCoin !== undefined) 
+                             document.getElementById('winCoinVal').textContent = Site.formatNumber(response.data.winCoin);
+                     }
+                } else {
+                     Site.showError(response.message || 'Verification failed');
+                }
+            });
+        }
+
+        function handleBuyMore() {
+            // Simply show the popup, data is pre-loaded via Razor
+            document.getElementById('selectPackagePopup').style.display = 'flex';
         }
-    }
-    
-    function closeConfirmPopup() {
-        document.getElementById('confirmBuyMorePopup').style.display = 'none';
-    }
-    
-    function handleConfirmBuy() {
-        const coins = document.getElementById('confirmCoinsAmount').textContent;
-        const htg = document.getElementById('confirmPriceAmount').textContent;
         
-        // TODO: Implement actual buy logic here
-        alert('Purchase confirmed: ' + coins + ' Coins for ' + htg + ' HTG');
-        closeConfirmPopup();
-    }
-    
-    // Close popup when clicking overlay
-    document.getElementById('selectPackagePopup')?.addEventListener('click', function(e) {
-        if (e.target === this) {
-            closePackagePopup();
+        function closePackagePopup() {
+            document.getElementById('selectPackagePopup').style.display = 'none';
         }
-    });
-    
-    document.getElementById('confirmBuyMorePopup')?.addEventListener('click', function(e) {
-        if (e.target === this) {
-            closeConfirmPopup();
+        
+        let selectedPackageCode = null;
+
+        function handlePackageNext() {
+            const selectedPackage = document.querySelector('input[name="package"]:checked');
+            if (selectedPackage) {
+                const packageCode = selectedPackage.value;
+                const coins = selectedPackage.getAttribute('data-coin');
+                const price = selectedPackage.getAttribute('data-price');
+                
+                selectedPackageCode = packageCode;
+
+                // Update confirm popup with selected values
+                document.getElementById('confirmCoinsAmount').textContent = Site.formatNumber(coins);
+                document.getElementById('confirmPriceAmount').textContent = Site.formatNumber(price);
+                
+                // Hide select popup and show confirm popup
+                closePackagePopup();
+                document.getElementById('confirmBuyMorePopup').style.display = 'flex';
+            } else {
+                Site.showError('Please select a package'); // Use new popup
+            }
         }
-    });
-    
-    document.getElementById('registerPopup')?.addEventListener('click', function(e) {
-        if (e.target === this) {
-            closeRegisterPopup();
+        
+        function closeConfirmPopup() {
+            document.getElementById('confirmBuyMorePopup').style.display = 'none';
         }
-    });
-    
-    document.getElementById('withdrawPopup')?.addEventListener('click', function(e) {
-        if (e.target === this) {
-            closeWithdrawPopup();
+        
+        function handleConfirmBuy() {
+            if (!selectedPackageCode) return;
+            
+            API.post('/Home/BuyMore', { packageCode: selectedPackageCode }, function(response) {
+                 if (response.errorCode === '0') {
+                     Site.showSuccess('@Language.StatusSuccessful');
+                     
+                     // Update coins
+                     if(response.data) {
+                         if(document.getElementById('betCoinVal')) document.getElementById('betCoinVal').textContent = Site.formatNumber(response.data.betCoin);
+                         if(document.getElementById('winCoinVal')) document.getElementById('winCoinVal').textContent = Site.formatNumber(response.data.winCoin);
+                     }
+
+                     closeConfirmPopup();
+                     // No reload needed
+                 } else {
+                     Site.showError(response.message);
+                 }
+            });
         }
-    });
+        
+        // Close popup when clicking overlay
+        document.getElementById('selectPackagePopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closePackagePopup();
+            }
+        });
+        
+        document.getElementById('confirmBuyMorePopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeConfirmPopup();
+            }
+        });
+        
+        document.getElementById('registerPopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeRegisterPopup();
+            }
+        });
+        
+        document.getElementById('withdrawPopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeWithdrawPopup();
+            }
+        });
 
-    function handlePlay() {
-        // TODO: Implement play logic
-        alert('Play clicked!');
-        // window.location.href = '/Home/Play';
-    }
-</script>
+        document.getElementById('messagePopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeMessagePopup();
+            }
+        });
+
+        document.getElementById('exchangeSuccessPopup')?.addEventListener('click', function(e) {
+            if (e.target === this) {
+                closeExchangeSuccessPopup();
+            }
+        });
+
+        function handlePlay() {
+            // TODO: Implement play logic
+            Site.showSuccess('Starting game...'); // Use new popup example
+            // window.location.href = '/Home/Play';
+        }
+    </script>
+}

+ 37 - 48
SicboSub/SicboSub.Web/Views/Home/MonthlyRanking.cshtml

@@ -1,7 +1,8 @@
+@model List<SicboSub.Web.Models.RankingHistoryItem>
 @{
     Layout = "_GameLayout";
 }
-
+@using SicboSub.Web.Language;
 @section Styles {
     <link rel="stylesheet" href="~/css/sicbo-ranking.css" />
 }
@@ -28,66 +29,54 @@
             <!-- Switch Button -->
             <a href="@Url.Action("DailyRanking", "Home")" class="switch-button">
                 <img class="switch-icon" src="~/img/017-strategy.png" alt="" />
-                <span class="switch-text">Switch to Daily</span>
+                <span class="switch-text">@Language.SwitchToDaily</span>
             </a>
             
             <!-- Title -->
             <div class="ranking-title monthly">
-                <span class="title-line">Monthly</span>
-                <span class="title-line">Ranking</span>
+                <span class="title-line">@Language.Monthly</span>
+                <span class="title-line">@Language.Ranking</span>
             </div>
         </div>
 
         <!-- Table Header -->
         <div class="ranking-table-header">
-            <div class="col-top">Top</div>
-            <div class="col-player">Player</div>
-            <div class="col-rewards">Rewards</div>
+            <div class="col-top">@Language.Top</div>
+            <div class="col-player">@Language.Player</div>
+            <div class="col-player">@Language.Time</div>
+            <div class="col-rewards">@Language.Rewards</div>
         </div>
 
         <!-- Table Body -->
         <div class="ranking-table-body">
-            <!-- Row 1 - Gold -->
-            <div class="ranking-row gold">
-                <div class="col-top">1</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+10.000</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 2 - Silver -->
-            <div class="ranking-row silver">
-                <div class="col-top">2</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+5.000</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 3 - Bronze -->
-            <div class="ranking-row bronze">
-                <div class="col-top">3</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+2.500</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 4 -->
-            <div class="ranking-row">
-                <div class="col-top">4</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+1.500</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 5 -->
-            <div class="ranking-row">
-                <div class="col-top">5</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+750</span> <span class="reward-unit">Coins</span></div>
-            </div>
-            
-            <!-- Row 6 -->
-            <div class="ranking-row">
-                <div class="col-top">6</div>
-                <div class="col-player">0912 345 678</div>
-                <div class="col-rewards"><span class="reward-value">+500</span> <span class="reward-unit">Coins</span></div>
-            </div>
+            @if (Model != null && Model.Count > 0)
+            {
+                int top = 1;
+                foreach (var item in Model)
+                {
+                    var rowClass = "";
+                    if (top == 1) rowClass = "gold";
+                    else if (top == 2) rowClass = "silver";
+                    else if (top == 3) rowClass = "bronze";
+
+                    <div class="ranking-row @rowClass">
+                        <div class="col-top">@item.rankPosition</div>
+                        <div class="col-player">@(string.IsNullOrEmpty(item.msisdn) ? "****" : item.msisdn)</div>
+                        <div class="col-player">@item.rankDate.ToString("dd/MM/yyyy")</div>
+                        <div class="col-rewards">
+                            <span class="reward-value">+@item.rewardValue.ToString("N0")</span> 
+                            <span class="reward-unit">@item.rewardUnit</span>
+                        </div>
+                    </div>
+                    top++;
+                }
+            }
+            else
+            {
+                <div class="ranking-row" style="justify-content:center;">
+                    <span></span>
+                </div>
+            }
         </div>
     </div>
 </div>

+ 5 - 5
SicboSub/SicboSub.Web/Views/Home/Winner.cshtml

@@ -1,7 +1,7 @@
 @{
     Layout = "_GameLayout";
 }
-
+@using SicboSub.Web.Language;
 @section Styles {
     <link rel="stylesheet" href="~/css/sicbo-winner.css" />
 }
@@ -38,8 +38,8 @@
             
             <!-- Title -->
             <div class="card-title daily-title">
-                <span class="title-line-1">Daily</span>
-                <span class="title-line-2">Ranking</span>
+                <span class="title-line-1">@Language.Daily</span>
+                <span class="title-line-2">@Language.Ranking</span>
             </div>
         </a>
 
@@ -65,8 +65,8 @@
             
             <!-- Title -->
             <div class="card-title monthly-title">
-                <span class="title-line-1">Monthly</span>
-                <span class="title-line-2">Ranking</span>
+                <span class="title-line-1">@Language.Monthly</span>
+                <span class="title-line-2">@Language.Ranking</span>
             </div>
         </a>
     </div>

+ 9 - 1
SicboSub/SicboSub.Web/Views/Shared/_GameLayout.cshtml

@@ -3,13 +3,21 @@
 <head>
     <meta charset="utf-8">
     <meta name="viewport" content="initial-scale=1, width=device-width">
+    <title>Sicbo Game</title>
 
-    <link rel="stylesheet" href="~/css/sicbo-game.css" />
+    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
+    <link rel="stylesheet" href="~/css/sicbo-game.css" asp-append-version="true" />
     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Kanit:wght@800;900&display=swap" />
     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=SF+Pro:wght@700;900&display=swap" />
     @RenderSection("Styles", required: false)
 </head>
 <body>
+
     @RenderBody()
+
+    <script src="~/lib/jquery/dist/jquery.min.js"></script>
+    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
+    <script src="~/js/site.js" asp-append-version="true"></script>
+    @RenderSection("Scripts", required: false)
 </body>
 </html>

+ 5 - 5
SicboSub/SicboSub.Web/Views/Shared/_GameMenu.cshtml

@@ -1,13 +1,13 @@
 @{
     var currentAction = ViewContext.RouteData.Values["action"]?.ToString() ?? "Index";
 }
-
+@using SicboSub.Web.Language;
 <div class="menu">
     <!-- Home Link -->
     <a href="@Url.Action("Index", "Home")" class="menu-inner @(currentAction == "Index" ? "menu-active" : "")" style="text-decoration: none; color: inherit; display: block;">
         <div class="esports-parent">
             <img class="esports-icon" src="~/img/046-esports.svg" alt="">
-            <b class="history">Home</b>
+            <b class="history">@Language.Home</b>
         </div>
     </a>
 
@@ -15,7 +15,7 @@
     <a href="@Url.Action("History", "Home")" class="menu-child @(currentAction == "History" ? "menu-active" : "")" style="text-decoration: none; color: inherit; display: block;">
         <div class="esports-parent">
             <img class="hourglass-icon" src="~/img/023-hourglass.svg" alt="">
-            <b class="history">History</b>
+            <b class="history">@Language.History</b>
         </div>
     </a>
 
@@ -23,7 +23,7 @@
     <a href="@Url.Action("Winner", "Home")" class="menu-child @(currentAction == "Winner" ? "menu-active" : "")" style="text-decoration: none; color: inherit; display: block;">
         <div class="esports-parent">
             <img class="hourglass-icon" src="~/img/032-ranking.svg" alt="">
-            <b class="winner">Winner</b>
+            <b class="winner">@Language.Winner</b>
         </div>
     </a>
 
@@ -31,7 +31,7 @@
     <a href="@Url.Action("Account", "Home")" class="menu-child @(currentAction == "Account" ? "menu-active" : "")" style="text-decoration: none; color: inherit; display: block;">
         <div class="esports-parent">
             <img class="inventory-icon" src="~/img/037-inventory.svg" alt="">
-            <b class="account">Account</b>
+            <b class="account">@Language.Account</b>
         </div>
     </a>
 </div>

+ 0 - 49
SicboSub/SicboSub.Web/Views/Shared/_Layout.cshtml

@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>@ViewData["Title"] - SicboSub.Web</title>
-    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
-    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
-    <link rel="stylesheet" href="~/SicboSub.Web.styles.css" asp-append-version="true" />
-</head>
-<body>
-    <header>
-        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
-            <div class="container-fluid">
-                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">SicboSub.Web</a>
-                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
-                        aria-expanded="false" aria-label="Toggle navigation">
-                    <span class="navbar-toggler-icon"></span>
-                </button>
-                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
-                    <ul class="navbar-nav flex-grow-1">
-                        <li class="nav-item">
-                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
-                        </li>
-                        <li class="nav-item">
-                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
-                        </li>
-                    </ul>
-                </div>
-            </div>
-        </nav>
-    </header>
-    <div class="container">
-        <main role="main" class="pb-3">
-            @RenderBody()
-        </main>
-    </div>
-
-    <footer class="border-top footer text-muted">
-        <div class="container">
-            &copy; 2026 - SicboSub.Web - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
-        </div>
-    </footer>
-    <script src="~/lib/jquery/dist/jquery.min.js"></script>
-    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
-    <script src="~/js/site.js" asp-append-version="true"></script>
-    @await RenderSectionAsync("Scripts", required: false)
-</body>
-</html>

+ 0 - 48
SicboSub/SicboSub.Web/Views/Shared/_Layout.cshtml.css

@@ -1,48 +0,0 @@
-/* Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
-for details on configuring this project to bundle and minify static web assets. */
-
-a.navbar-brand {
-  white-space: normal;
-  text-align: center;
-  word-break: break-all;
-}
-
-a {
-  color: #0077cc;
-}
-
-.btn-primary {
-  color: #fff;
-  background-color: #1b6ec2;
-  border-color: #1861ac;
-}
-
-.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
-  color: #fff;
-  background-color: #1b6ec2;
-  border-color: #1861ac;
-}
-
-.border-top {
-  border-top: 1px solid #e5e5e5;
-}
-.border-bottom {
-  border-bottom: 1px solid #e5e5e5;
-}
-
-.box-shadow {
-  box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
-}
-
-button.accept-policy {
-  font-size: 1rem;
-  line-height: inherit;
-}
-
-.footer {
-  position: absolute;
-  bottom: 0;
-  width: 100%;
-  white-space: nowrap;
-  line-height: 60px;
-}

+ 1 - 1
SicboSub/SicboSub.Web/Views/_ViewStart.cshtml

@@ -1,3 +1,3 @@
 @{
-    Layout = "_Layout";
+    Layout = "_GameLayout";
 }

+ 18 - 1
SicboSub/SicboSub.Web/appsettings.json

@@ -5,5 +5,22 @@
       "Microsoft.AspNetCore": "Warning"
     }
   },
-  "AllowedHosts": "*"
+  "AllowedHosts": "*",
+  "Url": "http://127.0.0.1:9106",
+  "RedirectUrl": "http://localhost:5042?token=",
+  "PackageCodeDaily": "SICBO_DAY",
+  "Kestrel": {
+    "EndPoints": {
+      "Http": {
+        "Url": "http://127.0.0.1:5042"
+      }
+      //"Https": {
+      //  "Url": "https://0.0.0.0:9107",
+      //  "Certificate": {
+      //    "Path": "/path/to/certificate.pfx",
+      //    "Password": "your-password"
+      //  }
+      //}
+    }
+  }
 }

+ 25 - 0
SicboSub/SicboSub.Web/log4net.config

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<log4net>
+  <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
+    <file value="logs/sicbo-web-.log" />
+    <appendToFile value="true" />
+    <rollingStyle value="Date" />
+    <datePattern value="yyyyMMdd" />
+    <staticLogFileName value="false" />
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+  
+  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
+    <layout type="log4net.Layout.PatternLayout">
+      <conversionPattern value="%date{HH:mm:ss} %-5level %logger - %message%newline" />
+    </layout>
+  </appender>
+
+  <root>
+    <level value="DEBUG" />
+    <appender-ref ref="RollingFileAppender" />
+    <appender-ref ref="ConsoleAppender" />
+  </root>
+</log4net>

+ 58 - 1
SicboSub/SicboSub.Web/wwwroot/css/sicbo-account.css

@@ -125,13 +125,70 @@
 
 /* Settings Icon */
 .settings-icon {
-    width: 100%;
+/*    width: 100%;*/
     height: 36px;
     object-fit: contain;
     cursor: pointer;
     transition: transform 0.2s ease;
 }
 
+
 .settings-icon:hover {
     transform: scale(1.1);
 }
+
+/* Withdraw Options Dropdown */
+.withdraw-options {
+    position: absolute;
+    top: 40px; 
+    right: 0;
+    min-width: 200px;
+    background: rgba(0, 0, 0, 0.9);
+    border: 1px solid #c9a861;
+    border-radius: 8px;
+    z-index: 1000;
+    padding: 8px;
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+    box-shadow: 0 4px 10px rgba(0,0,0,0.5);
+}
+
+.withdraw-options.hidden {
+    display: none;
+}
+
+.withdraw-item {
+    padding: 8px 12px;
+    border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+    cursor: pointer;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    transition: background 0.2s;
+}
+
+.withdraw-item:last-child {
+    border-bottom: none;
+}
+
+.withdraw-item:hover {
+    background: rgba(201, 168, 97, 0.2);
+}
+
+.withdraw-name {
+    font-size: 14px;
+    color: #fff;
+    font-weight: 500;
+}
+
+.withdraw-cost {
+    font-size: 14px;
+    color: #ffd700;
+    font-weight: 700;
+}
+
+/* Ensure parent has relative positioning for absolute dropdown */
+.info-row.with-icon {
+    position: relative;
+}

+ 271 - 7
SicboSub/SicboSub.Web/wwwroot/css/sicbo-popup.css

@@ -226,13 +226,17 @@
     color: #c9a861;
 }
 
+/* ========================================
+   Register Popup Styles
+   ======================================== */
+
 /* ========================================
    Register Popup Styles
    ======================================== */
 
 .register-popup {
-    width: 210px;
-    min-height: 120px;
+    width: 300px;
+    min-height: 160px;
     padding: 10px 12px;
     overflow: visible;
     position: relative;
@@ -247,7 +251,6 @@
 .register-character {
     position: absolute;
     left: 40px;
-    top: -10px;
     width: 110px;
     height: 130px;
     z-index: 1;
@@ -285,10 +288,10 @@
 /* Text Content - bottom left, on top of character */
 .register-text {
     position: absolute;
-    bottom: -40px;
+    top: 80px;
     left: 10px;
     text-align: left;
-    width: 50%;
+    width: 60%;
     z-index: 5;
 }
 
@@ -309,11 +312,11 @@
 /* Register Confirm Button - bottom right, on top of character */
 .register-confirm-btn {
     position: absolute;
-    bottom: -40px;
+    top: 80px;
     right: 0px;
     flex: unset;
     width: auto;
-    padding: 4px 12px;
+    padding: 6px 16px;
     z-index: 5;
 }
 
@@ -517,3 +520,264 @@
     transform: translateY(-2px);
     box-shadow: 0 4px 15px rgba(225, 197, 156, 0.4);
 }
+
+/* ========================================
+   Message Popup Styles (Success/Error)
+   ======================================== */
+
+.message-popup {
+    width: 280px; /* Consistent width */
+    text-align: center;
+}
+
+.message-content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 15px;
+}
+
+.message-icon {
+    font-size: 40px;
+    line-height: 1;
+}
+
+.message-icon.success {
+    color: #4cd964;
+    text-shadow: 0 0 10px rgba(76, 217, 100, 0.5);
+}
+
+.message-icon.error {
+    color: #ff3b30;
+    text-shadow: 0 0 10px rgba(255, 59, 48, 0.5);
+}
+
+.message-text {
+    font-size: 16px;
+    font-weight: 600;
+    color: #fff;
+    margin-bottom: 5px;
+}
+
+/* ========================================
+   OTP Popup Styles
+   ======================================== */
+.otp-popup {
+    width: 320px;
+    text-align: center;
+    background: #000; /* Ensure black background */
+    border: 2px solid #c9a861;
+}
+
+.otp-content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 20px;    
+    padding: 10px 0;
+}
+
+.otp-content p {
+    font-size: 15px;
+    font-weight: 600;
+    color: #fff;
+    margin: 0;
+}
+
+.otp-inputs {
+    display: flex;
+    justify-content: center;
+    gap: 8px;
+    margin: 10px 0;
+}
+
+.otp-box {
+    width: 40px;
+    height: 50px;
+    background: #000;
+    border: 1px solid #c9a861;
+    border-radius: 8px;
+    color: #fff;
+    font-size: 24px;
+    font-weight: 700;
+    text-align: center;
+    outline: none;
+    font-family: 'Kanit', sans-serif;
+}
+
+.otp-box:focus {
+    border-color: #ffe3aa;
+    box-shadow: 0 0 10px rgba(201, 168, 97, 0.4);
+}
+
+.otp-content .popup-btn {
+    width: 140px;
+    padding: 10px;
+    border-radius: 25px;
+    font-size: 16px;
+    flex: none;
+}
+
+.withdraw-amount-display {
+    font-size: 24px;
+    font-weight: 700;
+    color: #fff;
+    margin: 10px 0;
+}
+
+.amount-highlight {
+    color: #ffe3aa;
+    font-size: 32px;
+}
+
+.withdraw-details {
+    width: 100%;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 8px;
+    padding: 10px;
+    margin-top: 5px;
+}
+
+.detail-row {
+    display: flex;
+    justify-content: space-between;
+    margin-bottom: 4px;
+    font-size: 14px;
+}
+
+.detail-row:last-child {
+    margin-bottom: 0;
+}
+
+.detail-label {
+    color: rgba(255, 255, 255, 0.6);
+}
+
+.detail-value {
+    color: #fff;
+    font-weight: 600;
+}
+
+/* ========================================
+   Custom Exchange Success Popup Styles
+   ======================================== */
+
+.exchange-popup-container-custom {
+    position: relative;
+    width: 500px;
+    height: 320px;
+    /* Placeholder for user background image. 
+       User should replace the URL below. */
+    background-color: #7b0d1e; 
+    background-image: url('../img/exchange_success_bg.png'); 
+    background-size: cover;
+    background-position: center;
+    border-radius: 25px;
+    border: 3px solid #dac486; /* Gold/Beige border */
+    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.8), inset 0 0 20px rgba(0,0,0,0.5);
+    display: flex;
+    flex-direction: column;
+    justify-content: flex-end; /* Push content to bottom */
+    padding-bottom: 30px;
+    align-items: center;
+    font-family: 'Kanit', sans-serif;
+    animation: popupPop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+}
+
+@keyframes popupPop {
+    0% { transform: scale(0.5); opacity: 0; }
+    100% { transform: scale(1); opacity: 1; }
+}
+
+/* Close Button (Top Right Red Circle) */
+.exchange-close-btn-custom {
+    position: absolute;
+    top: -20px;
+    right: -20px;
+    width: 44px;
+    height: 44px;
+    background: #ff0000; /* Bright red */
+    border: 3px solid #dac486; /* Gold border */
+    border-radius: 50%;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
+    z-index: 10;
+    transition: transform 0.2s;
+}
+
+.exchange-close-btn-custom:hover {
+    transform: scale(1.1);
+}
+
+/* Content Container */
+.exchange-success-content-custom {
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    text-align: center;
+    padding: 0 20px;
+}
+
+/* Title "Congratulations!" */
+.exchange-title-custom {
+    font-family: 'Kanit', sans-serif;
+    font-size: 42px;
+    font-weight: 900;
+    font-style: italic;
+    background: linear-gradient(180deg, #fff8e7 0%, #dac486 100%);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    color: #dac486;
+    -webkit-text-stroke: 1.5px #000;
+    filter: drop-shadow(3px 3px 0 #000);
+    margin-bottom: 10px;
+    line-height: 1;
+    transform: rotate(-2deg);
+}
+
+/* Message Text */
+.exchange-message-custom {
+    font-size: 16px;
+    font-weight: 600;
+    background: linear-gradient(180deg, #fff8e7 0%, #dac486 100%);
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    background-clip: text;
+    color: #dac486;
+    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.8));
+    margin-bottom: 25px;
+    max-width: 80%;
+    line-height: 1.4;
+}
+
+/* Bottom Action Button "Close" */
+.exchange-action-btn-custom {
+    min-width: 160px;
+    padding: 10px 0;
+    font-family: 'Kanit', sans-serif;
+    font-size: 24px;
+    font-weight: 800;
+    color: #000;
+    background: linear-gradient(180deg, #fff8e7 0%, #dac486 100%);
+    border: 2px solid #000;
+    border-radius: 12px;
+    cursor: pointer;
+    box-shadow: 0 4px 0 #000, 0 5px 10px rgba(0,0,0,0.5);
+    transition: all 0.1s;
+    text-transform: capitalize;
+}
+
+.exchange-action-btn-custom:hover {
+    transform: translateY(2px);
+    box-shadow: 0 2px 0 #000, 0 3px 6px rgba(0,0,0,0.5);
+}
+
+.exchange-action-btn-custom:active {
+    transform: translateY(4px);
+    box-shadow: 0 0 0 #000, 0 0 0 rgba(0,0,0,0.5);
+}

binární
SicboSub/SicboSub.Web/wwwroot/img/exchange_success_bg.png


+ 198 - 3
SicboSub/SicboSub.Web/wwwroot/js/site.js

@@ -1,4 +1,199 @@
-// Please see documentation at https://learn.microsoft.com/aspnet/core/client-side/bundling-and-minification
-// for details on configuring this project to bundle and minify static web assets.
+/**
+ * Site JavaScript - Các tiện ích chung cho website
+ * Sử dụng với server-side authentication (Session)
+ */
 
-// Write your JavaScript code.
+const Site = {
+    /**
+     * Hiển thị loading overlay
+     */
+    showLoading: function() {
+        if ($('#loading-overlay').length === 0) {
+            $('body').append('<div id="loading-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:9999;display:flex;align-items:center;justify-content:center;"><div class="spinner-border text-light" role="status"></div></div>');
+        }
+        $('#loading-overlay').show();
+    },
+
+    /**
+     * Ẩn loading overlay
+     */
+    hideLoading: function() {
+        $('#loading-overlay').hide();
+    },
+
+    /**
+     * Hiển thị thông báo thành công
+     */
+    showSuccess: function(message) {
+        if (typeof Swal !== 'undefined') {
+            Swal.fire({
+                icon: 'success',
+                title: 'Thành công',
+                text: message,
+                timer: 2000,
+                showConfirmButton: false
+            });
+        }
+    },
+
+    /**
+     * Hiển thị thông báo lỗi
+     */
+    showError: function(message) {
+        if (typeof Swal !== 'undefined') {
+            Swal.fire({
+                icon: 'error',
+                title: 'Lỗi',
+                text: message
+            });
+        }
+    },
+
+    /**
+     * Format số với dấu phẩy
+     */
+    formatNumber: function(num) {
+        if (num === null || num === undefined) return '0';
+        return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
+    },
+
+    /**
+     * Format ngày tháng
+     */
+    formatDate: function(dateStr) {
+        if (!dateStr) return '';
+        var date = new Date(dateStr);
+        return date.toLocaleDateString('vi-VN');
+    },
+
+    /**
+     * Format ngày giờ
+     */
+    formatDateTime: function(dateStr) {
+        if (!dateStr) return '';
+        var date = new Date(dateStr);
+        return date.toLocaleString('vi-VN');
+    }
+};
+
+/**
+ * API Helper - Gọi các endpoint trong HomeController
+ * Server-side sẽ xử lý authentication qua Session
+ */
+const API = {
+    /**
+     * POST request chung
+     */
+    post: function(url, data, successCallback, errorCallback) {
+        Site.showLoading();
+        
+        $.ajax({
+            url: url,
+            type: 'POST',
+            contentType: 'application/json',
+            data: JSON.stringify(data || {}),
+            success: function(response) {
+                Site.hideLoading();
+                
+                if (response.errorCode === '0' || response.errorCode === 0) {
+                    if (typeof successCallback === 'function') {
+                        successCallback(response);
+                    }
+                } else {
+                    if (typeof errorCallback === 'function') {
+                        errorCallback(response);
+                    } else {
+                        Site.showError(response.message || 'Có lỗi xảy ra');
+                    }
+                }
+            },
+            error: function(xhr, status, error) {
+                Site.hideLoading();
+                console.error('API error:', error);
+                if (typeof errorCallback === 'function') {
+                    errorCallback({ errorCode: '-999', message: 'Lỗi kết nối' });
+                } else {
+                    Site.showError('Không thể kết nối đến server');
+                }
+            }
+        });
+    },
+
+    /**
+     * Refresh thông tin user
+     */
+    refreshProfile: function(callback) {
+        this.post('/Home/RefreshProfile', {}, callback);
+    },
+
+    /**
+     * Đăng xuất
+     */
+    logout: function(callback) {
+        this.post('/Home/DoLogout', {}, function(response) {
+            if (typeof callback === 'function') {
+                callback(response);
+            }
+            // Redirect về trang chủ
+            window.location.href = '/';
+        });
+    },
+
+    /**
+     * Lấy lịch sử chơi game
+     */
+    getPlayHistory: function(fromDate, toDate, page, pageSize, callback) {
+        this.post('/Home/GetPlayHistory', {
+            fromDate: fromDate,
+            toDate: toDate,
+            page: page || 1,
+            pageSize: pageSize || 10
+        }, callback);
+    },
+
+    /**
+     * Lấy lịch sử ranking
+     */
+    getRankingHistory: function(rankType, fromDate, toDate, page, pageSize, callback) {
+        this.post('/Home/GetRankingHistory', {
+            rankType: rankType,
+            fromDate: fromDate,
+            toDate: toDate,
+            page: page || 1,
+            pageSize: pageSize || 10
+        }, callback);
+    },
+
+    /**
+     * Lấy danh sách gói Exchange
+     */
+    getExchangeConfigs: function(callback) {
+        this.post('/Home/GetExchangeConfigs', {}, callback);
+    },
+
+    /**
+     * Request OTP cho Exchange
+     */
+    requestExchangeOtp: function(configId, callback, errorCallback) {
+        this.post('/Home/RequestExchangeOtp', { configId: configId }, callback, errorCallback);
+    },
+
+    /**
+     * Verify OTP
+     */
+    verifyExchangeOtp: function(otpCode, callback, errorCallback) {
+        this.post('/Home/VerifyExchangeOtp', { otpCode: otpCode }, callback, errorCallback);
+    },
+
+    /**
+     * Resend OTP
+     */
+    resendExchangeOtp: function(callback, errorCallback) {
+        this.post('/Home/ResendExchangeOtp', {}, callback, errorCallback);
+    }
+};
+
+// Document ready
+$(document).ready(function() {
+    console.log('Site initialized');
+});

+ 1 - 1
SicboSubWs/SicboSubWs/src/com/vas/sicbosubnc/wsfw/common/Common.java

@@ -102,7 +102,7 @@ public class Common {
         public static final String IN_TURN = "1";
         public static final String FOREIGN_LANGUAGE = "0";
         public static final String GLOBAL_LANGUAGE = "1";
-        public static final int SPIN_FREE = 5;
+        public static final int SPIN_FREE = 500;
         public static final int MAX_MINIGAME_REWARD = 2;
         public static final int MONEY_MINIGAME_REWARD = 1500;
         public static final int MONEY_HIGHEST_PLAYING_TIMES_REWARD = 50;

+ 113 - 8
SicboSubWs/SicboSubWs/src/com/vas/sicbosubnc/wsfw/database/WsProcessUtils.java

@@ -37,6 +37,8 @@ import com.vas.sicbosubnc.wsfw.obj.draw.LuckySprin;
 import com.vas.sicbosubnc.wsfw.obj.draw.PrizeObj;
 import com.vas.sicbosubnc.wsfw.obj.draw.PrizeWinner;
 import com.vas.sicbosubnc.wsfw.obj.draw.SpinResultObj;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
 
 
 import java.sql.*;
@@ -72,6 +74,8 @@ public class WsProcessUtils extends DbProcessorAbstract {
     // Them phan check user
     private final String SQL_GET_USER_BY_MSISDN
             = "select * from account_user WHERE msisdn = ? and status <> 0 and service_id = ?";
+    private final String SQL_GET_USER
+            = "select * from account_user WHERE msisdn = ? and status <> 0 ";
     
     private final String SQL_GET_LISTPRIZE_BY_ACTIONTYPE
             = "select * from list_prize WHERE action_type = ? and status <> 0 ";
@@ -1587,7 +1591,28 @@ public class WsProcessUtils extends DbProcessorAbstract {
         }
         return rs;
     }
-
+    public AccountInfo iGetAccount(String msisdn) {
+            AccountInfo user = null;
+            long timeBegin = System.currentTimeMillis();
+            int count = 1;
+            while (user == null) {
+                try {
+                    user = getAccount(msisdn);
+                } catch (Exception ex) {
+                    br.setLength(0);
+                    br.append(loggerLabel).append("ERROR - ").append(count).append("\n").append(sqlGetUser);
+                    logger.error(br, ex);
+                    count++;
+                }
+                if (user == null && System.currentTimeMillis() - timeBegin > WebserviceManager.breakQuery) {
+                    br.setLength(0);
+                    br.append(loggerLabel).append(new Date()).append("==>BREAK query iGetAccountByMsisdn\n");
+                    logger.error(br);
+                    break;
+                }
+            }
+            return user;
+        }
     public AccountInfo iGetAccountByMsisdn(String msisdn, String productName) {
         AccountInfo user = null;
         long timeBegin = System.currentTimeMillis();
@@ -1611,6 +1636,60 @@ public class WsProcessUtils extends DbProcessorAbstract {
         return user;
     }
     
+    private AccountInfo getAccount(String msisdn) throws SQLException {
+        ResultSet rs = null;
+        PreparedStatement ps = null;
+        AccountInfo user = null;
+        long timeStart = System.currentTimeMillis();
+        Connection connection = null;
+        try {
+            connection = getConnection(dbName);
+            ps = connection.prepareStatement(SQL_GET_USER);
+            if (WebserviceManager.enableQueryDbTimeout) {
+                ps.setQueryTimeout(WebserviceManager.queryDbTimeout);
+            }
+            ps.setString(1, msisdn);
+            rs = ps.executeQuery();
+            user = new AccountInfo();
+            logTime("getAccountByMsisdn", timeStart);
+            if (rs.next()) {
+                logTime("next", timeStart);
+                user.setAccountId(rs.getString(AccountInfo.ACCOUNT_ID));
+                user.setMsisdn(rs.getString(AccountInfo.MSISDN));
+                user.setUsers(rs.getString(AccountInfo.USERS));
+                user.setPassword(rs.getString(AccountInfo.PASSWORD));
+                user.setServiceId(rs.getString(AccountInfo.SERVICE_ID));
+                user.setCreateDate(rs.getString(AccountInfo.CREATE_DATE));
+                user.setUpdateDate(rs.getString(AccountInfo.UPDATE_DATE));
+                user.setIsActive(rs.getString(AccountInfo.IS_ACTIVE));
+                user.setChannel(rs.getString(AccountInfo.CHANNEL));
+                user.setFreeSpin(rs.getString(AccountInfo.FREE_SPIN));
+                user.setTotalSpin(rs.getString(AccountInfo.TOTAL_SPIN));
+                user.setRole(rs.getString(AccountInfo.ROLE));
+                user.setLanguage(rs.getString(AccountInfo.LANGUAGE));
+                user.setIsLock(rs.getString(AccountInfo.IS_LOCK));
+                user.setTotalFalse(rs.getString(AccountInfo.TOTAL_FALSE));
+                user.setTimeLock(rs.getString(AccountInfo.TIME_LOCK));
+                user.setStatus(rs.getString(AccountInfo.STATUS));
+                user.setPoint(rs.getString(AccountInfo.POINT));
+                user.setLastUpdate(rs.getString(AccountInfo.LAST_UPDATE));
+                user.setLastLogin(rs.getString(AccountInfo.LAST_LOGIN));
+                user.setBirthday(rs.getString(AccountInfo.BIRTHDAY));
+                user.setEmail(rs.getString(AccountInfo.EMAIL));
+                user.setPicture(rs.getString(AccountInfo.PICTURE));
+                user.setFullName(rs.getString(AccountInfo.FULLNAME));
+            }
+            return user;
+        } catch (SQLException ex) {
+            throw ex;
+        } finally {
+            closeResultSet(rs);
+            closeStatement(ps, SQL_GET_USER_BY_MSISDN);
+            closeConnection(connection);
+            logTime("Time to getAccountByMsisdn", timeStart);
+        }
+    }
+    
 
     private AccountInfo getAccountByMsisdn(String msisdn, String productName) throws SQLException {
         ResultSet rs = null;
@@ -2310,7 +2389,7 @@ public class WsProcessUtils extends DbProcessorAbstract {
         Boolean result = false;
 
         while (true) {
-            result = iInsertAccountUser(msisdn, password, channel, productName);
+            result = iInsertAccountUser(msisdn, createMD5(password), channel, productName);
             if (result != null) {
                 break;
             } else {
@@ -2331,12 +2410,38 @@ public class WsProcessUtils extends DbProcessorAbstract {
         return result;
     }
 
+    public static String createMD5(String inforRequest) {
+        // Trong Java Core thường dùng logger (log4j, slf4j), ở đây tôi mô phỏng flow của bạn
+        // System.out.println("inforRequest: " + inforRequest); 
+
+        try {
+            // 1. Khởi tạo instance MD5
+            MessageDigest md = MessageDigest.getInstance("MD5");
+
+            // 2. ComputeHash tương đương: dùng getBytes(UTF_8) để đồng nhất với .NET
+            byte[] hashBytes = md.digest(inforRequest.getBytes(StandardCharsets.UTF_8));
+
+            // 3. Convert byte array sang Hex string (Lowercase, không dấu gạch ngang)
+            StringBuilder sb = new StringBuilder();
+            for (byte b : hashBytes) {
+                // & 0xff để xử lý byte signed trong Java về unsigned như .NET
+                sb.append(String.format("%02x", b));
+            }
+
+            String text = sb.toString();
+            // System.out.println("myHash: " + text);
+            return text;
+
+        } catch (Exception e) {
+            throw new RuntimeException("MD5 algorithm not found", e);
+        }
+    }
     private Boolean iInsertAccountUser(String msisdn, String password, String channel, String productName) {
         long timeStart = System.currentTimeMillis();
         PreparedStatement ps = null;
         Connection connection = null;
-        String sql1 = "insert into account_user (id, msisdn, users, pass, channel, free_spin, service_id) \n"
-                + "values(account_seq.nextval, ?, ?, ?, ?, ?, ?)";
+        String sql1 = "insert into account_user (id, msisdn, USERNAME, PASSWORD, channel, free_spin, service_id,BET_COIN) \n"
+                + "values(account_seq.nextval, ?, ?, ?, ?, ?, ?,?)";
         try {
             connection = getConnection(dbName);
             ps = connection.prepareStatement(sql1);
@@ -2349,6 +2454,7 @@ public class WsProcessUtils extends DbProcessorAbstract {
             ps.setString(4, channel);
             ps.setInt(5, Common.Constant.SPIN_FREE);
             ps.setString(6, productName);
+            ps.setInt(7, Common.Constant.SPIN_FREE);
             ps.execute();
             return true;
         } catch (Exception ex) {
@@ -6962,7 +7068,7 @@ public class WsProcessUtils extends DbProcessorAbstract {
         CallableStatement cs = null;
         ResultSet rs = null;
         Connection connection = null;
-        String sql = "{call ADD_TURN_SPIN ( ?, ? )}";
+        String sql = "{call ADD_COIN ( ?, ? )}";
         try {
             connection = getConnection(dbName);
             cs = connection.prepareCall(sql);
@@ -6974,12 +7080,12 @@ public class WsProcessUtils extends DbProcessorAbstract {
             cs.setInt(2, turn);
             cs.executeUpdate();
         } catch (Exception ex) {
-            logger.error("Error call ADD_TURN_SPIN", ex);
+            logger.error("Error call ADD_COIN", ex);
         } finally {
             closeResource(rs);
             closeResource(cs);
             closeResource(connection);
-            logTime("Time to call ADD_TURN_SPIN", timeStart);
+            logTime("Time to call ADD_COIN", timeStart);
         }
         return null;
     }
@@ -7052,5 +7158,4 @@ public class WsProcessUtils extends DbProcessorAbstract {
     }
 
     
-    
 }

+ 61 - 94
SicboSubWs/SicboSubWs/src/com/vas/webservices/SicboSubWs.java

@@ -159,7 +159,6 @@ public class SicboSubWs extends WebserviceAbstract {
             // check existed
             AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, productInfo.getProductName());
 //            UserProfile userProfile = db.iGetUserProfileByMsisdn(msisdn);
-
             if (accountInfo == null) {
                 logger.error("Error check exist account: " + msisdn);
                 response.setErrorCode(Common.ErrorCode.QUERY_ERROR);
@@ -214,11 +213,6 @@ public class SicboSubWs extends WebserviceAbstract {
             //insert chargelog
             if (fee > 0) {
                 ChargeLog chargeLog = new ChargeLog();
-//                if(productInfo.getProductName().equals(Common.Constant.MR_DAY)){
-//                  chargeLog.setFee(productInfo.getFee());  
-//                }else{
-//                  chargeLog.setFee(fee);
-//                }
                 chargeLog.setFee(productInfo.getFee());
                 chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                 chargeLog.setMsisdn(msisdn);
@@ -230,37 +224,15 @@ public class SicboSubWs extends WebserviceAbstract {
             // send message
             String message = "";
             if (!isCreated) {
-//                message = MessageResponse.get(Common.Message.REGISTER_SUCCESS + "_" + productInfo.getProductName(),
-//                        Common.Message.REGISTER_SUCCESS, logger);
-//                message = MessageResponse.get(Common.Message.CREATE_ACCOUNT_SUCCESS, logger);
                 message = MessageResponse.get(Common.Message.CREATE_ACCOUNT_SUCCESS,
                         Common.Message.CREATE_ACCOUNT_SUCCESS, logger);
-//                message = message.replace("%fee%", fee + "");
                 message = message.replaceAll("%password%", password);
-//                message = message.replaceAll("%expire%", sdf.format(reg.getExpireTime()));
-//                SmsMtObj mt = new SmsMtObj();
-//                mt.setMsisdn(msisdn);
-//                mt.setChannel(Common.CHANNEL);
-//                mt.setMessage(message);
-//                db.insertMt(mt);
             }
-//            else {
-//                message = MessageResponse.get(Common.Message.REGISTER_SUCCESS_USSD + "_" + productInfo.getProductName(),
-//                        Common.Message.REGISTER_SUCCESS_USSD, logger);
-//            }
-//            message = MessageResponse.get(Common.Message.REGISTER_SUCCESS, logger);
             message = MessageResponse.get(Common.Message.REGISTER_SUCCESS,
                     Common.Message.REGISTER_SUCCESS, logger);
-//            message = message.replaceAll("%package%", productInfo.getProductName());
             message = message.replaceAll("%fee%", String.valueOf(productInfo.getFee()));
             message = message.replaceAll("%spin%", String.valueOf(productInfo.getNumberSpin()));
 
-//            if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_2))
-//                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_2);
-//            else if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_3))
-//                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_3);
-//            else if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_5))
-//                message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_5);
             if (productInfo.getProductName().equals(Common.Constant.REGISTER_DAILY_HEALTH)) {
                 message = message.replaceAll("%command%", Common.Constant.OFF_DAILY_HEALTH);
                 message = message.replaceAll("%package%", Common.Constant.REGISTER_DAILY_HEALTH + "");
@@ -277,11 +249,6 @@ public class SicboSubWs extends WebserviceAbstract {
                 message = message.replaceAll("%describer%", Common.Constant.DESCRIBER_HEALTH + "");
             }
 
-//            SmsMtObj mt = new SmsMtObj();
-//            mt.setMsisdn(msisdn);
-//            mt.setChannel(Common.CHANNEL);
-//            mt.setMessage(message);
-//            db.insertMt(mt);
             response.setErrorCode(Common.ErrorCode.SUCCESS);
             response.setContent(message);
 
@@ -695,7 +662,7 @@ public class SicboSubWs extends WebserviceAbstract {
             if (SUCCESS.equals(response.getErrorCode())) {
 //------danh cho thị trường không có otp ------------------
                 // kiem tra thong tin dang nhap
-                /*
+                
                 userInfo = authenticate(wsUser, wsPass, ip);
                 if (userInfo == null || userInfo.getWsUserId() <= 0) {
                     response.setErrorCode(WRONG_PASSWORD);
@@ -725,7 +692,7 @@ public class SicboSubWs extends WebserviceAbstract {
                         String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
                         logger.info("after get product info " + fee);
                         // right -----------------------------------------------
-                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
+//                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
                         
                         String errorCode = resultPaid.split("\\|")[0];
                         if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
@@ -764,6 +731,9 @@ public class SicboSubWs extends WebserviceAbstract {
                             boolean isCreated = true;
                             // check existed
                             AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, serviceId);
+                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
+                                accountInfo = db.iGetAccount(msisdn);
+                            }
                             // create account
                             String password = generateValidateCode(4);
                             if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
@@ -783,7 +753,7 @@ public class SicboSubWs extends WebserviceAbstract {
                                 mt.setMessage(message);
                                 db.insertMt(mt);
                             }
-
+                            db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                             // send message
                             message = MessageResponse.get(Common.Message.REGISTER_SUCCESS,
                                     Common.Message.REGISTER_SUCCESS, logger);
@@ -791,7 +761,7 @@ public class SicboSubWs extends WebserviceAbstract {
                             message = message.replace("%spin%", productInfo.getNumberSpin() + "");
 
                             // check user have registered in the past
-                            if (!db.checkRegisteredForTheFirstTime(msisdn, serviceId)) {
+                            if (!db.checkRegisteredForTheFirstTime(msisdn,String.valueOf(productInfo.getProductId()) )) {
                                 response.setErrorCode(Common.ErrorCode.SUCCESS_FOR_THE_FIRST_TIME_REGISTER);
                             } else {
                                 response.setErrorCode(Common.ErrorCode.SUCCESS);
@@ -805,48 +775,48 @@ public class SicboSubWs extends WebserviceAbstract {
                         }
                     }
                 }
-                */
+                
 //---------------------ket thuc danh cho natcom -------------------------------------------------
                 
 //-------------- bat dau danh cho thi truong co dung otp    ---------------------------------------           
                  
-                userInfo = authenticate(wsUser, wsPass, ip);
-                if (userInfo == null || userInfo.getWsUserId() <= 0) {
-                    response.setErrorCode(WRONG_PASSWORD);
-                    response.setContent("Authenticate fail!");
-                } else {
-                    msisdn = formatMsisdn(msisdn);
-                    List<RegisterInfo> listReg = db.getRegisterInday(msisdn, packageName);
-                    if (listReg != null && !listReg.isEmpty()) {
-                        response.setErrorCode(Common.ErrorCode.ALREADY_REGISTER);
-                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ALREADY_REGISTERED, logger));
-                    } else {
-                        ProductInfo productInfo = getProductByName(packageName);
-                        String resultPaid = "0";
-                        int fee = (int) productInfo.getFee();
-                        // not waiting confirm
-                        String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
-                        logger.info("REQ: " + REQ);
-                        logger.info("after get product info " + fee);
-
-                        // right -----------------------------------------------
-                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
-                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
-                            logger.info("Create otp success " + msisdn + ", fee " + fee);
-
-                            // send message
-                            String message = MessageResponse.get(Common.Message.REGISTER_WAIT_CONFIRM + "_" + productInfo.getProductName(),
-                                    Common.Message.REGISTER_WAIT_CONFIRM, logger);
-
-                            response.setErrorCode(Common.ErrorCode.WAITING_OTP);
-                            response.setContent(message);
-                            response.setResultCode(REQ);
-                        } else {
-                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
-                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
-                        }
-                    }
-                }
+//                userInfo = authenticate(wsUser, wsPass, ip);
+//                if (userInfo == null || userInfo.getWsUserId() <= 0) {
+//                    response.setErrorCode(WRONG_PASSWORD);
+//                    response.setContent("Authenticate fail!");
+//                } else {
+//                    msisdn = formatMsisdn(msisdn);
+//                    List<RegisterInfo> listReg = db.getRegisterInday(msisdn, packageName);
+//                    if (listReg != null && !listReg.isEmpty()) {
+//                        response.setErrorCode(Common.ErrorCode.ALREADY_REGISTER);
+//                        response.setContent(MessageResponse.getDefaultMessage(Common.Message.ALREADY_REGISTERED, logger));
+//                    } else {
+//                        ProductInfo productInfo = getProductByName(packageName);
+//                        String resultPaid = "0";
+//                        int fee = (int) productInfo.getFee();
+//                        // not waiting confirm
+//                        String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
+//                        logger.info("REQ: " + REQ);
+//                        logger.info("after get product info " + fee);
+//
+//                        // right -----------------------------------------------
+//                        resultPaid = ws.requestMpsOtp(msisdn, fee, REQ, productInfo.getProductName());
+//                        if (WSProcessor.LIST_SUCCESS_RES.contains(resultPaid)) {
+//                            logger.info("Create otp success " + msisdn + ", fee " + fee);
+//
+//                            // send message
+//                            String message = MessageResponse.get(Common.Message.REGISTER_WAIT_CONFIRM + "_" + productInfo.getProductName(),
+//                                    Common.Message.REGISTER_WAIT_CONFIRM, logger);
+//
+//                            response.setErrorCode(Common.ErrorCode.WAITING_OTP);
+//                            response.setContent(message);
+//                            response.setResultCode(REQ);
+//                        } else {
+//                            response.setErrorCode(WSProcessor.getErrorCodeFromResult(logger, resultPaid));
+//                            response.setContent(WSProcessor.getMessageFromResult(logger, resultPaid));
+//                        }
+//                    }
+//                }
                 
 // -------------Ket thuc danh cho thi truong có otp------------------
             }
@@ -977,6 +947,9 @@ public class SicboSubWs extends WebserviceAbstract {
                             boolean isCreated = true;
                             // check existed
                             AccountInfo accountInfo = db.iGetAccountByMsisdn(msisdn, productInfo.getProductName());
+                            if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
+                                accountInfo = db.iGetAccount(msisdn);
+                            }
                             // create account
                             String password = generateValidateCode(4);
                             if (accountInfo.getMsisdn() == null || accountInfo.getMsisdn().isEmpty()) {
@@ -1434,8 +1407,8 @@ public class SicboSubWs extends WebserviceAbstract {
                     String REQ = reqDf.format(new Date()) + "1" + msisdn.substring(Common.COUNTRY_CODE.length());
 
                     // charge
-                  String resultPaid = ws.chargeFeeOtp(msisdn, moneyCharge, REQ);
-//                    String resultPaid = "0";
+//                  String resultPaid = ws.chargeFeeOtp(msisdn, moneyCharge, REQ);
+                    String resultPaid = "0";
                     boolean registered = false;
                     List<RegisterInfo> listRegInday = null;
                     listRegInday = db.getRegisterInday(msisdn, productInfo.getProductName());
@@ -1461,7 +1434,6 @@ public class SicboSubWs extends WebserviceAbstract {
                             reg = listRegInday.get(0);
                             db.iInsertRegisterInfo(reg);
                         }
-                        Boolean msisdnTool = db.getMsisdnTool(msisdn);
 
                         //insert chargelog
                         if (moneyCharge > 0) {
@@ -1469,14 +1441,7 @@ public class SicboSubWs extends WebserviceAbstract {
                             chargeLog.setFee(moneyCharge);
                             chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                             chargeLog.setMsisdn(msisdn);
-                            String mTOOL_RUN = MessageResponse.get(Common.Message.TOOL_RUN,logger);
-                            if(mTOOL_RUN.equals("START") && msisdnTool == true){
-                                chargeLog.setDescription("Charge tool " + productInfo.getProductName());
-                                chargeLog.setAccountId("1");
-                            }else{
-                                chargeLog.setDescription("Charge");
-                            }
-                            
+                            chargeLog.setDescription("Charge");
                             chargeLog.setStatus(Common.Constant.CHARGE_STATUS);
                             db.iInsertChargeLog(chargeLog);
                         }
@@ -1485,11 +1450,6 @@ public class SicboSubWs extends WebserviceAbstract {
                         db.addTurnSpin(msisdn,productInfo.getNumberSpin());
                         logger.info("Buy turn success success " + msisdn + ", fee " + fee);
                         
-                        LuckySprin mLuckySprin = db.igetLuckySprin(msisdn);
-                        if(mLuckySprin != null){
-                          response.setRemainSpin(mLuckySprin.getAdded()- mLuckySprin.getUsed());  
-                          response.setTotalSpin(mLuckySprin.getAdded());
-                        }
                         response.setMoneyDeducted(moneyCharge);
                         response.setTotalSpinAdd(productInfo.getNumberSpin());
                         
@@ -1681,7 +1641,6 @@ public class SicboSubWs extends WebserviceAbstract {
                     append("\n Msisdn:").append(msisdn).
                     append("\n ServiceId:").append(serviceId).
                     append("\n Fee:").append(fee).
-                    append("\n Top:").append(top).
                     append("\n Type:").append(type);
             logger.info(br);
 
@@ -1731,13 +1690,21 @@ public class SicboSubWs extends WebserviceAbstract {
                     } else {
 
                         int money = Integer.parseInt(fee);
-                        ws.addMoney(msisdn, money);
+//                        ws.addMoney(msisdn, money);
 
                         ChargeLog chargeLog = new ChargeLog();
                         chargeLog.setFee(-money);
                         chargeLog.setChargeTime(new Timestamp(System.currentTimeMillis()));
                         chargeLog.setMsisdn(msisdn);
-                        chargeLog.setDescription("Exchange points to money");
+                        if("DAILY".equals(type)){
+                           chargeLog.setDescription("Exchange points to money | DAILY");
+                        }else if("WEEKLY".equals(type) ){
+                            chargeLog.setDescription("Exchange points to money | WEEKLY");
+                        }else if("MONTHLY".equals(type)){
+                           chargeLog.setDescription("Exchange points to money | MONTHLY");
+                        }else{
+                           chargeLog.setDescription("Exchange points to money");
+                        }
                         chargeLog.setStatus(Common.Constant.UNCHARGE_STATUS);
                         db.iInsertChargeLog(chargeLog);
 

+ 1 - 1
SicboSubWs/etc/app.conf

@@ -6,7 +6,7 @@ APP_ID=WsUnews
 EXCHANGE_ENABLE=false
  
 #
-COUNTRY_CODE=258
+COUNTRY_CODE=509
 
 LOG_TO_DATABASE=true
 

+ 2 - 2
SicboSubWs/etc/database.xml

@@ -12,8 +12,8 @@
 	
 <property name="connection">jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=yes)(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1539))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1539))
 (CONNECT_DATA=(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=180)(DELAY=5))(SERVICE_NAME=ORA12C)))</property> 
-<property name="username">MO_HOBBY_HUB</property>
-	<property name="password">123456</property>
+<property name="username">sicbo</property>
+	<property name="password">qwK99QfuhEmcFE</property>
 	<!-- <property name="connection">jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=yes)(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))
 (CONNECT_DATA=(FAILOVER_MODE=(TYPE=select)(METHOD=basic)(RETRIES=180)(DELAY=5))(SERVICE_NAME=vascp)))</property>
 	<property name="username">hobby_hub</property>

+ 1 - 1
SicboSubWs/etc/webservices.xml

@@ -1,3 +1,3 @@
 <list>
-	<webservice name='HobbyHubMozWs' implementClass='com.vas.webservices.HobbyHubMozWs' ip='127.0.0.1' port='8199' path='HobbyHubMozWs'/>
+	<webservice name='SicboSubWs' implementClass='com.vas.webservices.SicboSubWs' ip='127.0.0.1' port='8199' path='SicboSubWs'/>
 </list>