30 changed files with 565 additions and 29 deletions
@ -0,0 +1,26 @@ |
|||
using BBWY.Server.Business; |
|||
using BBWY.Server.Model.Db; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
|||
|
|||
namespace BBWY.Server.API.Controllers |
|||
{ |
|||
[Produces("application/json")] |
|||
[Route("Api/[Controller]/[Action]")]
|
|||
[ApiController] |
|||
public class YunDingController : ControllerBase |
|||
{ |
|||
private YunDingBusiness yunDingBusiness; |
|||
public YunDingController(YunDingBusiness yunDingBusiness) |
|||
{ |
|||
this.yunDingBusiness = yunDingBusiness; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public void CreateKey() |
|||
{ |
|||
yunDingBusiness.CreateKey(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
using BBWY.Common.Models; |
|||
using BBWY.Server.Model.Db; |
|||
using Microsoft.Extensions.Caching.Memory; |
|||
using System; |
|||
|
|||
namespace BBWY.Server.Business |
|||
{ |
|||
public class YunDingBusiness : IDenpendency |
|||
{ |
|||
private IMemoryCache memoryCache; |
|||
private IFreeSql fsql; |
|||
private TimeSpan expirationTimeSpan = TimeSpan.FromDays(2); |
|||
public YunDingBusiness(IMemoryCache memoryCache, IFreeSql fsql) |
|||
{ |
|||
this.memoryCache = memoryCache; |
|||
this.fsql = fsql; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 创建云鼎Key
|
|||
/// </summary>
|
|||
public void CreateKey() |
|||
{ |
|||
var key = Guid.NewGuid().ToString(); |
|||
memoryCache.Set("YunDingKey", key, expirationTimeSpan); |
|||
fsql.Update<JDYunDingAPIKey>(1).Set(k => k.YunDingKey, key).ExecuteAffrows(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 刷新云鼎Key
|
|||
/// </summary>
|
|||
public void RefreshKey() |
|||
{ |
|||
var yundingKey = fsql.Select<JDYunDingAPIKey>(1).ToOne(); |
|||
memoryCache.Set("YunDingKey", yundingKey.YunDingKey, expirationTimeSpan); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 读取云鼎Key
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public string GetKey() |
|||
{ |
|||
return memoryCache.Get<string>("YunDingKey"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,18 @@ |
|||
using FreeSql.DataAnnotations; |
|||
|
|||
namespace BBWY.Server.Model.Db |
|||
{ |
|||
|
|||
[Table(Name = "jdyundingapikey", DisableSyncStructure = true)] |
|||
public partial class JDYunDingAPIKey |
|||
{ |
|||
|
|||
[Column(IsPrimary = true)] |
|||
public long Id { get; set; } |
|||
|
|||
[Column(StringLength = 50)] |
|||
public string YunDingKey { get; set; } |
|||
|
|||
} |
|||
|
|||
} |
@ -0,0 +1,12 @@ |
|||
{ |
|||
"version": 1, |
|||
"isRoot": true, |
|||
"tools": { |
|||
"dotnet-ef": { |
|||
"version": "6.0.10", |
|||
"commands": [ |
|||
"dotnet-ef" |
|||
] |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using BBWY.Server.Business; |
|||
using BBWY.Server.Model.Db; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
|||
|
|||
namespace JD.API.Controllers |
|||
{ |
|||
[Produces("application/json")] |
|||
[Route("Api/[Controller]/[Action]")]
|
|||
[ApiController] |
|||
public class YunDingController : ControllerBase |
|||
{ |
|||
private YunDingBusiness yunDingBusiness; |
|||
public YunDingController(YunDingBusiness yunDingBusiness) |
|||
{ |
|||
this.yunDingBusiness = yunDingBusiness; |
|||
} |
|||
|
|||
[HttpGet] |
|||
public void RefreshKey() |
|||
{ |
|||
yunDingBusiness.RefreshKey(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
using BBWY.Common.Models; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.Filters; |
|||
|
|||
namespace JD.API.Filters |
|||
{ |
|||
public class ResultFilter : IResultFilter |
|||
{ |
|||
public void OnResultExecuted(ResultExecutedContext context) |
|||
{ |
|||
|
|||
} |
|||
|
|||
public void OnResultExecuting(ResultExecutingContext context) |
|||
{ |
|||
if (context.Result is ObjectResult) |
|||
{ |
|||
var objectResult = context.Result as ObjectResult; |
|||
if (!(objectResult.Value is ApiResponse)) |
|||
{ |
|||
objectResult.Value = new ApiResponse() { Data = objectResult.Value }; |
|||
} |
|||
} |
|||
else if (context.Result is EmptyResult) |
|||
{ |
|||
context.Result = new ObjectResult(new ApiResponse()); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,24 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<GenerateDocumentationFile>True</GenerateDocumentationFile> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="FreeSql" Version="2.6.100" /> |
|||
<PackageReference Include="FreeSql.Provider.MySql" Version="2.6.100" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.21" /> |
|||
<PackageReference Include="NLog" Version="4.7.12" /> |
|||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\BBWY.Common\BBWY.Common.csproj" /> |
|||
<ProjectReference Include="..\BBWY.JDSDK\BBWY.JDSDK.csproj" /> |
|||
<ProjectReference Include="..\BBWY.Server.Business\BBWY.Server.Business.csproj" /> |
|||
<ProjectReference Include="..\BBWY.Server.Model\BBWY.Server.Model.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
|
|||
</Project> |
@ -0,0 +1,86 @@ |
|||
using BBWY.Common.Models; |
|||
using Microsoft.AspNetCore.Http; |
|||
using Newtonsoft.Json; |
|||
using NLog; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace JD.API.Middlewares |
|||
{ |
|||
public class CustomExceptionMiddleWare |
|||
{ |
|||
/// <summary>
|
|||
/// 管道请求委托
|
|||
/// </summary>
|
|||
private RequestDelegate _next; |
|||
|
|||
/// <summary>
|
|||
/// 需要处理的状态码字典
|
|||
/// </summary>
|
|||
private IDictionary<int, string> _exceptionStatusCodeDic; |
|||
|
|||
private ILogger logger; |
|||
|
|||
public CustomExceptionMiddleWare(RequestDelegate next, ILogger logger) |
|||
{ |
|||
_next = next; |
|||
this.logger = logger; |
|||
_exceptionStatusCodeDic = new Dictionary<int, string> |
|||
{ |
|||
{ 401, "未授权的请求" }, |
|||
{ 404, "找不到该资源" }, |
|||
{ 403, "访问被拒绝" }, |
|||
{ 500, "服务器发生意外的错误" }, |
|||
{ 503, "服务不可用" } |
|||
//其余状态自行扩展
|
|||
}; |
|||
} |
|||
|
|||
public async Task Invoke(HttpContext context) |
|||
{ |
|||
try |
|||
{ |
|||
await _next(context); //调用管道执行下一个中间件
|
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
if (ex is BusinessException) |
|||
{ |
|||
var busEx = ex as BusinessException; |
|||
context.Response.StatusCode = 200; //业务异常时将Http状态码改为200
|
|||
await ErrorHandle(context, busEx.Code, busEx.Message); |
|||
} |
|||
else |
|||
{ |
|||
context.Response.Clear(); |
|||
context.Response.StatusCode = 500; //发生未捕获的异常,手动设置状态码
|
|||
logger.Error(ex); //记录错误
|
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
if (_exceptionStatusCodeDic.TryGetValue(context.Response.StatusCode, out string exMsg)) |
|||
{ |
|||
await ErrorHandle(context, context.Response.StatusCode, exMsg); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 处理方式:返回Json格式
|
|||
/// </summary>
|
|||
/// <param name="context"></param>
|
|||
/// <param name="code"></param>
|
|||
/// <param name="exMsg"></param>
|
|||
/// <returns></returns>
|
|||
private async Task ErrorHandle(HttpContext context, int code, string exMsg) |
|||
{ |
|||
var apiResponse = ApiResponse.Error(code, exMsg); |
|||
var serialzeStr = JsonConvert.SerializeObject(apiResponse); |
|||
context.Response.ContentType = "application/json"; |
|||
await context.Response.WriteAsync(serialzeStr, Encoding.UTF8); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace JD.API |
|||
{ |
|||
public class Program |
|||
{ |
|||
public static void Main(string[] args) |
|||
{ |
|||
CreateHostBuilder(args).Build().Run(); |
|||
} |
|||
|
|||
public static IHostBuilder CreateHostBuilder(string[] args) => |
|||
Host.CreateDefaultBuilder(args) |
|||
.ConfigureWebHostDefaults(webBuilder => |
|||
{ |
|||
webBuilder.UseStartup<Startup>(); |
|||
}); |
|||
} |
|||
} |
@ -0,0 +1,30 @@ |
|||
{ |
|||
"$schema": "http://json.schemastore.org/launchsettings.json", |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "http://localhost:46194", |
|||
"sslPort": 0 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"launchUrl": "weatherforecast", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"JD.API": { |
|||
"commandName": "Project", |
|||
"launchBrowser": true, |
|||
"launchUrl": "weatherforecast", |
|||
"applicationUrl": "http://localhost:5000", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,149 @@ |
|||
using BBWY.Common.Http; |
|||
using BBWY.Server.Business; |
|||
using JD.API.Filters; |
|||
using JD.API.Middlewares; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.OpenApi.Models; |
|||
using Newtonsoft.Json.Serialization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace JD.API |
|||
{ |
|||
public class Startup |
|||
{ |
|||
public Startup(IConfiguration configuration) |
|||
{ |
|||
Configuration = configuration; |
|||
} |
|||
|
|||
public IConfiguration Configuration { get; } |
|||
|
|||
private bool isEnableSwagger; |
|||
|
|||
// This method gets called by the runtime. Use this method to add services to the container.
|
|||
public void ConfigureServices(IServiceCollection services) |
|||
{ |
|||
isEnableSwagger = Convert.ToBoolean(Configuration.GetSection("IsEnableSwagger").Value); |
|||
|
|||
services.AddHttpContextAccessor(); |
|||
services.AddHttpClient(); |
|||
services.AddMemoryCache(); |
|||
services.AddSingleton(typeof(NLog.ILogger), NLog.LogManager.GetCurrentClassLogger()); |
|||
|
|||
var fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.MySql, Configuration.GetConnectionString("DB")).Build(); |
|||
services.AddSingleton(typeof(IFreeSql), fsql); |
|||
|
|||
services.AddCors(options => |
|||
{ |
|||
options.AddDefaultPolicy(p => |
|||
{ |
|||
p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); |
|||
}); |
|||
}); |
|||
|
|||
services.AddControllers(configure => |
|||
{ |
|||
configure.Filters.Add<ResultFilter>(); |
|||
}).AddNewtonsoftJson(setupAction => |
|||
{ |
|||
setupAction.SerializerSettings.ContractResolver = new DefaultContractResolver(); |
|||
setupAction.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; |
|||
//setupAction.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
|
|||
//setupAction.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Include;
|
|||
}); |
|||
services.AddSingleton<RestApiService>(); |
|||
services.AddSingleton<PlatformSDKBusiness, JDBusiness>(); |
|||
services.AddSingleton<PlatformSDKBusiness, _1688Business>(); |
|||
services.AddSingleton<YunDingBusiness>(); |
|||
|
|||
if (isEnableSwagger) |
|||
{ |
|||
services.AddSwaggerGen(c => |
|||
{ |
|||
c.SwaggerDoc("v1", new OpenApiInfo |
|||
{ |
|||
Version = "v1.0.0", |
|||
Title = "JD云鼎API", |
|||
Description = "注意事项\r\n1.返回参数名称采用大驼峰命名\r\n2.ApiResponse为基础返回对象(Code,Data,Message),接口中所有的返回值均属于Data属性\r\n3.正常返回Code=200" |
|||
}); |
|||
// JWT认证
|
|||
//c.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
|
|||
//{
|
|||
// Scheme = JwtBearerDefaults.AuthenticationScheme,
|
|||
// BearerFormat = "JWT",
|
|||
// Type = SecuritySchemeType.ApiKey,
|
|||
// Name = "Authorization",
|
|||
// In = ParameterLocation.Header,
|
|||
// Description = "Authorization:Bearer {your JWT token}<br/>",
|
|||
//});
|
|||
//c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
|||
// {
|
|||
// {
|
|||
// new OpenApiSecurityScheme{Reference = new OpenApiReference
|
|||
// {
|
|||
// Type = ReferenceType.SecurityScheme,
|
|||
// Id = JwtBearerDefaults.AuthenticationScheme
|
|||
// }
|
|||
// },
|
|||
// new string[] { }
|
|||
// }
|
|||
// });
|
|||
|
|||
var executingAssembly = Assembly.GetExecutingAssembly(); |
|||
var assemblyNames = executingAssembly.GetReferencedAssemblies().Union(new AssemblyName[] { executingAssembly.GetName() }).ToArray(); |
|||
Array.ForEach(assemblyNames, (assemblyName) => |
|||
{ |
|||
//var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
|||
var xmlFile = $"{assemblyName.Name}.xml"; |
|||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); |
|||
if (!File.Exists(xmlPath)) |
|||
return; |
|||
c.IncludeXmlComments(xmlPath, true); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
|
|||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, YunDingBusiness yunDingBusiness) |
|||
{ |
|||
yunDingBusiness.RefreshKey(); |
|||
if (isEnableSwagger) |
|||
{ |
|||
app.UseSwagger(c => c.SerializeAsV2 = true) |
|||
.UseSwaggerUI(c => |
|||
{ |
|||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "BBWY API"); |
|||
c.RoutePrefix = string.Empty; |
|||
}); |
|||
} |
|||
|
|||
//if (env.IsDevelopment())
|
|||
//{
|
|||
// app.UseDeveloperExceptionPage();
|
|||
//}
|
|||
|
|||
app.UseMiddleware<CustomExceptionMiddleWare>(); |
|||
|
|||
app.UseRouting(); |
|||
|
|||
app.UseAuthorization(); |
|||
|
|||
app.UseEndpoints(endpoints => |
|||
{ |
|||
endpoints.MapControllers(); |
|||
}); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,15 @@ |
|||
using System; |
|||
|
|||
namespace JD.API |
|||
{ |
|||
public class WeatherForecast |
|||
{ |
|||
public DateTime Date { get; set; } |
|||
|
|||
public int TemperatureC { get; set; } |
|||
|
|||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); |
|||
|
|||
public string Summary { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information", |
|||
"Microsoft": "Warning", |
|||
"Microsoft.Hosting.Lifetime": "Information" |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,14 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information", |
|||
"Microsoft": "Warning", |
|||
"Microsoft.Hosting.Lifetime": "Information" |
|||
} |
|||
}, |
|||
"ConnectionStrings": { |
|||
"DB": "data source=rm-bp1508okrh23710yfao.mysql.rds.aliyuncs.com;port=3306;user id=qyroot;password=kaicn1132+-;initial catalog=bbwy_test;charset=utf8;sslmode=none;", |
|||
}, |
|||
"IsEnableSwagger": false, |
|||
"AllowedHosts": "*" |
|||
} |
Loading…
Reference in new issue