更新功能和文档: 增强支付系统、任务队列管理、用户作品管理等功能
This commit is contained in:
@@ -91,9 +91,7 @@ public class SecurityConfig {
|
||||
"http://localhost:3000",
|
||||
"http://127.0.0.1:3000",
|
||||
"http://localhost:5173",
|
||||
"http://127.0.0.1:5173",
|
||||
"https://*.ngrok.io",
|
||||
"https://*.ngrok-free.app"
|
||||
"http://127.0.0.1:5173"
|
||||
));
|
||||
configuration.setAllowedOriginPatterns(Arrays.asList(
|
||||
"https://*.ngrok.io",
|
||||
@@ -103,6 +101,7 @@ public class SecurityConfig {
|
||||
configuration.setAllowedHeaders(Arrays.asList("*"));
|
||||
configuration.setAllowCredentials(true);
|
||||
configuration.setExposedHeaders(Arrays.asList("Authorization"));
|
||||
configuration.setMaxAge(3600L); // 预检请求缓存时间
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.util.Locale;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.service.ApiResponseHandler;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import com.example.demo.service.ApiResponseHandler;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
|
||||
/**
|
||||
* API测试控制器
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.UserService;
|
||||
import com.example.demo.service.VerificationCodeService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
import jakarta.validation.Valid;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
@@ -114,11 +121,23 @@ public class AuthApiController {
|
||||
try {
|
||||
// 从邮箱生成用户名(去掉@符号及后面的部分)
|
||||
String username = email.split("@")[0];
|
||||
logger.info("邮箱验证码登录 - 原始邮箱: '{}', 生成的用户名: '{}'", email, username);
|
||||
|
||||
// 确保用户名长度不超过50个字符
|
||||
if (username.length() > 50) {
|
||||
username = username.substring(0, 50);
|
||||
logger.info("邮箱验证码登录 - 用户名过长,截断为: '{}'", username);
|
||||
}
|
||||
// 确保用户名唯一
|
||||
String originalUsername = username;
|
||||
int counter = 1;
|
||||
while (userService.findByUsername(username) != null) {
|
||||
username = originalUsername + counter;
|
||||
while (userService.findByUsernameOrNull(username) != null) {
|
||||
// 如果用户名过长,需要重新截断
|
||||
String newUsername = originalUsername + counter;
|
||||
if (newUsername.length() > 50) {
|
||||
newUsername = newUsername.substring(0, 50);
|
||||
}
|
||||
username = newUsername;
|
||||
counter++;
|
||||
}
|
||||
|
||||
@@ -145,6 +164,7 @@ public class AuthApiController {
|
||||
|
||||
// 生成JWT Token
|
||||
String token = jwtUtils.generateToken(user.getUsername(), user.getRole(), user.getId());
|
||||
logger.info("邮箱验证码登录 - 生成JWT token,用户名: '{}', 用户ID: {}", user.getUsername(), user.getId());
|
||||
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("success", true);
|
||||
|
||||
@@ -136,7 +136,7 @@ public class PaymentApiController {
|
||||
}
|
||||
|
||||
String orderId = (String) paymentData.get("orderId");
|
||||
String amountStr = (String) paymentData.get("amount");
|
||||
String amountStr = paymentData.get("amount") != null ? paymentData.get("amount").toString() : null;
|
||||
String method = (String) paymentData.get("method");
|
||||
|
||||
if (orderId == null || amountStr == null || method == null) {
|
||||
@@ -306,7 +306,7 @@ public class PaymentApiController {
|
||||
.body(createErrorResponse("请先登录后再创建支付记录"));
|
||||
}
|
||||
|
||||
String amountStr = (String) paymentData.get("amount");
|
||||
String amountStr = paymentData.get("amount") != null ? paymentData.get("amount").toString() : null;
|
||||
String method = (String) paymentData.get("method");
|
||||
|
||||
if (amountStr == null || method == null) {
|
||||
@@ -373,31 +373,42 @@ public class PaymentApiController {
|
||||
@RequestBody Map<String, Object> paymentData,
|
||||
Authentication authentication) {
|
||||
try {
|
||||
logger.info("收到创建支付宝支付请求,数据:{}", paymentData);
|
||||
|
||||
String username;
|
||||
if (authentication != null && authentication.isAuthenticated()) {
|
||||
username = authentication.getName();
|
||||
logger.info("用户已认证:{}", username);
|
||||
} else {
|
||||
logger.warn("用户未认证,拒绝支付请求");
|
||||
return ResponseEntity.badRequest()
|
||||
.body(createErrorResponse("请先登录后再创建支付"));
|
||||
}
|
||||
|
||||
Long paymentId = Long.valueOf(paymentData.get("paymentId").toString());
|
||||
logger.info("查找支付记录,ID:{}", paymentId);
|
||||
|
||||
Payment payment = paymentService.findById(paymentId)
|
||||
.orElseThrow(() -> new RuntimeException("支付记录不存在"));
|
||||
|
||||
// 检查权限
|
||||
if (!payment.getUser().getUsername().equals(username)) {
|
||||
logger.warn("用户{}无权限操作支付记录{}", username, paymentId);
|
||||
return ResponseEntity.status(403)
|
||||
.body(createErrorResponse("无权限操作此支付记录"));
|
||||
}
|
||||
|
||||
logger.info("开始调用支付宝服务创建支付,订单号:{},金额:{}", payment.getOrderId(), payment.getAmount());
|
||||
|
||||
// 调用支付宝接口创建支付
|
||||
String paymentUrl = alipayService.createPayment(payment);
|
||||
Map<String, Object> paymentResult = alipayService.createPayment(payment);
|
||||
|
||||
logger.info("支付宝二维码生成成功,订单号:{}", payment.getOrderId());
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", true);
|
||||
response.put("message", "支付宝支付创建成功");
|
||||
response.put("data", Map.of("paymentUrl", paymentUrl));
|
||||
response.put("message", "支付宝二维码生成成功");
|
||||
response.put("data", paymentResult);
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
@@ -449,47 +460,7 @@ public class PaymentApiController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝异步通知
|
||||
*/
|
||||
@PostMapping("/alipay/notify")
|
||||
public ResponseEntity<String> handleAlipayNotify(@RequestParam Map<String, String> params) {
|
||||
try {
|
||||
logger.info("收到支付宝异步通知:{}", params);
|
||||
|
||||
boolean success = alipayService.handleNotify(params);
|
||||
|
||||
if (success) {
|
||||
return ResponseEntity.ok("success");
|
||||
} else {
|
||||
return ResponseEntity.ok("fail");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理支付宝异步通知失败:", e);
|
||||
return ResponseEntity.ok("fail");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝同步返回
|
||||
*/
|
||||
@GetMapping("/alipay/return")
|
||||
public ResponseEntity<String> handleAlipayReturn(@RequestParam Map<String, String> params) {
|
||||
try {
|
||||
logger.info("收到支付宝同步返回:{}", params);
|
||||
|
||||
boolean success = alipayService.handleReturn(params);
|
||||
|
||||
if (success) {
|
||||
return ResponseEntity.ok("支付成功,正在跳转...");
|
||||
} else {
|
||||
return ResponseEntity.ok("支付验证失败");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("处理支付宝同步返回失败:", e);
|
||||
return ResponseEntity.ok("支付处理异常");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> createErrorResponse(String message) {
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.AlipayService;
|
||||
import com.example.demo.service.PayPalService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -16,10 +10,23 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.AlipayService;
|
||||
import com.example.demo.service.PayPalService;
|
||||
import com.example.demo.service.PaymentService;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/payment")
|
||||
@@ -73,8 +80,12 @@ public class PaymentController {
|
||||
// 根据支付方式创建支付
|
||||
String redirectUrl;
|
||||
if (payment.getPaymentMethod() == PaymentMethod.ALIPAY) {
|
||||
redirectUrl = alipayService.createPayment(payment);
|
||||
return "redirect:" + redirectUrl;
|
||||
Map<String, Object> paymentResult = alipayService.createPayment(payment);
|
||||
if (paymentResult.containsKey("qrCode")) {
|
||||
// 对于二维码支付,重定向到支付页面显示二维码
|
||||
return "redirect:/payment/qr?qrCode=" + paymentResult.get("qrCode");
|
||||
}
|
||||
return "redirect:/payment/error";
|
||||
} else if (payment.getPaymentMethod() == PaymentMethod.PAYPAL) {
|
||||
redirectUrl = payPalService.createPayment(payment);
|
||||
return "redirect:" + redirectUrl;
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.TaskQueue;
|
||||
import com.example.demo.service.TaskQueueService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.model.TaskQueue;
|
||||
import com.example.demo.service.TaskQueueService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
|
||||
/**
|
||||
* 任务队列API控制器
|
||||
*/
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
package com.example.demo.controller;
|
||||
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.service.TextToVideoService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.service.TextToVideoService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
|
||||
/**
|
||||
* 文生视频API控制器
|
||||
*/
|
||||
|
||||
@@ -195,3 +195,5 @@ public class PointsFreezeRecord {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -263,3 +263,5 @@ public class TaskQueue {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -255,3 +255,5 @@ public class TaskStatus {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package com.example.demo.model;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
@@ -31,9 +32,7 @@ public class User {
|
||||
@Column(nullable = false, unique = true, length = 100)
|
||||
private String email;
|
||||
|
||||
@NotBlank
|
||||
@Size(min = 6, max = 100)
|
||||
@Column(nullable = false)
|
||||
@Column(nullable = true)
|
||||
private String passwordHash;
|
||||
|
||||
@NotBlank
|
||||
|
||||
@@ -63,3 +63,5 @@ public interface TaskStatusRepository extends JpaRepository<TaskStatus, Long> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.example.demo.repository;
|
||||
|
||||
import com.example.demo.model.UserWork;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
@@ -9,9 +12,7 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import com.example.demo.model.UserWork;
|
||||
|
||||
/**
|
||||
* 用户作品仓库接口
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.example.demo.scheduler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -8,7 +10,6 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import com.example.demo.service.TaskCleanupService;
|
||||
import com.example.demo.service.TaskQueueService;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务队列定时调度器
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
package com.example.demo.security;
|
||||
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.UserService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.lang.NonNull;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.service.UserService;
|
||||
import com.example.demo.util.JwtUtils;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
@@ -41,7 +41,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response,
|
||||
@NonNull FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
logger.debug("JWT过滤器处理请求: {}", request.getRequestURI());
|
||||
logger.info("JWT过滤器处理请求: {}", request.getRequestURI());
|
||||
|
||||
try {
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
@@ -50,13 +50,14 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
String token = jwtUtils.extractTokenFromHeader(authHeader);
|
||||
logger.debug("提取的token: {}", token != null ? "存在" : "不存在");
|
||||
|
||||
if (token != null) {
|
||||
if (token != null && !token.equals("null") && !token.trim().isEmpty()) {
|
||||
String username = jwtUtils.getUsernameFromToken(token);
|
||||
logger.debug("从token获取用户名: {}", username);
|
||||
|
||||
if (username != null && jwtUtils.validateToken(token, username)) {
|
||||
logger.info("JWT认证 - 从token获取的用户名: '{}'", username);
|
||||
User user = userService.findByUsername(username);
|
||||
logger.debug("查找用户: {}", user != null ? user.getUsername() : "未找到");
|
||||
logger.info("JWT认证 - 数据库查找结果: {}", user != null ? "找到用户 '" + user.getUsername() + "'" : "未找到用户");
|
||||
|
||||
if (user != null) {
|
||||
// 创建用户权限列表
|
||||
@@ -64,7 +65,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
authorities.add(new SimpleGrantedAuthority(user.getRole()));
|
||||
|
||||
UsernamePasswordAuthenticationToken authToken =
|
||||
new UsernamePasswordAuthenticationToken(user, null, authorities);
|
||||
new UsernamePasswordAuthenticationToken(user.getUsername(), null, authorities);
|
||||
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||
logger.debug("JWT认证成功,用户: {}, 角色: {}", username, user.getRole());
|
||||
|
||||
@@ -34,3 +34,5 @@ public class PlainTextPasswordEncoder implements PasswordEncoder {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayTradePagePayModel;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.alipay.api.response.AlipayTradePagePayResponse;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.repository.PaymentRepository;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayTradePrecreateModel;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradePrecreateRequest;
|
||||
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.repository.PaymentRepository;
|
||||
|
||||
@Service
|
||||
public class AlipayService {
|
||||
@@ -56,60 +57,117 @@ public class AlipayService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建支付宝支付订单
|
||||
* 创建支付宝支付订单并生成二维码
|
||||
*/
|
||||
public String createPayment(Payment payment) {
|
||||
public Map<String, Object> createPayment(Payment payment) {
|
||||
try {
|
||||
logger.info("开始创建支付宝支付订单,订单号:{},金额:{}", payment.getOrderId(), payment.getAmount());
|
||||
|
||||
// 设置支付状态
|
||||
payment.setStatus(PaymentStatus.PENDING);
|
||||
payment.setPaymentMethod(PaymentMethod.ALIPAY);
|
||||
payment.setOrderId(generateOrderId());
|
||||
if (payment.getOrderId() == null || payment.getOrderId().isEmpty()) {
|
||||
payment.setOrderId(generateOrderId());
|
||||
}
|
||||
payment.setCallbackUrl(notifyUrl);
|
||||
payment.setReturnUrl(returnUrl);
|
||||
|
||||
// 保存支付记录
|
||||
paymentRepository.save(payment);
|
||||
logger.info("支付记录已保存,ID:{}", payment.getId());
|
||||
|
||||
// 创建支付宝客户端
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
gatewayUrl, appId, privateKey, "json", charset, publicKey, signType);
|
||||
// 调用真实的支付宝API
|
||||
return callRealAlipayAPI(payment);
|
||||
|
||||
// 设置请求参数
|
||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
||||
request.setReturnUrl(returnUrl);
|
||||
request.setNotifyUrl(notifyUrl);
|
||||
|
||||
// 设置业务参数
|
||||
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
||||
model.setOutTradeNo(payment.getOrderId());
|
||||
model.setTotalAmount(payment.getAmount().toString());
|
||||
model.setSubject(payment.getDescription() != null ? payment.getDescription() : "商品支付");
|
||||
model.setBody(payment.getDescription());
|
||||
model.setProductCode("FAST_INSTANT_TRADE_PAY");
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
// 调用API
|
||||
AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
logger.info("支付宝支付订单创建成功,订单号:{}", payment.getOrderId());
|
||||
return response.getBody();
|
||||
} else {
|
||||
logger.error("支付宝支付订单创建失败:{}", response.getMsg());
|
||||
payment.setStatus(PaymentStatus.FAILED);
|
||||
paymentRepository.save(payment);
|
||||
throw new RuntimeException("支付订单创建失败:" + response.getMsg());
|
||||
}
|
||||
|
||||
} catch (AlipayApiException e) {
|
||||
logger.error("支付宝API调用异常:", e);
|
||||
} catch (Exception e) {
|
||||
logger.error("创建支付订单时发生异常,订单号:{},错误:{}", payment.getOrderId(), e.getMessage(), e);
|
||||
payment.setStatus(PaymentStatus.FAILED);
|
||||
paymentRepository.save(payment);
|
||||
throw new RuntimeException("支付服务异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用真实的支付宝API
|
||||
*/
|
||||
private Map<String, Object> callRealAlipayAPI(Payment payment) throws Exception {
|
||||
// 创建支付宝客户端,增加超时时间
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
gatewayUrl, appId, privateKey, "json", charset, publicKey, signType);
|
||||
|
||||
// 设置连接和读取超时时间(30秒)
|
||||
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");
|
||||
System.setProperty("sun.net.client.defaultReadTimeout", "30000");
|
||||
|
||||
// 使用预创建API生成二维码
|
||||
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
|
||||
request.setNotifyUrl(notifyUrl);
|
||||
|
||||
// 设置业务参数
|
||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||
model.setOutTradeNo(payment.getOrderId());
|
||||
model.setTotalAmount(payment.getAmount().toString());
|
||||
model.setSubject(payment.getDescription() != null ? payment.getDescription() : "AIGC会员订阅");
|
||||
model.setBody(payment.getDescription() != null ? payment.getDescription() : "AIGC平台会员订阅服务");
|
||||
|
||||
request.setBizModel(model);
|
||||
|
||||
logger.info("调用支付宝预创建API,订单号:{},金额:{},商品名称:{}",
|
||||
model.getOutTradeNo(), model.getTotalAmount(), model.getSubject());
|
||||
|
||||
// 调用API,增加重试机制
|
||||
AlipayTradePrecreateResponse response = null;
|
||||
int maxRetries = 3;
|
||||
int retryCount = 0;
|
||||
|
||||
while (retryCount < maxRetries) {
|
||||
try {
|
||||
logger.info("正在调用支付宝API... (第{}次尝试)", retryCount + 1);
|
||||
response = alipayClient.execute(request);
|
||||
break; // 成功则跳出循环
|
||||
} catch (Exception e) {
|
||||
retryCount++;
|
||||
logger.warn("支付宝API调用失败,第{}次重试,错误:{}", retryCount, e.getMessage());
|
||||
if (retryCount >= maxRetries) {
|
||||
logger.error("支付宝API调用失败,已达到最大重试次数");
|
||||
throw new RuntimeException("支付宝API调用失败:" + e.getMessage());
|
||||
}
|
||||
try {
|
||||
Thread.sleep(2000); // 等待2秒后重试
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException("重试被中断", ie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("支付宝API响应状态:{}", response.isSuccess());
|
||||
logger.info("支付宝API响应码:{}", response.getCode());
|
||||
logger.info("支付宝API响应消息:{}", response.getMsg());
|
||||
logger.info("支付宝API响应子码:{}", response.getSubCode());
|
||||
logger.info("支付宝API响应子消息:{}", response.getSubMsg());
|
||||
|
||||
if (response.isSuccess()) {
|
||||
String qrCode = response.getQrCode();
|
||||
logger.info("支付宝二维码生成成功,订单号:{},二维码:{}", payment.getOrderId(), qrCode);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("qrCode", qrCode);
|
||||
result.put("outTradeNo", response.getOutTradeNo());
|
||||
result.put("success", true);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
logger.error("支付宝二维码生成失败,订单号:{},错误信息:{},子码:{},子消息:{}",
|
||||
payment.getOrderId(), response.getMsg(), response.getSubCode(), response.getSubMsg());
|
||||
payment.setStatus(PaymentStatus.FAILED);
|
||||
paymentRepository.save(payment);
|
||||
throw new RuntimeException("二维码生成失败:" + response.getMsg() + " - " + response.getSubMsg());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 处理支付宝异步通知
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.ImageToVideoTask;
|
||||
import com.example.demo.repository.ImageToVideoTaskRepository;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -14,15 +22,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import com.example.demo.model.ImageToVideoTask;
|
||||
import com.example.demo.repository.ImageToVideoTaskRepository;
|
||||
|
||||
/**
|
||||
* 图生视频服务类
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.*;
|
||||
import com.example.demo.repository.PaymentRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
@@ -15,6 +7,22 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.example.demo.model.Order;
|
||||
import com.example.demo.model.OrderItem;
|
||||
import com.example.demo.model.OrderStatus;
|
||||
import com.example.demo.model.OrderType;
|
||||
import com.example.demo.model.Payment;
|
||||
import com.example.demo.model.PaymentMethod;
|
||||
import com.example.demo.model.PaymentStatus;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.repository.PaymentRepository;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class PaymentService {
|
||||
@@ -291,11 +299,15 @@ public class PaymentService {
|
||||
*/
|
||||
public Payment createPayment(String username, String orderId, String amountStr, String method) {
|
||||
try {
|
||||
logger.info("创建支付 - 用户名: {}, 订单ID: {}, 金额: {}, 支付方式: {}", username, orderId, amountStr, method);
|
||||
logger.info("创建支付 - 用户名: '{}', 订单ID: {}, 金额: {}, 支付方式: {}", username, orderId, amountStr, method);
|
||||
|
||||
User user = userService.findByUsername(username);
|
||||
if (user == null) {
|
||||
logger.error("用户不存在: {}", username);
|
||||
User user;
|
||||
try {
|
||||
logger.info("PaymentService - 尝试查找用户: '{}'", username);
|
||||
user = userService.findByUsername(username);
|
||||
logger.info("PaymentService - 用户查找结果: {}", user != null ? "找到用户 '" + user.getUsername() + "'" : "未找到用户");
|
||||
} catch (Exception e) {
|
||||
logger.error("PaymentService - 用户查找异常: {}", username, e);
|
||||
// 如果是匿名用户,创建一个临时用户记录
|
||||
if (username.startsWith("anonymous_")) {
|
||||
user = createAnonymousUser(username);
|
||||
@@ -315,6 +327,7 @@ public class PaymentService {
|
||||
payment.setUser(user);
|
||||
payment.setOrderId(orderId);
|
||||
payment.setAmount(amount);
|
||||
payment.setCurrency("CNY"); // 设置默认货币为人民币
|
||||
payment.setPaymentMethod(paymentMethod);
|
||||
payment.setStatus(PaymentStatus.PENDING);
|
||||
payment.setCreatedAt(LocalDateTime.now());
|
||||
@@ -325,10 +338,12 @@ public class PaymentService {
|
||||
// 根据支付方式调用相应的支付服务
|
||||
if (paymentMethod == PaymentMethod.ALIPAY) {
|
||||
try {
|
||||
String paymentUrl = alipayService.createPayment(savedPayment);
|
||||
savedPayment.setPaymentUrl(paymentUrl);
|
||||
Map<String, Object> paymentResult = alipayService.createPayment(savedPayment);
|
||||
if (paymentResult.containsKey("qrCode")) {
|
||||
savedPayment.setPaymentUrl(paymentResult.get("qrCode").toString());
|
||||
}
|
||||
save(savedPayment);
|
||||
logger.info("支付宝支付URL生成成功: {}", paymentUrl);
|
||||
logger.info("支付宝二维码生成成功: {}", paymentResult.get("qrCode"));
|
||||
} catch (Exception e) {
|
||||
logger.error("调用支付宝支付接口失败:", e);
|
||||
// 不抛出异常,让前端处理
|
||||
|
||||
@@ -86,9 +86,9 @@ public class TaskStatusPollingService {
|
||||
|
||||
try {
|
||||
// 调用外部API查询状态
|
||||
HttpResponse<String> response = Unirest.post(apiBaseUrl + "/v1/videos")
|
||||
HttpResponse<String> response = Unirest.get(apiBaseUrl + "/v1/videos")
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.field("task_id", task.getExternalTaskId())
|
||||
.queryString("task_id", task.getExternalTaskId())
|
||||
.asString();
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
@@ -113,19 +113,41 @@ public class TaskStatusPollingService {
|
||||
*/
|
||||
private void updateTaskStatus(TaskStatus task, JsonNode responseJson) {
|
||||
try {
|
||||
// 检查base_resp状态
|
||||
JsonNode baseResp = responseJson.path("base_resp");
|
||||
if (!baseResp.isMissingNode() && baseResp.path("status_code").asInt() != 0) {
|
||||
String errorMsg = baseResp.path("status_msg").asText("Unknown error");
|
||||
task.markAsFailed(errorMsg);
|
||||
logger.warn("API返回错误: taskId={}, error={}", task.getTaskId(), errorMsg);
|
||||
taskStatusRepository.save(task);
|
||||
return;
|
||||
}
|
||||
|
||||
String status = responseJson.path("status").asText();
|
||||
int progress = responseJson.path("progress").asInt(0);
|
||||
String resultUrl = responseJson.path("result_url").asText();
|
||||
String resultUrl = null;
|
||||
String errorMessage = responseJson.path("error_message").asText();
|
||||
|
||||
task.incrementPollCount();
|
||||
task.setProgress(progress);
|
||||
|
||||
switch (status.toLowerCase()) {
|
||||
case "completed":
|
||||
case "success":
|
||||
task.markAsCompleted(resultUrl);
|
||||
logger.info("任务完成: taskId={}, resultUrl={}", task.getTaskId(), resultUrl);
|
||||
// 获取file_id并获取视频URL
|
||||
String fileId = responseJson.path("file_id").asText();
|
||||
if (!fileId.isEmpty()) {
|
||||
resultUrl = getVideoUrlFromFileId(fileId);
|
||||
if (resultUrl != null) {
|
||||
task.markAsCompleted(resultUrl);
|
||||
logger.info("任务完成: taskId={}, resultUrl={}", task.getTaskId(), resultUrl);
|
||||
} else {
|
||||
task.markAsFailed("无法获取视频URL");
|
||||
logger.warn("任务完成但无法获取视频URL: taskId={}, fileId={}", task.getTaskId(), fileId);
|
||||
}
|
||||
} else {
|
||||
task.markAsFailed("任务完成但未返回文件ID");
|
||||
logger.warn("任务完成但未返回文件ID: taskId={}", task.getTaskId());
|
||||
}
|
||||
break;
|
||||
|
||||
case "failed":
|
||||
@@ -136,6 +158,7 @@ public class TaskStatusPollingService {
|
||||
|
||||
case "processing":
|
||||
case "in_progress":
|
||||
case "pending":
|
||||
task.setStatus(TaskStatus.Status.PROCESSING);
|
||||
logger.info("任务处理中: taskId={}, progress={}%", task.getTaskId(), progress);
|
||||
break;
|
||||
@@ -152,6 +175,38 @@ public class TaskStatusPollingService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据file_id获取视频URL
|
||||
*/
|
||||
private String getVideoUrlFromFileId(String fileId) {
|
||||
try {
|
||||
HttpResponse<String> response = Unirest.get(apiBaseUrl + "/minimax/v1/files/retrieve")
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.queryString("file_id", fileId)
|
||||
.asString();
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
JsonNode responseJson = objectMapper.readTree(response.getBody());
|
||||
JsonNode fileNode = responseJson.path("file");
|
||||
if (!fileNode.isMissingNode()) {
|
||||
String downloadUrl = fileNode.path("download_url").asText();
|
||||
if (!downloadUrl.isEmpty()) {
|
||||
logger.info("成功获取视频URL: fileId={}, url={}", fileId, downloadUrl);
|
||||
return downloadUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn("获取视频URL失败: fileId={}, status={}, response={}",
|
||||
fileId, response.getStatus(), response.getBody());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("获取视频URL时发生错误: fileId={}, error={}", fileId, e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理超时任务
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.repository.TextToVideoTaskRepository;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -13,11 +17,8 @@ import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.repository.TextToVideoTaskRepository;
|
||||
|
||||
/**
|
||||
* 文生视频服务类
|
||||
|
||||
@@ -58,6 +58,11 @@ public class UserService {
|
||||
return userRepository.findByUsername(username).orElseThrow(() -> new IllegalArgumentException("用户不存在"));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public User findByUsernameOrNull(String username) {
|
||||
return userRepository.findByUsername(username).orElse(null);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public User create(String username, String email, String rawPassword) {
|
||||
return register(username, email, rawPassword);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package com.example.demo.service;
|
||||
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.model.UserWork;
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.model.ImageToVideoTask;
|
||||
import com.example.demo.repository.UserWorkRepository;
|
||||
import com.example.demo.repository.TextToVideoTaskRepository;
|
||||
import com.example.demo.repository.ImageToVideoTaskRepository;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -16,10 +14,13 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import com.example.demo.model.ImageToVideoTask;
|
||||
import com.example.demo.model.TextToVideoTask;
|
||||
import com.example.demo.model.User;
|
||||
import com.example.demo.model.UserWork;
|
||||
import com.example.demo.repository.ImageToVideoTaskRepository;
|
||||
import com.example.demo.repository.TextToVideoTaskRepository;
|
||||
import com.example.demo.repository.UserWorkRepository;
|
||||
|
||||
/**
|
||||
* 用户作品服务类
|
||||
@@ -314,13 +315,33 @@ public class UserWorkService {
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public Map<String, Object> getUserWorkStats(String username) {
|
||||
Object[] stats = userWorkRepository.getUserWorkStats(username);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("completedCount", stats[0] != null ? stats[0] : 0);
|
||||
result.put("processingCount", stats[1] != null ? stats[1] : 0);
|
||||
result.put("failedCount", stats[2] != null ? stats[2] : 0);
|
||||
result.put("totalPointsCost", stats[3] != null ? stats[3] : 0);
|
||||
|
||||
try {
|
||||
Object[] stats = userWorkRepository.getUserWorkStats(username);
|
||||
|
||||
// 安全地处理查询结果
|
||||
if (stats != null && stats.length >= 4) {
|
||||
result.put("completedCount", stats[0] != null ? stats[0] : 0);
|
||||
result.put("processingCount", stats[1] != null ? stats[1] : 0);
|
||||
result.put("failedCount", stats[2] != null ? stats[2] : 0);
|
||||
result.put("totalPointsCost", stats[3] != null ? stats[3] : 0);
|
||||
} else {
|
||||
// 如果查询结果格式不正确,使用默认值
|
||||
result.put("completedCount", 0);
|
||||
result.put("processingCount", 0);
|
||||
result.put("failedCount", 0);
|
||||
result.put("totalPointsCost", 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 如果查询失败,使用默认值
|
||||
logger.warn("获取用户作品统计失败,使用默认值: " + e.getMessage());
|
||||
result.put("completedCount", 0);
|
||||
result.put("processingCount", 0);
|
||||
result.put("failedCount", 0);
|
||||
result.put("totalPointsCost", 0);
|
||||
}
|
||||
|
||||
result.put("totalCount", userWorkRepository.countByUsername(username));
|
||||
result.put("publicCount", userWorkRepository.countPublicWorksByUsername(username));
|
||||
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package com.example.demo.util;
|
||||
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
|
||||
@Component
|
||||
public class JwtUtils {
|
||||
|
||||
@@ -120,17 +124,7 @@ public class JwtUtils {
|
||||
* 获取签名密钥
|
||||
*/
|
||||
private SecretKey getSigningKey() {
|
||||
// 确保密钥长度至少为256位(32字节)
|
||||
byte[] keyBytes = secret.getBytes();
|
||||
if (keyBytes.length < 32) {
|
||||
// 如果密钥太短,使用SHA-256哈希扩展
|
||||
try {
|
||||
java.security.MessageDigest sha = java.security.MessageDigest.getInstance("SHA-256");
|
||||
keyBytes = sha.digest(keyBytes);
|
||||
} catch (java.security.NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException("SHA-256 algorithm not available", e);
|
||||
}
|
||||
}
|
||||
return Keys.hmacShaKeyFor(keyBytes);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user