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(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(); // 注册微信服务 builder.Services.AddHttpClient(); // 注册腾讯 IM 服务 builder.Services.AddHttpClient(); builder.Services.AddSingleton(); // 注册微信支付服务 builder.Services.AddHttpClient(); // 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(); 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(); await BusinessHelpers.AutoConfirmExpiredOrders(db); await BusinessHelpers.UnfreezeEarnings(db); } catch (Exception ex) { Console.WriteLine($"[定时任务] 执行失败: {ex.Message}"); } } }); app.Run(); // 用于集成测试访问 public partial class Program { }