From 0bd2a07927acca4d20a8c7784c7c6d55685e930f Mon Sep 17 00:00:00 2001 From: zpc Date: Thu, 21 Nov 2024 04:44:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=B2=B8=E4=BA=91token?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/PaymentController.cs | 4 + .../Controllers/PlayGameController.cs | 38 +++++ .../Api/CloudGaming.Api/Program.cs | 11 +- .../CloudGaming.Code/AppExtend/AppConfig.cs | 5 + .../AppExtend/AppConfigurationExtend.cs | 2 +- .../AppExtend/ConfigModel/GameConfig.cs | 29 ++++ .../CloudGaming.Code/CloudGaming.Code.csproj | 2 + .../Code/CloudGaming.Code/Contract/IJYApi.cs | 24 +++ .../Filter/CustomResultFilter.cs | 41 +++++- .../Code/CloudGaming.Code/Game/PlayGameBLL.cs | 42 ++++++ .../CloudGaming.Code/Game/PlayGameExtend.cs | 44 ++++++ .../Code/CloudGaming.Code/JY/JYApiHandler.cs | 138 ++++++++++++++++++ .../CloudGaming.DtoModel/JY/GetTokenModel.cs | 24 +++ .../CloudGaming.DtoModel/JY/JYResponseCode.cs | 30 ++++ .../PlayGame/RequestBaseModel.cs | 19 +++ 15 files changed, 443 insertions(+), 10 deletions(-) create mode 100644 src/CloudGaming/Api/CloudGaming.Api/Controllers/PlayGameController.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/AppExtend/ConfigModel/GameConfig.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/Contract/IJYApi.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs create mode 100644 src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs create mode 100644 src/CloudGaming/Model/CloudGaming.DtoModel/JY/GetTokenModel.cs create mode 100644 src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYResponseCode.cs create mode 100644 src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/RequestBaseModel.cs diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/PaymentController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/PaymentController.cs index f38b127..a82b081 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/PaymentController.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/PaymentController.cs @@ -1,5 +1,6 @@ using CloudGaming.Api.Base; using CloudGaming.Code.Mall; +using CloudGaming.DtoModel.JY; using CloudGaming.DtoModel.Mall; using HuanMeng.DotNetCore.Base; @@ -8,6 +9,8 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; + namespace CloudGaming.Api.Controllers; @@ -43,6 +46,7 @@ public class PaymentController : CloudGamingControllerBase [Authorize] public async Task> GetOrderRewardsInfo(string orderId) { + OrderBLL orderBLL = new OrderBLL(ServiceProvider); return await orderBLL.GetOrderRewardsInfo(orderId); } diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/PlayGameController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/PlayGameController.cs new file mode 100644 index 0000000..d0965ff --- /dev/null +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/PlayGameController.cs @@ -0,0 +1,38 @@ +using CloudGaming.Api.Base; +using CloudGaming.Code.Contract; +using CloudGaming.Code.Game; +using CloudGaming.DtoModel.JY; +using CloudGaming.DtoModel.PlayGame; + +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +using Newtonsoft.Json; + +using Refit; + +namespace CloudGaming.Api.Controllers +{ + + public class PlayGameController : CloudGamingControllerBase + { + private IJYApi JYApi; + public PlayGameController(IServiceProvider _serviceProvider, IJYApi jYApi) : base(_serviceProvider) + { + JYApi = jYApi; + } + + /// + /// 获取token接口 + /// + /// + /// + [HttpPost] + public async Task GetToken([FromBody] RequestBaseModel requestBaseModel) + { + + PlayGameBLL playGameBLL = new PlayGameBLL(ServiceProvider, JYApi); + return await playGameBLL.GetTokenAsync(requestBaseModel); + } + } +} diff --git a/src/CloudGaming/Api/CloudGaming.Api/Program.cs b/src/CloudGaming/Api/CloudGaming.Api/Program.cs index 56d215c..398337a 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Program.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Program.cs @@ -19,6 +19,9 @@ using Microsoft.Extensions.Options; using CloudGaming.GameModel.Db.Db_Ext; using CloudGaming.Code.MiddlewareExtend; using CloudGaming.Code.Filter; +using CloudGaming.Code.Contract; +using Refit; +using CloudGaming.Code.JY; var builder = WebApplication.CreateBuilder(args); #region 日志 // Add services to the container. @@ -42,6 +45,7 @@ builder.Services.AddSingleton(typeof(ILogger), serviceProvi builder.Services.AddMemoryCache(); builder.Services.AddHttpClient(); builder.Services.AddHttpContextAccessor(); //添加httpContext注入访问 + #region 返回数据解析 //services.AddControllers(options => //{ @@ -104,7 +108,7 @@ builder.Services.AddSwaggerGen(c => var filePath = Path.GetFullPath(".versionDescribe"); if (File.Exists(filePath)) { - description= File.ReadAllText(filePath); + description = File.ReadAllText(filePath); //string[] lines = File.ReadAllLines(filePath); //foreach (string line in lines) //{ @@ -159,7 +163,12 @@ builder.AddJwtConfig(); var _myAllowSpecificOrigins = "_myAllowSpecificOrigins"; builder.Services.AddCustomCors(_myAllowSpecificOrigins); #endregion +builder.Services.AddScoped(); +// 配置 HttpClientFactory 和 Refit +builder.Services.AddRefitClient() + .AddHttpMessageHandler() + .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://default-api.example.com")); //添加jwt验证 //builder.AddJwtConfig(); diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfig.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfig.cs index 25d0a97..5203f9f 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfig.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfig.cs @@ -74,6 +74,11 @@ public class AppConfig /// public UserConfig UserConfig { get; set; } + /// + /// 游戏配置 + /// + public GameConfig GameConfig { get; set; } + /// /// 获取数据库连接字符串 /// diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs index 06f3cca..8542795 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/AppConfigurationExtend.cs @@ -193,7 +193,7 @@ namespace CloudGaming.Code.AppExtend } newAppConfig.UserConfig = appConfig.UserConfig; newAppConfig.Payment = appConfig.Payment; - + newAppConfig.GameConfig = appConfig.GameConfig; return newAppConfig; } diff --git a/src/CloudGaming/Code/CloudGaming.Code/AppExtend/ConfigModel/GameConfig.cs b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/ConfigModel/GameConfig.cs new file mode 100644 index 0000000..d178123 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/AppExtend/ConfigModel/GameConfig.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.AppExtend.ConfigModel +{ + /// + /// + /// + public class GameConfig + { + /// + /// 客户渠道Id,如:edb684859b848362ec56904286947614 + /// + public string ChannelId { get; set; } + + /// + /// 客户渠道key,加密使用 + /// + public string SignKey { get; set; } + + /// + /// 客户渠道地址 + /// + public string BsUrl { get; set; } + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/CloudGaming.Code.csproj b/src/CloudGaming/Code/CloudGaming.Code/CloudGaming.Code.csproj index 1567d09..e676297 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/CloudGaming.Code.csproj +++ b/src/CloudGaming/Code/CloudGaming.Code/CloudGaming.Code.csproj @@ -19,6 +19,8 @@ + + diff --git a/src/CloudGaming/Code/CloudGaming.Code/Contract/IJYApi.cs b/src/CloudGaming/Code/CloudGaming.Code/Contract/IJYApi.cs new file mode 100644 index 0000000..5006046 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Contract/IJYApi.cs @@ -0,0 +1,24 @@ +using CloudGaming.DtoModel.JY; + +using HuanMeng.DotNetCore.Base; + +using Refit; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.Contract +{ + /// + /// + /// + public interface IJYApi + { + + [Post("/jyapi/getToken")] + Task> GetToken([Body(BodySerializationMethod.UrlEncoded)] SortedDictionary data); + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs index 15e43da..3fd5e5c 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Filter/CustomResultFilter.cs @@ -1,5 +1,7 @@ +using Newtonsoft.Json; + namespace CloudGaming.Code.Filter; @@ -43,16 +45,39 @@ public class CustomResultFilter : IResultFilter object? value = null; if (!x.FullName.Contains("HuanMeng.DotNetCore.Base.BaseResponse")) { - BaseResponse baseResponse = new BaseResponse(ResonseCode.Success, "", objectResult.Value); - value = baseResponse; - // 获取当前执行的Action方法的信息并进行类型检查 - if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) + //特殊处理 + if (objectResult.Value is string) { - var messageAttribute = MessageAttributeExtend.GetMessageAttribute(controllerActionDescriptor); - // 如果存在MessageAttribute,则设置响应消息 - if (messageAttribute != null) + BaseResponse baseStringResponse = new BaseResponse(ResonseCode.Success, "", objectResult.Value.ToString()); + value = baseStringResponse; + if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) { - baseResponse.Message = messageAttribute.Message; + var messageAttribute = MessageAttributeExtend.GetMessageAttribute(controllerActionDescriptor); + // 如果存在MessageAttribute,则设置响应消息 + if (messageAttribute != null) + { + baseStringResponse.Message = messageAttribute.Message; + } + } + sw.Stop(); + context.HttpContext.Response.Headers.TryAdd("X-Request-Duration-Filter", sw.Elapsed.TotalMilliseconds.ToString()); + objectResult.Value = baseStringResponse.ToString(); + return; + + } + else + { + BaseResponse baseResponse = new BaseResponse(ResonseCode.Success, "", objectResult.Value); + value = baseResponse; + // 获取当前执行的Action方法的信息并进行类型检查 + if (context.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor) + { + var messageAttribute = MessageAttributeExtend.GetMessageAttribute(controllerActionDescriptor); + // 如果存在MessageAttribute,则设置响应消息 + if (messageAttribute != null) + { + baseResponse.Message = messageAttribute.Message; + } } } diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs new file mode 100644 index 0000000..b2bcb2f --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameBLL.cs @@ -0,0 +1,42 @@ +using CloudGaming.Code.AppExtend.ConfigModel; +using CloudGaming.Code.Contract; +using CloudGaming.DtoModel.PlayGame; + +using Refit; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + + +namespace CloudGaming.Code.Game +{ + public class PlayGameBLL : CloudGamingBase + { + private IJYApi JYApi { get; set; } + public PlayGameBLL(IServiceProvider serviceProvider, IJYApi jYApi) : base(serviceProvider) + { + JYApi = jYApi; + } + + public async Task GetTokenAsync(RequestBaseModel requestBaseModel) + { + if (_UserId == 0) + { + throw MessageBox.ErrorShow("请先登录"); + } + if (string.IsNullOrEmpty(requestBaseModel.Sn)) + { + throw MessageBox.ErrorShow("设备号不能为空"); + } + var dicParams = new SortedDictionary(); + dicParams.Add("sn", requestBaseModel.Sn); + dicParams.Add("client_sid", _UserId); + var data = await JYApi.GetToken(dicParams); + return data?.Data?.Token ?? ""; + } + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs new file mode 100644 index 0000000..853b8da --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Game/PlayGameExtend.cs @@ -0,0 +1,44 @@ +using CloudGaming.DtoModel.PlayGame; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.Game +{ + public static class PlayGameExtend + { + /// + /// + /// + /// + /// + /// + public static SortedDictionary GetDefaultParams(this RequestBaseModel requestBaseModel, CloudGamingBase cloudGamingBase) + { + + return GetDefaultParams(requestBaseModel, cloudGamingBase.AppConfig.GameConfig, cloudGamingBase.HttpContextAccessor.HttpContext.GetClientIpAddress(), cloudGamingBase._UserId); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public static SortedDictionary GetDefaultParams(this RequestBaseModel requestBaseModel, GameConfig gameConfig, string ip, int UserId) + { + var dicParams = new SortedDictionary(); + dicParams.Add("channel_id", gameConfig.ChannelId); + dicParams.Add("sn", requestBaseModel.Sn); + dicParams.Add("client_sid", UserId); + dicParams.Add("ip", ip); + dicParams.Add("time", DateTimeOffset.UtcNow.ToUnixTimeSeconds()); + return dicParams; + } + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs b/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs new file mode 100644 index 0000000..ee8bb70 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/JY/JYApiHandler.cs @@ -0,0 +1,138 @@ +using CloudGaming.Code.AppExtend; +using CloudGaming.Code.AppExtend.ConfigModel; +using CloudGaming.DtoModel.PlayGame; + +using Microsoft.Extensions.DependencyInjection; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.JY; + +/// +/// +/// +public class JYApiHandler : DelegatingHandler +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + 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) + { + var newUri = new Uri(new Uri(app.GameConfig.BsUrl), request.RequestUri.PathAndQuery); + + // 更新请求的 URI + request.RequestUri = newUri; + // 处理请求体 + if (request.Content is FormUrlEncodedContent) + { + 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()); + } + if (!parameters.ContainsKey("sign")) + { + var signKey = signEncode(parameters, app.GameConfig.SignKey); + parameters.Add("sign", signKey); + } + // 对参数进行加密(示例,使用简单的 Base64 编码) + var encryptedParameters = dic2PostData(parameters); + + // 更新请求体 + request.Content = new StringContent(encryptedParameters, Encoding.UTF8, "application/x-www-form-urlencoded"); + } + + } + var x = await base.SendAsync(request, cancellationToken); + var json = await x.Content.ReadAsStringAsync(); + //调用下一个处理器 + return x; + } + private SortedDictionary ParseFormData(string formData) + { + var parameters = new SortedDictionary(); + var pairs = formData.Split('&'); + + foreach (var pair in pairs) + { + var keyValue = pair.Split('='); + if (keyValue.Length == 2) + { + parameters[keyValue[0]] = keyValue[1]; + } + } + + return parameters; + } + /// + /// 字典参数 转 成url参数 + /// + /// + /// + private static 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(); + } + + /// + /// 签名参数 + /// + /// + /// + public static string signEncode(SortedDictionary dicParams, string key) + { + 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(); + } +} \ No newline at end of file diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/JY/GetTokenModel.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/GetTokenModel.cs new file mode 100644 index 0000000..2847457 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/GetTokenModel.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.JY +{ + /// + /// getToken返回值 + /// + public class GetTokenModel + { + /// + /// + /// + public string Token { get; set; } + + /// + /// + /// + public int Expire_time { get; set; } + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYResponseCode.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYResponseCode.cs new file mode 100644 index 0000000..c7ef612 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/JY/JYResponseCode.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.JY +{ + + /// + /// 鲸云api + /// + /// + public class JYResponseCode where T : class, new() + { + /// + /// 状态 + /// + public int Status { get; set; } + /// + /// 消息 + /// + public string Msg { get; set; } + + /// + /// 数据源 + /// + public T? Data { get; set; } + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/RequestBaseModel.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/RequestBaseModel.cs new file mode 100644 index 0000000..c817a61 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/PlayGame/RequestBaseModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.PlayGame +{ + /// + /// + /// + public class RequestBaseModel + { + /// + /// 设备号 + /// + public string Sn { get; set; } + } +}