From 93c27b5c55c97f8f281f51d48e3400ae595a5e96 Mon Sep 17 00:00:00 2001 From: zpc Date: Fri, 22 Nov 2024 04:23:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Code/CloudGaming.Code/Game/PlayGameBLL.cs | 40 +++- .../Code/CloudGaming.Code/JY/JYApiHandler.cs | 224 ++++++++++-------- .../CloudGaming.DtoModel/JY/JYApiResponse.cs | 15 +- .../PlayGame/PlayGameRequest.cs | 5 + 4 files changed, 173 insertions(+), 111 deletions(-) diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs index 7e1c7fd..78b9d13 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs @@ -37,10 +37,10 @@ namespace CloudGaming.Code.Game /// public async Task GetTokenAsync(RequestBaseModel requestBaseModel) { - //if (_UserId == 0) - //{ - // throw MessageBox.ErrorShow("请先登录"); - //} + if (_UserId == 0) + { + throw MessageBox.ErrorShow("请先登录"); + } if (string.IsNullOrEmpty(requestBaseModel.Sn)) { throw MessageBox.ErrorShow("设备号不能为空"); @@ -48,6 +48,7 @@ namespace CloudGaming.Code.Game //requestBaseModel.Sn = Guid.NewGuid().ToString(); JYRequestParameter requestParameter = new JYRequestParameter(requestBaseModel.Sn, _UserId); var data = await JYApi.GetToken(requestParameter); + //Console.WriteLine(data.TotalMilliseconds); if (data.IsSuccess) { return data?.Data?.Token ?? ""; @@ -78,6 +79,7 @@ namespace CloudGaming.Code.Game } var gameId = playGameRequest.GameId; var modelName = playGameRequest.ModelName; + var cpu = playGameRequest.Cpu; var userGame = await Dao.DaoPhone.Context.T_User_GameList.Where(it => (it.Status == (int)PlayGameStatus.游戏中 || it.Status == (int)PlayGameStatus.排队中) && it.UserId == _UserId).FirstOrDefaultAsync(); if (userGame != null && userGame.Status == (int)PlayGameStatus.游戏中) { @@ -104,6 +106,7 @@ namespace CloudGaming.Code.Game playGameSettings.HangUpTimer = 60 * 5; playGameSettings.ModelName = modelName; playGameSettings.StartResolution = "1080P"; + playGameRequest.Cpu = cpu; var data = await JYApi.PlayGame(playGameSettings); T_User_GameList t_User_GameList = new T_User_GameList() { @@ -116,9 +119,34 @@ namespace CloudGaming.Code.Game UpdateTime = DateTime.Now, UserId = _UserId, }; - + T_User_GameLog t_User_GameLog = new T_User_GameLog() + { + Cpu = cpu, + CreateTime = DateTime.Now, + DisplayGrade = 0, + GameId = gameId, + Gamekey = gameInfo.GameCloudId, + IP = this.HttpContextAccessor.HttpContext.GetClientIpAddress(), + ModelName = modelName, + PlayQueueId = 0, + PlayQueueStatus = 0, + QueueGrade = 0, + ScId = "", + Status = 0, + UpdateTime = DateTime.Now, + UserId = _UserId, + UserKey = "", + }; + T_User_PlayGmaeLog playGmaeLog = new T_User_PlayGmaeLog() + { + CreateTime = DateTime.Now, + DescribeContent = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户启动游戏;", + GameId = gameId, + UserId = _UserId, + }; if (data.IsLineUp) { + playGmaeLog.DescribeContent += $"用户开始排队;"; t_User_GameList.Status = (int)PlayGameStatus.排队中; await Dao.DaoPhone.Context.AddAsync(t_User_GameList); await Dao.DaoPhone.Context.SaveChangesAsync(); @@ -126,10 +154,12 @@ namespace CloudGaming.Code.Game } else if (data.IsSuccess) { + playGmaeLog.DescribeContent += $"用户启动游戏成功;"; await Dao.DaoPhone.Context.AddAsync(t_User_GameList); await Dao.DaoPhone.Context.SaveChangesAsync(); return new BaseResponse(ResponseCode.Success, "", data.Data); } + playGmaeLog.DescribeContent += $"用户游戏启动失败;"; return new BaseResponse(ResponseCode.Error, data.Msg, data.Data); } diff --git a/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs b/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs index daaf67c..286593f 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs @@ -6,7 +6,7 @@ using System.Text; namespace CloudGaming.Code.JY; /// -/// +/// JYAPI请求处理器 /// public class JYApiHandler : DelegatingHandler { @@ -14,69 +14,135 @@ public class JYApiHandler : DelegatingHandler public JYApiHandler(IHttpContextAccessor httpContextAccessor) { - _httpContextAccessor = httpContextAccessor; - } + /// + /// 发送请求的核心处理方法 + /// protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { - - // 访问 HttpContext - var httpContext = _httpContextAccessor.HttpContext; - var host = httpContext.Request.Host.Host; - var app = AppConfigurationExtend.GetAppConfig(host); - if (app != null) + try { - var newUri = new Uri(new Uri(app.GameConfig.BsUrl), request.RequestUri.PathAndQuery); + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext == null) + throw new InvalidOperationException("无法获取HttpContext。"); - // 更新请求的 URI - request.RequestUri = newUri; - // 处理请求体 - if (request.Content is FormUrlEncodedContent) + var host = httpContext.Request.Host.Host; + var app = AppConfigurationExtend.GetAppConfig(host); + if (app != null) { - var formData = await request.Content.ReadAsStringAsync(); - var parameters = ParseFormData(formData); - if (!parameters.ContainsKey("channel_id")) - { - parameters.Add("channel_id", app.GameConfig.ChannelId); - } - if (!parameters.ContainsKey("ip")) - { - parameters.Add("ip", httpContext.GetClientIpAddress()); - } - if (!parameters.ContainsKey("time")) - { - parameters.Add("time", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()); - } - string signKey = ""; - signKey = signEncode(parameters, app.GameConfig.SignKey); - // 对参数进行加密(示例,使用简单的 Base64 编码) - var encryptedParameters = dic2PostData(parameters) + "&sign=" + signKey; + UpdateRequestUri(request, app.GameConfig.BsUrl); - // 更新请求体 - request.Content = new StringContent(encryptedParameters, Encoding.UTF8, "application/x-www-form-urlencoded"); + if (request.Content is FormUrlEncodedContent) + { + await UpdateRequestContentAsync(request, app, httpContext); + } + } + var sw = Stopwatch.StartNew(); + var response = await base.SendAsync(request, cancellationToken); + sw.Stop(); + if (response.IsSuccessStatusCode) + { + await AttachDebugInfoAsync(request, response, sw.Elapsed.TotalMilliseconds.ToString()); } + return response; } - var settings = new JsonSerializerSettings + catch (Exception ex) { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore - }; - //var re = JsonConvert.SerializeObject(request, settings); - var response = await base.SendAsync(request, cancellationToken); - if (response.IsSuccessStatusCode) - { - var contentString = await response.Content.ReadAsStringAsync(); - var jobj = JsonConvert.DeserializeObject(contentString); - jobj["RequestStr"] = await request.ToJsonAsync(); - jobj["ResponseStr"] = SerializeHttpResponseMessage(response, contentString); - var json = JsonConvert.SerializeObject(jobj); - var newContent = new StringContent(json, Encoding.UTF8, "application/json"); - response.Content = newContent; + // 可根据实际需要扩展异常处理逻辑 + throw new HttpRequestException("发送请求时发生错误。", ex); } - return response; } + + /// + /// 更新请求的URI + /// + private void UpdateRequestUri(HttpRequestMessage request, string baseUrl) + { + var newUri = new Uri(new Uri(baseUrl), request.RequestUri.PathAndQuery); + request.RequestUri = newUri; + } + + /// + /// 更新请求内容 + /// + private async Task UpdateRequestContentAsync(HttpRequestMessage request, dynamic app, HttpContext httpContext) + { + var formData = await request.Content.ReadAsStringAsync(); + var parameters = ParseFormData(formData); + + AddDefaultParameters(parameters, app, httpContext); + + var signKey = GenerateSignature(parameters, app.GameConfig.SignKey); + var encryptedParameters = $"{ConvertDictionaryToPostData(parameters)}&sign={signKey}"; + + request.Content = new StringContent(encryptedParameters, Encoding.UTF8, "application/x-www-form-urlencoded"); + } + + /// + /// 添加默认参数 + /// + private void AddDefaultParameters(SortedDictionary parameters, dynamic app, HttpContext httpContext) + { + if (!parameters.ContainsKey("channel_id")) + { + parameters["channel_id"] = app.GameConfig.ChannelId; + } + + if (!parameters.ContainsKey("ip")) + { + parameters["ip"] = httpContext.GetClientIpAddress(); + } + + if (!parameters.ContainsKey("time")) + { + parameters["time"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(); + } + } + + /// + /// 生成签名 + /// + private string GenerateSignature(SortedDictionary parameters, string signKey) + { + var dataString = string.Join("&", parameters.Select(kv => $"{kv.Key}={kv.Value}")) + $"&key={signKey}"; + return MD5Encryption.ComputeMD5Hash(dataString).ToUpper(); + } + + /// + /// 附加调试信息到响应 + /// + private async Task AttachDebugInfoAsync(HttpRequestMessage request, HttpResponseMessage response, string totalMilliseconds) + { + var responseContent = await response.Content.ReadAsStringAsync(); + var responseJson = JsonConvert.DeserializeObject(responseContent); + + responseJson["RequestStr"] = await request.ToJsonAsync(); + responseJson["ResponseStr"] = SerializeResponse(response, responseContent); + responseJson["TotalMilliseconds"] = totalMilliseconds; + + var newContent = new StringContent(JsonConvert.SerializeObject(responseJson), Encoding.UTF8, "application/json"); + response.Content = newContent; + } + + /// + /// 序列化HTTP响应 + /// + private string SerializeResponse(HttpResponseMessage response, string content) + { + return JsonConvert.SerializeObject(new + { + response.StatusCode, + response.ReasonPhrase, + Headers = response.Headers, + Content = content + }); + } + /// + /// 解析表单数据 + /// private SortedDictionary ParseFormData(string formData) { var parameters = new SortedDictionary(); @@ -90,65 +156,15 @@ public class JYApiHandler : DelegatingHandler parameters[keyValue[0]] = keyValue[1]; } } - return parameters; } - /// - /// 字典参数 转 成url参数 - /// - /// - /// - private string dic2PostData(SortedDictionary dic) - { - StringBuilder postData = new StringBuilder(); - foreach (var item in dic) - { - //string s1 = HttpUtility.UrlEncode(item.Value.ToString()); - string s1 = item.Value.ToString(); - if (s1.Length > 0) - { - if (postData.Length == 0) - postData.AppendFormat("{0}={1}", item.Key, s1); - else - postData.AppendFormat("&{0}={1}", item.Key, s1); - } - } - return postData.ToString(); - } + /// - /// 签名参数 + /// 将字典转换为POST数据格式 /// - /// - /// - public string signEncode(SortedDictionary dicParams, string key) + private string ConvertDictionaryToPostData(SortedDictionary dictionary) { - StringBuilder str = new StringBuilder(); - foreach (var item in dicParams) - { - string s1 = item.Value.ToString(); - if (s1.Length > 0) - { - if (str.Length == 0) - str.AppendFormat("{0}={1}", item.Key, s1); - else - str.AppendFormat("&{0}={1}", item.Key, s1); - } - } - str.AppendFormat("&key={0}", key); - return MD5Encryption.ComputeMD5Hash(str.ToString()).ToUpper(); + return string.Join("&", dictionary.Select(kv => $"{kv.Key}={kv.Value}")); } - - public string SerializeHttpResponseMessage(HttpResponseMessage response, string content) - { - var responseInfo = new - { - StatusCode = response.StatusCode, - ReasonPhrase = response.ReasonPhrase, - Headers = response.Headers, - Content = content, - }; - - return JsonConvert.SerializeObject(responseInfo, Formatting.None); - } -} \ No newline at end of file +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYApiResponse.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYApiResponse.cs index 0654bcf..3276dc9 100644 --- a/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYApiResponse.cs +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYApiResponse.cs @@ -14,7 +14,18 @@ namespace CloudGaming.DtoModel.JY /// public class JYApiResponse : JYResponseCode where T : class, new() { - public string RequestStr { get; set; } // 请求信息 - public string ResponseStr { get; set; } // 响应信息 + /// + /// 请求信息 + /// + public string RequestStr { get; set; } + /// + /// 响应信息 + /// + public string ResponseStr { get; set; } + + /// + /// 请求耗时 + /// + public string TotalMilliseconds { get; set; } } } diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/PlayGameRequest.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/PlayGameRequest.cs index 18ba521..4a9ab82 100644 --- a/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/PlayGameRequest.cs +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/PlayGameRequest.cs @@ -19,5 +19,10 @@ namespace CloudGaming.DtoModel.PlayGame /// 手机型号 /// public string ModelName { get; set; } + + /// + /// cpu + /// + public string Cpu { get; set; } } }