Compare commits

...

2 Commits

Author SHA1 Message Date
niannian zheng
455d47f887 refactor(API): 统一路由格式并添加接口文档注释
- 将控制器路由从`[controller]`格式改为明确路径
- 为所有接口添加XML文档注释,说明功能和使用方法
- 保持路由风格一致,部分接口添加版本前缀
2026-02-28 16:02:59 +08:00
niannian zheng
d39a6347cd feat: 实现微信登录和用户信息管理功能
- 添加微信登录功能,支持通过微信小程序登录
- 实现用户信息管理接口,包括获取用户信息和统计数据
- 新增投资组合列表和总资产统计接口
- 完善JWT令牌生成逻辑,支持可选用户名
- 添加数据库初始化配置和连接字符串
- 移除传统登录和注册功能,专注微信登录方案
2026-02-26 11:56:14 +08:00
13 changed files with 455 additions and 162 deletions

View File

@ -4,80 +4,38 @@ using AssetManager.Services.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using AssetManager.Data;
using System.Linq;
namespace AssetManager.API.Controllers;
[ApiController]
[Route("api/[controller]")]
[Route("api/auth")]
public class AuthController : ControllerBase
{
private readonly ILogger<AuthController> _logger;
private readonly WechatService _wechatService;
private readonly JwtService _jwtService;
private readonly DatabaseService _databaseService;
public AuthController(ILogger<AuthController> logger, WechatService wechatService, JwtService jwtService)
public AuthController(ILogger<AuthController> logger, WechatService wechatService, JwtService jwtService, DatabaseService databaseService)
{
_logger = logger;
_wechatService = wechatService;
_jwtService = jwtService;
_databaseService = databaseService;
}
[HttpPost("login")]
public ActionResult<ApiResponse<LoginResponse>> Login([FromBody] LoginRequest request)
{
try
{
_logger.LogInformation($"Login attempt for user: {request.Email}");
// 模拟登录验证
if (request.Email == "test@example.com" && request.Password == "password123")
{
// 生成真实的JWT令牌
var token = _jwtService.GenerateToken("1", "Test User", request.Email);
var response = new LoginResponse
{
Token = token,
ExpireAt = DateTime.Now.AddHours(24).ToString("yyyy-MM-dd HH:mm:ss"),
User = new UserBasicInfo
{
UserName = "Test User",
Email = request.Email
}
};
_logger.LogInformation($"Login successful for user: {request.Email}");
return Ok(new ApiResponse<LoginResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "Login successful"
});
}
_logger.LogWarning($"Login failed for user: {request.Email}");
return Unauthorized(new ApiResponse<LoginResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "Invalid email or password"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during login");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<LoginResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = null,
message = ex.Message
});
}
}
/// <summary>
/// 微信登录接口
/// </summary>
/// <param name="request">登录请求参数,包含微信授权码和用户信息</param>
/// <returns>登录结果包含JWT令牌、用户信息和过期时间</returns>
/// <remarks>
/// 此接口用于微信小程序或公众号的用户登录通过微信授权码换取OpenID
/// 然后查找或创建用户并生成JWT令牌返回给客户端。
/// </remarks>
[HttpPost("wechat-login")]
public async Task<ActionResult<ApiResponse<WechatLoginResponse>>> WechatLogin([FromBody] WechatLoginRequest request)
{
@ -99,8 +57,43 @@ public class AuthController : ControllerBase
});
}
// 从数据库中查找用户
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.OpenId == authResult.OpenId).First();
// 如果用户不存在,创建一个新用户
if (user == null)
{
user = new User
{
Id = Guid.NewGuid().ToString(),
OpenId = authResult.OpenId,
UserName = request.NickName ?? "Wechat User",
Email = $"{authResult.OpenId}@wechat.com",
MemberLevel = "普通会员",
RunningDays = 0,
SignalsCaptured = 0,
WinRate = 0,
TotalTrades = 0,
TotalReturn = 0,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
db.Insertable(user).ExecuteCommand();
}
else
{
// 更新用户信息
if (!string.IsNullOrEmpty(request.NickName) && user.UserName != request.NickName)
{
user.UserName = request.NickName;
user.UpdatedAt = DateTime.Now;
db.Updateable(user).ExecuteCommand();
}
}
// 生成真实的JWT令牌
var token = _jwtService.GenerateToken(authResult.OpenId, request.NickName ?? "Wechat User", $"{authResult.OpenId}@wechat.com");
var token = _jwtService.GenerateToken(user.Id, user.UserName, user.Email);
var response = new WechatLoginResponse
{
@ -108,13 +101,14 @@ public class AuthController : ControllerBase
ExpireAt = DateTime.Now.AddHours(24).ToString("yyyy-MM-dd HH:mm:ss"),
User = new UserBasicInfo
{
UserName = request.NickName ?? "Wechat User",
Email = $"{authResult.OpenId}@wechat.com"
UserName = user.UserName,
Email = user.Email
},
OpenId = authResult.OpenId
OpenId = authResult.OpenId,
UserId = user.Id
};
_logger.LogInformation($"Wechat login successful for user: {authResult.OpenId}");
_logger.LogInformation($"Wechat login successful for user: {user.Id}");
return Ok(new ApiResponse<WechatLoginResponse>
{
@ -135,40 +129,4 @@ public class AuthController : ControllerBase
});
}
}
[HttpPost("register")]
public ActionResult<ApiResponse<RegisterResponse>> Register([FromBody] RegisterRequest request)
{
try
{
_logger.LogInformation($"Registration attempt for user: {request.Email}");
// 模拟注册
var response = new RegisterResponse
{
Id = Guid.NewGuid().ToString(),
Status = "success"
};
_logger.LogInformation($"Registration successful for user: {request.Email}");
return Ok(new ApiResponse<RegisterResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "Registration successful"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error during registration");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<RegisterResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = null,
message = ex.Message
});
}
}
}

View File

@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging;
namespace AssetManager.API.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
[Route("api/v1/portfolio")]
[Authorize]
public class PortfolioController : ControllerBase
{
@ -21,6 +21,14 @@ public class PortfolioController : ControllerBase
_portfolioService = portfolioService;
}
/// <summary>
/// 创建新投资组合
/// </summary>
/// <param name="request">投资组合创建请求参数</param>
/// <returns>创建的投资组合详情</returns>
/// <remarks>
/// 此接口用于创建新的投资组合。
/// </remarks>
[HttpPost]
public ActionResult<ApiResponse<CreatePortfolioResponse>> CreatePortfolio([FromBody] CreatePortfolioRequest request)
{
@ -52,6 +60,90 @@ public class PortfolioController : ControllerBase
}
}
/// <summary>
/// 获取投资组合列表
/// </summary>
/// <returns>投资组合列表</returns>
/// <remarks>
/// 此接口用于获取投资组合列表。
/// </remarks>
[HttpGet]
public ActionResult<ApiResponse<GetPortfoliosResponse>> GetPortfolios()
{
try
{
_logger.LogInformation("Request to get portfolios");
var response = _portfolioService.GetPortfolios();
_logger.LogInformation("Portfolios retrieved successfully");
return Ok(new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving portfolios");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<GetPortfoliosResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = null,
message = ex.Message
});
}
}
/// <summary>
/// 获取总资产情况
/// </summary>
/// <returns>总资产情况</returns>
/// <remarks>
/// 此接口用于获取用户的总资产情况。
/// </remarks>
[HttpGet("assets")]
public ActionResult<ApiResponse<TotalAssetsResponse>> GetTotalAssets()
{
try
{
_logger.LogInformation("Request to get total assets");
var response = _portfolioService.GetTotalAssets();
_logger.LogInformation("Total assets retrieved successfully");
return Ok(new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.Success,
data = response,
message = "success"
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving total assets");
return StatusCode(AssetManager.Models.StatusCodes.InternalServerError, new ApiResponse<TotalAssetsResponse>
{
code = AssetManager.Models.StatusCodes.InternalServerError,
data = null,
message = ex.Message
});
}
}
/// <summary>
/// 获取单个投资组合详情
/// </summary>
/// <param name="id">投资组合ID</param>
/// <returns>投资组合详情</returns>
/// <remarks>
/// 此接口用于获取指定投资组合的详细信息。
/// </remarks>
[HttpGet("{id}")]
public ActionResult<ApiResponse<PortfolioDetailResponse>> GetPortfolioById(string id)
{
@ -83,6 +175,16 @@ public class PortfolioController : ControllerBase
}
}
/// <summary>
/// 获取交易记录
/// </summary>
/// <param name="portfolioId">投资组合ID</param>
/// <param name="limit">每页记录数</param>
/// <param name="offset">偏移量</param>
/// <returns>交易记录列表</returns>
/// <remarks>
/// 此接口用于获取指定投资组合的交易记录。
/// </remarks>
[HttpGet("transactions")]
public ActionResult<ApiResponse<GetTransactionsResponse>> GetTransactions([FromQuery] string portfolioId, [FromQuery] int limit = 10, [FromQuery] int offset = 0)
{
@ -114,6 +216,14 @@ public class PortfolioController : ControllerBase
}
}
/// <summary>
/// 创建新交易
/// </summary>
/// <param name="request">交易创建请求参数</param>
/// <returns>创建的交易详情</returns>
/// <remarks>
/// 此接口用于创建新的交易。
/// </remarks>
[HttpPost("transactions")]
public ActionResult<ApiResponse<CreateTransactionResponse>> CreateTransaction([FromBody] CreateTransactionRequest request)
{

View File

@ -10,7 +10,7 @@ using System.Security.Claims;
namespace AssetManager.API.Controllers;
[ApiController]
[Route("api/v1/[controller]s")]
[Route("api/v1/strategy")]
[Authorize]
public class StrategyController : ControllerBase
{
@ -28,7 +28,14 @@ public class StrategyController : ControllerBase
return User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new Exception("User not authenticated");
}
[HttpGet]
/// <summary>
/// 获取策略列表
/// </summary>
/// <returns>策略列表</returns>
/// <remarks>
/// 此接口用于获取当前登录用户的所有策略列表。
/// </remarks>
[HttpGet("strategies")]
public ActionResult<ApiResponse<List<Strategy>>> GetStrategies()
{
try
@ -60,6 +67,14 @@ public class StrategyController : ControllerBase
}
}
/// <summary>
/// 获取单个策略详情
/// </summary>
/// <param name="id">策略ID</param>
/// <returns>策略详情</returns>
/// <remarks>
/// 此接口用于获取指定策略的详细信息。
/// </remarks>
[HttpGet("{id}")]
public ActionResult<ApiResponse<Strategy>> GetStrategyById(string id)
{
@ -92,6 +107,14 @@ public class StrategyController : ControllerBase
}
}
/// <summary>
/// 创建新策略
/// </summary>
/// <param name="request">策略创建请求参数</param>
/// <returns>创建的策略详情</returns>
/// <remarks>
/// 此接口用于创建新的策略。
/// </remarks>
[HttpPost]
public ActionResult<ApiResponse<Strategy>> CreateStrategy([FromBody] CreateStrategyRequest request)
{
@ -124,6 +147,15 @@ public class StrategyController : ControllerBase
}
}
/// <summary>
/// 更新策略
/// </summary>
/// <param name="id">策略ID</param>
/// <param name="request">策略更新请求参数</param>
/// <returns>更新后的策略详情</returns>
/// <remarks>
/// 此接口用于更新指定策略的信息。
/// </remarks>
[HttpPut("{id}")]
public ActionResult<ApiResponse<Strategy>> UpdateStrategy(string id, [FromBody] UpdateStrategyRequest request)
{
@ -156,6 +188,14 @@ public class StrategyController : ControllerBase
}
}
/// <summary>
/// 删除策略
/// </summary>
/// <param name="id">策略ID</param>
/// <returns>删除结果</returns>
/// <remarks>
/// 此接口用于删除指定的策略。
/// </remarks>
[HttpDelete("{id}")]
public ActionResult<ApiResponse<object>> DeleteStrategy(string id)
{

View File

@ -3,21 +3,31 @@ using AssetManager.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AssetManager.Data;
namespace AssetManager.API.Controllers;
[ApiController]
[Route("api/user")]
[Route("api/v1/user")]
[Authorize]
public class UserController : ControllerBase
{
private readonly ILogger<UserController> _logger;
private readonly DatabaseService _databaseService;
public UserController(ILogger<UserController> logger)
public UserController(ILogger<UserController> logger, DatabaseService databaseService)
{
_logger = logger;
_databaseService = databaseService;
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <returns>用户信息</returns>
/// <remarks>
/// 此接口用于获取当前登录用户的详细信息。
/// </remarks>
[HttpGet("info")]
public ActionResult<ApiResponse<UserInfoResponse>> GetUserInfo()
{
@ -25,14 +35,40 @@ public class UserController : ControllerBase
{
_logger.LogInformation("Request to get user info");
// 模拟返回用户信息
// 从JWT中获取用户ID
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new ApiResponse<UserInfoResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "User not authenticated"
});
}
// 从数据库中获取用户信息
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
if (user == null)
{
return NotFound(new ApiResponse<UserInfoResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "User not found"
});
}
var response = new UserInfoResponse
{
UserName = "Test User",
MemberLevel = "高级会员",
RunningDays = 180,
Avatar = "https://example.com/avatar.jpg",
Email = "test@example.com"
UserName = user.UserName,
MemberLevel = user.MemberLevel,
RunningDays = user.RunningDays,
Avatar = user.Avatar,
Email = user.Email
};
_logger.LogInformation("User info retrieved successfully");
@ -57,6 +93,13 @@ public class UserController : ControllerBase
}
}
/// <summary>
/// 获取用户统计数据
/// </summary>
/// <returns>用户统计数据</returns>
/// <remarks>
/// 此接口用于获取当前登录用户的统计数据,如捕获的信号数、胜率等。
/// </remarks>
[HttpGet("stats")]
public ActionResult<ApiResponse<UserStatsResponse>> GetUserStats()
{
@ -64,13 +107,39 @@ public class UserController : ControllerBase
{
_logger.LogInformation("Request to get user stats");
// 模拟返回用户统计数据
// 从JWT中获取用户ID
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new ApiResponse<UserStatsResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "User not authenticated"
});
}
// 从数据库中获取用户信息
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
if (user == null)
{
return NotFound(new ApiResponse<UserStatsResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "User not found"
});
}
var response = new UserStatsResponse
{
SignalsCaptured = 125,
WinRate = 68.5,
TotalTrades = 320,
AverageProfit = 5.2
SignalsCaptured = user.SignalsCaptured,
WinRate = (double)user.WinRate,
TotalTrades = user.TotalTrades,
AverageProfit = user.TotalTrades > 0 ? (double)user.TotalReturn / user.TotalTrades : 0
};
_logger.LogInformation("User stats retrieved successfully");
@ -95,6 +164,14 @@ public class UserController : ControllerBase
}
}
/// <summary>
/// 更新用户信息
/// </summary>
/// <param name="request">用户信息更新请求参数</param>
/// <returns>更新结果</returns>
/// <remarks>
/// 此接口用于更新当前登录用户的信息。
/// </remarks>
[HttpPut("info")]
public ActionResult<ApiResponse<UpdateUserResponse>> UpdateUserInfo([FromBody] UpdateUserRequest request)
{
@ -102,11 +179,42 @@ public class UserController : ControllerBase
{
_logger.LogInformation($"Request to update user info: {request.UserName}");
// 模拟更新用户信息
// 从JWT中获取用户ID
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return Unauthorized(new ApiResponse<UpdateUserResponse>
{
code = AssetManager.Models.StatusCodes.Unauthorized,
data = null,
message = "User not authenticated"
});
}
// 从数据库中获取用户信息
var db = _databaseService.GetDb();
var user = db.Queryable<User>().Where(u => u.Id == userId).First();
if (user == null)
{
return NotFound(new ApiResponse<UpdateUserResponse>
{
code = AssetManager.Models.StatusCodes.NotFound,
data = null,
message = "User not found"
});
}
// 更新用户信息
user.UserName = request.UserName;
user.UpdatedAt = DateTime.Now;
db.Updateable(user).ExecuteCommand();
var response = new UpdateUserResponse
{
Status = "updated",
UserName = request.UserName
UserName = user.UserName
};
_logger.LogInformation("User info updated successfully");

View File

@ -75,6 +75,9 @@ builder.Logging.AddDebug();
var app = builder.Build();
// 初始化数据库
app.Services.InitializeDatabase();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();

View File

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "server=localhost;Database=assetmanager;Uid=root;Pwd=your_password;CharSet=utf8mb4;"
}
}

View File

@ -8,7 +8,7 @@ public class SqlSugarConfig
{
return new SqlSugarScope(new ConnectionConfig()
{
ConnectionString = "server=localhost;Database=assetmanager;Uid=root;Pwd=your_password;CharSet=utf8mb4;",
ConnectionString = "server=43.167.226.216;Database=assetmanager;Uid=AssetManager;Pwd=2XpcnYGTpB5BhJyG;CharSet=utf8mb4;",
DbType = DbType.MySql,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute,

View File

@ -4,14 +4,6 @@ public class LoginRequest
{
public string Email { get; set; }
public string Password { get; set; }
public string OpenId { get; set; }
public string Nickname { get; set; }
public string AvatarUrl { get; set; }
public int Gender { get; set; }
public string Country { get; set; }
public string Province { get; set; }
public string City { get; set; }
public string Language { get; set; }
}
public class LoginResponse
@ -19,7 +11,7 @@ public class LoginResponse
public string Token { get; set; }
public string ExpireAt { get; set; }
public UserBasicInfo User { get; set; }
public UserInfo UserInfo { get; set; }
public string UserId { get; set; }
}
public class UserBasicInfo
@ -28,44 +20,17 @@ public class UserBasicInfo
public string Email { get; set; }
}
public class UserInfo
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Avatar { get; set; }
public string MemberLevel { get; set; }
public int RunningDays { get; set; }
public int SignalsCaptured { get; set; }
public double WinRate { get; set; }
public int TotalTrades { get; set; }
public double TotalReturn { get; set; }
public string CreatedAt { get; set; }
}
public class WechatLoginResponse
{
public string Token { get; set; }
public string ExpireAt { get; set; }
public UserBasicInfo User { get; set; }
public string OpenId { get; set; }
}
public class RegisterRequest
{
public string Email { get; set; }
public string Password { get; set; }
public string UserName { get; set; }
}
public class RegisterResponse
{
public string Id { get; set; }
public string Status { get; set; }
public string UserId { get; set; }
}
public class WechatLoginRequest
{
public string Code { get; set; }
public string NickName { get; set; }
public string? NickName { get; set; }
}

View File

@ -109,3 +109,33 @@ public class CreateTransactionResponse
public string status { get; set; }
public string createdAt { get; set; }
}
public class PortfolioListItem
{
public string id { get; set; }
public string name { get; set; }
public string tags { get; set; }
public string status { get; set; }
public string statusType { get; set; }
public string iconChar { get; set; }
public string iconBgClass { get; set; }
public string iconTextClass { get; set; }
public double value { get; set; }
public string currency { get; set; }
public double returnRate { get; set; }
public string returnType { get; set; }
}
public class GetPortfoliosResponse
{
public List<PortfolioListItem> items { get; set; }
}
public class TotalAssetsResponse
{
public double totalValue { get; set; }
public string currency { get; set; }
public double todayProfit { get; set; }
public string todayProfitCurrency { get; set; }
public double totalReturnRate { get; set; }
}

View File

@ -8,4 +8,6 @@ public interface IPortfolioService
PortfolioDetailResponse GetPortfolioById(string id);
GetTransactionsResponse GetTransactions(string portfolioId, int limit, int offset);
CreateTransactionResponse CreateTransaction(CreateTransactionRequest request);
GetPortfoliosResponse GetPortfolios();
TotalAssetsResponse GetTotalAssets();
}

View File

@ -108,4 +108,73 @@ public class PortfolioService : IPortfolioService
createdAt = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
};
}
public GetPortfoliosResponse GetPortfolios()
{
// 模拟获取投资组合列表
return new GetPortfoliosResponse
{
items = new List<PortfolioListItem>
{
new PortfolioListItem
{
id = "hfea-001",
name = "美股全天候杠杆",
tags = "HFEA · 季度调仓",
status = "监控中",
statusType = "green",
iconChar = "H",
iconBgClass = "bg-green-100",
iconTextClass = "text-green-700",
value = 156240,
currency = "USD",
returnRate = 42.82,
returnType = "positive"
},
new PortfolioListItem
{
id = "ma-002",
name = "纳指双均线趋势",
tags = "趋势跟踪 · 日线",
status = "等待信号",
statusType = "gray",
iconChar = "T",
iconBgClass = "bg-blue-100",
iconTextClass = "text-blue-700",
value = 412500,
currency = "USD",
returnRate = -1.79,
returnType = "negative"
},
new PortfolioListItem
{
id = "hk-003",
name = "港股价值投资",
tags = "价值投资 · 蓝筹",
status = "持有中",
statusType = "green",
iconChar = "H",
iconBgClass = "bg-green-100",
iconTextClass = "text-green-700",
value = 896000,
currency = "HKD",
returnRate = 12.56,
returnType = "positive"
}
}
};
}
public TotalAssetsResponse GetTotalAssets()
{
// 模拟获取总资产情况
return new TotalAssetsResponse
{
totalValue = 1284592.4,
currency = "CNY",
todayProfit = 12482,
todayProfitCurrency = "CNY",
totalReturnRate = 24.82
};
}
}

View File

@ -21,14 +21,19 @@ public class JwtService
public string GenerateToken(string userId, string userName, string email)
{
var claims = new[]
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, userId),
new Claim(JwtRegisteredClaimNames.Name, userName),
new Claim(JwtRegisteredClaimNames.Email, email),
new Claim(JwtRegisteredClaimNames.Sub, userId ?? ""),
new Claim(JwtRegisteredClaimNames.Email, email ?? ""),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
// 如果userName不为null添加到claims中
if (!string.IsNullOrEmpty(userName))
{
claims.Add(new Claim(JwtRegisteredClaimNames.Name, userName));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

View File

@ -13,8 +13,8 @@ public class WechatService
public WechatService(HttpClient httpClient)
{
_httpClient = httpClient;
_appId = "your-wechat-app-id"; // 替换为实际的微信小程序AppId
_appSecret = "your-wechat-app-secret"; // 替换为实际的微信小程序AppSecret
_appId = "wx245f0f3ebcfcf5a7"; // 替换为实际的微信小程序AppId
_appSecret = "809c740129bc8b434177ce12ef292dd0"; // 替换为实际的微信小程序AppSecret
}
public async Task<WechatAuthResult> GetOpenIdAsync(string code)