Просмотр исходного кода

fix(backend): 金融安全修复 — payment绕过/验证码stub/积分兑换/教师端点/类型转换

Xiaogang Liao 2 месяцев назад
Родитель
Сommit
0d1dcdb66b

+ 44 - 9
cfc-backend/src/main/java/com/etotem/cfc/controller/family/ParentController.java

@@ -4,11 +4,16 @@ import com.etotem.cfc.common.Result;
 import com.etotem.cfc.dto.CreateRewardDTO;
 import com.etotem.cfc.dto.CreateRewardDTO;
 import com.etotem.cfc.dto.RewardDTO;
 import com.etotem.cfc.dto.RewardDTO;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.entity.User;
+import com.etotem.cfc.entity.Wish;
+import com.etotem.cfc.mapper.WishMapper;
+import com.etotem.cfc.service.PointsService;
 import com.etotem.cfc.service.RewardService;
 import com.etotem.cfc.service.RewardService;
 import com.etotem.cfc.service.UserService;
 import com.etotem.cfc.service.UserService;
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
+import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 
 
@@ -22,6 +27,12 @@ public class ParentController {
     @Resource
     @Resource
     private UserService userService;
     private UserService userService;
 
 
+    @Resource
+    private WishMapper wishMapper;
+
+    @Resource
+    private PointsService pointsService;
+
     /**
     /**
      * 家长心愿单 - 创建心愿(直接进入可用列表)
      * 家长心愿单 - 创建心愿(直接进入可用列表)
      */
      */
@@ -85,21 +96,45 @@ public class ParentController {
     @PostMapping("/wishlist/{id}/exchange")
     @PostMapping("/wishlist/{id}/exchange")
     public Result<Map<String, Object>> exchangeParentWishlist(@PathVariable Long id,
     public Result<Map<String, Object>> exchangeParentWishlist(@PathVariable Long id,
                                                                @RequestAttribute("userId") Long userId) {
                                                                @RequestAttribute("userId") Long userId) {
-        // 家长兑换自己的心愿,直接扣积分
         User user = userService.getUserInfo(userId);
         User user = userService.getUserInfo(userId);
         if (user == null) {
         if (user == null) {
             return Result.error("用户不存在");
             return Result.error("用户不存在");
         }
         }
-        
-        // 家长积分在user表
-        if (user.getTotalPoints() == null) {
-            user.setTotalPoints(0);
+
+        Wish wish = wishMapper.selectById(id);
+        if (wish == null) {
+            return Result.error("心愿不存在");
         }
         }
-        
-        // TODO: 实现家长兑换逻辑(暂时返回成功)
-        Map<String, Object> result = new java.util.HashMap<>();
+
+        String status = wish.getStatus();
+        if (!"active".equals(status) && !"approved".equals(status)) {
+            return Result.error("心愿当前状态不可兑换(" + status + ")");
+        }
+
+        if (wish.getPointsRequired() == null || wish.getPointsRequired() <= 0) {
+            return Result.error("心愿未设置积分");
+        }
+
+        int currentBalance = user.getTotalPoints() == null ? 0 : user.getTotalPoints();
+        if (currentBalance < wish.getPointsRequired()) {
+            return Result.error("积分不足,需要" + wish.getPointsRequired() + "积分,当前" + currentBalance + "积分");
+        }
+
+        boolean deducted = pointsService.deductUserPoints(userId, wish.getPointsRequired(), "心愿兑换:" + wish.getTitle());
+        if (!deducted) {
+            return Result.error("积分扣除失败");
+        }
+
+        wish.setStatus("exchanging");
+        wish.setPointsDeductedAt(new Date());
+        wish.setExchangeRequestedAt(new Date());
+        wish.setUpdatedAt(new Date());
+        wishMapper.updateById(wish);
+
+        Map<String, Object> result = new HashMap<>();
         result.put("success", true);
         result.put("success", true);
-        result.put("newBalance", user.getTotalPoints());
+        result.put("newBalance", currentBalance - wish.getPointsRequired());
+        result.put("wishId", wish.getId());
         return Result.success(result);
         return Result.success(result);
     }
     }
 }
 }

+ 27 - 71
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/TeacherController.java

@@ -34,119 +34,75 @@ public class TeacherController {
     return Result.success(info);
     return Result.success(info);
   }
   }
 
 
-  /**
-   * 创建教学任务
-   */
-    @Operation(summary = "创建教学任务")
+    @Deprecated
+    @Operation(summary = "创建教学任务", deprecated = true)
     @PostMapping("/tasks")
     @PostMapping("/tasks")
     public Result<Long> createTask(@RequestAttribute("userId") Long teacherId,
     public Result<Long> createTask(@RequestAttribute("userId") Long teacherId,
       @RequestBody CreateTeacherTaskDTO dto) {
       @RequestBody CreateTeacherTaskDTO dto) {
-    // TODO: Implement createTask in TeacherService
-    // Long taskId = teacherService.createTask(teacherId, dto);
-    // return Result.success(taskId);
-    return Result.error("功能开发中");
+    throw new UnsupportedOperationException("教师功能暂未开放:createTask");
   }
   }
 
 
-  /**
-   * 获取教师任务列表
-   */
-    @Operation(summary = "获取教师任务列表")
+    @Deprecated
+    @Operation(summary = "获取教师任务列表", deprecated = true)
     @PostMapping("/tasks/list")
     @PostMapping("/tasks/list")
     public Result<List<TaskDTO>> getTaskList(@RequestAttribute("userId") Long teacherId) {
     public Result<List<TaskDTO>> getTaskList(@RequestAttribute("userId") Long teacherId) {
-    // TODO: Implement getTaskList in TeacherService
-    // List<TaskDTO> tasks = teacherService.getTaskList(teacherId);
-    // return Result.success(tasks);
-    return Result.success(null);
+    throw new UnsupportedOperationException("教师功能暂未开放:getTaskList");
   }
   }
 
 
-  /**
-   * 创建班级
-   */
-    @Operation(summary = "创建班级")
+    @Deprecated
+    @Operation(summary = "创建班级", deprecated = true)
     @PostMapping("/classes")
     @PostMapping("/classes")
     public Result<Long> createClass(@RequestAttribute("userId") Long teacherId,
     public Result<Long> createClass(@RequestAttribute("userId") Long teacherId,
       @RequestBody CreateClassDTO dto) {
       @RequestBody CreateClassDTO dto) {
-    // TODO: Implement createClass in TeacherService
-    // Long classId = teacherService.createClass(teacherId, dto);
-    // return Result.success(classId);
-    return Result.error("功能开发中");
+    throw new UnsupportedOperationException("教师功能暂未开放:createClass");
   }
   }
 
 
-  /**
-   * 获取教师班级列表
-   */
-    @Operation(summary = "获取教师班级列表")
+    @Deprecated
+    @Operation(summary = "获取教师班级列表", deprecated = true)
     @PostMapping("/classes/list")
     @PostMapping("/classes/list")
     public Result<List<ClassInfoDTO>> getClassList(@RequestAttribute("userId") Long teacherId) {
     public Result<List<ClassInfoDTO>> getClassList(@RequestAttribute("userId") Long teacherId) {
-    // TODO: Implement getClassList in TeacherService
-    // List<ClassInfoDTO> classes = teacherService.getClassList(teacherId);
-    // return Result.success(classes);
-    return Result.success(null);
+    throw new UnsupportedOperationException("教师功能暂未开放:getClassList");
   }
   }
 
 
-  /**
-   * 获取班级学生列表
-   */
-    @Operation(summary = "获取班级学生列表")
+    @Deprecated
+    @Operation(summary = "获取班级学生列表", deprecated = true)
     @PostMapping("/classes/{classId}/students")
     @PostMapping("/classes/{classId}/students")
     public Result<List<StudentInfoDTO>> getClassStudents(@RequestAttribute("userId") Long teacherId,
     public Result<List<StudentInfoDTO>> getClassStudents(@RequestAttribute("userId") Long teacherId,
       @PathVariable Long classId) {
       @PathVariable Long classId) {
-    // TODO: Implement getClassStudents in TeacherService
-    // List<StudentInfoDTO> students = teacherService.getClassStudents(teacherId, classId);
-    // return Result.success(students);
-    return Result.success(null);
+    throw new UnsupportedOperationException("教师功能暂未开放:getClassStudents");
   }
   }
 
 
-  /**
-   * 添加学生到班级
-   */
-    @Operation(summary = "添加学生到班级")
+    @Deprecated
+    @Operation(summary = "添加学生到班级", deprecated = true)
     @PostMapping("/classes/{classId}/students/add")
     @PostMapping("/classes/{classId}/students/add")
     public Result<Boolean> addStudentToClass(@RequestAttribute("userId") Long teacherId,
     public Result<Boolean> addStudentToClass(@RequestAttribute("userId") Long teacherId,
       @PathVariable Long classId,
       @PathVariable Long classId,
       @RequestBody Map<String, Long> body) {
       @RequestBody Map<String, Long> body) {
-    // Long studentId = body.get("studentId");
-    // boolean success = teacherService.addStudentToClass(teacherId, classId, studentId);
-    // return Result.success(success);
-    return Result.error("功能开发中");
+    throw new UnsupportedOperationException("教师功能暂未开放:addStudentToClass");
   }
   }
 
 
-  /**
-   * 从班级移除学生
-   */
-    @Operation(summary = "从班级移除学生")
+    @Deprecated
+    @Operation(summary = "从班级移除学生", deprecated = true)
     @DeleteMapping("/classes/{classId}/students/{studentId}")
     @DeleteMapping("/classes/{classId}/students/{studentId}")
     public Result<Boolean> removeStudentFromClass(@RequestAttribute("userId") Long teacherId,
     public Result<Boolean> removeStudentFromClass(@RequestAttribute("userId") Long teacherId,
       @PathVariable Long classId,
       @PathVariable Long classId,
       @PathVariable Long studentId) {
       @PathVariable Long studentId) {
-    // boolean success = teacherService.removeStudentFromClass(teacherId, classId, studentId);
-    // return Result.success(success);
-    return Result.error("功能开发中");
+    throw new UnsupportedOperationException("教师功能暂未开放:removeStudentFromClass");
   }
   }
 
 
-  /**
-   * 获取学生学习进度
-   */
-    @Operation(summary = "获取学生学习进度")
+    @Deprecated
+    @Operation(summary = "获取学生学习进度", deprecated = true)
     @PostMapping("/students/{studentId}/progress")
     @PostMapping("/students/{studentId}/progress")
     public Result<StudentProgressDTO> getStudentProgress(@RequestAttribute("userId") Long teacherId,
     public Result<StudentProgressDTO> getStudentProgress(@RequestAttribute("userId") Long teacherId,
       @PathVariable Long studentId) {
       @PathVariable Long studentId) {
-    // TODO: Implement getStudentProgress in TeacherService
-    // StudentProgressDTO progress = teacherService.getStudentProgress(teacherId, studentId);
-    // return Result.success(progress);
-    return Result.success(null);
+    throw new UnsupportedOperationException("教师功能暂未开放:getStudentProgress");
   }
   }
 
 
-  /**
-   * 获取班级学习报告
-   */
-    @Operation(summary = "获取班级学习报告")
+    @Deprecated
+    @Operation(summary = "获取班级学习报告", deprecated = true)
     @PostMapping("/classes/{classId}/report")
     @PostMapping("/classes/{classId}/report")
     public Result<ClassReportDTO> getClassReport(@RequestAttribute("userId") Long teacherId,
     public Result<ClassReportDTO> getClassReport(@RequestAttribute("userId") Long teacherId,
       @PathVariable Long classId) {
       @PathVariable Long classId) {
-    // TODO: Implement getClassReport in TeacherService
-    // ClassReportDTO report = teacherService.getClassReport(teacherId, classId);
-    // return Result.success(report);
-    return Result.success(null);
+    throw new UnsupportedOperationException("教师功能暂未开放:getClassReport");
   }
   }
 }
 }

+ 19 - 6
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -40,6 +40,9 @@ public class CommissionService {
 
 
     @Resource
     @Resource
     private ProductMapper productMapper;
     private ProductMapper productMapper;
+    
+    @Resource
+    private FamilyEarningsService familyEarningsService;
 
 
     @Resource
     @Resource
     private CommissionRecordMapper commissionRecordMapper;
     private CommissionRecordMapper commissionRecordMapper;
@@ -278,14 +281,24 @@ public class CommissionService {
                 }
                 }
             }
             }
 
 
-            // 创建L1佣金记录(金额>0才创建)
-            if (l1Amount > 0) {
-                createCommissionRecord(orderId, orderType, l1ReferrerId, buyerId,
-                        commissionType, orderAmount, 0, l1Amount,
-                        1, "settled", new Date());
+        // 创建L1佣金记录(金额>0才创建)
+        if (l1Amount > 0) {
+            createCommissionRecord(orderId, orderType, l1ReferrerId, buyerId, 
+                commissionType, orderAmount, 0, l1Amount,
+                1, "settled", new Date());
+            
+            // 获取推荐人的家庭ID并更新家庭公共账户
+            Long familyId = l1Referrer.getFamilyId();
+            if (familyId != null) {
+                try {
+                    familyEarningsService.earn(familyId, (long) l1Amount, l1ReferrerId);
+                } catch (Exception e) {
+                    log.error("更新家庭公共账户失败: familyId={}, amount={}", familyId, l1Amount, e);
+                }
             }
             }
+        }
 
 
-            // 更新推荐人的累计佣金
+        // 更新推荐人的累计佣金
             l1Referrer.setTotalCommissionEarned(
             l1Referrer.setTotalCommissionEarned(
                     (l1Referrer.getTotalCommissionEarned() != null ? l1Referrer.getTotalCommissionEarned() : 0L)
                     (l1Referrer.getTotalCommissionEarned() != null ? l1Referrer.getTotalCommissionEarned() : 0L)
                             + l1Amount);
                             + l1Amount);

+ 5 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/PaymentService.java

@@ -159,9 +159,11 @@ public class PaymentService implements PaymentServiceInterface {
 
 
     @Override
     @Override
     public Boolean processPayment(String orderNo, String payType) {
     public Boolean processPayment(String orderNo, String payType) {
-        // TODO: In production, this would integrate with WeChat Pay / Alipay
-        // For test stub, always return true (payment always succeeds)
-        return true;
+        if (testMode) {
+            log.info("【测试模式】处理支付:orderNo={}, payType={}", orderNo, payType);
+            return true;
+        }
+        throw new UnsupportedOperationException("Payment not configured for production");
     }
     }
 
 
     public Map<String, Object> createWechatPrepay(String orderNo, String description, Integer totalFee, String openid) {
     public Map<String, Object> createWechatPrepay(String orderNo, String description, Integer totalFee, String openid) {

+ 6 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/VerificationCodeService.java

@@ -48,9 +48,12 @@ public class VerificationCodeService implements VerificationCodeServiceInterface
         verificationCode.setUsed(0);
         verificationCode.setUsed(0);
         verificationCodeMapper.insert(verificationCode);
         verificationCodeMapper.insert(verificationCode);
 
 
-        // TODO: 调用短信平台发送验证码
-        log.info("生成验证码: phone={}, code={}, type={}", phone, code, type);
-        
+        if (testMode) {
+            log.info("Test mode: code = {}", code);
+        } else {
+            throw new UnsupportedOperationException("SMS provider not configured - cannot send SMS to " + phone);
+        }
+
         return code;
         return code;
     }
     }