Merge pull request 'dev' (#2) from dev into main

Reviewed-on: #2
This commit is contained in:
西街长安 2025-07-31 22:54:26 +08:00
commit d9b4583096
73 changed files with 7108 additions and 16 deletions

View File

@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.11.35312.102 VisualStudioVersion = 17.11.35312.102
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apimanager_backend", "Apimanager_backend\Apimanager_backend.csproj", "{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Apimanager_backend", "Apimanager_backend\Apimanager_backend.csproj", "{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Public", "Public\Public.csproj", "{3B2063E0-B7B1-4CCF-979C-0E533FE1A05E}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -15,6 +17,10 @@ Global
{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Release|Any CPU.Build.0 = Release|Any CPU {F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Release|Any CPU.Build.0 = Release|Any CPU
{3B2063E0-B7B1-4CCF-979C-0E533FE1A05E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B2063E0-B7B1-4CCF-979C-0E533FE1A05E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B2063E0-B7B1-4CCF-979C-0E533FE1A05E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B2063E0-B7B1-4CCF-979C-0E533FE1A05E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

Binary file not shown.

View File

@ -19,8 +19,14 @@
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.MariaDB" Version="1.0.1" /> <PackageReference Include="Serilog.Sinks.MariaDB" Version="1.0.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.6" />
<PackageReference Include="StackExchange.Redis" Version="2.8.16" /> <PackageReference Include="StackExchange.Redis" Version="2.8.16" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Public\Public.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -15,6 +15,14 @@ namespace Apimanager_backend.Config
CreateMap<CreateApiInfo, Api>(); CreateMap<CreateApiInfo, Api>();
CreateMap<Apipackage, PackageInfoDto>(); CreateMap<Apipackage, PackageInfoDto>();
CreateMap<AddPackageDto, Apipackage>(); CreateMap<AddPackageDto, Apipackage>();
CreateMap<OrderDto, Order>();
CreateMap<PaymentConfig, PaymentConfigDto>();
CreateMap<EpayResponse, PayReturnData>()
.ForMember(dest => dest.Success, opt => opt.MapFrom(src => src.code == 1))
.ForMember(dest => dest.QrCode, opt => opt.MapFrom(src => src.qrcode))
.ForMember(dest => dest.OrderNum, opt => opt.MapFrom(src => src.trade_no))
.ForMember(dest => dest.PayUrl, opt => opt.MapFrom(src => src.payurl))
.ForMember(dest => dest.Urlscheme, opt => opt.MapFrom(src => src.urlscheme));
} }
} }
} }

View File

@ -1,12 +1,15 @@
using Apimanager_backend.Dtos; using Apimanager_backend.Dtos;
using Apimanager_backend.Services; using Apimanager_backend.Services;
using Apimanager_backend.Tools;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json; using Newtonsoft.Json;
using Public;
using StackExchange.Redis; using StackExchange.Redis;
using System.ComponentModel; using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.RateLimiting;
namespace Apimanager_backend.Config namespace Apimanager_backend.Config
{ {
@ -22,10 +25,17 @@ namespace Apimanager_backend.Config
services.AddScoped<IAdminService, AdminService>(); services.AddScoped<IAdminService, AdminService>();
services.AddScoped<IApiService, ApiService>(); services.AddScoped<IApiService, ApiService>();
services.AddScoped<IPackageService, PackageService>(); services.AddScoped<IPackageService, PackageService>();
services.AddScoped<IOrderService, OrderService>();
services.AddScoped<IApiPackageItemService, ApiPackageItemService>();
services.AddScoped<IUserPackageService, UserPackageService>();
services.AddScoped<ISystemConfigService, SystemConfigService>(); services.AddScoped<ISystemConfigService, SystemConfigService>();
services.AddScoped<IPaymentConfigService, PaymentConfigService>();
services.AddScoped<IPayService, PayService>();
services.AddSingleton<ITokenService, TokenService>(); services.AddSingleton<ITokenService, TokenService>();
services.AddSingleton<IRefreshTokenService, RefreshTokenService>(); services.AddSingleton<IRefreshTokenService, RefreshTokenService>();
services.AddSingleton<IEmailService, EmailService>(); services.AddSingleton<IEmailService, EmailService>();
services.AddApiHandler(configuration);
services.AddRateLimit(configuration);
return services; return services;
} }
public static IServiceCollection AddJWTService(this IServiceCollection services,IConfiguration configuration) public static IServiceCollection AddJWTService(this IServiceCollection services,IConfiguration configuration)
@ -100,5 +110,76 @@ namespace Apimanager_backend.Config
}); });
return services; return services;
} }
public static IServiceCollection AddApiHandler(this IServiceCollection services,IConfiguration configuration1)
{
/*
var handlerTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => typeof(IBillableApiHandler).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);
foreach(var type in handlerTypes)
{
services.AddTransient(type);
}
*/
services.AddSingleton<PluginLoaderService>();
var pluginLoaderService = services.BuildServiceProvider()
.GetRequiredService<PluginLoaderService>();
pluginLoaderService.LoadPlugins(services);
services.AddScoped<BillableApiDispatcher>();
return services;
}
public static IServiceCollection AddRateLimit(this IServiceCollection service, IConfiguration configuration1)
{
service.AddRateLimiter(option =>
{
option.RejectionStatusCode = 429;
option.OnRejected = async (context, ct) =>
{
context.HttpContext.Response.ContentType = "application/json";
await context.HttpContext.Response.WriteAsJsonAsync(new ResponseBase<object?>()
{
Code = 3003,
Data = null,
Message = "API调用已达上限"
}, ct);
};
option.AddPolicy("DynamicPerUser", context =>
{
// 从前面中间件塞进来的 user 对象
var dto = context.Items["rateLimit"] as RateLimiterDto;
string partitionKey;
int limit;
if (dto is null)
{
return RateLimitPartition.GetConcurrencyLimiter("unauthorized", _ => new ConcurrencyLimiterOptions
{
PermitLimit = 0, // 不允许任何请求
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 0
});
}
else
{
partitionKey = dto.UserId.ToString();
limit = dto.RateLimit;
}
return RateLimitPartition.GetFixedWindowLimiter(
partitionKey,
_ => new FixedWindowRateLimiterOptions
{
PermitLimit = limit,
Window = TimeSpan.FromMinutes(1),
QueueLimit = 0,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});
});
});
return service;
}
} }
} }

View File

@ -47,7 +47,7 @@ namespace Apimanager_backend.Controllers
#endregion #endregion
#region API列表 #region API列表
[HttpGet] [HttpGet]
[Authorize(Roles = "User")] //[Authorize(Roles = "User")]
public async Task<ActionResult<ResponseBase<List<ApiInfoDto>>>> ApiList(int pageIndex,int pageSize,bool desc) public async Task<ActionResult<ResponseBase<List<ApiInfoDto>>>> ApiList(int pageIndex,int pageSize,bool desc)
{ {
var list = await apiService.GetApisAsync(pageIndex, pageSize, desc); var list = await apiService.GetApisAsync(pageIndex, pageSize, desc);

View File

@ -0,0 +1,48 @@
using Apimanager_backend.Dtos;
using Apimanager_backend.Models;
using Apimanager_backend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Apimanager_backend.Controllers
{
[Route("api/[controller][action]")]
[ApiController]
public class OrderController:ControllerBase
{
private IOrderService _orderService;
private ILogger<OrderController> _logger;
public OrderController(IOrderService orderService,ILogger<OrderController> logger)
{
_orderService = orderService;
_logger = logger;
}
//获取全部订单列表
[HttpGet]
[Authorize(Roles = "Admin")]
public async Task<ActionResult<ResponseBase<List<Order>>>> GetOrders(int pageIndex,int pageSize,bool desc)
{
var orderList = await _orderService.GetOrdersAsync(pageIndex,pageSize,desc, null);
var responseData = new ResponseBase<List<Order>>(
code:1000,
message:"Success",
data:orderList
);
return Ok(responseData);
}
//获取个人订单列表
[HttpGet]
[Authorize(Roles = "User")]
public async Task<ActionResult<ResponseBase<List<Order>>>> GetMyOrders(int pageIndex,int pageSize,bool desc)
{
string userId = User.Claims.First(x => x.Type == "userId").Value;
var orderList = await _orderService.GetOrdersAsync(pageIndex,pageSize,desc,int.Parse(userId));
var responseData = new ResponseBase<List<Order>>(
code:1000,
data:orderList,
message:"Success"
);
return Ok(responseData);
}
}
}

View File

@ -95,7 +95,7 @@ namespace Apimanager_backend.Controllers
#endregion #endregion
#region #region
[HttpGet] [HttpGet]
//[Authorize(Roles = "User")] [Authorize(Roles = "User")]
public async Task<ActionResult<ResponseBase<List<PackageInfoDto>>>> GetPackageList(int pageIndex,int pageSize,bool desc) public async Task<ActionResult<ResponseBase<List<PackageInfoDto>>>> GetPackageList(int pageIndex,int pageSize,bool desc)
{ {
var packageList = await packageService.GetAllPackagesAsync(pageIndex,pageSize,desc); var packageList = await packageService.GetAllPackagesAsync(pageIndex,pageSize,desc);

View File

@ -0,0 +1,83 @@
using Apimanager_backend.Dtos;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Models;
using Apimanager_backend.Services;
using Apimanager_backend.Tools;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Apimanager_backend.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class PayController : ControllerBase
{
private ILogger<PayController> _logger;
private IOrderService _orderService;
private IPaymentConfigService _paymentService;
private IPayService _payService;
public PayController(ILogger<PayController> logger,IOrderService order,IPaymentConfigService paymentConfigService,IPayService payService)
{
_logger = logger;
_orderService = order;
_paymentService = paymentConfigService;
_payService = payService;
}
[HttpPost]
[Authorize(Roles = "User")]
public async Task<IActionResult> CreatePayment([FromBody]CreatePaymentDto dto)
{
var userId = User.Claims.First(x => x.Type == "userId").Value;
//获取支付接口信息
var paymentConfig = await _paymentService.GetPaymentConfigInfoByTypeAsync(dto.PaymentType.ToString());
//创建订单
OrderDto order = new OrderDto();
order.Amount = dto.Amount;
order.OrderType = OrderType.Purchase;
order.UserId = int.Parse(userId);
order.PaymentType = dto.PaymentType;
Order orderRes = await _orderService.CreateOrderAsync(order);
switch (paymentConfig.PayType)
{
case PayType.None:
throw new BaseException(4001,"当前支付方式未配置");
case PayType.Epay:
var epayRes = await _payService.CreateEpay(orderRes, paymentConfig,dto.ReturnUrl);
return Ok(epayRes);
default:
throw new BaseException(4001, "不支持的支付方式");
}
}
[HttpGet]
public async Task<IActionResult> Notice(
int pid, string trade_no,string out_trade_no
, string type, string name, decimal money
, string trade_status, string sign, string sign_type
)
{
Dictionary<string, string> param = new Dictionary<string, string>();
param["pid"] = pid.ToString();
param["trade_no"] = trade_no;
param["out_trade_no"] = out_trade_no;
param["type"] = type;
param["name"] = name;
param["money"] = money.ToString();
param["trade_status"] = trade_status;
param["sign"] = sign;
param["sign_type"] = sign_type;
PaymentConfig paymentConfig = await _paymentService.GetPaymentConfigInfoByTypeAsync(type);
bool verifyRes = EpayHelper.VerifySign(param,paymentConfig.SecretKey);
if (!verifyRes)
{
throw new BaseException(4001, "签名校验失败");
}
OrderDto orderDto = new OrderDto();
orderDto.ThirdPartyOrderId = trade_no;
if (trade_status == "TRADE_SUCCESS") orderDto.Status = OrderStatus.Completed;
else orderDto.Status = OrderStatus.Failed;
await _orderService.UpdateOrderAsync(orderDto);
return Ok("Success");
}
}
}

View File

@ -0,0 +1,66 @@
using Apimanager_backend.Dtos;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Services;
using Apimanager_backend.Tools;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Public;
using System.Text.Json;
namespace Apimanager_backend.Controllers
{
[Route("api/[controller]/{code}")]
[ApiController]
public class PublicController : ControllerBase
{
private BillableApiDispatcher _dispatcher;
private IApiService _apiService;
private IWebHostEnvironment _webHostEnvironment;
public PublicController(BillableApiDispatcher billableApiDispatcher,IApiService apiService,IWebHostEnvironment webHostEnvironment)
{
_dispatcher = billableApiDispatcher;
_apiService = apiService;
_webHostEnvironment = webHostEnvironment;
}
[HttpGet,HttpDelete,HttpPost,HttpPut]
[EnableRateLimiting("DynamicPerUser")]
public async Task<IActionResult> Invoke(string code)
{
var requestMethod = HttpContext.Request.Method; // GET, POST, etc.
var api = await _apiService.GetApiInfoByEndpointAsync(code);
if (api == null || !api.IsActive)
throw new BaseException(3002,"接口不存在");
if (!string.Equals(api.Method.ToString(),requestMethod, StringComparison.OrdinalIgnoreCase))
throw new BaseException(3002,$"接口不支持{requestMethod}方法");
Dictionary<string, object> parameters = new Dictionary<string, object>();
// 获取参数
if ((requestMethod == "GET" && Request.Query.Count == 0) || (requestMethod == "POST" && Request.ContentLength == 0))
{
parameters = new Dictionary<string, object>();
}
else
{
parameters = requestMethod switch
{
"GET" => HttpContext.Request.Query.ToDictionary(x => x.Key, x => (object)x.Value.ToString()),
_ => await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(Request.Body)
};
}
//var userId = int.Parse(User.Claims.First(x => x.Type == "userId").Value);
var context = new ApiCallContext
{
UserId = -1,
HttpContext = HttpContext,
Parameters = parameters
};
var result = await _dispatcher.DispatchAsync(_webHostEnvironment.ContentRootPath,api.Id,api.Endpoint, context);
return Ok(result);
}
}
}

View File

@ -0,0 +1,236 @@
using Apimanager_backend.Exceptions;
using Apimanager_backend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SixLabors.ImageSharp; // 确保添加这个using
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using Apimanager_backend.Dtos;
namespace Apimanager_backend.Controllers
{
[ApiController]
[Route("api/[controller]/[action]")]
public class UploadController:ControllerBase
{
private ILogger<UploadController> _logger;
private readonly IWebHostEnvironment _environment;
private IUserService _userService;
// 最大文件大小 5MB
private const long MaxFileSize = 5 * 1024 * 1024;
// 允许的文件类型
private static readonly string[] AllowedExtensions = { ".jpg", ".jpeg", ".png", ".gif" };
public UploadController(ILogger<UploadController> logger,IWebHostEnvironment webHostEnvironment,IUserService userService)
{
_logger = logger;
_environment = webHostEnvironment;
_userService = userService;
}
[HttpPost]
[Authorize(Roles = "User")]
public async Task<IActionResult> UploadPic(IFormFile file)
{
try
{
// 1. 验证文件
if (file == null || file.Length == 0)
{
throw new BaseException(1001,"缺少文件");
}
// 2. 验证文件大小
if (file.Length > MaxFileSize)
{
throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}");
}
var basePath = _environment.WebRootPath ?? _environment.ContentRootPath;
// 3. 验证文件类型
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (string.IsNullOrEmpty(extension) || !AllowedExtensions.Contains(extension))
{
throw new BaseException(1001, "只支持 JPG, PNG, GIF 格式的图片");
}
// 5. 创建存储目录
var uploadsFolder = Path.Combine(basePath, "uploads", "avatars");
if (!Directory.Exists(uploadsFolder))
{
Directory.CreateDirectory(uploadsFolder);
}
var userId = User.Claims.First(x => x.Type == "userId").Value;
// 6. 生成唯一文件名
var uniqueFileName = $"{userId}_{DateTime.Now:yyyyMMddHHmmss}{extension}";
var filePath = Path.Combine(uploadsFolder, uniqueFileName);
// 7. 处理并保存图片
using (var image = await Image.LoadAsync(file.OpenReadStream()))
{
// 调整图片大小最大200x200
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(200, 200),
Mode = ResizeMode.Max
}));
// 保存为高质量JPEG
await image.SaveAsync(filePath);
}
// 8. 更新数据库中的头像路径
var avatarUrl = $"/uploads/avatars/{uniqueFileName}";
var result = await _userService.UpdateUserAvatarAsync(int.Parse(userId), avatarUrl);
if (!result)
{
// 如果数据库更新失败,删除已上传的文件
System.IO.File.Delete(filePath);
throw new BaseException(1004,"头像上传失败");
}
// 9. 返回成功响应
return Ok(new ResponseBase<object>(1000,"头像上传成功",null));
}
catch (Exception ex)
{
_logger.LogError(ex, "头像上传失败");
throw new BaseException(1004, "头像上传失败");
}
}
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> UploadLogo(IFormFile file)
{
try
{
// 1. 验证文件
if (file == null || file.Length == 0)
{
throw new BaseException(1001, "缺少文件");
}
// 2. 验证文件大小
if (file.Length > MaxFileSize)
{
throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}");
}
var basePath = _environment.WebRootPath ?? _environment.ContentRootPath;
// 3. 验证文件类型
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (string.IsNullOrEmpty(extension) || !AllowedExtensions.Contains(extension))
{
throw new BaseException(1001, "只支持 JPG, PNG, GIF 格式的图片");
}
// 5. 创建存储目录
var uploadsFolder = Path.Combine(basePath);
var filePath = Path.Combine(uploadsFolder, "logo.png");
// 7. 处理并保存图片
using (var image = await Image.LoadAsync(file.OpenReadStream()))
{
// 调整图片大小最大200x200
/*
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(200, 200),
Mode = ResizeMode.Max
}));
*/
// 强制保存为PNG高质量
await image.SaveAsync(filePath, new PngEncoder
{
CompressionLevel = PngCompressionLevel.BestCompression // 最佳压缩
});
}
// 9. 返回成功响应
return Ok(new ResponseBase<object>(1000, "LOGO上传成功", null));
}
catch (Exception ex)
{
_logger.LogError(ex, "LOGO上传失败");
throw new BaseException(1004, "LOGO上传失败");
}
}
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> UploadFavicon(IFormFile file)
{
try
{
// 1. 验证文件
if (file == null || file.Length == 0)
{
throw new BaseException(1001, "缺少文件");
}
// 2. 验证文件大小
if (file.Length > MaxFileSize)
{
throw new BaseException(1001, $"文件大小不能超过{MaxFileSize}");
}
var basePath = _environment.WebRootPath ?? _environment.ContentRootPath;
// 3. 验证文件类型
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (string.IsNullOrEmpty(extension) || extension != ".ico")
{
throw new BaseException(1001, "只支持 ICO 格式的图片");
}
// 3. 保存到网站根目录
var icoPath = Path.Combine(_environment.WebRootPath, "favicon.ico");
using (var stream = new FileStream(icoPath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
// 9. 返回成功响应
return Ok(new ResponseBase<object>(1000, "favicon上传成功", null));
}
catch (Exception ex)
{
_logger.LogError(ex, "Favicon上传失败");
throw new BaseException(1004, "Favicon上传失败");
}
}
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> UploadApi(IFormFile file)
{
if (file == null || file.Length == 0)
throw new BaseException(1001,"请上传文件");
// 检查扩展名
var ext = Path.GetExtension(file.FileName);
if (ext != ".dll")
throw new BaseException(1001, "只允许上传DLL");
// 插件保存路径
var saveDir = Path.Combine(_environment.ContentRootPath, "ApiHandler");
if (!Directory.Exists(saveDir))
Directory.CreateDirectory(saveDir);
var filePath = Path.Combine(saveDir, file.FileName);
// 保存文件
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Ok(new ResponseBase<object>(1000,"上传成功",null));
}
}
}

View File

@ -78,7 +78,7 @@ namespace Apimanager_backend.Controllers
[Authorize(Roles = "User")] [Authorize(Roles = "User")]
public async Task<ActionResult<ResponseBase<UserInfoDto?>>> Update([FromBody]UpdateUserDto dto) public async Task<ActionResult<ResponseBase<UserInfoDto?>>> Update([FromBody]UpdateUserDto dto)
{ {
var userId = User.Claims.First(x => x.ValueType == "userId").Value; var userId = User.Claims.First(x => x.Type == "userId").Value;
var userInfo = await userService.UpdateUserAsync(int.Parse(userId),dto); var userInfo = await userService.UpdateUserAsync(int.Parse(userId),dto);
var res = new ResponseBase<object?>( var res = new ResponseBase<object?>(
code:1000, code:1000,

View File

@ -13,6 +13,9 @@ namespace Apimanager_backend.Data
//自增 //自增
builder.Property(x => x.Id) builder.Property(x => x.Id)
.ValueGeneratedOnAdd(); .ValueGeneratedOnAdd();
//设置唯一
builder.HasIndex(x => x.Endpoint)
.IsUnique();
//外键 //外键
builder.HasOne(x => x.Package) builder.HasOne(x => x.Package)
.WithMany(u => u.Apis) .WithMany(u => u.Apis)

View File

@ -18,6 +18,10 @@ namespace Apimanager_backend.Data
public DbSet<OperationLog> OperationLogs { get; set; } public DbSet<OperationLog> OperationLogs { get; set; }
//订单表 //订单表
public DbSet<Order> Orders { get; set; } public DbSet<Order> Orders { get; set; }
//API套餐关联表
public DbSet<ApiPackageItem> apiPackageItems { get; set; }
//用户已订购套餐表 //用户已订购套餐表
public DbSet<UserPackage> UserPackages { get; set; } public DbSet<UserPackage> UserPackages { get; set; }
//用户角色表 //用户角色表
@ -26,14 +30,20 @@ namespace Apimanager_backend.Data
public DbSet<Log> Logs { get; set; } public DbSet<Log> Logs { get; set; }
//系统配置表 //系统配置表
public DbSet<SystemConfig> SystemConfigs { get; set; } public DbSet<SystemConfig> SystemConfigs { get; set; }
//支付配置
public DbSet<PaymentConfig> paymentConfigs { get; set; }
public ApiContext(DbContextOptions<ApiContext> options) : base(options) { } public ApiContext(DbContextOptions<ApiContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly); modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly);
// 配置全局查询筛选器 // 配置全局查询筛选器
modelBuilder.Entity<User>().HasQueryFilter(u => !u.IsDelete); modelBuilder.Entity<User>().HasQueryFilter(u => !u.IsDelete);
modelBuilder.Entity<UserRole>()
.HasQueryFilter(ur => !ur.User.IsDelete);
modelBuilder.Entity<Api>().HasQueryFilter(a => !a.IsDelete); modelBuilder.Entity<Api>().HasQueryFilter(a => !a.IsDelete);
modelBuilder.Entity<Apipackage>().HasQueryFilter(x => !x.IsDeleted); modelBuilder.Entity<Apipackage>().HasQueryFilter(x => !x.IsDeleted);
modelBuilder.Entity<Order>().HasQueryFilter(x => !x.IsDeleted);
//配置日志表 //配置日志表
modelBuilder.Entity<Log>().HasKey(x => x.Id); modelBuilder.Entity<Log>().HasKey(x => x.Id);
modelBuilder.Entity<Log>() modelBuilder.Entity<Log>()

View File

@ -0,0 +1,26 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class ApiPackageItemConfig : IEntityTypeConfiguration<ApiPackageItem>
{
public void Configure(EntityTypeBuilder<ApiPackageItem> builder)
{
//主键
builder.HasKey(x => x.Id);
//自增
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
//外键
builder.HasOne(x => x.Api)
.WithMany(u => u.ApiPackageItems)
.HasForeignKey(x => x.ApiId);
builder.HasOne(x => x.ApiPackage)
.WithMany(u => u.ApiPackageItems)
.HasForeignKey(x => x.ApiPackageId);
}
}
}

View File

@ -0,0 +1,22 @@
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Apimanager_backend.Data
{
public class PaymentConfigConfig : IEntityTypeConfiguration<PaymentConfig>
{
public void Configure(EntityTypeBuilder<PaymentConfig> builder)
{
builder.HasKey(x => x.Id);
builder.Property(x => x.Id)
.ValueGeneratedOnAdd();
builder.HasData(
new PaymentConfig() { Id = 1, Method = PaymentType.AliPay,PayType = PayType.Official, AppId = "", SecretKey = "", PublicKey = "", NotifyUrl = "", GatewayUrl = "", IsEnabled = false },
new PaymentConfig() { Id = 2, Method = PaymentType.WxPay, PayType = PayType.Official, AppId = "", SecretKey = "", PublicKey = "", NotifyUrl = "", GatewayUrl = "", IsEnabled = false },
new PaymentConfig() { Id = 3, Method = PaymentType.QQPay, PayType = PayType.Official, AppId = "", SecretKey = "", PublicKey = "", NotifyUrl = "", GatewayUrl = "", IsEnabled = false },
new PaymentConfig() { Id = 4, Method = PaymentType.Bank, PayType = PayType.Official, AppId = "", SecretKey = "", PublicKey = "", NotifyUrl = "", GatewayUrl = "", IsEnabled = false }
);
}
}
}

View File

@ -0,0 +1,26 @@
using System.Reflection;
using System.Runtime.Loader;
namespace Apimanager_backend.Data
{
// 隔离加载上下文
public class PluginLoadContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;
public PluginLoadContext(string pluginPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
}
protected override Assembly Load(AssemblyName assemblyName)
{
// 避免重复加载核心库
if (assemblyName.Name == "YourSharedContract")
return null;
string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
}
}
}

View File

@ -0,0 +1,13 @@
using Apimanager_backend.Models;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Dtos
{
public class CreatePaymentDto
{
public PaymentType PaymentType { get; set; }
[Required]
public decimal Amount { get; set; }
public string ReturnUrl { get; set; }
}
}

View File

@ -0,0 +1,12 @@
namespace Apimanager_backend.Dtos
{
public class EpayResponse
{
public int code { get; set; }
public string msg { get; set; }
public string trade_no { get; set; }
public string? payurl { get; set; }
public string? qrcode { get; set; }
public string? urlscheme { get; set; }
}
}

View File

@ -0,0 +1,45 @@
using Apimanager_backend.Models;
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Dtos
{
public class OrderDto
{
/// <summary>
/// 外键用户ID
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 订单号,唯一
/// </summary>
public string? OrderNumber { get; set; } // varchar(50)
/// <summary>
/// 第三方系统订单编号
/// </summary>
public string? ThirdPartyOrderId { get; set; } // varchar(100)
/// <summary>
/// 订单金额
/// </summary>
public decimal Amount { get; set; } // decimal(10, 2)
//支付方式
public PaymentType PaymentType { get; set; }
/// <summary>
/// 订单类型
/// </summary>
public OrderType OrderType { get; set; } // enum('Recharge','Purchase','Refund')
/// <summary>
/// 订单描述,可选的详细信息
/// </summary>
public string? Description { get; set; } // varchar(255)
public OrderStatus Status { get; set; }
}
}

View File

@ -0,0 +1,11 @@
namespace Apimanager_backend.Dtos
{
public class PayReturnData
{
public bool Success { get; set; }
public string? OrderNum { get; set; }
public string? PayUrl { get; set; }
public string? QrCode { get; set; }
public string? Urlscheme { get; set; }
}
}

View File

@ -0,0 +1,8 @@
namespace Apimanager_backend.Dtos
{
public class RateLimiterDto
{
public int UserId { get; set; }
public int RateLimit { get; set; }
}
}

View File

@ -7,9 +7,10 @@ namespace Apimanager_backend.Dtos
public int Id { get; set; } public int Id { get; set; }
public string UserName { get; set; } public string UserName { get; set; }
public string Email { get; set; } public string Email { get; set; }
public List<UserRole> Roles { get; set; } public List<UserRole>? Roles { get; set; }
public bool IsBan { get; set; } public bool IsBan { get; set; }
public decimal Balance { get; set; } public decimal Balance { get; set; }
public DateTime Created { get; set; } public DateTime Created { get; set; }
public List<UserPackage>? Packages { get; set; }
} }
} }

View File

@ -0,0 +1,575 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250728124413_add_order_isdeleted")]
partial class add_order_isdeleted
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 28, 12, 44, 13, 79, DateTimeKind.Utc).AddTicks(8845),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class add_order_isdeleted : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsDeleted",
table: "Orders",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 28, 12, 44, 13, 79, DateTimeKind.Utc).AddTicks(8845));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsDeleted",
table: "Orders");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2024, 11, 10, 13, 48, 10, 873, DateTimeKind.Utc).AddTicks(7811));
}
}
}

View File

@ -0,0 +1,676 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250729080100_add_PaymentConfig")]
partial class add_PaymentConfig
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("PaymentConfig");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 5,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 4,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 29, 8, 1, 0, 284, DateTimeKind.Utc).AddTicks(4585),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class add_PaymentConfig : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "UpdatedAt",
table: "Orders",
type: "datetime(6)",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime(6)");
migrationBuilder.AddColumn<DateTime>(
name: "PaiAt",
table: "Orders",
type: "datetime(6)",
nullable: true);
migrationBuilder.AddColumn<int>(
name: "PaymentType",
table: "Orders",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateTable(
name: "PaymentConfig",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Method = table.Column<int>(type: "int", nullable: false),
AppId = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SecretKey = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PublicKey = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NotifyUrl = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
GatewayUrl = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
ExtraSettingsJson = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_PaymentConfig", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "PaymentConfig",
columns: new[] { "Id", "AppId", "Description", "ExtraSettingsJson", "GatewayUrl", "IsEnabled", "Method", "NotifyUrl", "PublicKey", "SecretKey" },
values: new object[,]
{
{ 1, "", null, null, "", false, 0, "", "", "" },
{ 2, "", null, null, "", false, 1, "", "", "" },
{ 3, "", null, null, "", false, 3, "", "", "" },
{ 4, "", null, null, "", false, 2, "", "", "" },
{ 5, "", null, null, "", false, 4, "", "", "" }
});
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 29, 8, 1, 0, 284, DateTimeKind.Utc).AddTicks(4585));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PaymentConfig");
migrationBuilder.DropColumn(
name: "PaiAt",
table: "Orders");
migrationBuilder.DropColumn(
name: "PaymentType",
table: "Orders");
migrationBuilder.AlterColumn<DateTime>(
name: "UpdatedAt",
table: "Orders",
type: "datetime(6)",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime(6)",
oldNullable: true);
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 28, 12, 44, 13, 79, DateTimeKind.Utc).AddTicks(8845));
}
}
}

View File

@ -0,0 +1,720 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250729102235_add_apipackageItem")]
partial class add_apipackageItem
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("longtext");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("PaymentConfig");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 5,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 4,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 29, 10, 22, 34, 333, DateTimeKind.Utc).AddTicks(3700),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("ApiPackageItems");
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,74 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class add_apipackageItem : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ApiPackageItem",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ApiPackageId = table.Column<int>(type: "int", nullable: false),
ApiId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ApiPackageItem", x => x.Id);
table.ForeignKey(
name: "FK_ApiPackageItem_Apipackages_ApiPackageId",
column: x => x.ApiPackageId,
principalTable: "Apipackages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ApiPackageItem_Apis_ApiId",
column: x => x.ApiId,
principalTable: "Apis",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 29, 10, 22, 34, 333, DateTimeKind.Utc).AddTicks(3700));
migrationBuilder.CreateIndex(
name: "IX_ApiPackageItem_ApiId",
table: "ApiPackageItem",
column: "ApiId");
migrationBuilder.CreateIndex(
name: "IX_ApiPackageItem_ApiPackageId",
table: "ApiPackageItem",
column: "ApiPackageId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ApiPackageItem");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 29, 8, 1, 0, 284, DateTimeKind.Utc).AddTicks(4585));
}
}
}

View File

@ -0,0 +1,723 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250730145807_update_api_Endpoint")]
partial class update_api_Endpoint
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("Endpoint")
.IsUnique();
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("PaymentConfig");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
},
new
{
Id = 5,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 4,
NotifyUrl = "",
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 30, 14, 58, 7, 232, DateTimeKind.Utc).AddTicks(4921),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("ApiPackageItems");
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,63 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class update_api_Endpoint : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Endpoint",
table: "Apis",
type: "varchar(255)",
nullable: false,
oldClrType: typeof(string),
oldType: "longtext")
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 30, 14, 58, 7, 232, DateTimeKind.Utc).AddTicks(4921));
migrationBuilder.CreateIndex(
name: "IX_Apis_Endpoint",
table: "Apis",
column: "Endpoint",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Apis_Endpoint",
table: "Apis");
migrationBuilder.AlterColumn<string>(
name: "Endpoint",
table: "Apis",
type: "longtext",
nullable: false,
oldClrType: typeof(string),
oldType: "varchar(255)")
.Annotation("MySql:CharSet", "utf8mb4")
.OldAnnotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 29, 10, 22, 34, 333, DateTimeKind.Utc).AddTicks(3700));
}
}
}

View File

@ -0,0 +1,719 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250731061032_update_paymentconfig")]
partial class update_paymentconfig
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("Endpoint")
.IsUnique();
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<int>("PayType")
.HasColumnType("int");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("PaymentConfig");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 31, 6, 10, 31, 712, DateTimeKind.Utc).AddTicks(1486),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("ApiPackageItems");
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,82 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class update_paymentconfig : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "PaymentConfig",
keyColumn: "Id",
keyValue: 5);
migrationBuilder.AddColumn<int>(
name: "PayType",
table: "PaymentConfig",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.UpdateData(
table: "PaymentConfig",
keyColumn: "Id",
keyValue: 1,
column: "PayType",
value: 1);
migrationBuilder.UpdateData(
table: "PaymentConfig",
keyColumn: "Id",
keyValue: 2,
column: "PayType",
value: 1);
migrationBuilder.UpdateData(
table: "PaymentConfig",
keyColumn: "Id",
keyValue: 3,
column: "PayType",
value: 1);
migrationBuilder.UpdateData(
table: "PaymentConfig",
keyColumn: "Id",
keyValue: 4,
column: "PayType",
value: 1);
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 31, 6, 10, 31, 712, DateTimeKind.Utc).AddTicks(1486));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "PayType",
table: "PaymentConfig");
migrationBuilder.InsertData(
table: "PaymentConfig",
columns: new[] { "Id", "AppId", "Description", "ExtraSettingsJson", "GatewayUrl", "IsEnabled", "Method", "NotifyUrl", "PublicKey", "SecretKey" },
values: new object[] { 5, "", null, null, "", false, 4, "", "", "" });
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 30, 14, 58, 7, 232, DateTimeKind.Utc).AddTicks(4921));
}
}
}

View File

@ -0,0 +1,722 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250731074034_add_paymentconfig_url")]
partial class add_paymentconfig_url
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("Endpoint")
.IsUnique();
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<int>("PayType")
.HasColumnType("int");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.Property<string>("Url")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("paymentConfigs");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 31, 7, 40, 33, 590, DateTimeKind.Utc).AddTicks(5484),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("ApiPackageItems");
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,98 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class add_paymentconfig_url : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_PaymentConfig",
table: "PaymentConfig");
migrationBuilder.RenameTable(
name: "PaymentConfig",
newName: "paymentConfigs");
migrationBuilder.AddColumn<string>(
name: "Url",
table: "paymentConfigs",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddPrimaryKey(
name: "PK_paymentConfigs",
table: "paymentConfigs",
column: "Id");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 31, 7, 40, 33, 590, DateTimeKind.Utc).AddTicks(5484));
migrationBuilder.UpdateData(
table: "paymentConfigs",
keyColumn: "Id",
keyValue: 1,
column: "Url",
value: null);
migrationBuilder.UpdateData(
table: "paymentConfigs",
keyColumn: "Id",
keyValue: 2,
column: "Url",
value: null);
migrationBuilder.UpdateData(
table: "paymentConfigs",
keyColumn: "Id",
keyValue: 3,
column: "Url",
value: null);
migrationBuilder.UpdateData(
table: "paymentConfigs",
keyColumn: "Id",
keyValue: 4,
column: "Url",
value: null);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropPrimaryKey(
name: "PK_paymentConfigs",
table: "paymentConfigs");
migrationBuilder.DropColumn(
name: "Url",
table: "paymentConfigs");
migrationBuilder.RenameTable(
name: "paymentConfigs",
newName: "PaymentConfig");
migrationBuilder.AddPrimaryKey(
name: "PK_PaymentConfig",
table: "PaymentConfig",
column: "Id");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 31, 6, 10, 31, 712, DateTimeKind.Utc).AddTicks(1486));
}
}
}

View File

@ -0,0 +1,725 @@
// <auto-generated />
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Apimanager_backend.Migrations
{
[DbContext(typeof(ApiContext))]
[Migration("20250731104930_add_user_Avatar")]
partial class add_user_Avatar
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Endpoint")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsThirdParty")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("PackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("Endpoint")
.IsUnique();
b.HasIndex("PackageId");
b.ToTable("Apis");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("CallResult")
.HasColumnType("int");
b.Property<DateTime>("CallTime")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("UserId");
b.ToTable("CallLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<string>("Request")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Response")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ResponseType")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ApiId");
b.ToTable("ApiRequestExample");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CallLimit")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("OneMinuteLimit")
.HasColumnType("int");
b.Property<decimal>("Price")
.HasColumnType("decimal(65,30)");
b.HasKey("Id");
b.ToTable("Apipackages");
});
modelBuilder.Entity("Apimanager_backend.Models.Log", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Exception")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("LogLevel")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Message")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("MessageTemplate")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Properties")
.IsRequired()
.HasColumnType("longtext");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Logs");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("IpAddress")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("varchar(45)");
b.Property<string>("Operation")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("varchar(20)");
b.Property<int>("TargetId")
.HasColumnType("int");
b.Property<string>("TargetType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("UserAgent")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("OperationLogs");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<decimal>("Amount")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<int>("OrderType")
.HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("OrderNumber")
.IsUnique();
b.HasIndex("ThirdPartyOrderId")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("Orders");
});
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<int>("PayType")
.HasColumnType("int");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.Property<string>("Url")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("paymentConfigs");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ConfigBody")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ConfigName")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("SystemConfigs");
b.HasData(
new
{
Id = 1,
ConfigBody = "青蓝",
ConfigName = "SystemName"
},
new
{
Id = 2,
ConfigBody = "描述",
ConfigName = "SystemDescription"
},
new
{
Id = 3,
ConfigBody = "",
ConfigName = "LogoLocation"
},
new
{
Id = 4,
ConfigBody = "",
ConfigName = "FaviconLocation"
},
new
{
Id = 5,
ConfigBody = "13000000000",
ConfigName = "Phone"
},
new
{
Id = 6,
ConfigBody = "admin@admin.com",
ConfigName = "Email"
},
new
{
Id = 7,
ConfigBody = "{\"RegisterOn\":true,\"Emailvalidate\":true}",
ConfigName = "RegisterConfig"
});
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiKey")
.HasColumnType("longtext");
b.Property<string>("Avatar")
.HasColumnType("longtext");
b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("varchar(255)");
b.Property<bool>("IsBan")
.HasColumnType("tinyint(1)");
b.Property<bool>("IsDelete")
.HasColumnType("tinyint(1)");
b.Property<string>("PassHash")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("varchar(255)");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("varchar(255)");
b.HasKey("Id");
b.HasIndex("Email")
.IsUnique();
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users");
b.HasData(
new
{
Id = -1,
Balance = 0m,
CreatedAt = new DateTime(2025, 7, 31, 10, 49, 29, 419, DateTimeKind.Utc).AddTicks(6892),
Email = "admin1@admin.com",
IsBan = false,
IsDelete = false,
PassHash = "e10adc3949ba59abbe56e057f20f883e",
Username = "admin"
});
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ExpiryDate")
.HasColumnType("datetime(6)");
b.Property<int>("PackageId")
.HasColumnType("int");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("datetime(6)");
b.Property<int>("RemainingCalls")
.HasColumnType("int");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("UserId");
b.ToTable("UserPackages");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("Role")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("UserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UserRoles");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Apis")
.HasForeignKey("PackageId");
b.Navigation("Package");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiCalls")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("CallLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiRequestExamples")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
});
modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("operationLogs")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Order", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Orders")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b =>
{
b.HasOne("Apimanager_backend.Models.Apipackage", "Package")
.WithMany("Packages")
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Packages")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Package");
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.UserRole", b =>
{
b.HasOne("Apimanager_backend.Models.User", "User")
.WithMany("Roles")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("Apimanager_backend.Models.Api", b =>
{
b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples");
});
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{
b.Navigation("ApiPackageItems");
b.Navigation("Apis");
b.Navigation("Packages");
});
modelBuilder.Entity("Apimanager_backend.Models.User", b =>
{
b.Navigation("CallLogs");
b.Navigation("Orders");
b.Navigation("Packages");
b.Navigation("Roles");
b.Navigation("operationLogs");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Apimanager_backend.Migrations
{
/// <inheritdoc />
public partial class add_user_Avatar : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Avatar",
table: "Users",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
columns: new[] { "Avatar", "CreatedAt" },
values: new object[] { null, new DateTime(2025, 7, 31, 10, 49, 29, 419, DateTimeKind.Utc).AddTicks(6892) });
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Avatar",
table: "Users");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "Id",
keyValue: -1,
column: "CreatedAt",
value: new DateTime(2025, 7, 31, 7, 40, 33, 590, DateTimeKind.Utc).AddTicks(5484));
}
}
}

View File

@ -34,7 +34,7 @@ namespace Apimanager_backend.Migrations
b.Property<string>("Endpoint") b.Property<string>("Endpoint")
.IsRequired() .IsRequired()
.HasColumnType("longtext"); .HasColumnType("varchar(255)");
b.Property<bool>("IsActive") b.Property<bool>("IsActive")
.HasColumnType("tinyint(1)"); .HasColumnType("tinyint(1)");
@ -58,6 +58,9 @@ namespace Apimanager_backend.Migrations
b.HasKey("Id"); b.HasKey("Id");
b.HasIndex("Endpoint")
.IsUnique();
b.HasIndex("PackageId"); b.HasIndex("PackageId");
b.ToTable("Apis"); b.ToTable("Apis");
@ -90,6 +93,27 @@ namespace Apimanager_backend.Migrations
b.ToTable("CallLogs"); b.ToTable("CallLogs");
}); });
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("ApiId")
.HasColumnType("int");
b.Property<int>("ApiPackageId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("ApiId");
b.HasIndex("ApiPackageId");
b.ToTable("ApiPackageItem");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b => modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -243,6 +267,9 @@ namespace Apimanager_backend.Migrations
b.Property<string>("Description") b.Property<string>("Description")
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<bool>("IsDeleted")
.HasColumnType("tinyint(1)");
b.Property<string>("OrderNumber") b.Property<string>("OrderNumber")
.IsRequired() .IsRequired()
.HasColumnType("varchar(255)"); .HasColumnType("varchar(255)");
@ -250,13 +277,19 @@ namespace Apimanager_backend.Migrations
b.Property<int>("OrderType") b.Property<int>("OrderType")
.HasColumnType("int"); .HasColumnType("int");
b.Property<DateTime?>("PaiAt")
.HasColumnType("datetime(6)");
b.Property<int>("PaymentType")
.HasColumnType("int");
b.Property<int>("Status") b.Property<int>("Status")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("ThirdPartyOrderId") b.Property<string>("ThirdPartyOrderId")
.HasColumnType("varchar(255)"); .HasColumnType("varchar(255)");
b.Property<DateTime>("UpdatedAt") b.Property<DateTime?>("UpdatedAt")
.HasColumnType("datetime(6)"); .HasColumnType("datetime(6)");
b.Property<int>("UserId") b.Property<int>("UserId")
@ -275,6 +308,100 @@ namespace Apimanager_backend.Migrations
b.ToTable("Orders"); b.ToTable("Orders");
}); });
modelBuilder.Entity("Apimanager_backend.Models.PaymentConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("AppId")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<string>("ExtraSettingsJson")
.HasColumnType("longtext");
b.Property<string>("GatewayUrl")
.HasColumnType("longtext");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<int>("Method")
.HasColumnType("int");
b.Property<string>("NotifyUrl")
.HasColumnType("longtext");
b.Property<int>("PayType")
.HasColumnType("int");
b.Property<string>("PublicKey")
.HasColumnType("longtext");
b.Property<string>("SecretKey")
.HasColumnType("longtext");
b.Property<string>("Url")
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("paymentConfigs");
b.HasData(
new
{
Id = 1,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 0,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 2,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 1,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 3,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 3,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
},
new
{
Id = 4,
AppId = "",
GatewayUrl = "",
IsEnabled = false,
Method = 2,
NotifyUrl = "",
PayType = 1,
PublicKey = "",
SecretKey = ""
});
});
modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b => modelBuilder.Entity("Apimanager_backend.Models.SystemConfig", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -347,6 +474,9 @@ namespace Apimanager_backend.Migrations
b.Property<string>("ApiKey") b.Property<string>("ApiKey")
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<string>("Avatar")
.HasColumnType("longtext");
b.Property<decimal>("Balance") b.Property<decimal>("Balance")
.HasColumnType("decimal(65,30)"); .HasColumnType("decimal(65,30)");
@ -387,7 +517,7 @@ namespace Apimanager_backend.Migrations
{ {
Id = -1, Id = -1,
Balance = 0m, Balance = 0m,
CreatedAt = new DateTime(2024, 11, 10, 13, 48, 10, 873, DateTimeKind.Utc).AddTicks(7811), CreatedAt = new DateTime(2025, 7, 31, 10, 49, 29, 419, DateTimeKind.Utc).AddTicks(6892),
Email = "admin1@admin.com", Email = "admin1@admin.com",
IsBan = false, IsBan = false,
IsDelete = false, IsDelete = false,
@ -474,6 +604,25 @@ namespace Apimanager_backend.Migrations
b.Navigation("User"); b.Navigation("User");
}); });
modelBuilder.Entity("Apimanager_backend.Models.ApiPackageItem", b =>
{
b.HasOne("Apimanager_backend.Models.Api", "Api")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Apimanager_backend.Models.Apipackage", "ApiPackage")
.WithMany("ApiPackageItems")
.HasForeignKey("ApiPackageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Api");
b.Navigation("ApiPackage");
});
modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b => modelBuilder.Entity("Apimanager_backend.Models.ApiRequestExample", b =>
{ {
b.HasOne("Apimanager_backend.Models.Api", "Api") b.HasOne("Apimanager_backend.Models.Api", "Api")
@ -541,11 +690,15 @@ namespace Apimanager_backend.Migrations
{ {
b.Navigation("ApiCalls"); b.Navigation("ApiCalls");
b.Navigation("ApiPackageItems");
b.Navigation("ApiRequestExamples"); b.Navigation("ApiRequestExamples");
}); });
modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b => modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b =>
{ {
b.Navigation("ApiPackageItems");
b.Navigation("Apis"); b.Navigation("Apis");
b.Navigation("Packages"); b.Navigation("Packages");

View File

@ -58,6 +58,7 @@ namespace Apimanager_backend.Models
//导航属性 //导航属性
public Apipackage? Package { get; set; } public Apipackage? Package { get; set; }
public ICollection<ApiPackageItem> ApiPackageItems { get; set; }
public ICollection<ApiCallLog> ApiCalls { get; set; } public ICollection<ApiCallLog> ApiCalls { get; set; }
public ICollection<ApiRequestExample> ApiRequestExamples { get; set; } public ICollection<ApiRequestExample> ApiRequestExamples { get; set; }
} }

View File

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Apimanager_backend.Models
{
[Table("ApiPackageItem")]
public class ApiPackageItem
{
public int Id { get; set; }
public int ApiPackageId { get; set; }
public Apipackage ApiPackage { get; set; } = null!;
public int ApiId { get; set; }
public Api Api { get; set; } = null!;
}
}

View File

@ -44,6 +44,8 @@ namespace Apimanager_backend.Models
//导航属性 //导航属性
public ICollection<Api> Apis { get; set; } public ICollection<Api> Apis { get; set; }
public ICollection<ApiPackageItem> ApiPackageItems { get; set; }
public ICollection<UserPackage> Packages { get; set; } public ICollection<UserPackage> Packages { get; set; }
} }
} }

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models namespace Apimanager_backend.Models
{ {
[Index(nameof(OrderNumber), IsUnique = true)]
public class Order public class Order
{ {
/// <summary> /// <summary>
@ -30,6 +31,9 @@ namespace Apimanager_backend.Models
/// 订单金额 /// 订单金额
/// </summary> /// </summary>
public decimal Amount { get; set; } // decimal(10, 2) public decimal Amount { get; set; } // decimal(10, 2)
//支付方式
public PaymentType PaymentType { get; set; }
/// <summary> /// <summary>
/// 订单类型 /// 订单类型
@ -46,16 +50,24 @@ namespace Apimanager_backend.Models
/// </summary> /// </summary>
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp
//支付完成时间
public DateTime? PaiAt { get; set; }
/// <summary> /// <summary>
/// 更新时间,订单状态更新时间 /// 更新时间,订单状态更新时间
/// </summary> /// </summary>
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; // timestamp public DateTime? UpdatedAt { get; set; } = DateTime.UtcNow; // timestamp
/// <summary> /// <summary>
/// 订单描述,可选的详细信息 /// 订单描述,可选的详细信息
/// </summary> /// </summary>
public string? Description { get; set; } // varchar(255) public string? Description { get; set; } // varchar(255)
/// <summary>
/// 软删除
/// </summary>
public bool IsDeleted { get; set; } = false;
//导航属性 //导航属性
public User? User { get; set; } public User? User { get; set; }
} }

View File

@ -0,0 +1,9 @@
namespace Apimanager_backend.Models
{
public enum PayType
{
None = 0,
Official = 1,
Epay = 2
}
}

View File

@ -0,0 +1,43 @@
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class PaymentConfig
{
public int Id { get; set; }
/// <summary>支付方式(如 Alipay、WeChat、Stripe...</summary>
[Required]
public PaymentType Method { get; set; } // varchar(50)
//接口类型:官方/易支付等
public string? Url { get; set; }
[Required]
public PayType PayType { get; set; }
/// <summary>商户号或 AppId</summary>
public string? AppId { get; set; }
/// <summary>商户密钥 / 私钥</summary>
public string? SecretKey { get; set; }
/// <summary>公钥(如支付宝公钥)</summary>
public string? PublicKey { get; set; }
/// <summary>回调地址notify_url</summary>
public string? NotifyUrl { get; set; }
/// <summary>支付网关地址gateway URL</summary>
public string? GatewayUrl { get; set; }
/// <summary>是否启用此配置</summary>
public bool IsEnabled { get; set; } = true;
/// <summary>额外配置项JSON 格式可扩展</summary>
public string? ExtraSettingsJson { get; set; } // 可包含 cert 路径、支付版本等
/// <summary>备注</summary>
public string? Description { get; set; }
}
}

View File

@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace Apimanager_backend.Models
{
public class PaymentConfigDto
{
public int Id { get; set; }
/// <summary>支付方式(如 Alipay、WeChat、Stripe...</summary>
public PaymentType Method { get; set; } // varchar(50)
/// <summary>备注</summary>
public string? Description { get; set; }
}
}

View File

@ -0,0 +1,10 @@
namespace Apimanager_backend.Models
{
public enum PaymentType
{
AliPay = 0,
WxPay = 1,
Bank = 2,
QQPay =3
}
}

View File

@ -14,6 +14,7 @@ namespace Apimanager_backend.Models
/// </summary> /// </summary>
[Required] [Required]
public string Username { get; set; } // varchar(20) public string Username { get; set; } // varchar(20)
public string? Avatar { get; set; }
/// <summary> /// <summary>
/// 邮箱,唯一 /// 邮箱,唯一

View File

@ -10,6 +10,6 @@ namespace Apimanager_backend.Models
//导航属性 //导航属性
[JsonIgnore] [JsonIgnore]
public User User { get; set; } public User? User { get; set; }
} }
} }

View File

@ -1,7 +1,9 @@
using Apimanager_backend.Config; using Apimanager_backend.Config;
using Apimanager_backend.Data; using Apimanager_backend.Data;
using Apimanager_backend.Dtos;
using Apimanager_backend.Filters; using Apimanager_backend.Filters;
using Apimanager_backend.Filters.ExceptionFilter; using Apimanager_backend.Filters.ExceptionFilter;
using Apimanager_backend.Services;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Serilog; using Serilog;
@ -17,7 +19,7 @@ IConfiguration configuration = new ConfigurationBuilder()
.Build(); .Build();
string? redStr = configuration["Redis:ConnectionString"]; string? redStr = configuration["Redis:ConnectionString"];
string? constr = configuration.GetConnectionString("DefaultConnection"); string? constr = configuration.GetConnectionString("DefaultConnection");
//日志服务 //日志服务
/* /*
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug() .MinimumLevel.Debug()
@ -35,9 +37,9 @@ option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
builder.Services.AddAllService(configuration); builder.Services.AddAllService(configuration);
builder.Services.AddControllers(options => builder.Services.AddControllers(options =>
{ {
//模型验证 //模型验证
options.Filters.Add<ModelValidationFilter>(); options.Filters.Add<ModelValidationFilter>();
//Exception过滤器 //Exception过滤器
options.Filters.Add<generalExceptionFilter>(); options.Filters.Add<generalExceptionFilter>();
}).ConfigureApiBehaviorOptions(option => }).ConfigureApiBehaviorOptions(option =>
{ {
@ -53,6 +55,80 @@ builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(); builder.Services.AddSwaggerGen();
var app = builder.Build(); var app = builder.Build();
app.Use(async (ctx, next) =>
{
var controller = ctx.Request.RouteValues["controller"]?.ToString(); // YourController
var action = ctx.Request.RouteValues["action"]?.ToString();
if (controller != "Public" || action != "Invoke")
{
await next();
return;
}
if (ctx.Request.Headers.TryGetValue("Authorization", out var hdr) &&
hdr.ToString().StartsWith("Bearer "))
{
var token = hdr.ToString().Substring("Bearer ".Length).Trim();
var code = ctx.Request.RouteValues["code"]!.ToString()!;
RateLimiterDto rateLimiterDto = new RateLimiterDto();
var userService = ctx.RequestServices.GetRequiredService<IUserService>();
var apiService = ctx.RequestServices.GetRequiredService<IApiService>();
var apiPackageItemService = ctx.RequestServices.GetRequiredService<IApiPackageItemService>();
var userPackageService = ctx.RequestServices.GetRequiredService<IUserPackageService>();
var user = await userService.GetByTokenAsync(token);
var api = await apiService.GetApiInfoByEndpointAsync(code);
var apiPackages = await apiPackageItemService.GetApiPackageItemsByApiIdAsync(api.Id);
if (user == null || apiPackages.Count == 0)
{
ctx.Items["rateLimit"] = null;
}
else
{
var userPackages = await userPackageService.GetUserPackagesByUserIdAsync(user.Id);
if (userPackages.Count == 0)
{
ctx.Items["rateLimit"] = null;
}
// 提取 list2 中的所有 package.id变成 HashSet 提高查找效率
var apipackage1 = new HashSet<int>(apiPackages.Select(x => x.ApiPackage.Id));
var uPackages = userPackages
.Where(x => apipackage1.Contains(x.Package.Id)).ToList();
// 从 list1 中筛选出 user.id 存在于 list2 的项
var commonPackages = uPackages
.Select(x => x.Package)
.ToList();
var package = commonPackages.Count > 0 ? commonPackages.MaxBy(x => x.OneMinuteLimit) : null;
var data = package == null ? null : new RateLimiterDto()
{
UserId = user.Id,
RateLimit = package.OneMinuteLimit
};
ctx.Items["rateLimit"] = data;
ctx.Items["userPackages"] = uPackages;
}
}
else
{
ctx.Items["rateLimit"] = null;
}
if (ctx.Items["rateLimit"] == null)
{
ctx.Response.StatusCode = 429;
ctx.Response.ContentType = "application/json";
await ctx.Response.WriteAsJsonAsync(new ResponseBase<object>()
{
Code = 3003,
Data = null,
Message = "未授权或访问频率受限"
});
return; // ⛔ 不调用 next(),请求终止
}
await next();
return;
});
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
@ -66,6 +142,22 @@ app.UseCors("AllowAll");
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.UseRateLimiter();
/*
app.Use(async (context, next) =>
{
var controller = context.Request.RouteValues["controller"]?.ToString(); // YourController
var action = context.Request.RouteValues["action"]?.ToString(); // Invoke
var code = context.Request.RouteValues["code"]?.ToString(); // ← 就是你要的 GetUserList
Console.WriteLine($"控制器: {controller}, 实际方法: {code}(映射到 Invoke");
// 你可以根据 code 设置速率限制策略、权限校验等
await next();
});
*/
app.MapControllers(); app.MapControllers();
app.Run(); app.Run();

View File

@ -0,0 +1,22 @@
using Apimanager_backend.Data;
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
namespace Apimanager_backend.Services
{
public class ApiPackageItemService : IApiPackageItemService
{
private ApiContext _context;
private ILogger<ApiPackageItemService> _logger;
public ApiPackageItemService(ApiContext context,ILogger<ApiPackageItemService> logger)
{
_context = context;
_logger = logger;
}
public async Task<List<ApiPackageItem>> GetApiPackageItemsByApiIdAsync(int ApiId)
{
IQueryable<ApiPackageItem> query = _context.apiPackageItems.Include(x => x.ApiPackage).Where(x => x.ApiId == ApiId);
return await query.ToListAsync();
}
}
}

View File

@ -116,5 +116,16 @@ namespace Apimanager_backend.Services
return await context.Apis.CountAsync(); return await context.Apis.CountAsync();
} }
#endregion #endregion
#region Api路径获取api信息
public async Task<ApiInfoDto> GetApiInfoByEndpointAsync(string endpoint)
{
var apiInfo = await context.Apis.FirstOrDefaultAsync(x => x.Endpoint == endpoint);
if (apiInfo == null)
{
throw new BaseException(3002, "API不存在");
}
return mapper.Map<ApiInfoDto>(apiInfo);
}
#endregion
} }
} }

View File

@ -0,0 +1,10 @@

using Apimanager_backend.Models;
namespace Apimanager_backend.Services
{
public interface IApiPackageItemService
{
Task<List<ApiPackageItem>> GetApiPackageItemsByApiIdAsync(int ApiId);
}
}

View File

@ -55,6 +55,12 @@ namespace Apimanager_backend.Services
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Task<int> ApiCountAsync(); public Task<int> ApiCountAsync();
/// <summary>
/// 通过api路径获取api信息
/// </summary>
/// <param name="endpoint">api路径</param>
/// <returns></returns>
public Task<ApiInfoDto> GetApiInfoByEndpointAsync(string endpoint);
} }
} }

View File

@ -0,0 +1,24 @@
using Apimanager_backend.Dtos;
using Apimanager_backend.Models;
namespace Apimanager_backend.Services
{
public interface IOrderService
{
/// <summary>
/// 获取订单列表
/// </summary>
/// <param name="pageIndex">页索引</param>
/// <param name="pageSize">页大小</param>
/// <param name="desc">是否倒序</param>
/// <returns></returns>
Task<List<Order>> GetOrdersAsync(int pageIndex, int pageSize,bool desc,int? userId);
/// <summary>
/// 创建订单
/// </summary>
/// <param name="order">订单信息</param>
/// <returns></returns>
Task<Order> CreateOrderAsync(OrderDto order);
Task<bool> UpdateOrderAsync(OrderDto order);
}
}

View File

@ -0,0 +1,10 @@
using Apimanager_backend.Dtos;
using Apimanager_backend.Models;
namespace Apimanager_backend.Services
{
public interface IPayService
{
Task<PayReturnData> CreateEpay(Order order,PaymentConfig paymentConfig,string returnUrl);
}
}

View File

@ -0,0 +1,10 @@
using Apimanager_backend.Models;
namespace Apimanager_backend.Services
{
public interface IPaymentConfigService
{
Task<PaymentConfig> GetPaymentConfigInfoByTypeAsync(string payType);
Task<List<PaymentConfigDto>> GetAllPaymentAsync();
}
}

View File

@ -0,0 +1,9 @@
using Apimanager_backend.Models;
namespace Apimanager_backend.Services
{
public interface IUserPackageService
{
Task<List<UserPackage>> GetUserPackagesByUserIdAsync(int userId);
}
}

View File

@ -47,5 +47,18 @@ namespace Apimanager_backend.Services
/// <param name="email">邮箱</param> /// <param name="email">邮箱</param>
/// <returns></returns> /// <returns></returns>
Task<bool> IsEmailExist(string email); Task<bool> IsEmailExist(string email);
/// <summary>
/// 通过ApiToken获取用户
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
Task<UserInfoDto?> GetByTokenAsync(string token);
/// <summary>
/// 更新用户头像
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
Task<bool> UpdateUserAvatarAsync(int userId,string url);
} }
} }

View File

@ -0,0 +1,104 @@
using Apimanager_backend.Data;
using Apimanager_backend.Dtos;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Models;
using Apimanager_backend.Tools;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
namespace Apimanager_backend.Services
{
public class OrderService:IOrderService
{
private ApiContext _apiContext;
private IMapper mapper;
private ILogger<OrderService> logger;
public OrderService(ApiContext apiContext,IMapper mapper,ILogger<OrderService> logger)
{
_apiContext = apiContext;
this.mapper = mapper;
this.logger = logger;
}
#region
/// <summary>
/// 创建订单
/// </summary>
/// <param name="order">订单信息</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<Order> CreateOrderAsync(OrderDto order)
{
var transaction = await _apiContext.Database.BeginTransactionAsync();
try
{
Order orderInfo = mapper.Map<Order>(order);
//初始化信息
orderInfo.Status = OrderStatus.Pending;
orderInfo.CreatedAt = DateTime.Now;
orderInfo.OrderNumber = OrderNumberGenerator.Generate(order.UserId);
_apiContext.Orders.Add(orderInfo);
await _apiContext.SaveChangesAsync();
await transaction.CommitAsync();
return orderInfo;
}catch(Exception e)
{
//异常回滚
await transaction.RollbackAsync();
logger.LogError(e.Message);
throw new BaseException(4006,"支付系统错误");
}
}
#endregion
#region
/// <summary>
/// 获取订单列表
/// </summary>
/// <param name="pageIndex">索引</param>
/// <param name="pageSize">页大小</param>
/// <param name="desc">是否倒序</param>
/// <param name="userId">指定用户订单</param>
/// <returns></returns>
public async Task<List<Order>> GetOrdersAsync(int pageIndex, int pageSize, bool desc, int? userId)
{
IQueryable<Order> query = _apiContext.Orders.AsQueryable().OrderBy(x => x.Id);
if(userId != null)
{
query.Where(x => x.UserId == userId);
}
//倒序
if (desc)
{
query.OrderDescending();
}
//分页
query = query.Skip((pageIndex - 1) * pageSize).Take(pageSize);
return await query.ToListAsync();
}
#endregion
#region
public async Task<bool> UpdateOrderAsync(OrderDto order)
{
try
{
var data = await _apiContext.Orders.SingleOrDefaultAsync(x => x.OrderNumber == order.OrderNumber || x.ThirdPartyOrderId == order.ThirdPartyOrderId);
if (data == null)
{
throw new BaseException(4003, "订单未找到");
}
data.UpdatedAt = DateTime.Now;
data.Status = order.Status;
data.PaiAt = order.Status == OrderStatus.Completed ? DateTime.Now : null;
_apiContext.Orders.Update(data);
await _apiContext.SaveChangesAsync();
return true;
}catch(Exception e)
{
logger.LogError(e.Message);
throw new BaseException(4003, "订单未找到");
}
}
#endregion
}
}

View File

@ -0,0 +1,48 @@
using Apimanager_backend.Data;
using Apimanager_backend.Dtos;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Models;
using Apimanager_backend.Tools;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
namespace Apimanager_backend.Services
{
public class PayService : IPayService
{
private IMapper _mapper;
private ILogger<PayService> _logger;
private ApiContext _context;
public PayService(IMapper mapper,ILogger<PayService> logger,ApiContext apiContext)
{
_mapper = mapper;
_logger = logger;
_context = apiContext;
}
public async Task<PayReturnData> CreateEpay(Order order, PaymentConfig paymentConfig,string returnUrl)
{
try
{
var param = new Dictionary<string, string>();
param["pid"] = paymentConfig.AppId;
param["type"] = order.PaymentType.ToString().ToLower();
param["out_trade_no"] = order.OrderNumber;
param["notify_url"] = paymentConfig.NotifyUrl ?? "";
param["return_url"] = returnUrl;
param["name"] = "余额充值";
param["money"] = order.Amount.ToString();
param["clientip"] = "192.168.5.1";
param["device"] = "pc";
var res = await EpayHelper.ApiPayAsync(param, paymentConfig.SecretKey, paymentConfig.Url);
order.ThirdPartyOrderId = res.trade_no;
_context.Orders.Update(order);
await _context.SaveChangesAsync();
return _mapper.Map<PayReturnData>(res);
}catch(Exception e)
{
_logger.LogError(e.Message);
throw new BaseException(4001,"支付请求无效");
}
}
}
}

View File

@ -0,0 +1,40 @@
using Apimanager_backend.Data;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Models;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
namespace Apimanager_backend.Services
{
public class PaymentConfigService : IPaymentConfigService
{
private ApiContext _context;
private ILogger<PaymentConfigService> _logger;
private IMapper _mapper;
public PaymentConfigService(ApiContext context,ILogger<PaymentConfigService> logger,IMapper mapper)
{
_context = context;
_logger = logger;
_mapper = mapper;
}
public async Task<List<PaymentConfigDto>> GetAllPaymentAsync()
{
var data = await _context.paymentConfigs.Where(x => x.IsEnabled).ToListAsync();
return _mapper.Map<List<PaymentConfigDto>>(data);
}
public async Task<PaymentConfig> GetPaymentConfigInfoByTypeAsync(string payType)
{
if(!Enum.TryParse(payType, true, out PaymentType parsedPayType))
{
throw new BaseException(4001, "未配置该支付方式的通道");
}
var data = await _context.paymentConfigs.SingleOrDefaultAsync(x => x.Method == parsedPayType);
if(data == null)
{
throw new BaseException(4001, "未配置该支付方式的通道");
}
return data;
}
}
}

View File

@ -0,0 +1,62 @@
using Apimanager_backend.Data;
using Public;
using System.Reflection;
namespace Apimanager_backend.Services
{
// PluginLoaderService.cs
public class PluginLoaderService
{
private readonly IWebHostEnvironment _env;
private readonly ILogger<PluginLoaderService> _logger;
public PluginLoaderService(
IWebHostEnvironment env,
ILogger<PluginLoaderService> logger)
{
_env = env;
_logger = logger;
}
public void LoadPlugins(IServiceCollection services)
{
var pluginsDir = Path.Combine(_env.ContentRootPath, "ApiHandler");
Directory.CreateDirectory(pluginsDir);
foreach (var dllPath in Directory.GetFiles(pluginsDir, "*.dll"))
{
try
{
var assembly = LoadPluginAssembly(dllPath);
RegisterPluginServices(assembly, services);
_logger.LogInformation($"已加载插件: {Path.GetFileName(dllPath)}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"加载插件失败: {dllPath}");
}
}
}
private Assembly LoadPluginAssembly(string dllPath)
{
// 使用隔离的加载上下文
var loadContext = new PluginLoadContext(dllPath);
return loadContext.LoadFromAssemblyPath(dllPath);
}
private void RegisterPluginServices(Assembly assembly, IServiceCollection services)
{
foreach (var type in assembly.GetTypes())
{
if (typeof(IBillableApiHandler).IsAssignableFrom(type) &&
!type.IsInterface &&
!type.IsAbstract)
{
services.AddTransient(typeof(IBillableApiHandler), type);
services.AddTransient(type); // 同时注册具体类型
}
}
}
}
}

View File

@ -0,0 +1,21 @@

using Apimanager_backend.Data;
using Apimanager_backend.Models;
using Microsoft.EntityFrameworkCore;
namespace Apimanager_backend.Services
{
public class UserPackageService : IUserPackageService
{
private ApiContext _context;
public UserPackageService(ApiContext apiContext)
{
_context = apiContext;
}
public async Task<List<UserPackage>> GetUserPackagesByUserIdAsync(int userId)
{
IQueryable<UserPackage> query = _context.UserPackages.Include(x => x.Package).Where(x => x.UserId == userId);
return await query.ToListAsync();
}
}
}

View File

@ -101,5 +101,29 @@ namespace Apimanager_backend.Services
await apiContext.SaveChangesAsync(); await apiContext.SaveChangesAsync();
return mapper.Map<UserInfoDto>(user); return mapper.Map<UserInfoDto>(user);
} }
public async Task<UserInfoDto?> GetByTokenAsync(string token)
{
User? user = await apiContext.Users.Include(x => x.Roles).Include(x => x.Packages).SingleOrDefaultAsync(x => x.ApiKey == token);
//未找到用户
if (user == null)
{
return null;
}
return mapper.Map<UserInfoDto>(user);
}
public async Task<bool> UpdateUserAvatarAsync(int userId,string url)
{
var user = await apiContext.Users.FirstOrDefaultAsync(x => x.Id == userId);
if (user == null)
{
return false;
}
user.Avatar = url;
apiContext.Users.Update(user);
await apiContext.SaveChangesAsync();
return true;
}
} }
} }

View File

@ -0,0 +1,100 @@
using Apimanager_backend.Models;
using System.Reflection;
using System;
using Apimanager_backend.Data;
using Microsoft.EntityFrameworkCore;
using Apimanager_backend.Exceptions;
using Apimanager_backend.Dtos;
using Public;
using Apimanager_backend.Services;
namespace Apimanager_backend.Tools
{
public class BillableApiDispatcher
{
private readonly IServiceProvider _serviceProvider;
private readonly ApiContext _db;
private PluginLoaderService _pluginLoaderService;
public BillableApiDispatcher(IServiceProvider sp, ApiContext db,PluginLoaderService pluginLoaderService)
{
_serviceProvider = sp;
_db = db;
_pluginLoaderService = pluginLoaderService;
}
public async Task<object> DispatchAsync(string webPath,int apiId,string code, ApiCallContext context)
{
//_pluginLoaderService.LoadPlugins(new ServiceCollection());
// 1. 安全验证
string dllPath = webPath + "\\ApiHandler\\" + code + ".dll";
if (!System.IO.File.Exists(dllPath))
throw new BaseException(3002, "接口实现未找到");
// 2. 加载程序集
var assembly = Assembly.LoadFrom(dllPath); // 或使用 AssemblyLoadContext.Default.LoadFromAssemblyPath
// 3. 查找实现类
var type = assembly.GetTypes()
.FirstOrDefault(t =>
typeof(IBillableApiHandler).IsAssignableFrom(t) &&
!t.IsInterface &&
!t.IsAbstract &&
t.Name.Equals(code, StringComparison.OrdinalIgnoreCase));
if (type == null)
throw new BaseException(3002,"接口实现未找到");
List<UserPackage> userPackages = context.HttpContext.Items["userPackages"] as List<UserPackage>;
List<UserPackage> userPackageList = null;
if (userPackages == null || !(userPackages is IEnumerable<UserPackage>))
{
throw new BaseException(3004, "未购买该API套餐或权限不足");
}
userPackageList = ((IEnumerable<UserPackage>)userPackages).ToList();
userPackageList = userPackageList.Where(x => x.ExpiryDate > DateTime.Now).ToList();
if (userPackageList.Count == 0)
{
throw new BaseException(3004, "未购买该API套餐或权限不足");
}
var maxCountUserPackage = userPackageList.MaxBy(x => x.RemainingCalls);
if (maxCountUserPackage.RemainingCalls <= 0)
{
throw new BaseException(3004, "套餐可用额度不足");
}
var uPackage = await _db.UserPackages.SingleOrDefaultAsync(x => x.Id == maxCountUserPackage.Id);
if (uPackage == null)
{
throw new BaseException(3004, "未购买该API套餐或权限不足");
}
uPackage.RemainingCalls -= 1;
_db.UserPackages.Update(uPackage);
var handler = (IBillableApiHandler)Activator.CreateInstance(type)!;
// 执行接口
var result = await handler.ExecuteAsync(context);
// 记录调用日志
_db.CallLogs.Add(new ApiCallLog
{
ApiId = apiId,
UserId = context.UserId,
CallTime = DateTime.UtcNow
});
await _db.SaveChangesAsync();
return result;
}
}
}

View File

@ -0,0 +1,53 @@
using Apimanager_backend.Dtos;
using Newtonsoft.Json;
using System.Security.Cryptography;
using System.Text;
namespace Apimanager_backend.Tools
{
public static class EpayHelper
{
/// <summary>
/// 创建签名
/// </summary>
public static string CreateSign(Dictionary<string, string> parameters, string key)
{
var sorted = parameters
.Where(kv => !string.IsNullOrEmpty(kv.Value) && kv.Key != "sign" && kv.Key != "sign_type")
.OrderBy(kv => kv.Key)
.ToList();
string query = string.Join("&", sorted.Select(kv => $"{kv.Key}={kv.Value}"));
string toSign = query + key;
using (var md5 = MD5.Create())
{
byte[] hash = md5.ComputeHash(Encoding.UTF8.GetBytes(toSign));
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
}
/// <summary>
/// 发起API支付返回 json
/// </summary>
public static async Task<EpayResponse?> ApiPayAsync(Dictionary<string, string> parameters, string key,string baseUrl)
{
parameters["sign_type"] = "MD5";
parameters["sign"] = CreateSign(parameters, key);
using var client = new HttpClient();
var content = new FormUrlEncodedContent(parameters);
var response = await client.PostAsync($"{baseUrl}/mapi.php", content);
return JsonConvert.DeserializeObject<EpayResponse>(await response.Content.ReadAsStringAsync());
}
/// <summary>
/// 校验签名(通常用于异步通知/页面跳转)
/// </summary>
public static bool VerifySign(Dictionary<string, string> parameters, string key)
{
if (!parameters.TryGetValue("sign", out string originalSign)) return false;
string newSign = CreateSign(parameters, key);
return originalSign.Equals(newSign, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@ -0,0 +1,14 @@
namespace Apimanager_backend.Tools
{
public static class OrderNumberGenerator
{
public static string Generate(int userId = 0, string prefix = "ORD")
{
var datePart = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff"); // 17位
var userPart = (userId % 10000).ToString("D4"); // 后4位用户ID
var randPart = Random.Shared.Next(1000, 9999).ToString(); // 4位随机数
return $"{prefix}{datePart}{userPart}{randPart}"; // 最终ORD + 时间 + 用户 + 随机数
}
}
}

View File

@ -0,0 +1,29 @@
namespace Apimanager_backend.Tools
{
public static class UserInfoHelper
{
public static string GetClientIp(HttpContext context)
{
var ip = context.Connection.RemoteIpAddress?.ToString();
// 支持代理(如 Nginx时使用 X-Forwarded-For
if (context.Request.Headers.ContainsKey("X-Forwarded-For"))
{
ip = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
}
return ip ?? "unknown";
}
public static string GetDeviceType(HttpContext context)
{
var userAgent = context.Request.Headers["User-Agent"].ToString().ToLower();
if (userAgent.Contains("mobile") || userAgent.Contains("android") || userAgent.Contains("iphone"))
return "mobile";
return "pc";
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

12
Public/ApiCallContext.cs Normal file
View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Http;
namespace Public
{
public class ApiCallContext
{
public int UserId { get; set; }
public Dictionary<string, object> Parameters { get; set; } = new();
public HttpContext HttpContext { get; set; } = null!;
}
}

View File

@ -0,0 +1,8 @@
namespace Public
{
public interface IBillableApiHandler
{
/// <summary>执行 API 主逻辑</summary>
Task<object> ExecuteAsync(ApiCallContext context);
}
}

13
Public/Public.csproj Normal file
View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
</ItemGroup>
</Project>