All checks were successful
continuous-integration/drone/push Build is passing
159 lines
4.4 KiB
C#
159 lines
4.4 KiB
C#
using System.Text;
|
||
using CampusErrand.Data;
|
||
using CampusErrand.Models;
|
||
using CampusErrand.Services;
|
||
using CampusErrand.Endpoints;
|
||
using CampusErrand.Helpers;
|
||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.IdentityModel.Tokens;
|
||
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
|
||
// 数据库配置
|
||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")!;
|
||
builder.Services.AddDbContext<AppDbContext>(options =>
|
||
options.UseSqlServer(connectionString));
|
||
|
||
// Redis 分布式缓存配置
|
||
builder.Services.AddStackExchangeRedisCache(options =>
|
||
{
|
||
options.Configuration = builder.Configuration["Redis:Configuration"];
|
||
options.InstanceName = "CampusErrand:";
|
||
});
|
||
|
||
// JWT 认证配置
|
||
var jwtConfig = builder.Configuration.GetSection("Jwt");
|
||
var secretKey = Encoding.UTF8.GetBytes(jwtConfig["Secret"]!);
|
||
|
||
builder.Services.AddAuthentication(options =>
|
||
{
|
||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||
})
|
||
.AddJwtBearer(options =>
|
||
{
|
||
options.TokenValidationParameters = new TokenValidationParameters
|
||
{
|
||
ValidateIssuer = true,
|
||
ValidateAudience = true,
|
||
ValidateLifetime = true,
|
||
ValidateIssuerSigningKey = true,
|
||
ValidIssuer = jwtConfig["Issuer"],
|
||
ValidAudience = jwtConfig["Audience"],
|
||
IssuerSigningKey = new SymmetricSecurityKey(secretKey),
|
||
ClockSkew = TimeSpan.Zero
|
||
};
|
||
});
|
||
|
||
// 角色授权策略
|
||
builder.Services.AddAuthorizationBuilder()
|
||
.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"))
|
||
.AddPolicy("UserOrAdmin", policy => policy.RequireRole("User", "Runner", "Admin"));
|
||
|
||
// CORS 配置
|
||
builder.Services.AddCors(options =>
|
||
{
|
||
options.AddDefaultPolicy(policy =>
|
||
{
|
||
policy.AllowAnyOrigin()
|
||
.AllowAnyMethod()
|
||
.AllowAnyHeader();
|
||
});
|
||
});
|
||
|
||
// 注册 JWT 服务
|
||
builder.Services.AddSingleton<JwtService>();
|
||
|
||
// 注册微信服务
|
||
builder.Services.AddHttpClient<IWeChatService, WeChatService>();
|
||
|
||
// 注册腾讯 IM 服务
|
||
builder.Services.AddHttpClient();
|
||
builder.Services.AddSingleton<TencentIMService>();
|
||
|
||
// 注册微信支付服务
|
||
builder.Services.AddHttpClient<WxPayService>();
|
||
|
||
// OpenAPI 文档(.NET 10 内置)
|
||
builder.Services.AddOpenApi();
|
||
|
||
var app = builder.Build();
|
||
|
||
// 中间件管道
|
||
if (app.Environment.IsDevelopment())
|
||
{
|
||
app.MapOpenApi();
|
||
// Swagger UI 用于可视化调试
|
||
app.UseSwaggerUI(options =>
|
||
{
|
||
options.SwaggerEndpoint("/openapi/v1.json", "校园跑腿 API v1");
|
||
});
|
||
}
|
||
|
||
app.UseCors();
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
// 注册各模块端点
|
||
app.MapAuthEndpoints();
|
||
app.MapIMEndpoints();
|
||
app.MapBannerEndpoints();
|
||
app.MapServiceEntryEndpoints();
|
||
app.MapOrderEndpoints();
|
||
app.MapShopEndpoints();
|
||
app.MapEarningEndpoints();
|
||
app.MapMessageEndpoints();
|
||
app.MapAdminEndpoints();
|
||
app.MapConfigEndpoints();
|
||
app.MapRunnerEndpoints();
|
||
|
||
// 自动执行数据库迁移(仅关系型数据库,跳过 InMemory 测试环境)
|
||
using (var scope = app.Services.CreateScope())
|
||
{
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
if (db.Database.IsRelational() && !(db.Database.ProviderName?.Contains("InMemory") ?? false))
|
||
{
|
||
db.Database.Migrate();
|
||
}
|
||
|
||
// 初始化默认佣金规则(如果为空)
|
||
if (!db.CommissionRules.Any())
|
||
{
|
||
db.CommissionRules.Add(new CommissionRule
|
||
{
|
||
MinAmount = 0m,
|
||
MaxAmount = null,
|
||
RateType = CommissionRateType.Percentage,
|
||
Rate = 10m // 默认抽成 10%
|
||
});
|
||
db.SaveChanges();
|
||
Console.WriteLine("[初始化] 已创建默认佣金规则:10% 抽成");
|
||
}
|
||
}
|
||
|
||
// 注册后台定时任务:每10分钟执行一次自动确认和解冻
|
||
_ = Task.Run(async () =>
|
||
{
|
||
while (true)
|
||
{
|
||
await Task.Delay(TimeSpan.FromMinutes(10));
|
||
try
|
||
{
|
||
using var scope = app.Services.CreateScope();
|
||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||
await BusinessHelpers.AutoConfirmExpiredOrders(db);
|
||
await BusinessHelpers.UnfreezeEarnings(db);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"[定时任务] 执行失败: {ex.Message}");
|
||
}
|
||
}
|
||
});
|
||
|
||
app.Run();
|
||
|
||
// 用于集成测试访问
|
||
public partial class Program { }
|