Browse Source

完善项目

master
shanji 3 years ago
parent
commit
9e6c5f23bf
  1. 11
      Binance.TradeRobot.API/Binance.TradeRobot.API.csproj
  2. 91
      Binance.TradeRobot.API/CustomMiddleWare/CustomExceptionMiddleWare.cs
  3. 139
      Binance.TradeRobot.API/Extensions/StartupExtenions.cs
  4. 30
      Binance.TradeRobot.API/Filters/ResultFilter.cs
  5. 14
      Binance.TradeRobot.API/NLog.config
  6. 37
      Binance.TradeRobot.API/Startup.cs
  7. 6
      Binance.TradeRobot.API/appsettings.json
  8. 7
      Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj
  9. 36
      Binance.TradeRobot.Business/NLogManager.cs
  10. 16
      Binance.TradeRobot.Model/Base/ApiResponse.cs
  11. 17
      Binance.TradeRobot.Model/Base/Enums.cs
  12. 5
      Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj
  13. 45
      Binance.TradeRobot.Model/Db/User.cs
  14. 46
      Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs
  15. 59
      Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs
  16. 1
      Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat

11
Binance.TradeRobot.API/Binance.TradeRobot.API.csproj

@ -2,8 +2,19 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="FreeSql" Version="3.0.100" />
<PackageReference Include="FreeSql.Provider.SqlServer" Version="3.0.100" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.22" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.22" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.12" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Binance.TradeRobot.Business\Binance.TradeRobot.Business.csproj" /> <ProjectReference Include="..\Binance.TradeRobot.Business\Binance.TradeRobot.Business.csproj" />
<ProjectReference Include="..\Binance.TradeRobot.Model\Binance.TradeRobot.Model.csproj" /> <ProjectReference Include="..\Binance.TradeRobot.Model\Binance.TradeRobot.Model.csproj" />

91
Binance.TradeRobot.API/CustomMiddleWare/CustomExceptionMiddleWare.cs

@ -0,0 +1,91 @@
using Binance.TradeRobot.Business;
using Binance.TradeRobot.Model.Base;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Binance.TradeRobot.API.Middlewares
{
public class CustomExceptionMiddleWare
{
/// <summary>
/// 管道请求委托
/// </summary>
private RequestDelegate _next;
/// <summary>
/// 需要处理的状态码字典
/// </summary>
private IDictionary<int, string> _exceptionStatusCodeDic;
private NLogManager nLogManager;
/// <summary>
///
/// </summary>
/// <param name="next"></param>
/// <param name="nLogManager"></param>
public CustomExceptionMiddleWare(RequestDelegate next, NLogManager nLogManager)
{
_next = next;
this.nLogManager = nLogManager;
_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; //发生未捕获的异常,手动设置状态码
nLogManager.Default().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 = new ApiResponse() { Code = code, Message = exMsg };
var serialzeStr = JsonConvert.SerializeObject(apiResponse);
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(serialzeStr, Encoding.UTF8);
}
}
}

139
Binance.TradeRobot.API/Extensions/StartupExtenions.cs

@ -0,0 +1,139 @@
using Binance.TradeRobot.API.Middlewares;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Binance.TradeRobot.API.Extensions
{
public static class StartupExtenions
{
/// <summary>
/// 批量注册服务
/// </summary>
/// <param name="services">DI服务</param>
/// <param name="assemblys">需要批量注册的程序集集合</param>
/// <param name="baseType">基础类/接口</param>
/// <param name="serviceLifetime">服务生命周期</param>
/// <returns></returns>
public static IServiceCollection BatchRegisterService(this IServiceCollection services, Assembly[] assemblys, Type baseType, ServiceLifetime serviceLifetime = ServiceLifetime.Singleton)
{
List<Type> typeList = new List<Type>(); //所有符合注册条件的类集合
foreach (var assembly in assemblys)
{
//筛选当前程序集下符合条件的类
var types = assembly.GetTypes().Where(t => !t.IsInterface && !t.IsSealed && !t.IsAbstract && baseType.IsAssignableFrom(t));
if (types != null && types.Count() > 0)
typeList.AddRange(types);
}
if (typeList.Count() == 0)
return services;
var typeDic = new Dictionary<Type, Type[]>(); //待注册集合
foreach (var type in typeList)
{
var interfaces = type.GetInterfaces(); //获取接口
typeDic.Add(type, interfaces);
}
if (typeDic.Keys.Count() > 0)
{
foreach (var instanceType in typeDic.Keys)
{
foreach (var interfaceType in typeDic[instanceType])
{
//根据指定的生命周期进行注册
services.Add(new ServiceDescriptor(interfaceType, instanceType, serviceLifetime));
}
}
}
return services;
}
/// <summary>
/// 注册自定义异常中间件
/// </summary>
/// <param name="app"></param>
/// <returns></returns>
public static IApplicationBuilder UseCustomException(this IApplicationBuilder app)
{
return app.UseMiddleware<CustomExceptionMiddleWare>();
}
/// <summary>
/// 添加Swagger服务
/// </summary>
/// <param name="services"></param>
/// <param name="title"></param>
/// <returns></returns>
public static IServiceCollection AddSwagger(this IServiceCollection services, string title)
{
return services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1.0.0",
Title = title,
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);
});
});
}
//public static IServiceCollection AddWebSocket(this IServiceCollection services)
//{
// services.AddSingleton<WebSocketConnectionManager>();
// services.AddSingleton<WebSocketHandler, TradeRobotWebSocketHandler>();
// return services;
//}
/// <summary>
/// 注册websocket中间件
/// </summary>
/// <param name="app"></param>
/// <param name="handler"></param>
/// <returns></returns>
//public static IApplicationBuilder UseWebSocketMiddleware(this IApplicationBuilder app, WebSocketHandler handler)
//{
// // return app.Map(path, (_app) => _app.UseMiddleware<WebSocketManagerMiddleware>(handler));
// return app.UseMiddleware<WebSocketManagerMiddleware>(handler);
//}
}
}

30
Binance.TradeRobot.API/Filters/ResultFilter.cs

@ -0,0 +1,30 @@
using Binance.TradeRobot.Model.Base;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace Binance.TradeRobot.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());
}
}
}
}

14
Binance.TradeRobot.API/NLog.config

@ -0,0 +1,14 @@
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<targets>
<target name="errorFile" xsi:type="File" fileName="${basedir}/logs/${logger}/error/${shortdate}.txt"
layout="${longdate} | ${level:uppercase=false} ${newline}${message} ${newline}${onexception:${exception:format=tostring} ${newline}${stacktrace} ${newline}${newline}"
autoFlush="true"/>
<target name="infoFile" xsi:type="File" fileName="${basedir}/logs/${logger}/info/${shortdate}.txt"
layout="${longdate} | ${level:uppercase=false} ${newline}${message} ${newline}"
autoFlush="true"/>
</targets>
<rules>
<logger name="*" level="Error" writeTo="errorFile"/>
<logger name="*" level="Info" writeTo="infoFile" />
</rules>
</nlog>

37
Binance.TradeRobot.API/Startup.cs

@ -1,15 +1,11 @@
using Binance.TradeRobot.API.Filters;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Newtonsoft.Json.Serialization;
using System; using Yitter.IdGenerator;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Binance.TradeRobot.API namespace Binance.TradeRobot.API
{ {
@ -25,7 +21,32 @@ namespace Binance.TradeRobot.API
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddControllers(); var fsql = new FreeSql.FreeSqlBuilder().UseConnectionString(FreeSql.DataType.SqlServer, Configuration.GetConnectionString("DB")).Build();
services.AddSingleton(typeof(IFreeSql), fsql);
var idOption = new IdGeneratorOptions(1);
var idGenerator = new DefaultIdGenerator(idOption);
services.AddSingleton(typeof(IIdGenerator), idGenerator);
services.AddHttpContextAccessor();
services.AddHttpClient();
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;
});
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

6
Binance.TradeRobot.API/appsettings.json

@ -6,5 +6,9 @@
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"ConnectionStrings": {
//"DB": "Data Source=192.168.201.44;Initial Catalog=HY.TradingRobot.DB;User ID=sa;Pwd=kaicn1132+-;"
"DB": "Data Source=.;Initial Catalog=Binance.TradeRobot.DB;User ID=sa;Pwd=pc911103;"
}
} }

7
Binance.TradeRobot.Business/Binance.TradeRobot.Business.csproj

@ -5,6 +5,13 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="FreeSql" Version="3.0.100" />
<PackageReference Include="FreeSql.Provider.SqlServer" Version="3.0.100" />
<PackageReference Include="NLog" Version="4.7.13" />
<PackageReference Include="Yitter.IdGenerator" Version="1.0.12" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Binance.TradeRobot.Model\Binance.TradeRobot.Model.csproj" /> <ProjectReference Include="..\Binance.TradeRobot.Model\Binance.TradeRobot.Model.csproj" />
</ItemGroup> </ItemGroup>

36
Binance.TradeRobot.Business/NLogManager.cs

@ -0,0 +1,36 @@
using NLog;
using System.Collections.Generic;
namespace Binance.TradeRobot.Business
{
public class NLogManager
{
private IDictionary<string, ILogger> loggerDictionary = new Dictionary<string, ILogger>();
private string defaultLoggerName = "default";
public NLogManager()
{
loggerDictionary = new Dictionary<string, ILogger>()
{
{ "default",NLog.LogManager.GetLogger(defaultLoggerName)}
};
}
public ILogger Default()
{
return loggerDictionary[defaultLoggerName];
}
public ILogger GetLogger(string loggerName)
{
if (string.IsNullOrEmpty(loggerName))
return Default();
if (!loggerDictionary.TryGetValue(loggerName, out ILogger logger))
{
logger = NLog.LogManager.GetLogger(loggerName);
loggerDictionary.TryAdd(loggerName, logger);
}
return logger;
}
}
}

16
Binance.TradeRobot.Model/Base/ApiResponse.cs

@ -0,0 +1,16 @@
namespace Binance.TradeRobot.Model.Base
{
public class ApiResponse<T>
{
public int Code { get; set; } = 200;
public T Data { get; set; }
public string Message { get; set; }
}
public class ApiResponse : ApiResponse<object>
{
}
}

17
Binance.TradeRobot.Model/Base/Enums.cs

@ -4,6 +4,21 @@ namespace Binance.TradeRobot.Model.Base
{ {
public class Enums public class Enums
{ {
#region 基本
public enum BusinessType
{
/// <summary>
/// 现货
/// </summary>
Spot = 0,
/// <summary>
/// 合约
/// </summary>
Prep = 1
}
#endregion
#region 用户资金 #region 用户资金
/// <summary> /// <summary>
/// 资金变更类型 追投=0,提现=1,转移=2 /// 资金变更类型 追投=0,提现=1,转移=2
@ -40,9 +55,7 @@ namespace Binance.TradeRobot.Model.Base
/// </summary> /// </summary>
public enum RobotStatus public enum RobotStatus
{ {
[Description("停止")]
Stop = 0, Stop = 0,
[Description("运行中")]
Runing = 1 Runing = 1
} }
#endregion #endregion

5
Binance.TradeRobot.Model/Binance.TradeRobot.Model.csproj

@ -6,8 +6,11 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Db\" />
<Folder Include="Dto\" /> <Folder Include="Dto\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="FreeSql" Version="3.0.100" />
</ItemGroup>
</Project> </Project>

45
Binance.TradeRobot.Model/Db/User.cs

@ -0,0 +1,45 @@
using FreeSql.DataAnnotations;
using System;
namespace Binance.TradeRobot.Model.Db
{
[Table(DisableSyncStructure = true)]
public partial class User {
[Column(IsPrimary = true)]
public long Id { get; set; }
/// <summary>
/// 投资本金
/// </summary>
[ Column(DbType = "decimal(18,8)")]
public decimal CostAmount { get; set; } = 0.0M;
[Column(InsertValueSql = "getdate()")]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 收益
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal Profit { get; set; } = 0.0M;
[Column(StringLength = 20)]
public string Pwd { get; set; }
[Column(InsertValueSql = "getdate()")]
public DateTime? UpdateTime { get; set; }
[Column(StringLength = 20)]
public string UserName { get; set; }
/// <summary>
/// 提前金额
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal WithdrawAmount { get; set; } = 0.0M;
}
}

46
Binance.TradeRobot.Model/Db/UserAccountFundChangeRecord.cs

@ -0,0 +1,46 @@
using Binance.TradeRobot.Model.Base;
using FreeSql.DataAnnotations;
using System;
namespace Binance.TradeRobot.Model.Db
{
[Table(DisableSyncStructure = true)]
public partial class UserAccountFundChangeRecord
{
[Column(IsPrimary = true)]
public long Id { get; set; }
/// <summary>
/// 变更金额
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal ChangeAmount { get; set; }
[Column(InsertValueSql = "getdate()")]
public DateTime? CreateTime { get; set; }
[Column(MapType = typeof(int))]
public Enums.FundDirection Direction { get; set; }
[Column(MapType = typeof(int))]
public Enums.CapitalChangeType OperationType { get; set; }
/// <summary>
/// 操作者Id
/// </summary>
public long OperationUserId { get; set; }
/// <summary>
/// 用户Id
/// </summary>
public long UserId { get; set; }
/// <summary>
/// 对端用户Id
/// </summary>
public long? ToUserId { get; set; }
}
}

59
Binance.TradeRobot.Model/Db/UserAccountProfitLossRecord.cs

@ -0,0 +1,59 @@
using Binance.TradeRobot.Model.Base;
using FreeSql.DataAnnotations;
using System;
namespace Binance.TradeRobot.Model.Db
{
[Table(DisableSyncStructure = true)]
public partial class UserAccountProfitLossRecord
{
/// <summary>
/// 业务类型
/// </summary>
[Column(MapType = typeof(int))]
public Enums.BusinessType BusinessType { get; set; }
/// <summary>
/// 变更金额
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal ChangeAmount { get; set; } = 0.0M;
[Column(InsertValueSql = "getdate()")]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 分红比例
/// </summary>
[Column(DbType = "decimal(18,2)")]
public decimal DividendRatio { get; set; } = 0.0M;
public long? Id { get; set; }
public long OrderId { get; set; }
/// <summary>
/// 订单利润
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal OrderProfit { get; set; } = 0.0M;
public long RobotId { get; set; }
public long UserId { get; set; }
/// <summary>
/// 用户投资收益
/// </summary>
[Column(DbType = "decimal(18,8)")]
public decimal UserProfit { get; set; } = 0.0M;
}
}

1
Binance.TradeRobot.Model/Db/代码生成/__重新生成.bat

@ -0,0 +1 @@
FreeSql.Generator -Razor 1 -NameOptions 1,0,0,0 -NameSpace Binance.TradeRobot.Model.Db -DB "SqlServer,data source=.;initial catalog=Binance.TradeRobot.DB;User Id=sa;Password=pc911103;TrustServerCertificate=true;pooling=true;max pool size=2" -FileName "{name}.cs"
Loading…
Cancel
Save