From 2ce0dcdbc79a01c486cce40cef238e8b5c3e90c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= <2919054393@qq.com> Date: Sun, 20 Oct 2024 23:44:02 +0800 Subject: [PATCH 01/23] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20.gitattributes?= =?UTF-8?q?=E3=80=81.gitignore=20=E5=92=8C=20README.md=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 63 +++++++++ .gitignore | 363 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 3 files changed, 427 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3f9186e --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Apimanager_backend \ No newline at end of file From 7b22e6631039988940a72850eaf1b3659e54ba93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= <2919054393@qq.com> Date: Sun, 20 Oct 2024 23:44:04 +0800 Subject: [PATCH 02/23] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apimanager_backend.sln | 25 +++++++++++ Apimanager_backend/Apimanager_backend.csproj | 13 ++++++ Apimanager_backend/Apimanager_backend.http | 6 +++ .../Controllers/WeatherForecastController.cs | 33 +++++++++++++++ Apimanager_backend/Program.cs | 25 +++++++++++ .../Properties/launchSettings.json | 41 +++++++++++++++++++ Apimanager_backend/WeatherForecast.cs | 13 ++++++ .../appsettings.Development.json | 8 ++++ Apimanager_backend/appsettings.json | 9 ++++ 9 files changed, 173 insertions(+) create mode 100644 Apimanager_backend.sln create mode 100644 Apimanager_backend/Apimanager_backend.csproj create mode 100644 Apimanager_backend/Apimanager_backend.http create mode 100644 Apimanager_backend/Controllers/WeatherForecastController.cs create mode 100644 Apimanager_backend/Program.cs create mode 100644 Apimanager_backend/Properties/launchSettings.json create mode 100644 Apimanager_backend/WeatherForecast.cs create mode 100644 Apimanager_backend/appsettings.Development.json create mode 100644 Apimanager_backend/appsettings.json diff --git a/Apimanager_backend.sln b/Apimanager_backend.sln new file mode 100644 index 0000000..36300f7 --- /dev/null +++ b/Apimanager_backend.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35312.102 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apimanager_backend", "Apimanager_backend\Apimanager_backend.csproj", "{F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F4FD5145-6971-4032-B2B6-D7A61AF8BB2E}.Debug|Any CPU.ActiveCfg = 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.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1E84B967-07AF-4318-9BC3-8C66563CE795} + EndGlobalSection +EndGlobal diff --git a/Apimanager_backend/Apimanager_backend.csproj b/Apimanager_backend/Apimanager_backend.csproj new file mode 100644 index 0000000..9daa180 --- /dev/null +++ b/Apimanager_backend/Apimanager_backend.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Apimanager_backend/Apimanager_backend.http b/Apimanager_backend/Apimanager_backend.http new file mode 100644 index 0000000..1122844 --- /dev/null +++ b/Apimanager_backend/Apimanager_backend.http @@ -0,0 +1,6 @@ +@Apimanager_backend_HostAddress = http://localhost:5292 + +GET {{Apimanager_backend_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Apimanager_backend/Controllers/WeatherForecastController.cs b/Apimanager_backend/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..028579e --- /dev/null +++ b/Apimanager_backend/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Apimanager_backend.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/Apimanager_backend/Program.cs b/Apimanager_backend/Program.cs new file mode 100644 index 0000000..48863a6 --- /dev/null +++ b/Apimanager_backend/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/Apimanager_backend/Properties/launchSettings.json b/Apimanager_backend/Properties/launchSettings.json new file mode 100644 index 0000000..dd75711 --- /dev/null +++ b/Apimanager_backend/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:1132", + "sslPort": 44318 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5292", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7031;http://localhost:5292", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Apimanager_backend/WeatherForecast.cs b/Apimanager_backend/WeatherForecast.cs new file mode 100644 index 0000000..d21615d --- /dev/null +++ b/Apimanager_backend/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace Apimanager_backend +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/Apimanager_backend/appsettings.Development.json b/Apimanager_backend/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Apimanager_backend/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Apimanager_backend/appsettings.json b/Apimanager_backend/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Apimanager_backend/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From 8309927364f6484f217fe35f4799b620851002a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Wed, 23 Oct 2024 01:33:18 +0000 Subject: [PATCH 03/23] Update README.md --- README.md | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f9186e..bdd64a4 100644 --- a/README.md +++ b/README.md @@ -1 +1,77 @@ -# Apimanager_backend \ No newline at end of file +## 项目背景 + +简单描述该API的背景、用途及目标用户。 + +## 功能概述 + +1. ##### 用户管理 + + - 登录、注册 + - 用户账号信息管理 + - 用户充值、消费记录查询 + +2. ##### API访问管理 + + - 用户密钥生成和管理 + - API管理 + - 调用次数和消费金额限制 + - 付费套餐管理 + +3. ##### 支付模块 + +4. ##### 订单模块 + + - 订单生成 + - 消费提醒(超额/余额不足) + +5. ##### 系统监控模块 + + - 调用记录 + - 异常告警 + +## 系统依赖 + +- **.NET 6.0 或更高版本** +- **Entity Framework Core** 用于数据库操作 +- **MySQL** 作为后端数据库 +- **Swagger** 用于API文档自动生成 +- **JWT** 实现用户认证和授权 + +## 项目结构 + +```perl +api-billing-system/ +│ +├── API/ # API控制器及路由 +├── Services/ # 业务逻辑层 +├── Models/ # 数据模型定义 +├── Data/ # 数据库上下文及迁移文件 +├── Config/ # 系统配置文件 +├── Tests/ # 单元测试及集成测试 +├── Tools/ # 工具类 +└── README.md # 项目文档(本文件) + +``` + + + +## 模块划分 + +1. **API 控制器** + +- 负责处理用户请求并返回结果。 +- 提供如用户注册、登录、查询调用次数等API端点。 + +1. ##### **业务逻辑层(Services)** + +- 负责具体业务逻辑,如套餐管理、消费计算等。 +- 实现支付网关集成。 + +1. **数据模型(Models)** + +- 定义数据库中的表结构,如用户表、订单表等。 + +1. **数据库(Data)** + +- 提供数据库连接及操作支持。 +- 包含数据库上下文类及数据库迁移文件。 \ No newline at end of file From 16deb8ab9fab24cca0797c8d60c7206867284a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:17:44 +0000 Subject: [PATCH 04/23] Update file DatabaseDefine.md --- DatabaseDefine.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 DatabaseDefine.md diff --git a/DatabaseDefine.md b/DatabaseDefine.md new file mode 100644 index 0000000..3ee9762 --- /dev/null +++ b/DatabaseDefine.md @@ -0,0 +1,59 @@ +# 数据库定义 + +### 用户表(Users) + +| 字段名 | 类型 | 描述 | 备注 | +| --------- | -------------------- | -------- | ------------ | +| Id | int | 用户ID | 主键自增 | +| Username | varchar(20) | 用户名 | 唯一 | +| Email | varchar(20) | 邮箱 | 唯一 | +| PassHash | varchar(255) | 密码哈希 | | +| Role | Enum('Admin','User') | 用户角色 | | +| IsBan | boolean | 是否禁用 | | +| Balance | Decimal(10) | 余额 | | +| CreatedAt | Timestamp | 创建时间 | 默认当前时间 | + +### API表(Apis) + +| 字段名 | 数据类型 | 描述 | 备注 | +| ------------ | ------------------------------- | ------------- | ---------------------- | +| Id | int | 主键,自增 | | +| Name | varchar(20) | api名称 | | +| Endpoint | varchar(255) | api地址 | | +| Method | enum('GET','POST','PUT',DELETE) | 调用方法 | | +| PackageId | int | 套餐Id | 默认为空(免费无限制) | +| IsThirdParty | boolean | 是否第三方API | | +| PricePercall | decimal(10,2) | 调用价格 | | +| IsActive | boolean | 是否启用 | | +| CreatedAt | timestamp | 创建时间 | 默认当前时间 | + +### 支付记录表(Payments) + +| 字段名 | 数据类型 | 描述 | 备注 | +| ----------- | ---------------------------- | ---------- | ------------------ | +| Id | int | 主键,自增 | | +| UserId | int | 外键 | 用户ID | +| Amount | decimal(10,2) | 支付金额 | 正数充值,负数扣费 | +| PaymentType | enum('Recharge','Deduction') | 支付类型 | 充值或扣费 | +| PaymentAt | timestamp | 充值时间 | | + +### 套餐表(ApiPackages) + +| 字段名 | 数据类型 | 描述 | 备注 | +| --------- | ------------- | ------------ | ---- | +| Id | int | 主键,自增 | | +| Name | varchar(20) | 套餐名称 | | +| CallLimit | int | 最大调用次数 | | +| Price | decimal(10,2) | 价格 | | +| CreatedAt | timestamp | 创建时间 | | + +### 用户套餐关系表(UserPackages) + +| 字段名 | 数据类型 | 描述 | 备注 | +| -------------- | --------- | ------------ | ------ | +| Id | int | 主键,自增 | | +| UserId | int | 外键 | 用户ID | +| PackageId | int | 外键 | 套餐ID | +| RemainingCalls | int | 剩余调用次数 | | +| PurchasedAt | timestamp | 购买时间 | | + From de17c65a44eceff02e2bac29d6174b159179cdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:21:35 +0000 Subject: [PATCH 06/23] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DatabaseDefine.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DatabaseDefine.md b/DatabaseDefine.md index 3ee9762..122bcf8 100644 --- a/DatabaseDefine.md +++ b/DatabaseDefine.md @@ -1,4 +1,4 @@ -# 数据库定义 +# 数据库定义文档 ### 用户表(Users) From 795e71cfcc84c337184ae97433453915221449dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:27:26 +0000 Subject: [PATCH 07/23] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DatabaseDefine.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DatabaseDefine.md b/DatabaseDefine.md index 122bcf8..9ac951e 100644 --- a/DatabaseDefine.md +++ b/DatabaseDefine.md @@ -1,4 +1,4 @@ -# 数据库定义文档 +# 数据库定义 ### 用户表(Users) @@ -57,3 +57,7 @@ | RemainingCalls | int | 剩余调用次数 | | | PurchasedAt | timestamp | 购买时间 | | +> [!CAUTION] +> +> 注:删除用户时需要保证数据一致性。 + From eb8a0f8c57287c484a921392eb44d520d6ed93a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:35:13 +0000 Subject: [PATCH 08/23] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DatabaseDefine.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/DatabaseDefine.md b/DatabaseDefine.md index 9ac951e..9f0bed6 100644 --- a/DatabaseDefine.md +++ b/DatabaseDefine.md @@ -23,19 +23,30 @@ | Method | enum('GET','POST','PUT',DELETE) | 调用方法 | | | PackageId | int | 套餐Id | 默认为空(免费无限制) | | IsThirdParty | boolean | 是否第三方API | | -| PricePercall | decimal(10,2) | 调用价格 | | | IsActive | boolean | 是否启用 | | | CreatedAt | timestamp | 创建时间 | 默认当前时间 | +### API调用表(ApiCallLogs) + +| 字段名 | 数据类型 | 描述 | 备注 | +| ---------- | --------- | -------------- | ------------ | +| Id | int | 主键,自增 | | +| UserId | int | 外键 | 用户ID | +| ApiId | int | 外键 | APIID | +| CallTime | timestamp | 调用时间 | 默认当前时间 | +| CallResult | int | 调用结果状态码 | | + + + ### 支付记录表(Payments) -| 字段名 | 数据类型 | 描述 | 备注 | -| ----------- | ---------------------------- | ---------- | ------------------ | -| Id | int | 主键,自增 | | -| UserId | int | 外键 | 用户ID | -| Amount | decimal(10,2) | 支付金额 | 正数充值,负数扣费 | -| PaymentType | enum('Recharge','Deduction') | 支付类型 | 充值或扣费 | -| PaymentAt | timestamp | 充值时间 | | +| 字段名 | 数据类型 | 描述 | 备注 | +| ----------- | ---------------------------- | ---------- | ---------------------------------- | +| Id | int | 主键,自增 | | +| UserId | int | 外键 | 用户ID | +| Amount | decimal(10,2) | 支付金额 | 正数充值,负数扣费 | +| PaymentType | enum('Recharge','Deduction') | 支付类型 | 充值或扣费,后续增加退款等其余类型 | +| PaymentAt | timestamp | 充值时间 | | ### 套餐表(ApiPackages) From d8954884d090e6d39f77227b4e5a91a98c1c3dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:44:04 +0000 Subject: [PATCH 09/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bdd64a4..88e70b3 100644 --- a/README.md +++ b/README.md @@ -74,4 +74,11 @@ api-billing-system/ 1. **数据库(Data)** - 提供数据库连接及操作支持。 -- 包含数据库上下文类及数据库迁移文件。 \ No newline at end of file +- 包含数据库上下文类及数据库迁移文件。 + +### 项目文档列表 + +- [x] 项目文档 **README.md** +- [x] 数据库文档 **Database.md** +- [ ] 错误码文档 **ErrorCode.md** +- [ ] API文档 \ No newline at end of file From f94003fcbadddae090c8bc997a58206c62ec0cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:44:36 +0000 Subject: [PATCH 10/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 88e70b3..73754c2 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ api-billing-system/ - 提供数据库连接及操作支持。 - 包含数据库上下文类及数据库迁移文件。 -### 项目文档列表 +## 项目文档列表 - [x] 项目文档 **README.md** - [x] 数据库文档 **Database.md** From 7cbf8f696170b7495b021b00cbc8e58f3a73ea30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 02:48:54 +0000 Subject: [PATCH 11/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 73754c2..693f616 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,10 @@ api-billing-system/ ├── Config/ # 系统配置文件 ├── Tests/ # 单元测试及集成测试 ├── Tools/ # 工具类 -└── README.md # 项目文档(本文件) - +├── README.md # 项目文档(本文件) +├── Database.md # 数据库定义文档 +├── APIDefine.md # API定义文档 +└── ErrorCode.md # 错误码文档 ``` @@ -81,4 +83,5 @@ api-billing-system/ - [x] 项目文档 **README.md** - [x] 数据库文档 **Database.md** - [ ] 错误码文档 **ErrorCode.md** +- [ ] API定义文档 **APIDefine.md** - [ ] API文档 \ No newline at end of file From f51c4c4f83554b4511c8e682816d46978d93949d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 12:54:48 +0000 Subject: [PATCH 12/23] =?UTF-8?q?API=E5=AE=9A=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIDefine.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 APIDefine.md diff --git a/APIDefine.md b/APIDefine.md new file mode 100644 index 0000000..514162b --- /dev/null +++ b/APIDefine.md @@ -0,0 +1,37 @@ +## API路径及方法定义 + +| 模块 | 接口名称 | 路径 | 方法 | 描述 | +| -------- | ------------ | ------------------------------------------------------------ | ------ | ---------------- | +| 用户 | 登录 | /api/user/login | POST | 用户登录 | +| | 注册 | /api/user/register | POST | 用户注册 | +| | 登出 | /api/user/logout | POST | 用户登出 | +| | 重置密码 | /api/user/resetpassword | POST | 找回密码 | +| | 用户信息 | /api/user/info/{id} | GET | 获取用户信息 | +| | 修改用户信息 | /api/user/update | POST | 修改用户信息 | +| | 用户充值 | /api/user/recharge | POST | 用户充值 | +| | 充值记录 | /api/user/rechargelog?userid={id}&starttime={time}&endtime={time}&type={type}&page={index}&pagesize={size}&desc={true\|false} | GET | 充值记录查询 | +| | 添加用户 | /api/admin/adduser | POST | 管理员添加用户 | +| | 删除用户 | /api/admin/deleteuser/{id} | DELETE | 管理员删除用户 | +| | 添加余额 | /api/admin/updatebalace | POST | 管理员修改余额 | +| | 禁用用户 | /api/admin/ban/{id} | POST | 禁用用户 | +| | 用户列表 | /api/admin/userlist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询用户列表 | +| API | 添加接口 | /api/admin/addapi | POST | 添加API | +| | 删除接口 | /api/admin/deleteapi/{id} | DELETE | 删除API | +| | 禁用接口 | /api/admin/banapi/{id} | POST | 禁用API | +| | 修改接口 | /api/admin/updateapi?id={id} | POST | 修改接口信息 | +| | 接口信息 | /api/apiinfo/{id} | GET | 获取API信息 | +| | 接口列表 | /api/admin/apilist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询接口列表 | +| | 接口调用查询 | /api/apilog?userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&apiid={id}&userid={id}&pagesize={size}&desc={true\|false} | GET | 查询接口调用 | +| 套餐 | 添加套餐 | /api/admin/addpackage | POST | 添加套餐 | +| | 修改套餐 | /api/admin/updatepackage?id={id} | POST | 修改套餐信息 | +| | 删除套餐 | /api/admin/deletepackage/{id} | DELETE | 删除套餐 | +| | 套餐列表 | /api/admin/packagelist?page={index}&pagesize={size} | GET | 套餐列表 | +| | 购买套餐 | /api/user/buypackage/?packageid={id} | POST | 购买套餐 | +| 支付 | 支付记录查询 | /api/payment/log?payid={id}&userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&pagesize={size}&desc={true\|false} | GET | 支付记录查询 | +| | 订单查询 | /api/payment/orderlog?page={index}&pagesize={size}&starttime={time}&endtime={time}&status={status} | GET | 订单查询 | +| | 取消订单 | /api/user/cancelorder/{id} | DELETE | 取消订单 | +| 用户套餐 | 添加用户套餐 | /api/admin/userpackageadd | POST | 添加用户关联套餐 | +| | 删除用户套餐 | /api/admin/userpackagedelete/{id} | DELETE | 删除用户关联套餐 | +| | 用户套餐查询 | /api/admin/userpackagelist/{id} | GET | 用户关联套餐查询 | +| 系统配置 | 配置修改 | /api/admin/updateconfig | POST | 系统配置修改 | + From 61bc34f27662b1fbb8b1f080a7a9459843e4444a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:13:17 +0000 Subject: [PATCH 13/23] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DatabaseDefine.md | 51 +++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/DatabaseDefine.md b/DatabaseDefine.md index 9f0bed6..e97afce 100644 --- a/DatabaseDefine.md +++ b/DatabaseDefine.md @@ -36,27 +36,45 @@ | CallTime | timestamp | 调用时间 | 默认当前时间 | | CallResult | int | 调用结果状态码 | | +### 订单表(Orders) +| 字段名 | 数据类型 | 描述 | 备注 | +| ----------------- | ------------------------------------------------ | ------------------ | -------------------------------- | +| Id | int | 主键,自增 | | +| UserId | int | 外键 | 用户ID | +| OrderNumber | varchar(50) | 订单号 | 唯一订单编号,适合与外部系统对接 | +| ThirdPartyOrderId | varchar(100) | 第三方系统订单编号 | 可用于追踪第三方支付 | +| Amount | decimal(10,2) | 订单金额 | 正数充值或消费,负数表示退款 | +| OrderType | enum('Recharge','Purchase', 'Refund') | 订单类型 | 充值、购买、退款等 | +| Status | enum('Pending','Completed','Cancelled','Failed') | 订单状态 | 订单状态:进行中、完成、取消等 | +| CreatedAt | timestamp | 创建时间 | 订单创建时间 | +| UpdatedAt | timestamp | 更新时间 | 订单状态更新时间 | +| Description | varchar(255) | 订单描述 | 可选的详细信息,解释订单用途 | -### 支付记录表(Payments) +### 操作日志表(OperationLogs) -| 字段名 | 数据类型 | 描述 | 备注 | -| ----------- | ---------------------------- | ---------- | ---------------------------------- | -| Id | int | 主键,自增 | | -| UserId | int | 外键 | 用户ID | -| Amount | decimal(10,2) | 支付金额 | 正数充值,负数扣费 | -| PaymentType | enum('Recharge','Deduction') | 支付类型 | 充值或扣费,后续增加退款等其余类型 | -| PaymentAt | timestamp | 充值时间 | | +| 字段名 | 数据类型 | 描述 | 备注 | +| ----------- | ------------ | ------------ | ---------------------------------- | +| Id | int | 主键,自增 | | +| UserId | int | 操作人ID | 操作者的用户ID(通常是管理员) | +| Operation | varchar(20) | 操作类型 | 描述操作的具体内容,例如“禁用用户” | +| TargetType | varchar(50) | 目标类型 | 操作的对象类型,例如“用户” | +| TargetId | int | 目标对象ID | 操作对象的具体ID | +| CreatedAt | timestamp | 操作时间 | 操作发生时间 | +| IpAddress | varchar(45) | 操作来源IP | | +| UserAgent | varchar(255) | 操作设备信息 | | +| Description | varchar(255) | 操作描述 | 可选的详细说明,解释操作原因等 | ### 套餐表(ApiPackages) -| 字段名 | 数据类型 | 描述 | 备注 | -| --------- | ------------- | ------------ | ---- | -| Id | int | 主键,自增 | | -| Name | varchar(20) | 套餐名称 | | -| CallLimit | int | 最大调用次数 | | -| Price | decimal(10,2) | 价格 | | -| CreatedAt | timestamp | 创建时间 | | +| 字段名 | 数据类型 | 描述 | 备注 | +| ---------- | ------------- | ------------ | ---------------------- | +| Id | int | 主键,自增 | | +| Name | varchar(20) | 套餐名称 | | +| CallLimit | int | 最大调用次数 | | +| Price | decimal(10,2) | 价格 | | +| ExpiryDate | timestamp | 套餐过期时间 | 可用于控制套餐是否过期 | +| CreatedAt | timestamp | 创建时间 | | ### 用户套餐关系表(UserPackages) @@ -70,5 +88,4 @@ > [!CAUTION] > -> 注:删除用户时需要保证数据一致性。 - +> 注:删除用户时需要保证数据一致性。 \ No newline at end of file From d5d619c18fde53addaf731ad40df4e933289054f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:13:52 +0000 Subject: [PATCH 14/23] =?UTF-8?q?API=E5=AE=9A=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- APIDefine.md | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/APIDefine.md b/APIDefine.md index 514162b..98140ff 100644 --- a/APIDefine.md +++ b/APIDefine.md @@ -1,37 +1,37 @@ ## API路径及方法定义 -| 模块 | 接口名称 | 路径 | 方法 | 描述 | -| -------- | ------------ | ------------------------------------------------------------ | ------ | ---------------- | -| 用户 | 登录 | /api/user/login | POST | 用户登录 | -| | 注册 | /api/user/register | POST | 用户注册 | -| | 登出 | /api/user/logout | POST | 用户登出 | -| | 重置密码 | /api/user/resetpassword | POST | 找回密码 | -| | 用户信息 | /api/user/info/{id} | GET | 获取用户信息 | -| | 修改用户信息 | /api/user/update | POST | 修改用户信息 | -| | 用户充值 | /api/user/recharge | POST | 用户充值 | -| | 充值记录 | /api/user/rechargelog?userid={id}&starttime={time}&endtime={time}&type={type}&page={index}&pagesize={size}&desc={true\|false} | GET | 充值记录查询 | -| | 添加用户 | /api/admin/adduser | POST | 管理员添加用户 | -| | 删除用户 | /api/admin/deleteuser/{id} | DELETE | 管理员删除用户 | -| | 添加余额 | /api/admin/updatebalace | POST | 管理员修改余额 | -| | 禁用用户 | /api/admin/ban/{id} | POST | 禁用用户 | -| | 用户列表 | /api/admin/userlist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询用户列表 | -| API | 添加接口 | /api/admin/addapi | POST | 添加API | -| | 删除接口 | /api/admin/deleteapi/{id} | DELETE | 删除API | -| | 禁用接口 | /api/admin/banapi/{id} | POST | 禁用API | -| | 修改接口 | /api/admin/updateapi?id={id} | POST | 修改接口信息 | -| | 接口信息 | /api/apiinfo/{id} | GET | 获取API信息 | -| | 接口列表 | /api/admin/apilist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询接口列表 | -| | 接口调用查询 | /api/apilog?userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&apiid={id}&userid={id}&pagesize={size}&desc={true\|false} | GET | 查询接口调用 | -| 套餐 | 添加套餐 | /api/admin/addpackage | POST | 添加套餐 | -| | 修改套餐 | /api/admin/updatepackage?id={id} | POST | 修改套餐信息 | -| | 删除套餐 | /api/admin/deletepackage/{id} | DELETE | 删除套餐 | -| | 套餐列表 | /api/admin/packagelist?page={index}&pagesize={size} | GET | 套餐列表 | -| | 购买套餐 | /api/user/buypackage/?packageid={id} | POST | 购买套餐 | -| 支付 | 支付记录查询 | /api/payment/log?payid={id}&userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&pagesize={size}&desc={true\|false} | GET | 支付记录查询 | -| | 订单查询 | /api/payment/orderlog?page={index}&pagesize={size}&starttime={time}&endtime={time}&status={status} | GET | 订单查询 | -| | 取消订单 | /api/user/cancelorder/{id} | DELETE | 取消订单 | -| 用户套餐 | 添加用户套餐 | /api/admin/userpackageadd | POST | 添加用户关联套餐 | -| | 删除用户套餐 | /api/admin/userpackagedelete/{id} | DELETE | 删除用户关联套餐 | -| | 用户套餐查询 | /api/admin/userpackagelist/{id} | GET | 用户关联套餐查询 | -| 系统配置 | 配置修改 | /api/admin/updateconfig | POST | 系统配置修改 | +| 模块 | 接口名称 | 路径 | 方法 | 描述 | +| -------- | ---------------- | ------------------------------------------------------------ | ------ | ---------------- | +| 用户 | 登录 | /api/user/login | POST | 用户登录 | +| | 注册 | /api/user/register | POST | 用户注册 | +| | 登出 | /api/user/logout | POST | 用户登出 | +| | 重置密码 | /api/user/resetpassword | POST | 找回密码 | +| | 用户信息 | /api/user/info/{id} | GET | 获取用户信息 | +| | 修改用户信息 | /api/user/update | POST | 修改用户信息 | +| | 用户充值 | /api/user/recharge | POST | 用户充值 | +| | 添加用户 | /api/admin/adduser | POST | 管理员添加用户 | +| | 删除用户 | /api/admin/deleteuser/{id} | DELETE | 管理员删除用户 | +| | 添加余额 | /api/admin/updatebalace | POST | 管理员修改余额 | +| | 禁用用户 | /api/admin/ban/{id} | POST | 禁用用户 | +| | 用户列表 | /api/admin/userlist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询用户列表 | +| API | 添加接口 | /api/admin/addapi | POST | 添加API | +| | 删除接口 | /api/admin/deleteapi/{id} | DELETE | 删除API | +| | 禁用接口 | /api/admin/banapi/{id} | POST | 禁用API | +| | 修改接口 | /api/admin/updateapi?id={id} | POST | 修改接口信息 | +| | 接口信息 | /api/apiinfo/{id} | GET | 获取API信息 | +| | 接口列表 | /api/admin/apilist?page={index}&pagesize={size}&desc={true\|false} | GET | 查询接口列表 | +| | 接口调用查询 | /api/apilog?userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&apiid={id}&userid={id}&pagesize={size}&desc={true\|false} | GET | 查询接口调用 | +| 套餐 | 添加套餐 | /api/admin/addpackage | POST | 添加套餐 | +| | 修改套餐 | /api/admin/updatepackage?id={id} | POST | 修改套餐信息 | +| | 删除套餐 | /api/admin/deletepackage/{id} | DELETE | 删除套餐 | +| | 套餐列表 | /api/admin/packagelist?page={index}&pagesize={size} | GET | 套餐列表 | +| | 购买套餐 | /api/user/buypackage/?packageid={id} | POST | 购买套餐 | +| 订单 | 支付记录查询 | /api/payment/loglist?payid={id}&userid={id}&starttime={time}&endtime={time}&method={method}&page={index}&pagesize={size}&desc={true\|false} | GET | 支付记录查询 | +| | 订单信息查询 | /api/payment/orderlog/{id} | POST | 订单查询 | +| | 取消订单 | /api/payment/cancelorder/{id} | DELETE | 取消订单 | +| 用户套餐 | 添加用户套餐 | /api/admin/userpackageadd | POST | 添加用户关联套餐 | +| | 修改用户套餐时间 | /api/admin/userpackageupdate/id={id}&expire={time} | DELETE | 删除用户关联套餐 | +| | 用户套餐查询 | /api/admin/userpackagelist/{id} | GET | 用户已购套餐查询 | +| 系统配置 | 配置修改 | /api/admin/updateconfig | POST | 系统配置修改 | +| 操作日志 | 操作日志列表 | /api/operation/log?userid={id}&page={index}&pagesize={size}&starttime={time}&endtime={time}&desc={true\|false} | GET | 操作日志查询 | From 2c43e0401eec7f0f1589240b4e2bb780ca08b32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:18:15 +0000 Subject: [PATCH 15/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 693f616..8979b5e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## 项目背景 -简单描述该API的背景、用途及目标用户。 +API管理与用户服务系统是一个集用户管理、API管理、套餐销售与支付管理为一体的综合平台。该系统为用户提供注册、登录、充值和套餐购买等功能,管理员则可以通过系统对API进行统一管理、用户操作日志的记录与查看,以及管理订单与支付情况。整个项目采用了RESTful架构风格,通过简洁的接口设计确保系统的可扩展性、易维护性以及与第三方服务对接的能力。 ## 功能概述 @@ -49,9 +49,9 @@ api-billing-system/ ├── Config/ # 系统配置文件 ├── Tests/ # 单元测试及集成测试 ├── Tools/ # 工具类 -├── README.md # 项目文档(本文件) -├── Database.md # 数据库定义文档 -├── APIDefine.md # API定义文档 +├── README.md # 项目文档(本文件) +├── Database.md # 数据库定义文档 +├── APIDefine.md # API定义文档 └── ErrorCode.md # 错误码文档 ``` @@ -83,5 +83,5 @@ api-billing-system/ - [x] 项目文档 **README.md** - [x] 数据库文档 **Database.md** - [ ] 错误码文档 **ErrorCode.md** -- [ ] API定义文档 **APIDefine.md** +- [x] API定义文档 **APIDefine.md** - [ ] API文档 \ No newline at end of file From fce71874e36db8e962fde18235ac8d47c4cd2071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:19:20 +0000 Subject: [PATCH 16/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8979b5e..da2a611 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ api-billing-system/ ├── Config/ # 系统配置文件 ├── Tests/ # 单元测试及集成测试 ├── Tools/ # 工具类 -├── README.md # 项目文档(本文件) -├── Database.md # 数据库定义文档 -├── APIDefine.md # API定义文档 +├── README.md # 项目文档(本文件) +├── Database.md # 数据库定义文档 +├── APIDefine.md # API定义文档 └── ErrorCode.md # 错误码文档 ``` From d2bd1d82c65ca7d14d376d41dd6d2019be80ba78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:29:48 +0000 Subject: [PATCH 17/23] =?UTF-8?q?=E9=94=99=E8=AF=AF=E7=A0=81=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ErrorCode.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 ErrorCode.md diff --git a/ErrorCode.md b/ErrorCode.md new file mode 100644 index 0000000..9c36c73 --- /dev/null +++ b/ErrorCode.md @@ -0,0 +1,58 @@ +## 错误码定义 + +#### 通用错误码(1xxx) + +| 错误码 | HTTP状态码 | 描述 | Message | +| ------ | ---------- | -------------------- | --------------------- | +| 1000 | 200 | 成功 | Success | +| 1001 | 400 | 参数错误 | Invalid parameters | +| 1002 | 401 | 用户未登录或认证失败 | Unauthorized | +| 1003 | 403 | 无权限访问 | Forbidden | +| 1004 | 404 | 资源未找到 | Resource not found | +| 1005 | 500 | 服务器内部错误 | Internal server error | +| 1006 | 503 | 服务暂时不可用 | Service unavailable | + +#### 用户模块错误码(2xxx) + +| 错误码 | HTTP状态码 | 描述 | Message | +| ------ | ---------- | -------------------- | ---------------------------- | +| 2000 | 200 | 登录成功 | Login successful | +| 2001 | 401 | 用户名或密码错误 | Invalid username or password | +| 2002 | 401 | 用户账户被禁用 | User account is disabled | +| 2003 | 409 | 用户名已存在 | Username already exists | +| 2004 | 404 | 用户不存在 | User not found | +| 2005 | 409 | 邮箱已存在 | Email already exists | +| 2006 | 403 | 用户无权限进行该操作 | Permission denied | +| 2007 | 400 | 密码重置失败 | Password reset failed | + +#### API模块错误码(3xxx) + +| 错误码 | HTTP状态码 | 描述 | Message | +| ------ | ---------- | ------------------------- | ------------------------------------------ | +| 3000 | 200 | API调用成功 | API call successful | +| 3001 | 403 | API访问受限 | API access restricted | +| 3002 | 404 | API不存在 | API not found | +| 3003 | 429 | API调用次数超限 | API call limit exceeded | +| 3004 | 403 | 未购买该API套餐或权限不足 | API package not purchased or access denied | +| 3005 | 500 | API调用失败,服务器错误 | API call failed, server error | + +#### 套餐与支付模块错误码(4xxx) + +| 错误码 | HTTP状态码 | 描述 | Message | +| ------ | ---------- | ------------------ | ------------------------------------ | +| 4000 | 200 | 支付成功 | Payment successful | +| 4001 | 400 | 支付请求无效 | Invalid payment request | +| 4002 | 402 | 支付失败,余额不足 | Payment failed, insufficient balance | +| 4003 | 404 | 订单未找到 | Order not found | +| 4004 | 409 | 重复支付或订单冲突 | Duplicate payment or order conflict | +| 4005 | 500 | 支付系统错误 | Payment system error | +| 4006 | 200 | 退款成功 | Refund successful | + +#### 日志与系统模块错误码(5xxx) + +| 错误码 | HTTP状态码 | 描述 | Message | +| ------ | ---------- | ------------------ | -------------------------- | +| 5000 | 200 | 日志查询成功 | Log retrieval successful | +| 5001 | 404 | 日志记录未找到 | Log record not found | +| 5002 | 500 | 日志服务异常 | Log service error | +| 5003 | 403 | 无权限查看操作日志 | No permission to view logs | \ No newline at end of file From 05e3b9ee67bad5116a99d5b0a2c5dd754f1eef75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:30:38 +0000 Subject: [PATCH 18/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da2a611..c0a68dd 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,6 @@ api-billing-system/ - [x] 项目文档 **README.md** - [x] 数据库文档 **Database.md** -- [ ] 错误码文档 **ErrorCode.md** +- [x] 错误码文档 **ErrorCode.md** - [x] API定义文档 **APIDefine.md** - [ ] API文档 \ No newline at end of file From 39ab11ddb6dd08c4c313bfc59e819d726a2bd90c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 13:41:46 +0000 Subject: [PATCH 19/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c0a68dd..19f3107 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ api-billing-system/ ├── Config/ # 系统配置文件 ├── Tests/ # 单元测试及集成测试 ├── Tools/ # 工具类 -├── README.md # 项目文档(本文件) -├── Database.md # 数据库定义文档 -├── APIDefine.md # API定义文档 +├── README.md # 项目文档(本文件) +├── Database.md # 数据库定义文档 +├── APIDefine.md # API定义文档 └── ErrorCode.md # 错误码文档 ``` @@ -80,8 +80,8 @@ api-billing-system/ ## 项目文档列表 -- [x] 项目文档 **README.md** +- [x] 项目文档 **README.md** - [x] 数据库文档 **Database.md** - [x] 错误码文档 **ErrorCode.md** - [x] API定义文档 **APIDefine.md** -- [ ] API文档 \ No newline at end of file +- [ ] API文档 **[Apifox - 接口文档分享](https://apifox.com/apidoc/shared-8730c2eb-595b-4cf4-941d-d58914d4cd1e)** \ No newline at end of file From 8b841e5218fa0ae8e6350f499005b3fa002c271a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Thu, 24 Oct 2024 14:31:32 +0000 Subject: [PATCH 20/23] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DatabaseDefine.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DatabaseDefine.md b/DatabaseDefine.md index e97afce..3b0ad48 100644 --- a/DatabaseDefine.md +++ b/DatabaseDefine.md @@ -10,6 +10,7 @@ | PassHash | varchar(255) | 密码哈希 | | | Role | Enum('Admin','User') | 用户角色 | | | IsBan | boolean | 是否禁用 | | +| IsDelete | boolean | 是否删除 | | | Balance | Decimal(10) | 余额 | | | CreatedAt | Timestamp | 创建时间 | 默认当前时间 | @@ -24,6 +25,7 @@ | PackageId | int | 套餐Id | 默认为空(免费无限制) | | IsThirdParty | boolean | 是否第三方API | | | IsActive | boolean | 是否启用 | | +| isDelete | boolean | 是否删除 | | | CreatedAt | timestamp | 创建时间 | 默认当前时间 | ### API调用表(ApiCallLogs) From 89d74e83b14f9cf0b6a90481a6683dcd6feef595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=97=E6=B5=94?= Date: Wed, 23 Oct 2024 01:33:18 +0000 Subject: [PATCH 21/23] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E8=A1=A8=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apimanager_backend/Apimanager_backend.csproj | 12 + .../Controllers/WeatherForecastController.cs | 33 -- Apimanager_backend/Data/ApiCallLogConfig.cs | 26 ++ Apimanager_backend/Data/ApiConfig.cs | 23 ++ Apimanager_backend/Data/ApiContext.cs | 30 ++ Apimanager_backend/Data/OperationLogConfig.cs | 22 + Apimanager_backend/Data/OrderConfig.cs | 28 ++ Apimanager_backend/Data/UserConfig.cs | 23 ++ Apimanager_backend/Data/UserPackageConfig.cs | 25 ++ .../20241024162342_Init-Database.Designer.cs | 378 ++++++++++++++++++ .../20241024162342_Init-Database.cs | 295 ++++++++++++++ .../Migrations/ApiContextModelSnapshot.cs | 375 +++++++++++++++++ Apimanager_backend/Models/Api.cs | 59 +++ Apimanager_backend/Models/ApiCallLog.cs | 35 ++ Apimanager_backend/Models/ApiMethod.cs | 10 + Apimanager_backend/Models/Apipackage.cs | 44 ++ Apimanager_backend/Models/OperationLog.cs | 61 +++ Apimanager_backend/Models/Order.cs | 62 +++ Apimanager_backend/Models/OrderStatus.cs | 10 + Apimanager_backend/Models/OrderType.cs | 9 + Apimanager_backend/Models/User.cs | 60 +++ Apimanager_backend/Models/UserPackage.cs | 33 ++ Apimanager_backend/Models/UserRole.cs | 8 + Apimanager_backend/Program.cs | 14 + Apimanager_backend/WeatherForecast.cs | 13 - Apimanager_backend/appsettings.json | 5 +- README.md | 78 +++- 27 files changed, 1723 insertions(+), 48 deletions(-) delete mode 100644 Apimanager_backend/Controllers/WeatherForecastController.cs create mode 100644 Apimanager_backend/Data/ApiCallLogConfig.cs create mode 100644 Apimanager_backend/Data/ApiConfig.cs create mode 100644 Apimanager_backend/Data/ApiContext.cs create mode 100644 Apimanager_backend/Data/OperationLogConfig.cs create mode 100644 Apimanager_backend/Data/OrderConfig.cs create mode 100644 Apimanager_backend/Data/UserConfig.cs create mode 100644 Apimanager_backend/Data/UserPackageConfig.cs create mode 100644 Apimanager_backend/Migrations/20241024162342_Init-Database.Designer.cs create mode 100644 Apimanager_backend/Migrations/20241024162342_Init-Database.cs create mode 100644 Apimanager_backend/Migrations/ApiContextModelSnapshot.cs create mode 100644 Apimanager_backend/Models/Api.cs create mode 100644 Apimanager_backend/Models/ApiCallLog.cs create mode 100644 Apimanager_backend/Models/ApiMethod.cs create mode 100644 Apimanager_backend/Models/Apipackage.cs create mode 100644 Apimanager_backend/Models/OperationLog.cs create mode 100644 Apimanager_backend/Models/Order.cs create mode 100644 Apimanager_backend/Models/OrderStatus.cs create mode 100644 Apimanager_backend/Models/OrderType.cs create mode 100644 Apimanager_backend/Models/User.cs create mode 100644 Apimanager_backend/Models/UserPackage.cs create mode 100644 Apimanager_backend/Models/UserRole.cs delete mode 100644 Apimanager_backend/WeatherForecast.cs diff --git a/Apimanager_backend/Apimanager_backend.csproj b/Apimanager_backend/Apimanager_backend.csproj index 9daa180..ce65827 100644 --- a/Apimanager_backend/Apimanager_backend.csproj +++ b/Apimanager_backend/Apimanager_backend.csproj @@ -7,7 +7,19 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/Apimanager_backend/Controllers/WeatherForecastController.cs b/Apimanager_backend/Controllers/WeatherForecastController.cs deleted file mode 100644 index 028579e..0000000 --- a/Apimanager_backend/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Apimanager_backend.Controllers -{ - [ApiController] - [Route("[controller]")] - public class WeatherForecastController : ControllerBase - { - private static readonly string[] Summaries = new[] - { - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - }; - - private readonly ILogger _logger; - - public WeatherForecastController(ILogger logger) - { - _logger = logger; - } - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git a/Apimanager_backend/Data/ApiCallLogConfig.cs b/Apimanager_backend/Data/ApiCallLogConfig.cs new file mode 100644 index 0000000..b4484b0 --- /dev/null +++ b/Apimanager_backend/Data/ApiCallLogConfig.cs @@ -0,0 +1,26 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class ApiCallLogConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //外键:API + builder.HasOne(x => x.Api) + .WithMany(u => u.ApiCalls) + .HasForeignKey(x => x.ApiId); + //外键:User + builder.HasOne(x => x.User) + .WithMany(u => u.CallLogs) + .HasForeignKey(x => x.UserId); + } + } +} diff --git a/Apimanager_backend/Data/ApiConfig.cs b/Apimanager_backend/Data/ApiConfig.cs new file mode 100644 index 0000000..cf36445 --- /dev/null +++ b/Apimanager_backend/Data/ApiConfig.cs @@ -0,0 +1,23 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class ApiConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //外键 + builder.HasOne(x => x.Package) + .WithMany(u => u.Apis) + .HasForeignKey(x => x.PackageId); + + } + } +} diff --git a/Apimanager_backend/Data/ApiContext.cs b/Apimanager_backend/Data/ApiContext.cs new file mode 100644 index 0000000..1be7614 --- /dev/null +++ b/Apimanager_backend/Data/ApiContext.cs @@ -0,0 +1,30 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using System.Reflection; + +namespace Apimanager_backend.Data +{ + public class ApiContext:DbContext + { + //API表 + public DbSet Apis { get; set; } + //用户表 + public DbSet Users { get; set; } + //API调用日志 + public DbSet CallLogs { get; set; } + //套餐表 + public DbSet Apipackages { get; set; } + //操作日志表 + public DbSet OperationLogs { get; set; } + //订单表 + public DbSet Orders { get; set; } + //用户已订购套餐表 + public DbSet UserPackages { get; set; } + public ApiContext(DbContextOptions options) : base(options) { } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApiContext).Assembly); + } + + } +} diff --git a/Apimanager_backend/Data/OperationLogConfig.cs b/Apimanager_backend/Data/OperationLogConfig.cs new file mode 100644 index 0000000..01d83ae --- /dev/null +++ b/Apimanager_backend/Data/OperationLogConfig.cs @@ -0,0 +1,22 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class OperationLogConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //外键 + builder.HasOne(x => x.User) + .WithMany(u => u.operationLogs) + .HasForeignKey(x => x.UserId); + } + } +} diff --git a/Apimanager_backend/Data/OrderConfig.cs b/Apimanager_backend/Data/OrderConfig.cs new file mode 100644 index 0000000..50d6452 --- /dev/null +++ b/Apimanager_backend/Data/OrderConfig.cs @@ -0,0 +1,28 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class OrderConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //唯一索引 + builder.HasIndex(x => x.OrderNumber) + .IsUnique(); + //唯一索引 + builder.HasIndex(x => x.ThirdPartyOrderId) + .IsUnique(); + //外键 + builder.HasOne(x => x.User) + .WithMany(u => u.Orders) + .HasForeignKey(x => x.UserId); + } + } +} diff --git a/Apimanager_backend/Data/UserConfig.cs b/Apimanager_backend/Data/UserConfig.cs new file mode 100644 index 0000000..7b5058a --- /dev/null +++ b/Apimanager_backend/Data/UserConfig.cs @@ -0,0 +1,23 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class UserConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //唯一索引 + builder.HasIndex(x => x.Username) + .IsUnique(); + builder.HasIndex(x => x.Email) + .IsUnique(); + } + } +} diff --git a/Apimanager_backend/Data/UserPackageConfig.cs b/Apimanager_backend/Data/UserPackageConfig.cs new file mode 100644 index 0000000..032d923 --- /dev/null +++ b/Apimanager_backend/Data/UserPackageConfig.cs @@ -0,0 +1,25 @@ +using Apimanager_backend.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Apimanager_backend.Data +{ + public class UserPackageConfig : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + //主键 + builder.HasKey(x => x.Id); + //自增 + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + //外键 + builder.HasOne(x => x.User) + .WithMany(u => u.Packages) + .HasForeignKey(x => x.UserId); + builder.HasOne(x => x.Package) + .WithMany(u => u.Packages) + .HasForeignKey(x => x.PackageId); + } + } +} diff --git a/Apimanager_backend/Migrations/20241024162342_Init-Database.Designer.cs b/Apimanager_backend/Migrations/20241024162342_Init-Database.Designer.cs new file mode 100644 index 0000000..d3bb34c --- /dev/null +++ b/Apimanager_backend/Migrations/20241024162342_Init-Database.Designer.cs @@ -0,0 +1,378 @@ +// +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("20241024162342_Init-Database")] + partial class InitDatabase + { + /// + 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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDelete") + .HasColumnType("tinyint(1)"); + + b.Property("IsThirdParty") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("PackageId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PackageId"); + + b.ToTable("Apis"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ApiId") + .HasColumnType("int"); + + b.Property("CallResult") + .HasColumnType("int"); + + b.Property("CallTime") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ApiId"); + + b.HasIndex("UserId"); + + b.ToTable("CallLogs"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CallLimit") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Apipackages"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IpAddress") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("varchar(45)"); + + b.Property("Operation") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("TargetType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("OperationLogs"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("ThirdPartyOrderId") + .HasColumnType("varchar(255)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("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.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Balance") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("IsBan") + .HasColumnType("tinyint(1)"); + + b.Property("IsDelete") + .HasColumnType("tinyint(1)"); + + b.Property("PassHash") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("Role") + .HasColumnType("int"); + + b.Property("Username") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PackageId") + .HasColumnType("int"); + + b.Property("PurchasedAt") + .HasColumnType("datetime(6)"); + + b.Property("RemainingCalls") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PackageId"); + + b.HasIndex("UserId"); + + b.ToTable("UserPackages"); + }); + + 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.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.Api", b => + { + b.Navigation("ApiCalls"); + }); + + 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("operationLogs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Apimanager_backend/Migrations/20241024162342_Init-Database.cs b/Apimanager_backend/Migrations/20241024162342_Init-Database.cs new file mode 100644 index 0000000..3de7b1b --- /dev/null +++ b/Apimanager_backend/Migrations/20241024162342_Init-Database.cs @@ -0,0 +1,295 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Apimanager_backend.Migrations +{ + /// + public partial class InitDatabase : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Apipackages", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "varchar(20)", maxLength: 20, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CallLimit = table.Column(type: "int", nullable: false), + Price = table.Column(type: "decimal(65,30)", nullable: false), + ExpiryDate = table.Column(type: "datetime(6)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Apipackages", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Username = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Email = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + PassHash = table.Column(type: "varchar(255)", maxLength: 255, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Role = table.Column(type: "int", nullable: false), + IsBan = table.Column(type: "tinyint(1)", nullable: false), + IsDelete = table.Column(type: "tinyint(1)", nullable: false), + Balance = table.Column(type: "decimal(65,30)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Apis", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "varchar(200)", maxLength: 200, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Endpoint = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Method = table.Column(type: "int", nullable: false), + PackageId = table.Column(type: "int", nullable: true), + IsThirdParty = table.Column(type: "tinyint(1)", nullable: false), + IsActive = table.Column(type: "tinyint(1)", nullable: false), + IsDelete = table.Column(type: "tinyint(1)", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Apis", x => x.Id); + table.ForeignKey( + name: "FK_Apis_Apipackages_PackageId", + column: x => x.PackageId, + principalTable: "Apipackages", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "OperationLogs", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + Operation = table.Column(type: "varchar(20)", maxLength: 20, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TargetType = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TargetId = table.Column(type: "int", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + IpAddress = table.Column(type: "varchar(45)", maxLength: 45, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + UserAgent = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_OperationLogs", x => x.Id); + table.ForeignKey( + name: "FK_OperationLogs_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + OrderNumber = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ThirdPartyOrderId = table.Column(type: "varchar(255)", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Amount = table.Column(type: "decimal(65,30)", nullable: false), + OrderType = table.Column(type: "int", nullable: false), + Status = table.Column(type: "int", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false), + Description = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "UserPackages", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + PackageId = table.Column(type: "int", nullable: false), + RemainingCalls = table.Column(type: "int", nullable: false), + PurchasedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserPackages", x => x.Id); + table.ForeignKey( + name: "FK_UserPackages_Apipackages_PackageId", + column: x => x.PackageId, + principalTable: "Apipackages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserPackages_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "CallLogs", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "int", nullable: false), + ApiId = table.Column(type: "int", nullable: false), + CallTime = table.Column(type: "datetime(6)", nullable: false), + CallResult = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CallLogs", x => x.Id); + table.ForeignKey( + name: "FK_CallLogs_Apis_ApiId", + column: x => x.ApiId, + principalTable: "Apis", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_CallLogs_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Apis_PackageId", + table: "Apis", + column: "PackageId"); + + migrationBuilder.CreateIndex( + name: "IX_CallLogs_ApiId", + table: "CallLogs", + column: "ApiId"); + + migrationBuilder.CreateIndex( + name: "IX_CallLogs_UserId", + table: "CallLogs", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_OperationLogs_UserId", + table: "OperationLogs", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_OrderNumber", + table: "Orders", + column: "OrderNumber", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Orders_ThirdPartyOrderId", + table: "Orders", + column: "ThirdPartyOrderId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Orders_UserId", + table: "Orders", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserPackages_PackageId", + table: "UserPackages", + column: "PackageId"); + + migrationBuilder.CreateIndex( + name: "IX_UserPackages_UserId", + table: "UserPackages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Users_Email", + table: "Users", + column: "Email", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Users_Username", + table: "Users", + column: "Username", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CallLogs"); + + migrationBuilder.DropTable( + name: "OperationLogs"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "UserPackages"); + + migrationBuilder.DropTable( + name: "Apis"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.DropTable( + name: "Apipackages"); + } + } +} diff --git a/Apimanager_backend/Migrations/ApiContextModelSnapshot.cs b/Apimanager_backend/Migrations/ApiContextModelSnapshot.cs new file mode 100644 index 0000000..83d8249 --- /dev/null +++ b/Apimanager_backend/Migrations/ApiContextModelSnapshot.cs @@ -0,0 +1,375 @@ +// +using System; +using Apimanager_backend.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Apimanager_backend.Migrations +{ + [DbContext(typeof(ApiContext))] + partial class ApiContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(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("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Endpoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDelete") + .HasColumnType("tinyint(1)"); + + b.Property("IsThirdParty") + .HasColumnType("tinyint(1)"); + + b.Property("Method") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("PackageId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PackageId"); + + b.ToTable("Apis"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.ApiCallLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ApiId") + .HasColumnType("int"); + + b.Property("CallResult") + .HasColumnType("int"); + + b.Property("CallTime") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ApiId"); + + b.HasIndex("UserId"); + + b.ToTable("CallLogs"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.Apipackage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CallLimit") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ExpiryDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("Price") + .HasColumnType("decimal(65,30)"); + + b.HasKey("Id"); + + b.ToTable("Apipackages"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.OperationLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("IpAddress") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("varchar(45)"); + + b.Property("Operation") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("TargetId") + .HasColumnType("int"); + + b.Property("TargetType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("UserAgent") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("OperationLogs"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("OrderNumber") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("OrderType") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("ThirdPartyOrderId") + .HasColumnType("varchar(255)"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("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.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Balance") + .HasColumnType("decimal(65,30)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("IsBan") + .HasColumnType("tinyint(1)"); + + b.Property("IsDelete") + .HasColumnType("tinyint(1)"); + + b.Property("PassHash") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("Role") + .HasColumnType("int"); + + b.Property("Username") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("Email") + .IsUnique(); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Apimanager_backend.Models.UserPackage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("PackageId") + .HasColumnType("int"); + + b.Property("PurchasedAt") + .HasColumnType("datetime(6)"); + + b.Property("RemainingCalls") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("PackageId"); + + b.HasIndex("UserId"); + + b.ToTable("UserPackages"); + }); + + 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.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.Api", b => + { + b.Navigation("ApiCalls"); + }); + + 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("operationLogs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Apimanager_backend/Models/Api.cs b/Apimanager_backend/Models/Api.cs new file mode 100644 index 0000000..85b8d23 --- /dev/null +++ b/Apimanager_backend/Models/Api.cs @@ -0,0 +1,59 @@ +using Apimanager_backend.Data; +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Models +{ + public class Api + { + /// + /// 主键,自增 + /// + public int Id { get; set; } + + /// + /// API名称 + /// + [MaxLength(200)] + [Required] + public string Name { get; set; } // varchar(20) + + /// + /// API地址 + /// + [Required] + public string Endpoint { get; set; } // varchar(255) + + /// + /// 调用方法 + /// + public ApiMethod Method { get; set; } // enum('GET','POST','PUT', 'DELETE') + + /// + /// 套餐Id,默认为空(免费无限制) + /// + public int? PackageId { get; set; } // int? 使其可为null + + /// + /// 是否第三方API + /// + public bool IsThirdParty { get; set; } // boolean + + /// + /// 是否启用 + /// + public bool IsActive { get; set; } // boolean + /// + /// 是否删除 + /// + public bool IsDelete { get; set; } // boolean + + /// + /// 创建时间,默认当前时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp + + //导航属性 + public Apipackage? Package { get; set; } + public ICollection ApiCalls { get; set; } + } +} diff --git a/Apimanager_backend/Models/ApiCallLog.cs b/Apimanager_backend/Models/ApiCallLog.cs new file mode 100644 index 0000000..234b42d --- /dev/null +++ b/Apimanager_backend/Models/ApiCallLog.cs @@ -0,0 +1,35 @@ +namespace Apimanager_backend.Models +{ + public class ApiCallLog + { + /// + /// 主键,自增 + /// + public int Id { get; set; } + + /// + /// 外键,用户ID + /// + public int UserId { get; set; } + + /// + /// 外键,API ID + /// + public int ApiId { get; set; } + + /// + /// 调用时间,默认当前时间 + /// + public DateTime CallTime { get; set; } = DateTime.UtcNow; // Timestamp + + /// + /// 调用结果状态码 + /// + public int CallResult { get; set; } // 调用结果状态码 + + + //导航属性 + public User? User { get; set; } + public Api? Api { get; set; } + } +} diff --git a/Apimanager_backend/Models/ApiMethod.cs b/Apimanager_backend/Models/ApiMethod.cs new file mode 100644 index 0000000..2d736c9 --- /dev/null +++ b/Apimanager_backend/Models/ApiMethod.cs @@ -0,0 +1,10 @@ +namespace Apimanager_backend.Models +{ + public enum ApiMethod + { + GET, + POST, + PUT, + DELETE + } +} diff --git a/Apimanager_backend/Models/Apipackage.cs b/Apimanager_backend/Models/Apipackage.cs new file mode 100644 index 0000000..fc031ba --- /dev/null +++ b/Apimanager_backend/Models/Apipackage.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Models +{ + public class Apipackage + { + /// + /// 主键,自增 + /// + [Key] + public int Id { get; set; } + + /// + /// 套餐名称 + /// + [MaxLength(20)] + public string Name { get; set; } // varchar(20) + + /// + /// 最大调用次数 + /// + public int CallLimit { get; set; } // int + + /// + /// 价格 + /// + public decimal Price { get; set; } // decimal(10,2) + + /// + /// 套餐过期时间,可用于控制套餐是否过期 + /// + public DateTime ExpiryDate { get; set; } // timestamp + + /// + /// 创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp + + //导航属性 + public ICollection Apis { get; set; } + public ICollection Packages { get; set; } + } +} diff --git a/Apimanager_backend/Models/OperationLog.cs b/Apimanager_backend/Models/OperationLog.cs new file mode 100644 index 0000000..1cebed2 --- /dev/null +++ b/Apimanager_backend/Models/OperationLog.cs @@ -0,0 +1,61 @@ +using Microsoft.AspNetCore.Antiforgery; +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Models +{ + public class OperationLog + { + /// + /// 主键,自增 + /// + public int Id { get; set; } + + /// + /// 操作人ID,操作者的用户ID(通常是管理员) + /// + public int UserId { get; set; } + + /// + /// 操作类型,描述操作的具体内容 + /// + [Required] + [MaxLength(20)] + public string Operation { get; set; } // varchar(20) + + /// + /// 目标类型,操作的对象类型 + /// + [Required] + [MaxLength(50)] + public string TargetType { get; set; } // varchar(50) + + /// + /// 目标对象ID,操作对象的具体ID + /// + public int TargetId { get; set; } + + /// + /// 操作时间,操作发生时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp + + /// + /// 操作来源IP + /// + [MaxLength(45)] + public string IpAddress { get; set; } // varchar(45) + + /// + /// 操作设备信息 + /// + public string UserAgent { get; set; } // varchar(255) + + /// + /// 操作描述,可选的详细说明,解释操作原因等 + /// + public string Description { get; set; } // varchar(255) + + //导航属性 + public User? User { get; set; } + } +} diff --git a/Apimanager_backend/Models/Order.cs b/Apimanager_backend/Models/Order.cs new file mode 100644 index 0000000..804b846 --- /dev/null +++ b/Apimanager_backend/Models/Order.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Models +{ + public class Order + { + /// + /// 主键,自增 + /// + public int Id { get; set; } + + /// + /// 外键,用户ID + /// + public int UserId { get; set; } + + /// + /// 订单号,唯一 + /// + [Required] + public string OrderNumber { get; set; } // varchar(50) + + /// + /// 第三方系统订单编号 + /// + public string? ThirdPartyOrderId { get; set; } // varchar(100) + + /// + /// 订单金额 + /// + public decimal Amount { get; set; } // decimal(10, 2) + + /// + /// 订单类型 + /// + public OrderType OrderType { get; set; } // enum('Recharge','Purchase','Refund') + + /// + /// 订单状态 + /// + public OrderStatus Status { get; set; } // enum('Pending','Completed','Cancelled','Failed') + + /// + /// 创建时间,订单创建时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // timestamp + + /// + /// 更新时间,订单状态更新时间 + /// + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; // timestamp + + /// + /// 订单描述,可选的详细信息 + /// + public string? Description { get; set; } // varchar(255) + + //导航属性 + public User? User { get; set; } + } +} diff --git a/Apimanager_backend/Models/OrderStatus.cs b/Apimanager_backend/Models/OrderStatus.cs new file mode 100644 index 0000000..9477196 --- /dev/null +++ b/Apimanager_backend/Models/OrderStatus.cs @@ -0,0 +1,10 @@ +namespace Apimanager_backend.Models +{ + public enum OrderStatus + { + Pending, + Completed, + Cancelled, + Failed + } +} diff --git a/Apimanager_backend/Models/OrderType.cs b/Apimanager_backend/Models/OrderType.cs new file mode 100644 index 0000000..d3f8f22 --- /dev/null +++ b/Apimanager_backend/Models/OrderType.cs @@ -0,0 +1,9 @@ +namespace Apimanager_backend.Models +{ + public enum OrderType + { + Recharge, + Purchase, + Refund + } +} diff --git a/Apimanager_backend/Models/User.cs b/Apimanager_backend/Models/User.cs new file mode 100644 index 0000000..07c11fc --- /dev/null +++ b/Apimanager_backend/Models/User.cs @@ -0,0 +1,60 @@ +using System.ComponentModel.DataAnnotations; + +namespace Apimanager_backend.Models +{ + public class User + { + /// + /// 用户ID,主键,自增 + /// + public int Id { get; set; } + + /// + /// 用户名,唯一 + /// + [Required] + public string Username { get; set; } // varchar(20) + + /// + /// 邮箱,唯一 + /// + public string Email { get; set; } // varchar(20) + + /// + /// 密码哈希 + /// + [Required] + [MaxLength(255)] + public string PassHash { get; set; } // varchar(255) + + /// + /// 用户角色 + /// + public UserRole Role { get; set; } // Enum('Admin','User') + + /// + /// 是否禁用 + /// + public bool IsBan { get; set; } // boolean + /// + /// 是否删除 + /// + public bool IsDelete { get; set; } // boolean + + /// + /// 余额 + /// + public decimal Balance { get; set; } // Decimal(10) + + /// + /// 创建时间,默认当前时间 + /// + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Timestamp + + //导航属性 + public ICollection Packages { get; set; } + public ICollection operationLogs { get; set; } + public ICollection CallLogs { get; set; } + public ICollection Orders { get; set; } + } +} diff --git a/Apimanager_backend/Models/UserPackage.cs b/Apimanager_backend/Models/UserPackage.cs new file mode 100644 index 0000000..bee6120 --- /dev/null +++ b/Apimanager_backend/Models/UserPackage.cs @@ -0,0 +1,33 @@ +namespace Apimanager_backend.Models +{ + public class UserPackage + {/// + /// 主键,自增 + /// + public int Id { get; set; } + + /// + /// 外键,用户ID + /// + public int UserId { get; set; } + + /// + /// 外键,套餐ID + /// + public int PackageId { get; set; } + + /// + /// 剩余调用次数 + /// + public int RemainingCalls { get; set; } + + /// + /// 购买时间 + /// + public DateTime PurchasedAt { get; set; } = DateTime.UtcNow; // timestamp + + //导航属性 + public User? User { get; set; } + public Apipackage? Package { get; set; } + } +} diff --git a/Apimanager_backend/Models/UserRole.cs b/Apimanager_backend/Models/UserRole.cs new file mode 100644 index 0000000..cbd29ff --- /dev/null +++ b/Apimanager_backend/Models/UserRole.cs @@ -0,0 +1,8 @@ +namespace Apimanager_backend.Models +{ + public enum UserRole + { + Admin = 0, + User = 1 + } +} diff --git a/Apimanager_backend/Program.cs b/Apimanager_backend/Program.cs index 48863a6..8661d8a 100644 --- a/Apimanager_backend/Program.cs +++ b/Apimanager_backend/Program.cs @@ -1,7 +1,21 @@ +using Apimanager_backend.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + var builder = WebApplication.CreateBuilder(args); // Add services to the container. +IConfiguration configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) + .Build(); + +string? constr = configuration.GetConnectionString("DefaultConnection"); +builder.Services.AddDbContext(option => +option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr)) +); + builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); diff --git a/Apimanager_backend/WeatherForecast.cs b/Apimanager_backend/WeatherForecast.cs deleted file mode 100644 index d21615d..0000000 --- a/Apimanager_backend/WeatherForecast.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Apimanager_backend -{ - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } - } -} diff --git a/Apimanager_backend/appsettings.json b/Apimanager_backend/appsettings.json index 10f68b8..8fbdf86 100644 --- a/Apimanager_backend/appsettings.json +++ b/Apimanager_backend/appsettings.json @@ -5,5 +5,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "ConnectionStrings": { + "DefaultConnection": "server=192.168.5.200;username=root;password=768788Dyw@;port=3306;database=api_billing_system;SslMode=Preferred;" + } } diff --git a/README.md b/README.md index 3f9186e..bdd64a4 100644 --- a/README.md +++ b/README.md @@ -1 +1,77 @@ -# Apimanager_backend \ No newline at end of file +## 项目背景 + +简单描述该API的背景、用途及目标用户。 + +## 功能概述 + +1. ##### 用户管理 + + - 登录、注册 + - 用户账号信息管理 + - 用户充值、消费记录查询 + +2. ##### API访问管理 + + - 用户密钥生成和管理 + - API管理 + - 调用次数和消费金额限制 + - 付费套餐管理 + +3. ##### 支付模块 + +4. ##### 订单模块 + + - 订单生成 + - 消费提醒(超额/余额不足) + +5. ##### 系统监控模块 + + - 调用记录 + - 异常告警 + +## 系统依赖 + +- **.NET 6.0 或更高版本** +- **Entity Framework Core** 用于数据库操作 +- **MySQL** 作为后端数据库 +- **Swagger** 用于API文档自动生成 +- **JWT** 实现用户认证和授权 + +## 项目结构 + +```perl +api-billing-system/ +│ +├── API/ # API控制器及路由 +├── Services/ # 业务逻辑层 +├── Models/ # 数据模型定义 +├── Data/ # 数据库上下文及迁移文件 +├── Config/ # 系统配置文件 +├── Tests/ # 单元测试及集成测试 +├── Tools/ # 工具类 +└── README.md # 项目文档(本文件) + +``` + + + +## 模块划分 + +1. **API 控制器** + +- 负责处理用户请求并返回结果。 +- 提供如用户注册、登录、查询调用次数等API端点。 + +1. ##### **业务逻辑层(Services)** + +- 负责具体业务逻辑,如套餐管理、消费计算等。 +- 实现支付网关集成。 + +1. **数据模型(Models)** + +- 定义数据库中的表结构,如用户表、订单表等。 + +1. **数据库(Data)** + +- 提供数据库连接及操作支持。 +- 包含数据库上下文类及数据库迁移文件。 \ No newline at end of file From 298b7900ec357a50ec6ca6df580ee13793733ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E8=93=9D?= <2919054393@qq.com> Date: Thu, 24 Oct 2024 16:45:54 +0000 Subject: [PATCH 22/23] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 19f3107..e83113f 100644 --- a/README.md +++ b/README.md @@ -49,9 +49,9 @@ api-billing-system/ ├── Config/ # 系统配置文件 ├── Tests/ # 单元测试及集成测试 ├── Tools/ # 工具类 -├── README.md # 项目文档(本文件) -├── Database.md # 数据库定义文档 -├── APIDefine.md # API定义文档 +├── README.md # 项目文档(本文件) +├── Database.md # 数据库定义文档 +├── APIDefine.md # API定义文档 └── ErrorCode.md # 错误码文档 ``` From 222eefc596c866178d9cde34a37569e1cea64fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9D=92=E8=93=9D?= <2919054393@qq.com> Date: Thu, 24 Oct 2024 17:02:09 +0000 Subject: [PATCH 23/23] =?UTF-8?q?Update=20README.md=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e83113f..44be4e1 100644 --- a/README.md +++ b/README.md @@ -84,4 +84,4 @@ api-billing-system/ - [x] 数据库文档 **Database.md** - [x] 错误码文档 **ErrorCode.md** - [x] API定义文档 **APIDefine.md** -- [ ] API文档 **[Apifox - 接口文档分享](https://apifox.com/apidoc/shared-8730c2eb-595b-4cf4-941d-d58914d4cd1e)** \ No newline at end of file +- [ ] API文档 **[API文档](https://apifox.com/apidoc/shared-8730c2eb-595b-4cf4-941d-d58914d4cd1e)** \ No newline at end of file