Selaa lähdekoodia

代码优化重构

skyline 1 kuukausi sitten
vanhempi
säilyke
ee88a2b632
48 muutettua tiedostoa jossa 1673 lisäystä ja 1586 poistoa
  1. 4 4
      haha-admin/src/main/java/com/haha/admin/controller/AdminController.java
  2. 4 4
      haha-admin/src/main/java/com/haha/admin/controller/AdminLoginController.java
  3. 13 24
      haha-admin/src/main/java/com/haha/admin/controller/AnnouncementController.java
  4. 7 51
      haha-admin/src/main/java/com/haha/admin/controller/CheckinController.java
  5. 3 3
      haha-admin/src/main/java/com/haha/admin/controller/DashboardController.java
  6. 4 5
      haha-admin/src/main/java/com/haha/admin/controller/DataPermissionController.java
  7. 3 3
      haha-admin/src/main/java/com/haha/admin/controller/DataSyncController.java
  8. 32 25
      haha-admin/src/main/java/com/haha/admin/controller/DictController.java
  9. 5 7
      haha-admin/src/main/java/com/haha/admin/controller/InventoryController.java
  10. 12 18
      haha-admin/src/main/java/com/haha/admin/controller/NewProductApplyController.java
  11. 4 4
      haha-admin/src/main/java/com/haha/admin/controller/RoleController.java
  12. 4 3
      haha-admin/src/main/java/com/haha/admin/controller/ShopController.java
  13. 3 3
      haha-admin/src/main/java/com/haha/admin/controller/UserController.java
  14. 5 33
      haha-admin/src/main/java/com/haha/admin/dto/PageQueryDTO.java
  15. 12 30
      haha-admin/src/main/java/com/haha/admin/task/StatisticsTask.java
  16. 40 0
      haha-common/src/main/java/com/haha/common/constant/AnnouncementConstants.java
  17. 38 0
      haha-common/src/main/java/com/haha/common/constant/CallbackConstants.java
  18. 37 0
      haha-common/src/main/java/com/haha/common/constant/CheckinConstants.java
  19. 12 0
      haha-common/src/main/java/com/haha/common/constant/OrderConstants.java
  20. 57 23
      haha-common/src/main/java/com/haha/common/constant/RedisConstants.java
  21. 67 4
      haha-common/src/main/java/com/haha/common/constant/ResponseEnum.java
  22. 43 0
      haha-common/src/main/java/com/haha/common/dto/BasePageQueryDTO.java
  23. 48 0
      haha-common/src/main/java/com/haha/common/enums/ApplyStatus.java
  24. 71 0
      haha-common/src/main/java/com/haha/common/utils/PageUtil.java
  25. 105 0
      haha-common/src/main/java/com/haha/common/utils/RequestParseUtil.java
  26. 0 51
      haha-common/src/main/java/com/haha/common/vo/RedisConstants.java
  27. 5 33
      haha-entity/src/main/java/com/haha/entity/dto/PageQueryDTO.java
  28. 3 3
      haha-miniapp/src/main/java/com/haha/miniapp/controller/AppAnnouncementController.java
  29. 13 52
      haha-miniapp/src/main/java/com/haha/miniapp/controller/CallbackController.java
  30. 8 9
      haha-miniapp/src/main/java/com/haha/miniapp/controller/DeviceController.java
  31. 3 2
      haha-miniapp/src/main/java/com/haha/miniapp/controller/InviteController.java
  32. 7 6
      haha-miniapp/src/main/java/com/haha/miniapp/controller/LoginController.java
  33. 47 275
      haha-miniapp/src/main/java/com/haha/miniapp/controller/OrderController.java
  34. 47 299
      haha-miniapp/src/main/java/com/haha/miniapp/controller/PayScoreController.java
  35. 30 123
      haha-miniapp/src/main/java/com/haha/miniapp/controller/PaymentController.java
  36. 28 108
      haha-miniapp/src/main/java/com/haha/miniapp/controller/StatusQueryController.java
  37. 9 0
      haha-service/src/main/java/com/haha/service/CheckinRecordService.java
  38. 16 17
      haha-service/src/main/java/com/haha/service/DictService.java
  39. 29 0
      haha-service/src/main/java/com/haha/service/OrderService.java
  40. 43 0
      haha-service/src/main/java/com/haha/service/StatusQueryService.java
  41. 57 9
      haha-service/src/main/java/com/haha/service/impl/CheckinRecordServiceImpl.java
  42. 202 340
      haha-service/src/main/java/com/haha/service/impl/DictServiceImpl.java
  43. 6 8
      haha-service/src/main/java/com/haha/service/impl/HahaCallbackServiceImpl.java
  44. 5 4
      haha-service/src/main/java/com/haha/service/impl/NewProductApplyServiceImpl.java
  45. 129 3
      haha-service/src/main/java/com/haha/service/impl/OrderServiceImpl.java
  46. 108 0
      haha-service/src/main/java/com/haha/service/impl/StatusQueryServiceImpl.java
  47. 80 0
      haha-service/src/main/java/com/haha/service/payment/payscore/PayScoreService.java
  48. 165 0
      haha-service/src/main/java/com/haha/service/payment/payscore/impl/PayScoreServiceImpl.java

+ 4 - 4
haha-admin/src/main/java/com/haha/admin/controller/AdminController.java

@@ -7,8 +7,8 @@ import com.haha.common.annotation.Log;
 import com.haha.common.enums.OperationType;
 import com.haha.common.vo.Result;
 import com.haha.entity.Admin;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
@@ -17,12 +17,12 @@ import java.util.Map;
  * 管理员管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/user")
 public class AdminController {
-    
-    @Autowired
-    private AdminService adminService;
+
+    private final AdminService adminService;
     
     /**
      * 分页查询管理员列表

+ 4 - 4
haha-admin/src/main/java/com/haha/admin/controller/AdminLoginController.java

@@ -8,8 +8,8 @@ import com.haha.common.annotation.Log;
 import com.haha.common.enums.OperationType;
 import com.haha.common.vo.LoginVO;
 import com.haha.common.vo.Result;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
@@ -18,12 +18,12 @@ import java.util.Map;
  * 管理员登录控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/login")
 public class AdminLoginController {
-    
-    @Autowired
-    private AdminLoginService adminLoginService;
+
+    private final AdminLoginService adminLoginService;
     
     /**
      * 管理员登录

+ 13 - 24
haha-admin/src/main/java/com/haha/admin/controller/AnnouncementController.java

@@ -4,12 +4,15 @@ import cn.dev33.satoken.stp.StpUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.haha.admin.annotation.RequirePermission;
 import com.haha.common.annotation.Log;
+import com.haha.common.constant.AnnouncementConstants;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.enums.OperationType;
+import com.haha.common.utils.PageUtil;
 import com.haha.common.vo.Result;
 import com.haha.entity.Announcement;
 import com.haha.service.AnnouncementService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.time.LocalDateTime;
@@ -20,12 +23,12 @@ import java.util.Map;
  * 系统公告管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/announcement")
 public class AnnouncementController {
 
-    @Autowired
-    private AnnouncementService announcementService;
+    private final AnnouncementService announcementService;
 
     /**
      * 分页查询公告列表
@@ -33,27 +36,13 @@ public class AnnouncementController {
     @RequirePermission("announcement:read")
     @GetMapping("/list")
     public Result<Map<String, Object>> list(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
+        int[] pageParams = PageUtil.parsePageParams(params);
+        int page = pageParams[0];
+        int pageSize = pageParams[1];
 
         IPage<Announcement> pageResult = announcementService.getPage(page, pageSize, params);
 
-        Map<String, Object> result = new HashMap<>();
-        result.put("list", pageResult.getRecords());
-        result.put("total", pageResult.getTotal());
-        result.put("page", page);
-        result.put("pageSize", pageSize);
-
-        return Result.success(result);
+        return Result.success(PageUtil.buildPageResult(pageResult, page, pageSize));
     }
 
     /**
@@ -77,8 +66,8 @@ public class AnnouncementController {
     @PostMapping
     public Result<Announcement> create(@RequestBody Announcement announcement) {
         try {
-            announcement.setStatus(0); // 默认草稿状态
-            announcement.setIsTop(0);  // 默认不置顶
+            announcement.setStatus(AnnouncementConstants.STATUS_DRAFT); // 默认草稿状态
+            announcement.setIsTop(AnnouncementConstants.NOT_TOP);  // 默认不置顶
             announcement.setReadCount(0);
             announcement.setCreateTime(LocalDateTime.now());
             announcement.setUpdateTime(LocalDateTime.now());
@@ -193,7 +182,7 @@ public class AnnouncementController {
         try {
             boolean success = announcementService.setTop(id, isTop);
             if (success) {
-                return Result.success(isTop == 1 ? "置顶成功" : "取消置顶成功");
+                return Result.success(isTop == AnnouncementConstants.IS_TOP ? "置顶成功" : "取消置顶成功");
             } else {
                 return Result.error("操作失败,公告不存在");
             }

+ 7 - 51
haha-admin/src/main/java/com/haha/admin/controller/CheckinController.java

@@ -3,6 +3,7 @@ package com.haha.admin.controller;
 import cn.dev33.satoken.stp.StpUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.haha.admin.annotation.RequirePermission;
+import com.haha.common.constant.CheckinConstants;
 import com.haha.entity.dto.CheckinQueryDTO;
 import com.haha.entity.dto.CheckinSubmitDTO;
 import com.haha.common.annotation.Log;
@@ -11,8 +12,8 @@ import com.haha.common.vo.Result;
 import com.haha.entity.CheckinRecord;
 import com.haha.service.CheckinRecordService;
 import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -23,12 +24,12 @@ import java.util.Map;
  * 签到管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/checkin")
 public class CheckinController {
 
-    @Autowired
-    private CheckinRecordService checkinRecordService;
+    private final CheckinRecordService checkinRecordService;
 
     /**
      * 提交签到
@@ -54,7 +55,7 @@ public class CheckinController {
             Map<String, Object> result = new HashMap<>();
             result.put("id", record.getId());
             result.put("type", record.getCheckinType());
-            result.put("typeName", "inventory_tally".equals(record.getCheckinType()) ? "理货盘点签到" : "补货确认签到");
+            result.put("typeName", CheckinConstants.getTypeName(record.getCheckinType()));
             result.put("status", record.getStatus());
             result.put("checkinTime", record.getCheckinTime());
 
@@ -151,53 +152,8 @@ public class CheckinController {
                 return Result.error("没有需要同步的记录");
             }
 
-            List<CheckinRecord> records = new java.util.ArrayList<>();
-            for (Map<String, Object> data : recordsData) {
-                CheckinRecord record = new CheckinRecord();
-                record.setCheckinType((String) data.get("type"));
-                record.setUserId(StpUtil.getLoginIdAsLong());
-                record.setUserName((String) data.get("userName"));
-                record.setUserNo((String) data.get("userNo"));
-                record.setShopId(data.get("shopId") != null ? Long.valueOf(data.get("shopId").toString()) : null);
-                record.setDeviceId((String) data.get("deviceId"));
-
-                @SuppressWarnings("unchecked")
-                Map<String, Object> location = (Map<String, Object>) data.get("location");
-                if (location != null) {
-                    record.setLatitude(new java.math.BigDecimal(location.get("latitude").toString()));
-                    record.setLongitude(new java.math.BigDecimal(location.get("longitude").toString()));
-                    record.setAddress((String) location.get("address"));
-                    record.setAccuracy(location.get("accuracy") != null ? Integer.valueOf(location.get("accuracy").toString()) : null);
-                }
-
-                @SuppressWarnings("unchecked")
-                List<Map<String, Object>> photos = (List<Map<String, Object>>) data.get("photos");
-                if (photos != null) {
-                    record.setPhotos(com.alibaba.fastjson2.JSON.toJSONString(photos));
-                }
-
-                record.setRemark((String) data.get("remark"));
-                record.setOfflineId((String) data.get("offlineId"));
-                record.setStatus("pending");
-
-                String createdAt = (String) data.get("createdAt");
-                if (createdAt != null) {
-                    try {
-                        record.setCheckinTime(java.time.LocalDateTime.parse(createdAt.replace(" ", "T")));
-                        record.setCreateTime(record.getCheckinTime());
-                    } catch (Exception e) {
-                        record.setCheckinTime(java.time.LocalDateTime.now());
-                        record.setCreateTime(java.time.LocalDateTime.now());
-                    }
-                } else {
-                    record.setCheckinTime(java.time.LocalDateTime.now());
-                    record.setCreateTime(java.time.LocalDateTime.now());
-                }
-
-                records.add(record);
-            }
-
-            Map<String, Object> result = checkinRecordService.syncOfflineCheckins(records);
+            Long userId = StpUtil.getLoginIdAsLong();
+            Map<String, Object> result = checkinRecordService.syncOfflineCheckinsFromData(recordsData, userId);
             return Result.success("同步完成", result);
         } catch (Exception e) {
             log.error("同步离线签到失败", e);

+ 3 - 3
haha-admin/src/main/java/com/haha/admin/controller/DashboardController.java

@@ -3,8 +3,8 @@ package com.haha.admin.controller;
 import com.haha.admin.annotation.RequirePermission;
 import com.haha.common.vo.Result;
 import com.haha.service.DashboardService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
@@ -13,12 +13,12 @@ import java.util.Map;
  * 首页数据看板控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/dashboard")
 public class DashboardController {
 
-    @Autowired
-    private DashboardService dashboardService;
+    private final DashboardService dashboardService;
 
     /**
      * 获取概览数据(今日实时数据)

+ 4 - 5
haha-admin/src/main/java/com/haha/admin/controller/DataPermissionController.java

@@ -7,8 +7,8 @@ import com.haha.common.vo.Result;
 import com.haha.entity.DataPermission;
 import com.haha.service.DataPermissionService;
 import com.haha.service.RoleService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -18,15 +18,14 @@ import java.util.Map;
  * 数据权限管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/permission")
 public class DataPermissionController {
 
-    @Autowired
-    private DataPermissionService dataPermissionService;
+    private final DataPermissionService dataPermissionService;
 
-    @Autowired
-    private RoleService roleService;
+    private final RoleService roleService;
 
     /**
      * 获取所有权限列表

+ 3 - 3
haha-admin/src/main/java/com/haha/admin/controller/DataSyncController.java

@@ -7,8 +7,8 @@ import com.haha.common.enums.OperationType;
 import com.haha.common.vo.Result;
 import com.haha.entity.SyncRecord;
 import com.haha.service.DataSyncService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
@@ -17,12 +17,12 @@ import java.util.Map;
  * 数据同步控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/sync")
 public class DataSyncController {
 
-    @Autowired
-    private DataSyncService dataSyncService;
+    private final DataSyncService dataSyncService;
 
     /**
      * 同步设备数据

+ 32 - 25
haha-admin/src/main/java/com/haha/admin/controller/DictController.java

@@ -7,8 +7,8 @@ import com.haha.common.vo.Result;
 import com.haha.entity.DictData;
 import com.haha.entity.DictType;
 import com.haha.service.DictService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -18,124 +18,129 @@ import java.util.Map;
  * 字典管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/dict")
 public class DictController {
 
-    @Autowired
-    private DictService dictService;
+    private final DictService dictService;
 
     @RequirePermission("dict:read")
     @PostMapping("/type/list")
     public Result<Map<String, Object>> getDictTypeList(@RequestBody Map<String, Object> params) {
-        return dictService.getDictTypeList(params);
+        return Result.success("查询成功", dictService.getDictTypeList(params));
     }
 
     @RequirePermission("dict:read")
     @GetMapping("/type/{id}")
     public Result<DictType> getDictTypeById(@PathVariable Long id) {
-        return dictService.getDictTypeById(id);
+        return Result.success("查询成功", dictService.getDictTypeById(id));
     }
 
     @RequirePermission("dict:read")
     @GetMapping("/type/code/{dictCode}")
     public Result<DictType> getDictTypeByCode(@PathVariable String dictCode) {
-        return dictService.getDictTypeByCode(dictCode);
+        return Result.success("查询成功", dictService.getDictTypeByCode(dictCode));
     }
 
     @RequirePermission("dict:create")
     @Log(module = "字典管理", operation = OperationType.INSERT, summary = "新增字典类型")
     @PostMapping("/type/add")
     public Result<Void> addDictType(@RequestBody DictType dictType) {
-        return dictService.addDictType(dictType);
+        dictService.addDictType(dictType);
+        return Result.success("添加成功");
     }
 
     @RequirePermission("dict:update")
     @Log(module = "字典管理", operation = OperationType.UPDATE, summary = "修改字典类型")
     @PostMapping("/type/update")
     public Result<Void> updateDictType(@RequestBody DictType dictType) {
-        return dictService.updateDictType(dictType);
+        dictService.updateDictType(dictType);
+        return Result.success("修改成功");
     }
 
     @RequirePermission("dict:delete")
     @Log(module = "字典管理", operation = OperationType.DELETE, summary = "删除字典类型")
     @DeleteMapping("/type/{id}")
     public Result<Void> deleteDictType(@PathVariable Long id) {
-        return dictService.deleteDictType(id);
+        dictService.deleteDictType(id);
+        return Result.success("删除成功");
     }
 
     @RequirePermission("dict:delete")
     @Log(module = "字典管理", operation = OperationType.DELETE, summary = "批量删除字典类型")
     @PostMapping("/type/batch-delete")
     public Result<Void> batchDeleteDictType(@RequestBody List<Long> ids) {
-        return dictService.batchDeleteDictType(ids);
+        dictService.batchDeleteDictType(ids);
+        return Result.success("批量删除成功");
     }
 
     @GetMapping("/data/list/{dictCode}")
     public Result<List<DictData>> getDictDataList(@PathVariable String dictCode) {
-        return dictService.getDictDataList(dictCode);
+        return Result.success("查询成功", dictService.getDictDataList(dictCode));
     }
 
     @RequirePermission("dict:read")
     @PostMapping("/data/page")
     public Result<Map<String, Object>> getDictDataPage(@RequestBody Map<String, Object> params) {
-        return dictService.getDictDataPage(params);
+        return Result.success("查询成功", dictService.getDictDataPage(params));
     }
 
     @RequirePermission("dict:read")
     @GetMapping("/data/{id}")
     public Result<DictData> getDictDataById(@PathVariable Long id) {
-        return dictService.getDictDataById(id);
+        return Result.success("查询成功", dictService.getDictDataById(id));
     }
 
     @RequirePermission("dict:create")
     @Log(module = "字典管理", operation = OperationType.INSERT, summary = "新增字典数据")
     @PostMapping("/data/add")
     public Result<Void> addDictData(@RequestBody DictData dictData) {
-        return dictService.addDictData(dictData);
+        dictService.addDictData(dictData);
+        return Result.success("添加成功");
     }
 
     @RequirePermission("dict:update")
     @Log(module = "字典管理", operation = OperationType.UPDATE, summary = "修改字典数据")
     @PostMapping("/data/update")
     public Result<Void> updateDictData(@RequestBody DictData dictData) {
-        return dictService.updateDictData(dictData);
+        dictService.updateDictData(dictData);
+        return Result.success("修改成功");
     }
 
     @RequirePermission("dict:delete")
     @Log(module = "字典管理", operation = OperationType.DELETE, summary = "删除字典数据")
     @DeleteMapping("/data/{id}")
     public Result<Void> deleteDictData(@PathVariable Long id) {
-        return dictService.deleteDictData(id);
+        dictService.deleteDictData(id);
+        return Result.success("删除成功");
     }
 
     @RequirePermission("dict:delete")
     @Log(module = "字典管理", operation = OperationType.DELETE, summary = "批量删除字典数据")
     @PostMapping("/data/batch-delete")
     public Result<Void> batchDeleteDictData(@RequestBody List<Long> ids) {
-        return dictService.batchDeleteDictData(ids);
+        dictService.batchDeleteDictData(ids);
+        return Result.success("批量删除成功");
     }
 
     @GetMapping("/all")
     public Result<Map<String, List<DictData>>> getAllDictData() {
-        Map<String, List<DictData>> data = dictService.getAllDictData();
-        return Result.success("查询成功", data);
+        return Result.success("查询成功", dictService.getAllDictData());
     }
 
     @GetMapping("/label")
     public Result<String> getDictLabel(
             @RequestParam String dictCode,
             @RequestParam String itemValue) {
-        String label = dictService.getDictLabel(dictCode, itemValue);
-        return Result.success("查询成功", label);
+        return Result.success("查询成功", dictService.getDictLabel(dictCode, itemValue));
     }
 
     @GetMapping("/value")
     public Result<String> getDictValue(
             @RequestParam String dictCode,
             @RequestParam String itemLabel) {
-        String value = dictService.getDictValue(dictCode, itemLabel);
-        return Result.success("查询成功", value);
+        return Result.success("查询成功", dictService.getDictValue(dictCode, itemLabel));
     }
 
     @PostMapping("/refresh-cache")
@@ -148,13 +153,15 @@ public class DictController {
     @Log(module = "字典管理", operation = OperationType.EXPORT, summary = "导出字典数据")
     @GetMapping("/export/{dictCode}")
     public Result<Void> exportDictData(@PathVariable String dictCode) {
-        return dictService.exportDictData(dictCode);
+        dictService.exportDictData(dictCode);
+        return Result.success("导出成功");
     }
 
     @RequirePermission("dict:import")
     @Log(module = "字典管理", operation = OperationType.IMPORT, summary = "导入字典数据")
     @PostMapping("/import")
     public Result<Void> importDictData(@RequestBody List<DictData> dataList) {
-        return dictService.importDictData(dataList);
+        dictService.importDictData(dataList);
+        return Result.success("导入成功");
     }
 }

+ 5 - 7
haha-admin/src/main/java/com/haha/admin/controller/InventoryController.java

@@ -12,8 +12,8 @@ import com.haha.entity.StockRecord;
 import com.haha.service.DeviceInventoryService;
 import com.haha.service.InventoryLogService;
 import com.haha.service.StockRecordService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -24,18 +24,16 @@ import java.util.Map;
  * 库存管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/inventory")
 public class InventoryController {
 
-    @Autowired
-    private DeviceInventoryService deviceInventoryService;
+    private final DeviceInventoryService deviceInventoryService;
 
-    @Autowired
-    private InventoryLogService inventoryLogService;
+    private final InventoryLogService inventoryLogService;
 
-    @Autowired
-    private StockRecordService stockRecordService;
+    private final StockRecordService stockRecordService;
 
     // ==================== 库存查询 ====================
 

+ 12 - 18
haha-admin/src/main/java/com/haha/admin/controller/NewProductApplyController.java

@@ -4,12 +4,15 @@ import cn.dev33.satoken.stp.StpUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.haha.admin.annotation.RequirePermission;
 import com.haha.common.annotation.Log;
+import com.haha.common.enums.ApplyStatus;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.enums.OperationType;
+import com.haha.common.utils.PageUtil;
 import com.haha.common.vo.Result;
 import com.haha.entity.NewProductApply;
 import com.haha.service.NewProductApplyService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -19,12 +22,12 @@ import java.util.Map;
  * 新品申请控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/new-product-apply")
 public class NewProductApplyController {
 
-    @Autowired
-    private NewProductApplyService newProductApplyService;
+    private final NewProductApplyService newProductApplyService;
 
     /**
      * 分页查询新品申请列表
@@ -34,18 +37,9 @@ public class NewProductApplyController {
     @RequirePermission("product-apply:read")
     @GetMapping("/list")
     public Result<Map<String, Object>> list(@RequestParam Map<String, Object> params) {
-        int page = 1;
-        int pageSize = 10;
-        
-        Object pageObj = params.get("page");
-        if (pageObj != null && !pageObj.toString().isEmpty()) {
-            page = Integer.parseInt(pageObj.toString());
-        }
-        
-        Object pageSizeObj = params.get("pageSize");
-        if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
-            pageSize = Integer.parseInt(pageSizeObj.toString());
-        }
+        int[] pageParams = PageUtil.parsePageParams(params);
+        int page = pageParams[0];
+        int pageSize = pageParams[1];
         
         IPage<NewProductApply> pageResult = newProductApplyService.getPage(page, pageSize, params);
         
@@ -117,7 +111,7 @@ public class NewProductApplyController {
             Long userId = StpUtil.getLoginIdAsLong();
             String userName = StpUtil.getLoginIdAsString();
             
-            apply.setStatus(0); // 待提交状态
+            apply.setStatus(ApplyStatus.DRAFT.getCode()); // 待提交状态
             apply.setApplicantId(userId);
             apply.setApplicantName(userName);
             
@@ -146,7 +140,7 @@ public class NewProductApplyController {
             }
             
             // 只有待提交状态才能修改
-            if (existing.getStatus() != 0) {
+            if (existing.getStatus() != ApplyStatus.DRAFT.getCode()) {
                 return Result.error("只有待提交状态的申请才能修改");
             }
             
@@ -175,7 +169,7 @@ public class NewProductApplyController {
             }
             
             // 只有待提交状态才能删除
-            if (existing.getStatus() != 0) {
+            if (existing.getStatus() != ApplyStatus.DRAFT.getCode()) {
                 return Result.error("只有待提交状态的申请才能删除");
             }
             

+ 4 - 4
haha-admin/src/main/java/com/haha/admin/controller/RoleController.java

@@ -7,8 +7,8 @@ import com.haha.common.annotation.Log;
 import com.haha.common.enums.OperationType;
 import com.haha.common.vo.Result;
 import com.haha.entity.Role;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -18,12 +18,12 @@ import java.util.Map;
  * 角色管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/role")
 public class RoleController {
-    
-    @Autowired
-    private RoleService roleService;
+
+    private final RoleService roleService;
     
     /**
      * 分页查询角色列表

+ 4 - 3
haha-admin/src/main/java/com/haha/admin/controller/ShopController.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.haha.admin.annotation.RequirePermission;
 import com.haha.admin.dto.ShopQueryDTO;
 import com.haha.common.annotation.Log;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.enums.OperationType;
 import com.haha.common.vo.PageResult;
 import com.haha.common.vo.Result;
@@ -67,7 +68,7 @@ public class ShopController {
     public Result<Shop> getById(@PathVariable Long id) {
         Shop shop = shopService.getShopWithStats(id);
         if (shop == null) {
-            return Result.error(404, "门店不存在");
+            return ResponseEnum.SHOP_NOT_FOUND.toResult();
         }
         return Result.success("查询成功", shop);
     }
@@ -133,11 +134,11 @@ public class ShopController {
         // 检查门店是否有设备
         Shop shop = shopService.getShopWithStats(id);
         if (shop == null) {
-            return Result.error(404, "门店不存在");
+            return ResponseEnum.SHOP_NOT_FOUND.toResult();
         }
         
         if (shop.getDeviceCount() != null && shop.getDeviceCount() > 0) {
-            return Result.error(400, "该门店下存在设备,无法删除");
+            return ResponseEnum.STATUS_NOT_ALLOWED.toResult("该门店下存在设备,无法删除");
         }
         
         shopService.removeById(id);

+ 3 - 3
haha-admin/src/main/java/com/haha/admin/controller/UserController.java

@@ -7,8 +7,8 @@ import com.haha.common.enums.OperationType;
 import com.haha.common.vo.Result;
 import com.haha.entity.User;
 import com.haha.service.UserService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -18,12 +18,12 @@ import java.util.Map;
  * 客户管理控制器
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/users")
 public class UserController {
 
-    @Autowired
-    private UserService userService;
+    private final UserService userService;
 
     /**
      * 分页查询客户列表

+ 5 - 33
haha-admin/src/main/java/com/haha/admin/dto/PageQueryDTO.java

@@ -1,42 +1,14 @@
 package com.haha.admin.dto;
 
+import com.haha.common.dto.BasePageQueryDTO;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 /**
  * 分页查询基础DTO
+ * 继承自通用BasePageQueryDTO,保持向后兼容
  */
 @Data
-public class PageQueryDTO {
-    
-    /**
-     * 当前页码,默认第1页
-     */
-    private Integer page = 1;
-    
-    /**
-     * 每页条数,默认10条
-     */
-    private Integer pageSize = 10;
-    
-    /**
-     * 获取偏移量
-     */
-    public int getOffset() {
-        return (page - 1) * pageSize;
-    }
-    
-    /**
-     * 校验并修正分页参数
-     */
-    public void validate() {
-        if (page == null || page < 1) {
-            page = 1;
-        }
-        if (pageSize == null || pageSize < 1) {
-            pageSize = 10;
-        }
-        if (pageSize > 100) {
-            pageSize = 100;  // 限制最大每页条数
-        }
-    }
+@EqualsAndHashCode(callSuper = true)
+public class PageQueryDTO extends BasePageQueryDTO {
 }

+ 12 - 30
haha-admin/src/main/java/com/haha/admin/task/StatisticsTask.java

@@ -5,8 +5,8 @@ import com.haha.entity.*;
 import com.haha.mapper.*;
 import com.haha.common.constant.OrderConstants;
 import com.haha.common.utils.TraceIdUtils;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
@@ -19,38 +19,20 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 @Slf4j
+@RequiredArgsConstructor
 @Component
 public class StatisticsTask {
 
-    @Autowired
-    private OrderMapper orderMapper;
-
-    @Autowired
-    private OrderItemMapper orderItemMapper;
-
-    @Autowired
-    private DeviceMapper deviceMapper;
-
-    @Autowired
-    private ShopMapper shopMapper;
-
-    @Autowired
-    private UserMapper userMapper;
-
-    @Autowired
-    private StatCategoryDailyMapper statCategoryDailyMapper;
-
-    @Autowired
-    private StatProductDailyMapper statProductDailyMapper;
-
-    @Autowired
-    private StatDeviceDailyMapper statDeviceDailyMapper;
-
-    @Autowired
-    private StatShopDailyMapper statShopDailyMapper;
-
-    @Autowired
-    private StatUserRepurchaseMapper statUserRepurchaseMapper;
+    private final OrderMapper orderMapper;
+    private final OrderItemMapper orderItemMapper;
+    private final DeviceMapper deviceMapper;
+    private final ShopMapper shopMapper;
+    private final UserMapper userMapper;
+    private final StatCategoryDailyMapper statCategoryDailyMapper;
+    private final StatProductDailyMapper statProductDailyMapper;
+    private final StatDeviceDailyMapper statDeviceDailyMapper;
+    private final StatShopDailyMapper statShopDailyMapper;
+    private final StatUserRepurchaseMapper statUserRepurchaseMapper;
 
     @Scheduled(cron = "0 5 0 * * ?")
     public void aggregateDailyStatistics() {

+ 40 - 0
haha-common/src/main/java/com/haha/common/constant/AnnouncementConstants.java

@@ -0,0 +1,40 @@
+package com.haha.common.constant;
+
+/**
+ * 公告相关常量
+ */
+public final class AnnouncementConstants {
+
+    private AnnouncementConstants() {}
+
+    // ==================== 公告状态 ====================
+
+    /** 草稿状态 */
+    public static final int STATUS_DRAFT = 0;
+
+    /** 已发布状态 */
+    public static final int STATUS_PUBLISHED = 1;
+
+    /** 已下线状态 */
+    public static final int STATUS_OFFLINE = 2;
+
+    // ==================== 置顶状态 ====================
+
+    /** 不置顶 */
+    public static final int NOT_TOP = 0;
+
+    /** 置顶 */
+    public static final int IS_TOP = 1;
+
+    /**
+     * 获取公告状态描述
+     */
+    public static String getStatusDesc(int status) {
+        return switch (status) {
+            case STATUS_DRAFT -> "草稿";
+            case STATUS_PUBLISHED -> "已发布";
+            case STATUS_OFFLINE -> "已下线";
+            default -> "未知";
+        };
+    }
+}

+ 38 - 0
haha-common/src/main/java/com/haha/common/constant/CallbackConstants.java

@@ -0,0 +1,38 @@
+package com.haha.common.constant;
+
+/**
+ * 微信支付回调响应常量
+ */
+public final class CallbackConstants {
+
+    private CallbackConstants() {}
+
+    // ==================== 微信支付分回调响应 ====================
+
+    /** 微信支付分成功响应 */
+    public static final String WECHAT_PAYSCORE_SUCCESS = "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
+
+    /** 微信支付分失败响应 */
+    public static final String WECHAT_PAYSCORE_FAIL = "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+
+    // ==================== 微信支付V3回调响应 ====================
+
+    /** 微信V3成功响应 */
+    public static final String WECHAT_V3_SUCCESS = "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
+
+    /** 微信V3失败响应 */
+    public static final String WECHAT_V3_FAIL = "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+
+    // ==================== 哈哈平台回调响应 ====================
+
+    /** 哈哈平台成功响应 */
+    public static final String HAHA_SUCCESS = "success";
+
+    // ==================== 支付宝回调响应 ====================
+
+    /** 支付宝成功响应 */
+    public static final String ALIPAY_SUCCESS = "success";
+
+    /** 通用失败响应 */
+    public static final String FAIL = "fail";
+}

+ 37 - 0
haha-common/src/main/java/com/haha/common/constant/CheckinConstants.java

@@ -0,0 +1,37 @@
+package com.haha.common.constant;
+
+/**
+ * 签到相关常量
+ */
+public final class CheckinConstants {
+
+    private CheckinConstants() {}
+
+    // ==================== 签到类型 ====================
+
+    /** 理货盘点签到 */
+    public static final String TYPE_INVENTORY_TALLY = "inventory_tally";
+
+    /** 补货确认签到 */
+    public static final String TYPE_REPLENISHMENT = "replenishment";
+
+    // ==================== 签到状态 ====================
+
+    /** 待同步 */
+    public static final String STATUS_PENDING = "pending";
+
+    /** 已同步 */
+    public static final String STATUS_SYNCED = "synced";
+
+    /**
+     * 获取签到类型描述
+     */
+    public static String getTypeName(String checkinType) {
+        if (TYPE_INVENTORY_TALLY.equals(checkinType)) {
+            return "理货盘点签到";
+        } else if (TYPE_REPLENISHMENT.equals(checkinType)) {
+            return "补货确认签到";
+        }
+        return "未知签到类型";
+    }
+}

+ 12 - 0
haha-common/src/main/java/com/haha/common/constant/OrderConstants.java

@@ -46,6 +46,18 @@ public final class OrderConstants {
      */
     public static final String PAY_STATUS_REFUND = "REFUND";
     
+    // ==================== 订单类型 ====================
+    
+    /**
+     * 订单类型:正常购物
+     */
+    public static final String ORDER_TYPE_NORMAL = "NORMAL";
+    
+    /**
+     * 订单类型:异物放入(不在用户端展示)
+     */
+    public static final String ORDER_TYPE_IN = "IN";
+    
     // ==================== 状态描述 ====================
     
     /**

+ 57 - 23
haha-common/src/main/java/com/haha/common/constant/RedisConstants.java

@@ -2,40 +2,74 @@ package com.haha.common.constant;
 
 /**
  * Redis键常量类
+ * 统一管理所有Redis缓存键名
  */
-public class RedisConstants {
+public final class RedisConstants {
     
-    /**
-     * Sa-Token 用户Token键前缀
-     */
+    private RedisConstants() {}
+    
+    // ==================== Sa-Token 相关 ====================
+    
+    /** Sa-Token 用户Token键前缀 */
     public static final String SA_TOKEN_USER_TOKEN_KEY = "sa:token:%s";
     
-    /**
-     * Sa-Token 用户登录ID键前缀
-     */
+    /** Sa-Token 用户登录ID键前缀 */
     public static final String SA_TOKEN_USER_LOGIN_ID_KEY = "sa:loginid:%s";
     
-    /**
-     * 设备状态键前缀
-     */
+    /** Sa-Token 用户会话键前缀 */
+    public static final String SA_TOKEN_USER_KEY_PREFIX = "satoken:user:";
+    
+    // ==================== 设备状态相关 ====================
+    
+    /** 设备状态键前缀(带格式化占位符) */
     public static final String DEVICE_STATUS_KEY = "device:status:%s";
     
-    /**
-     * 用户信息键前缀
-     */
-    public static final String USER_INFO_KEY = "user:info:%s";
+    /** 设备状态键前缀(haha平台回调格式) */
+    public static final String HAHA_DEVICE_STATUS_KEY = "haha:device:status:";
     
-    /**
-     * 设备告警冷却键前缀,参数:设备ID、告警类型
-     */
+    /** 设备信息缓存键 */
+    public static final String DEVICE_INFO_KEY = "device:info:%s";
+    
+    /** 设备信息缓存键前缀 */
+    public static final String DEVICE_INFO_KEY_PREFIX = "device:info:";
+    
+    // ==================== 设备告警相关 ====================
+    
+    /** 设备告警冷却键前缀,参数:设备ID、告警类型 */
     public static final String DEVICE_ALERT_COOLDOWN_KEY = "device:alert:cooldown:%s:%s";
     
-    /**
-     * 设备最后在线时间键前缀,参数:设备ID
-     */
+    /** 设备最后在线时间键前缀,参数:设备ID */
     public static final String DEVICE_LAST_ONLINE_KEY = "device:last:online:%s";
     
-    private RedisConstants() {
-        // 私有构造函数,防止实例化
-    }
+    // ==================== 识别结果相关 ====================
+    
+    /** AI识别结果键前缀 */
+    public static final String HAHA_RECOGNIZE_RESULT_KEY = "haha:recognize:result:";
+    
+    // ==================== 订单信息相关 ====================
+    
+    /** 订单信息键前缀(haha平台回调格式) */
+    public static final String HAHA_ORDER_INFO_KEY = "haha:order:info:";
+    
+    /** 临时订单键前缀 */
+    public static final String ORDER_TEMP_KEY = "order:temp:%s";
+    public static final String ORDER_TEMP_KEY_PREFIX = "order:temp:";
+    
+    // ==================== 用户信息相关 ====================
+    
+    /** 用户信息缓存键 */
+    public static final String USER_INFO_KEY = "user:info:%s";
+    public static final String USER_INFO_KEY_PREFIX = "user:info:";
+    
+    // ==================== 商品信息相关 ====================
+    
+    /** 商品信息缓存键 */
+    public static final String PRODUCT_INFO_KEY = "product:info:%s";
+    public static final String PRODUCT_INFO_KEY_PREFIX = "product:info:";
+    
+    // ==================== 分布式锁相关 ====================
+    
+    /** 开门分布式锁键前缀 */
+    public static final String LOCK_DOOR_KEY = "lock:door:%s";
+    public static final String LOCK_DOOR_KEY_PREFIX = "lock:door:";
 }

+ 67 - 4
haha-common/src/main/java/com/haha/common/constant/ResponseEnum.java

@@ -1,6 +1,7 @@
 package com.haha.common.constant;
 
 import com.haha.common.exception.BusinessExceptionAssert;
+import com.haha.common.vo.Result;
 import lombok.Getter;
 
 /**
@@ -23,14 +24,62 @@ public enum ResponseEnum implements BusinessExceptionAssert {
     DB_ERROR(999, "数据异常"),
     PARAMS_ERROR(1000, "参数异常"),
 
+    // ==================== 通用业务错误码 ====================
+
+    /** 资源不存在 */
+    NOT_FOUND(404, "资源不存在"),
+    /** 参数不能为空 */
+    PARAM_REQUIRED(400, "参数不能为空"),
+    /** 参数格式错误 */
+    PARAM_FORMAT_ERROR(400, "参数格式错误"),
+    /** 无权操作 */
+    FORBIDDEN(403, "无权操作"),
+    /** 操作失败 */
+    OPERATION_FAILED(500, "操作失败"),
+    /** 状态不允许操作 */
+    STATUS_NOT_ALLOWED(400, "当前状态不允许此操作"),
+
+    // ==================== 业务实体缺失 ====================
+
+    /** 用户不存在 */
+    USER_NOT_FOUND(404, "用户不存在"),
+    /** 订单不存在 */
+    ORDER_NOT_FOUND(404, "订单不存在"),
+    /** 门店不存在 */
+    SHOP_NOT_FOUND(404, "门店不存在"),
+    /** 公告不存在 */
+    ANNOUNCEMENT_NOT_FOUND(404, "公告不存在"),
+    /** 角色不存在 */
+    ROLE_NOT_FOUND(404, "角色不存在"),
+    /** 字典类型不存在 */
+    DICT_TYPE_NOT_FOUND(404, "字典类型不存在"),
+    /** 字典数据不存在 */
+    DICT_DATA_NOT_FOUND(404, "字典数据不存在"),
+    /** 字典编码已存在 */
+    DICT_CODE_DUPLICATE(400, "字典编码已存在"),
+    /** 字典项值已存在 */
+    DICT_ITEM_VALUE_DUPLICATE(400, "该字典下已存在相同的字典项值"),
+    /** 系统内置字典不允许删除 */
+    DICT_SYSTEM_NO_DELETE(400, "系统内置字典不允许删除"),
+    /** 导入数据不能为空 */
+    IMPORT_DATA_EMPTY(400, "导入数据不能为空"),
+    /** 签到记录不存在 */
+    CHECKIN_NOT_FOUND(404, "签到记录不存在"),
+    /** 申请记录不存在 */
+    APPLY_NOT_FOUND(404, "申请记录不存在"),
+    /** 设备无商品信息 */
+    DEVICE_NO_PRODUCTS(404, "该设备暂无商品信息"),
+
+    // ==================== 微信小程序 ====================
 
-    // 微信小程序
     WX_MP_LOGIN_ERROR(301, "微信登录异常"),
 
-    // 微信支付
-    WX_PAY_AMOUNT_ERROR(300001,"微信支付金额异常"),
+    // ==================== 微信支付 ====================
+
+    WX_PAY_AMOUNT_ERROR(300001, "微信支付金额异常"),
+
+    // ==================== 登录 权限 ====================
 
-    // 登录 权限
     LOGIN_FAILED(10001, "用户名或密码错误"),
     NO_PERMISSION(10002, "无访问权限");
 
@@ -41,4 +90,18 @@ public enum ResponseEnum implements BusinessExceptionAssert {
         this.code = code;
         this.message = message;
     }
+
+    /**
+     * 根据此枚举生成Result错误响应
+     */
+    public <T> Result<T> toResult() {
+        return Result.error(this.code, this.message);
+    }
+
+    /**
+     * 根据此枚举生成Result错误响应,覆盖消息
+     */
+    public <T> Result<T> toResult(String message) {
+        return Result.error(this.code, message);
+    }
 }

+ 43 - 0
haha-common/src/main/java/com/haha/common/dto/BasePageQueryDTO.java

@@ -0,0 +1,43 @@
+package com.haha.common.dto;
+
+import lombok.Data;
+
+/**
+ * 分页查询基础DTO
+ * 统一分页参数定义,所有分页查询DTO应继承此类
+ */
+@Data
+public class BasePageQueryDTO {
+
+    /**
+     * 当前页码,默认第1页
+     */
+    private Integer page = 1;
+
+    /**
+     * 每页条数,默认10条
+     */
+    private Integer pageSize = 10;
+
+    /**
+     * 获取偏移量
+     */
+    public int getOffset() {
+        return (page - 1) * pageSize;
+    }
+
+    /**
+     * 校验并修正分页参数
+     */
+    public void validate() {
+        if (page == null || page < 1) {
+            page = 1;
+        }
+        if (pageSize == null || pageSize < 1) {
+            pageSize = 10;
+        }
+        if (pageSize > 100) {
+            pageSize = 100;  // 限制最大每页条数
+        }
+    }
+}

+ 48 - 0
haha-common/src/main/java/com/haha/common/enums/ApplyStatus.java

@@ -0,0 +1,48 @@
+package com.haha.common.enums;
+
+import lombok.Getter;
+
+/**
+ * 新品申请状态枚举
+ */
+@Getter
+public enum ApplyStatus {
+
+    DRAFT(0, "待提交"),
+    PENDING(1, "审核中"),
+    APPROVED(2, "已通过"),
+    REJECTED(3, "已拒绝");
+
+    private final int code;
+    private final String description;
+
+    ApplyStatus(int code, String description) {
+        this.code = code;
+        this.description = description;
+    }
+
+    public static ApplyStatus fromCode(Integer code) {
+        if (code == null) {
+            return null;
+        }
+        for (ApplyStatus status : values()) {
+            if (status.code == code) {
+                return status;
+            }
+        }
+        return null;
+    }
+
+    public static boolean isDraft(Integer code) {
+        return code != null && code == DRAFT.code;
+    }
+
+    public static boolean isPending(Integer code) {
+        return code != null && code == PENDING.code;
+    }
+
+    public static String getDescription(Integer code) {
+        ApplyStatus status = fromCode(code);
+        return status != null ? status.description : "未知";
+    }
+}

+ 71 - 0
haha-common/src/main/java/com/haha/common/utils/PageUtil.java

@@ -0,0 +1,71 @@
+package com.haha.common.utils;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.haha.common.constant.CommonConstants;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 分页工具类
+ * 统一分页参数解析和结果构建
+ */
+public final class PageUtil {
+
+    private PageUtil() {}
+
+    /**
+     * 从请求参数Map中解析分页参数
+     *
+     * @param params 请求参数Map
+     * @return 包含 page 和 pageSize 的数组 [page, pageSize]
+     */
+    public static int[] parsePageParams(Map<String, Object> params) {
+        int page = CommonConstants.DEFAULT_PAGE;
+        int pageSize = CommonConstants.DEFAULT_PAGE_SIZE;
+
+        if (params != null) {
+            Object pageObj = params.get("page");
+            if (pageObj != null && !pageObj.toString().isEmpty()) {
+                try {
+                    page = Integer.parseInt(pageObj.toString());
+                    if (page < 1) {
+                        page = CommonConstants.DEFAULT_PAGE;
+                    }
+                } catch (NumberFormatException ignored) {
+                }
+            }
+
+            Object pageSizeObj = params.get("pageSize");
+            if (pageSizeObj != null && !pageSizeObj.toString().isEmpty()) {
+                try {
+                    pageSize = Integer.parseInt(pageSizeObj.toString());
+                    if (pageSize < 1 || pageSize > CommonConstants.MAX_PAGE_SIZE) {
+                        pageSize = CommonConstants.DEFAULT_PAGE_SIZE;
+                    }
+                } catch (NumberFormatException ignored) {
+                }
+            }
+        }
+
+        return new int[]{page, pageSize};
+    }
+
+    /**
+     * 构建分页结果Map
+     *
+     * @param pageResult MyBatis-Plus分页结果
+     * @param page      当前页码
+     * @param pageSize  每页条数
+     * @param <T>       数据类型
+     * @return 分页结果Map
+     */
+    public static <T> Map<String, Object> buildPageResult(IPage<T> pageResult, int page, int pageSize) {
+        Map<String, Object> result = new HashMap<>();
+        result.put("list", pageResult.getRecords());
+        result.put("total", pageResult.getTotal());
+        result.put("page", page);
+        result.put("pageSize", pageSize);
+        return result;
+    }
+}

+ 105 - 0
haha-common/src/main/java/com/haha/common/utils/RequestParseUtil.java

@@ -0,0 +1,105 @@
+package com.haha.common.utils;
+
+import com.alibaba.fastjson2.JSON;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.BufferedReader;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * HTTP请求参数解析工具类
+ * 统一处理从HttpServletRequest中读取JSON、XML、form-urlencoded格式的参数
+ */
+@Slf4j
+public class RequestParseUtil {
+
+    private RequestParseUtil() {}
+
+    /**
+     * 从HttpServletRequest中读取请求体内容
+     *
+     * @param request HTTP请求对象
+     * @return 请求体字符串
+     */
+    public static String readRequestBody(HttpServletRequest request) {
+        StringBuilder sb = new StringBuilder();
+        try (BufferedReader reader = request.getReader()) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (Exception e) {
+            log.error("读取请求体失败", e);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 解析请求参数,支持 JSON 和 form-urlencoded 两种格式
+     *
+     * @param request       HTTP请求对象
+     * @param requestParams form表单参数(@RequestParam捕获的参数)
+     * @return 参数Map
+     */
+    public static Map<String, Object> parseRequestParams(HttpServletRequest request, Map<String, String> requestParams) {
+        Map<String, Object> params = new HashMap<>();
+
+        String contentType = request.getContentType();
+        log.debug("请求Content-Type: {}", contentType);
+
+        try {
+            if (contentType != null && contentType.toLowerCase().contains("application/json")) {
+                // JSON 格式:从 request body 读取
+                String body = readRequestBody(request);
+                if (body != null && !body.isEmpty()) {
+                    params = JSON.parseObject(body, Map.class);
+                    log.debug("解析JSON参数: {}", params.size());
+                }
+            } else if (contentType != null && contentType.toLowerCase().contains("text/xml")) {
+                // XML 格式(微信支付回调):从 request body 读取原始XML
+                String body = readRequestBody(request);
+                if (body != null && !body.isEmpty()) {
+                    params.put("xmlBody", body);
+                    log.debug("解析XML参数");
+                }
+            } else {
+                // form-urlencoded 格式:使用 @RequestParam 捕获的参数
+                if (requestParams != null && !requestParams.isEmpty()) {
+                    params.putAll(requestParams);
+                    log.debug("解析表单参数: {}", params.size());
+                }
+            }
+        } catch (Exception e) {
+            log.error("解析请求参数失败", e);
+        }
+
+        return params;
+    }
+
+    /**
+     * 从HttpServletRequest中读取微信支付回调请求头和请求体
+     *
+     * @param request HTTP请求对象
+     * @return 包含body和微信签名头的参数Map
+     */
+    public static Map<String, Object> parseWechatPayCallbackParams(HttpServletRequest request) {
+        String body = readRequestBody(request);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("body", body);
+        params.put("Wechatpay-Timestamp", request.getHeader("Wechatpay-Timestamp"));
+        params.put("Wechatpay-Nonce", request.getHeader("Wechatpay-Nonce"));
+        params.put("Wechatpay-Signature", request.getHeader("Wechatpay-Signature"));
+        params.put("Wechatpay-Serial", request.getHeader("Wechatpay-Serial"));
+        params.put("Wechatpay-Signature-Type", request.getHeader("Wechatpay-Signature-Type"));
+
+        log.info("微信支付回调请求头: Timestamp={}, Nonce={}, Serial={}",
+                params.get("Wechatpay-Timestamp"),
+                params.get("Wechatpay-Nonce"),
+                params.get("Wechatpay-Serial"));
+
+        return params;
+    }
+}

+ 0 - 51
haha-common/src/main/java/com/haha/common/vo/RedisConstants.java

@@ -1,51 +0,0 @@
-package com.haha.common;
-
-/**
- * Redis 缂撳瓨閿父閲忕被
- * 缁熶竴绠$悊鎵€鏈?Redis 缂撳瓨鐨勯敭鍚?
- */
-public class RedisConstants {
-
-    /**
-     * Sa-Token 鐢ㄦ埛浼氳瘽鐩稿叧
-     */
-    public static final String SA_TOKEN_USER_KEY_PREFIX = "satoken:user:";
-    public static final String SA_TOKEN_USER_LOGIN_ID_KEY = "satoken:loginId:%s";
-    public static final String SA_TOKEN_USER_TOKEN_KEY = "satoken:token:%s";
-
-    /**
-     * 璁惧鐘舵€佺浉鍏?
-     */
-    public static final String DEVICE_STATUS_KEY_PREFIX = "device_status:";
-    public static final String DEVICE_STATUS_KEY = "device_status:%s";
-
-    /**
-     * 鍒嗗竷寮忛攣鐩稿叧
-     */
-    public static final String LOCK_DOOR_KEY_PREFIX = "lock:door:";
-    public static final String LOCK_DOOR_KEY = "lock:door:%s";
-
-    /**
-     * 涓存椂璁㈠崟鐩稿叧
-     */
-    public static final String ORDER_TEMP_KEY_PREFIX = "order:temp:";
-    public static final String ORDER_TEMP_KEY = "order:temp:%s";
-
-    /**
-     * 鐢ㄦ埛淇℃伅缂撳瓨鐩稿叧
-     */
-    public static final String USER_INFO_KEY_PREFIX = "user:info:";
-    public static final String USER_INFO_KEY = "user:info:%s";
-
-    /**
-     * 鍟嗗搧淇℃伅缂撳瓨鐩稿叧
-     */
-    public static final String PRODUCT_INFO_KEY_PREFIX = "product:info:";
-    public static final String PRODUCT_INFO_KEY = "product:info:%s";
-
-    /**
-     * 璁惧淇℃伅缂撳瓨鐩稿叧
-     */
-    public static final String DEVICE_INFO_KEY_PREFIX = "device:info:";
-    public static final String DEVICE_INFO_KEY = "device:info:%s";
-}

+ 5 - 33
haha-entity/src/main/java/com/haha/entity/dto/PageQueryDTO.java

@@ -1,42 +1,14 @@
 package com.haha.entity.dto;
 
+import com.haha.common.dto.BasePageQueryDTO;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 /**
  * 分页查询基础DTO
+ * 继承自通用BasePageQueryDTO,保持向后兼容
  */
 @Data
-public class PageQueryDTO {
-    
-    /**
-     * 当前页码,默认第1页
-     */
-    private Integer page = 1;
-    
-    /**
-     * 每页条数,默认10条
-     */
-    private Integer pageSize = 10;
-    
-    /**
-     * 获取偏移量
-     */
-    public int getOffset() {
-        return (page - 1) * pageSize;
-    }
-    
-    /**
-     * 校验并修正分页参数
-     */
-    public void validate() {
-        if (page == null || page < 1) {
-            page = 1;
-        }
-        if (pageSize == null || pageSize < 1) {
-            pageSize = 10;
-        }
-        if (pageSize > 100) {
-            pageSize = 100;
-        }
-    }
+@EqualsAndHashCode(callSuper = true)
+public class PageQueryDTO extends BasePageQueryDTO {
 }

+ 3 - 3
haha-miniapp/src/main/java/com/haha/miniapp/controller/AppAnnouncementController.java

@@ -3,8 +3,8 @@ package com.haha.miniapp.controller;
 import com.haha.common.vo.Result;
 import com.haha.entity.Announcement;
 import com.haha.service.AnnouncementService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -13,12 +13,12 @@ import java.util.List;
  * 小程序公告接口
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/announcement")
 public class AppAnnouncementController {
 
-    @Autowired
-    private AnnouncementService announcementService;
+    private final AnnouncementService announcementService;
 
     /**
      * 获取公告列表

+ 13 - 52
haha-miniapp/src/main/java/com/haha/miniapp/controller/CallbackController.java

@@ -2,18 +2,18 @@ package com.haha.miniapp.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import com.alibaba.fastjson2.JSON;
+import com.haha.common.constant.CallbackConstants;
 import com.haha.common.enums.NotifyType;
+import com.haha.common.utils.RequestParseUtil;
 import com.haha.service.HahaCallbackService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 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.RestController;
 
 import jakarta.servlet.http.HttpServletRequest;
-import java.io.BufferedReader;
-import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -39,13 +39,13 @@ import java.util.Map;
  * - 未正确响应会触发重试机制
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/callback/haha")
 @SaIgnore
 public class CallbackController {
 
-    @Autowired
-    private HahaCallbackService hahaCallbackService;
+    private final HahaCallbackService hahaCallbackService;
 
     /**
      * 消息回调通知统一入口
@@ -61,29 +61,29 @@ public class CallbackController {
     public String handleMessageCallback(HttpServletRequest request, 
                                          @RequestParam(required = false) Map<String, String> requestParams) {
         try {
-            Map<String, Object> params = parseRequestParams(request, requestParams);
+            Map<String, Object> params = RequestParseUtil.parseRequestParams(request, requestParams);
 
             log.info("收到消息回调通知: {}", JSON.toJSONString(params));
 
             String notifyType = (String) params.get("notify_type");
             if (notifyType == null || notifyType.isEmpty()) {
                 log.warn("消息回调缺少 notify_type 参数");
-                return "success";
+                return CallbackConstants.HAHA_SUCCESS;
             }
 
             NotifyType type = NotifyType.fromCode(notifyType);
             if (type == null) {
                 log.warn("未知的消息通知类型: {}", notifyType);
-                return "success";
+                return CallbackConstants.HAHA_SUCCESS;
             }
 
             hahaCallbackService.handleMessage(params);
 
-            return "success";
+            return CallbackConstants.HAHA_SUCCESS;
 
         } catch (Exception e) {
             log.error("处理消息回调通知失败", e);
-            return "success";
+            return CallbackConstants.HAHA_SUCCESS;
         }
     }
 
@@ -102,57 +102,18 @@ public class CallbackController {
     public String handleOrderCallback(HttpServletRequest request,
                                        @RequestParam(required = false) Map<String, String> requestParams) {
         try {
-            Map<String, Object> params = parseRequestParams(request, requestParams);
+            Map<String, Object> params = RequestParseUtil.parseRequestParams(request, requestParams);
 
             log.info("收到订单回调通知: {}", JSON.toJSONString(params));
 
             hahaCallbackService.handleOrderCallback(params);
 
-            return "success";
+            return CallbackConstants.HAHA_SUCCESS;
 
         } catch (Exception e) {
             log.error("处理订单回调通知失败", e);
-            return "success";
+            return CallbackConstants.HAHA_SUCCESS;
         }
     }
 
-    /**
-     * 解析请求参数,支持 JSON 和 form-urlencoded 两种格式
-     *
-     * @param request HTTP请求对象
-     * @param requestParams form表单参数
-     * @return 参数Map
-     */
-    private Map<String, Object> parseRequestParams(HttpServletRequest request, Map<String, String> requestParams) {
-        Map<String, Object> params = new HashMap<>();
-
-        String contentType = request.getContentType();
-        log.debug("请求Content-Type: {}", contentType);
-
-        try {
-            if (contentType != null && contentType.toLowerCase().contains("application/json")) {
-                StringBuilder sb = new StringBuilder();
-                try (BufferedReader reader = request.getReader()) {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        sb.append(line);
-                    }
-                }
-                String body = sb.toString();
-                if (body != null && !body.isEmpty()) {
-                    params = JSON.parseObject(body, Map.class);
-                    log.debug("解析JSON参数: {}", params.size());
-                }
-            } else {
-                if (requestParams != null && !requestParams.isEmpty()) {
-                    params.putAll(requestParams);
-                    log.debug("解析表单参数: {}", params.size());
-                }
-            }
-        } catch (Exception e) {
-            log.error("解析请求参数失败", e);
-        }
-
-        return params;
-    }
 }

+ 8 - 9
haha-miniapp/src/main/java/com/haha/miniapp/controller/DeviceController.java

@@ -3,6 +3,7 @@ package com.haha.miniapp.controller;
 import cn.dev33.satoken.stp.StpUtil;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.dto.FloorConfig;
 import com.haha.common.vo.OpenDoorVO;
 import com.haha.common.vo.Result;
@@ -10,8 +11,8 @@ import com.haha.entity.LayerTemplate;
 import com.haha.service.DeviceService;
 import com.haha.service.LayerTemplateService;
 import com.haha.sdk.exception.HahaException;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -23,15 +24,13 @@ import java.util.Map;
  * Controller层仅负责接收请求、参数校验、调用Service、返回响应
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/device")
 public class DeviceController {
 
-    @Autowired
-    private DeviceService deviceService;
-
-    @Autowired
-    private LayerTemplateService layerTemplateService;
+    private final DeviceService deviceService;
+    private final LayerTemplateService layerTemplateService;
 
     private final ObjectMapper objectMapper = new ObjectMapper();
 
@@ -46,7 +45,7 @@ public class DeviceController {
         // 1. 参数校验
         String deviceId = params.get("deviceId");
         if (deviceId == null || deviceId.trim().isEmpty()) {
-            return Result.error(400, "参数错误:deviceId 不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:deviceId 不能为空");
         }
 
         try {
@@ -75,7 +74,7 @@ public class DeviceController {
                 return Result.error(500, message);
             }
             
-            return Result.error(500, "系统繁忙,请稍后重试");
+            return ResponseEnum.OPERATION_FAILED.toResult("系统繁忙,请稍后重试");
         }
     }
 
@@ -92,7 +91,7 @@ public class DeviceController {
             // 查询设备层模板(无需登录,允许未登录用户查看柜内商品)
             LayerTemplate template = layerTemplateService.getByDeviceId(deviceId);
             if (template == null) {
-                return Result.error(404, "该设备暂无商品信息");
+                return ResponseEnum.DEVICE_NO_PRODUCTS.toResult();
             }
 
             // 3. 解析层数据

+ 3 - 2
haha-miniapp/src/main/java/com/haha/miniapp/controller/InviteController.java

@@ -1,6 +1,7 @@
 package com.haha.miniapp.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.vo.PageResult;
 import com.haha.common.vo.Result;
 import com.haha.entity.InviteActivity;
@@ -77,7 +78,7 @@ public class InviteController {
         Long userId = StpUtil.getLoginIdAsLong();
 
         if (!params.containsKey("inviteCode")) {
-            return Result.error(400, "参数错误:inviteCode 不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:inviteCode 不能为空");
         }
 
         String inviteCode = params.get("inviteCode").toString();
@@ -92,7 +93,7 @@ public class InviteController {
 
         if (record == null) {
             log.warn("[邀请] 邀请码无效或已过期 - userId: {}, inviteCode: {}", userId, inviteCode);
-            return Result.error(400, "邀请码无效或已过期");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult("邀请码无效或已过期");
         }
 
         boolean success = inviteActivityService.bindInviteRelation(

+ 7 - 6
haha-miniapp/src/main/java/com/haha/miniapp/controller/LoginController.java

@@ -2,11 +2,12 @@ package com.haha.miniapp.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import cn.dev33.satoken.stp.StpUtil;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.vo.Result;
 import com.haha.service.LoginService;
 import com.haha.common.vo.LoginVO;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -15,13 +16,13 @@ import org.springframework.web.bind.annotation.RestController;
 import java.util.Map;
 
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/login")
 @SaIgnore
 public class LoginController {
-    
-    @Autowired
-    private LoginService loginService;
+
+    private final LoginService loginService;
     
     /**
      * 微信小程序手机号快速登录
@@ -38,11 +39,11 @@ public class LoginController {
         
         if (code == null || code.isEmpty()) {
             log.warn("[登录] 微信小程序手机号登录失败 - code为空");
-            return Result.error(400, "登录凭证不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("登录凭证不能为空");
         }
         if (phoneCode == null || phoneCode.isEmpty()) {
             log.warn("[登录] 微信小程序手机号登录失败 - phoneCode为空");
-            return Result.error(400, "手机号凭证不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("手机号凭证不能为空");
         }
         
         try {

+ 47 - 275
haha-miniapp/src/main/java/com/haha/miniapp/controller/OrderController.java

@@ -1,19 +1,13 @@
 package com.haha.miniapp.controller;
 
 import cn.dev33.satoken.stp.StpUtil;
-import com.alibaba.fastjson2.JSON;
-import com.alibaba.fastjson2.JSONArray;
-import com.alibaba.fastjson2.JSONObject;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.vo.Result;
-import com.haha.entity.Order;
 import com.haha.service.OrderService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -21,306 +15,84 @@ import java.util.Map;
  * 订单相关接口
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/order")
 public class OrderController {
 
-    @Autowired
-    private OrderService orderService;
-
-    @Autowired
-    private com.haha.common.config.CommonConfig commonConfig;
-
-    @Autowired
-    private com.haha.service.OrderGoodsService orderGoodsService;
+    private final OrderService orderService;
 
     /**
      * 获取订单列表
-     *
-     * 业务流程:
-     * 1. 获取当前登录用户ID
-     * 2. 根据状态筛选查询订单列表
-     * 3. 解析订单商品信息
-     * 4. 返回订单列表
-     *
-     * @param params 包含 status(可选,订单状态:0-待支付,1-已完成,2-已取消)
-     * @return 订单列表
      */
     @PostMapping("/list")
     public Result<List<Map<String, Object>>> getOrderList(@RequestBody(required = false) Map<String, Object> params) {
-        try {
-            Long userId = StpUtil.getLoginIdAsLong();
-            log.info("用户 {} 请求订单列表", userId);
-
-            Integer status = null;
-            if (params != null && params.containsKey("status")) {
-                status = Integer.valueOf(params.get("status").toString());
-            }
+        Long userId = StpUtil.getLoginIdAsLong();
+        log.info("用户 {} 请求订单列表", userId);
 
-            List<Order> orders = orderService.getOrderListByUserId(userId, status);
-
-            List<Map<String, Object>> orderList = new ArrayList<>();
-            for (Order order : orders) {
-                Map<String, Object> orderMap = new HashMap<>();
-                orderMap.put("id", order.getId());
-                orderMap.put("orderNo", order.getOrderNo());
-                orderMap.put("orderName", order.getOrderName() != null ? order.getOrderName() : "");
-                orderMap.put("outTradeNo", order.getOutTradeNo());
-                orderMap.put("deviceId", order.getDeviceId());
-                orderMap.put("totalAmount", order.getTotalAmount());
-                orderMap.put("discountAmount", order.getDiscountAmount() != null ? order.getDiscountAmount() : 0);
-                orderMap.put("paidAmount", order.getPaidAmount() != null ? order.getPaidAmount() : order.getTotalAmount());
-                orderMap.put("payStatus", order.getPayStatus());
-                orderMap.put("status", order.getStatus());
-                orderMap.put("createTime", order.getCreateTime());
-                orderMap.put("payTime", order.getPayTime());
-                orderMap.put("confidence", order.getConfidence());
-                
-                // 从数据库查询订单商品信息(包含图片)
-                List<Map<String, Object>> products = getProductsFromDatabase(order.getId());
-                orderMap.put("products", products);
-
-                orderList.add(orderMap);
-            }
+        Integer status = null;
+        if (params != null && params.containsKey("status")) {
+            status = Integer.valueOf(params.get("status").toString());
+        }
 
-            log.info("用户 {} 查询到 {} 条订单", userId, orderList.size());
-            return Result.success("查询成功", orderList);
+        List<Map<String, Object>> orderList = orderService.getUserOrderListWithProducts(userId, status);
 
-        } catch (Exception e) {
-            log.error("查询订单列表失败", e);
-            return Result.error("查询订单列表失败");
-        }
+        log.info("用户 {} 查询到 {} 条订单", userId, orderList.size());
+        return Result.success("查询成功", orderList);
     }
 
     /**
      * 获取订单详情
-     *
-     * 业务流程:
-     * 1. 参数校验
-     * 2. 获取当前登录用户ID
-     * 3. 查询订单详情
-     * 4. 验证订单归属
-     * 5. 解析订单商品信息
-     * 6. 返回订单详情
-     *
-     * @param params 包含 orderId(订单ID)或 orderNo(订单号)或 outTradeNo(商户订单号)
-     * @return 订单详情
      */
     @PostMapping("/detail")
     public Result<Map<String, Object>> getOrderDetail(@RequestBody Map<String, Object> params) {
-        try {
-            Long userId = StpUtil.getLoginIdAsLong();
-
-            Order order = null;
-
-            if (params.containsKey("orderId")) {
-                Long orderId = Long.valueOf(params.get("orderId").toString());
-                order = orderService.getById(orderId);
-                log.info("用户 {} 通过订单ID {} 查询订单详情", userId, orderId);
-            } else if (params.containsKey("orderNo")) {
-                String orderNo = params.get("orderNo").toString();
-                order = orderService.lambdaQuery()
-                    .eq(Order::getOrderNo, orderNo)
-                    .one();
-                log.info("用户 {} 通过订单号 {} 查询订单详情", userId, orderNo);
-            } else if (params.containsKey("outTradeNo")) {
-                String outTradeNo = params.get("outTradeNo").toString();
-                order = orderService.getOrderByOutTradeNo(outTradeNo);
-                log.info("用户 {} 通过商户订单号 {} 查询订单详情", userId, outTradeNo);
-            } else {
-                return Result.error(400, "参数错误:必须提供 orderId、orderNo 或 outTradeNo");
-            }
-
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-
-            if (!order.getUserId().equals(userId)) {
-                log.warn("用户 {} 尝试访问不属于自己的订单 {}", userId, order.getId());
-                return Result.error(403, "无权访问该订单");
-            }
-
-            // IN类型订单(异物放入)不在用户端展示
-            if ("IN".equals(order.getOrderType())) {
-                return Result.error(404, "订单不存在");
-            }
-
-            Map<String, Object> orderDetail = new HashMap<>();
-            orderDetail.put("id", order.getId());
-            orderDetail.put("orderNo", order.getOrderNo());
-            orderDetail.put("orderName", order.getOrderName() != null ? order.getOrderName() : "");
-            orderDetail.put("outTradeNo", order.getOutTradeNo());
-            orderDetail.put("deviceId", order.getDeviceId());
-            orderDetail.put("totalAmount", order.getTotalAmount());
-            orderDetail.put("discountAmount", order.getDiscountAmount() != null ? order.getDiscountAmount() : 0);
-            orderDetail.put("paidAmount", order.getPaidAmount() != null ? order.getPaidAmount() : order.getTotalAmount());
-            orderDetail.put("payStatus", order.getPayStatus());
-            orderDetail.put("status", order.getStatus());
-            orderDetail.put("createTime", order.getCreateTime());
-            orderDetail.put("payTime", order.getPayTime());
-            orderDetail.put("confidence", order.getConfidence());
-            
-            // 从数据库查询订单商品信息(包含图片)
-            List<Map<String, Object>> products = getProductsFromDatabase(order.getId());
-            orderDetail.put("products", products);
-
-            String statusText = getStatusText(order.getStatus());
-            orderDetail.put("statusText", statusText);
-
-            log.info("用户 {} 查询订单详情成功: {}", userId, order.getOrderNo());
-            return Result.success("查询成功", orderDetail);
+        Long userId = StpUtil.getLoginIdAsLong();
+
+        Long orderId = null;
+        String orderNo = null;
+        String outTradeNo = null;
+
+        if (params.containsKey("orderId")) {
+            orderId = Long.valueOf(params.get("orderId").toString());
+            log.info("用户 {} 通过订单ID {} 查询订单详情", userId, orderId);
+        } else if (params.containsKey("orderNo")) {
+            orderNo = params.get("orderNo").toString();
+            log.info("用户 {} 通过订单号 {} 查询订单详情", userId, orderNo);
+        } else if (params.containsKey("outTradeNo")) {
+            outTradeNo = params.get("outTradeNo").toString();
+            log.info("用户 {} 通过商户订单号 {} 查询订单详情", userId, outTradeNo);
+        } else {
+            return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:必须提供 orderId、orderNo 或 outTradeNo");
+        }
 
-        } catch (Exception e) {
-            log.error("查询订单详情失败", e);
-            return Result.error("查询订单详情失败");
+        Map<String, Object> orderDetail = orderService.getUserOrderDetail(userId, orderId, orderNo, outTradeNo);
+        if (orderDetail == null) {
+            return ResponseEnum.ORDER_NOT_FOUND.toResult();
         }
+
+        log.info("用户 {} 查询订单详情成功", userId);
+        return Result.success("查询成功", orderDetail);
     }
 
     /**
      * 取消订单
-     *
-     * @param params 包含 orderId(订单ID)
-     * @return 操作结果
      */
     @PostMapping("/cancel")
     public Result<Void> cancelOrder(@RequestBody Map<String, Object> params) {
-        try {
-            Long userId = StpUtil.getLoginIdAsLong();
-
-            if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
-            }
-
-            Long orderId = Long.valueOf(params.get("orderId").toString());
-
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-
-            if (!order.getUserId().equals(userId)) {
-                log.warn("用户 {} 尝试取消不属于自己的订单 {}", userId, orderId);
-                return Result.error(403, "无权操作该订单");
-            }
-
-            if (order.getStatus() != 0) {
-                return Result.error(400, "该订单不能取消");
-            }
-
-            boolean success = orderService.cancelOrder(orderId);
-
-            if (success) {
-                log.info("用户 {} 取消订单 {} 成功", userId, orderId);
-                return Result.success("订单已取消", null);
-            } else {
-                return Result.error("取消订单失败");
-            }
+        Long userId = StpUtil.getLoginIdAsLong();
 
-        } catch (Exception e) {
-            log.error("取消订单失败", e);
-            return Result.error("取消订单失败");
+        if (!params.containsKey("orderId")) {
+            return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
         }
-    }
 
-    /**
-     * 解析商品列表数组
-     * 支持两种格式:
-     * 1. {"goods":[...]} - 回调数据格式
-     * 2. [...] - 直接数组格式
-     */
-    private JSONArray parseItemsArray(String itemsStr) {
-        if (itemsStr == null || itemsStr.isEmpty()) {
-            return new JSONArray();
-        }
-        
-        String trimmed = itemsStr.trim();
-        if (trimmed.startsWith("{")) {
-            JSONObject obj = JSON.parseObject(itemsStr);
-            JSONArray goods = obj.getJSONArray("goods");
-            return goods != null ? goods : new JSONArray();
-        } else if (trimmed.startsWith("[")) {
-            return JSON.parseArray(itemsStr);
-        }
-        return new JSONArray();
-    }
+        Long orderId = Long.valueOf(params.get("orderId").toString());
 
-    /**
-     * 标准化图片 URL
-     * 如果图片链接已经是完整的 URL(包含 http://或 https://),则保持不变
-     * 否则添加配置的图片域名前缀
-     *
-     * @param picUrl 原始图片链接
-     * @return 标准化后的图片链接
-     */
-    private String normalizeImageUrl(String picUrl) {
-        if (picUrl == null || picUrl.isEmpty()) {
-            return picUrl;
-        }
-        
-        // 如果已经是完整的 URL(以 http://或 https://开头),则直接返回
-        if (picUrl.startsWith("http://") || picUrl.startsWith("https://")) {
-            return picUrl;
-        }
-        
-        // 否则添加域名前缀
-        return commonConfig.getImageDomainPrefix() + picUrl;
-    }
-
-    /**
-     * 从数据库查询订单商品信息
-     *
-     * @param orderId 订单 ID
-     * @return 商品列表
-     */
-    private List<Map<String, Object>> getProductsFromDatabase(Long orderId) {
-        List<Map<String, Object>> products = new ArrayList<>();
-        
-        if (orderId == null) {
-            return products;
-        }
-        
-        try {
-            // 使用 OrderGoodsService 查询订单商品
-            List<com.haha.common.vo.OrderItemVO> goodsList = orderGoodsService.getVOByOrderId(orderId);
-            
-            if (goodsList != null && !goodsList.isEmpty()) {
-                for (com.haha.common.vo.OrderItemVO goods : goodsList) {
-                    Map<String, Object> product = new HashMap<>();
-                    product.put("id", goods.getId());
-                    product.put("name", goods.getProductName());
-                    product.put("price", goods.getPrice());
-                    product.put("quantity", goods.getProductNum());
-                    // 处理图片链接
-                    product.put("image", normalizeImageUrl(goods.getPic()));
-                    product.put("subtotal", goods.getPrice() != null && goods.getProductNum() != null 
-                        ? goods.getPrice().multiply(new BigDecimal(goods.getProductNum())) 
-                        : new BigDecimal(0));
-                    products.add(product);
-                }
-            }
-        } catch (Exception e) {
-            log.error("查询订单 {} 的商品信息失败:{}", orderId, e.getMessage());
-        }
-        
-        return products;
-    }
-
-    /**
-     * 获取订单状态文本
-     */
-    private String getStatusText(Integer status) {
-        if (status == null) {
-            return "未知";
-        }
-        switch (status) {
-            case 0:
-                return "待支付";
-            case 1:
-                return "已完成";
-            case 2:
-                return "已取消";
-            default:
-                return "未知";
+        boolean success = orderService.cancelUserOrder(userId, orderId);
+        if (success) {
+            log.info("用户 {} 取消订单 {} 成功", userId, orderId);
+            return Result.success("订单已取消", null);
+        } else {
+            return Result.error("取消订单失败");
         }
     }
 }

+ 47 - 299
haha-miniapp/src/main/java/com/haha/miniapp/controller/PayScoreController.java

@@ -3,12 +3,10 @@ package com.haha.miniapp.controller;
 import cn.dev33.satoken.annotation.SaIgnore;
 import cn.dev33.satoken.stp.StpUtil;
 import com.alibaba.fastjson2.JSON;
+import com.haha.common.constant.CallbackConstants;
+import com.haha.common.constant.ResponseEnum;
+import com.haha.common.utils.RequestParseUtil;
 import com.haha.common.vo.Result;
-import com.haha.entity.Order;
-import com.haha.entity.User;
-import com.haha.service.OrderService;
-import com.haha.service.UserService;
-import com.haha.service.payment.config.WxPayConfig;
 import com.haha.service.payment.payscore.*;
 import com.haha.service.payment.payscore.PayScoreCreateRequest.PostPayment;
 import com.haha.service.payment.payscore.PayScoreCompleteRequest.PostDiscount;
@@ -17,9 +15,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.BufferedReader;
 import java.math.BigDecimal;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,19 +29,10 @@ import java.util.Map;
 @RequiredArgsConstructor
 public class PayScoreController {
 
-    private static final int PAYSCORE_ENABLED = 1;
-
     private final PayScoreService payScoreService;
-    private final OrderService orderService;
-    private final UserService userService;
-    // todo 微信支付开通好后放开
-//    private final WxPayConfig wxPayConfig;
 
     /**
      * 检查用户是否已开通微信支付分
-     * GET /api/payscore/check-enable
-     *
-     * @return 开通状态
      */
     @GetMapping("/check-enable")
     public Result<Map<String, Object>> checkPayscoreEnabled() {
@@ -53,19 +40,9 @@ public class PayScoreController {
         log.info("用户 {} 查询支付分开通状态", userId);
 
         try {
-            User user = userService.getById(userId);
-            if (user == null) {
-                return Result.error(404, "用户不存在");
-            }
-
-            boolean isEnabled = isPayscoreEnabled(user);
-            Map<String, Object> data = new HashMap<>();
-            data.put("enabled", isEnabled);
-            data.put("userId", userId);
-
-            log.info("用户 {} 支付分开通状态:{}", userId, isEnabled ? "已开通" : "未开通");
+            Map<String, Object> data = payScoreService.checkPayscoreEnabled(userId);
+            log.info("用户 {} 支付分开通状态:{}", userId, data.get("enabled"));
             return Result.success("查询成功", data);
-
         } catch (Exception e) {
             log.error("查询支付分开通状态失败 - userId: {}", userId, e);
             return Result.error("查询失败:" + e.getMessage());
@@ -74,11 +51,6 @@ public class PayScoreController {
 
     /**
      * 开通微信支付分(调起小程序授权页面)
-     * POST /api/payscore/enable
-     *
-     * @param params 请求参数(可选)
-     *   - openId: 用户微信 openId(用于验证)
-     * @return 开通结果(包含跳转参数)
      */
     @PostMapping("/enable")
     public Result<Map<String, Object>> enablePayscore(@RequestBody(required = false) Map<String, Object> params) {
@@ -86,29 +58,12 @@ public class PayScoreController {
         log.info("用户 {} 申请开通支付分", userId);
 
         try {
-            User user = userService.getById(userId);
-            if (user == null) {
-                return Result.error(404, "用户不存在");
-            }
-
-            // 如果已经开通,直接返回成功
-            if (isPayscoreEnabled(user)) {
-                log.info("用户 {} 已开通支付分,无需重复开通", userId);
-                Map<String, Object> data = new HashMap<>();
-                data.put("enabled", true);
-                data.put("userId", userId);
+            Map<String, Object> data = payScoreService.enablePayscore(userId);
+            if (Boolean.TRUE.equals(data.get("enabled"))) {
                 return Result.success("您已开通微信支付分", data);
             }
-
-            // 生成微信商户订单号
-            String outOrderNo = generatePayscoreOrderNo(userId);
-
-            // 构建返回数据,供前端调起微信支付分开通页面
-            Map<String, Object> data = buildEnableData(userId, outOrderNo);
-
-            log.info("用户 {} 准备开通支付分,outOrderNo: {}", userId, outOrderNo);
+            log.info("用户 {} 准备开通支付分,outOrderNo: {}", userId, data.get("outOrderNo"));
             return Result.success("请完成支付分授权", data);
-
         } catch (Exception e) {
             log.error("开通支付分失败 - userId: {}", userId, e);
             return Result.error("开通失败:" + e.getMessage());
@@ -117,11 +72,6 @@ public class PayScoreController {
 
     /**
      * 确认开通微信支付分(用户完成授权后调用)
-     * POST /api/payscore/confirm-enable
-     *
-     * @param params 请求参数
-     *   - outOrderNo: 微信商户订单号(必填)
-     * @return 开通结果
      */
     @PostMapping("/confirm-enable")
     public Result<Map<String, Object>> confirmEnablePayscore(@RequestBody Map<String, Object> params) {
@@ -130,99 +80,27 @@ public class PayScoreController {
 
         try {
             if (!params.containsKey("outOrderNo")) {
-                return Result.error(400, "参数错误:outOrderNo 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:outOrderNo 不能为空");
             }
 
             String outOrderNo = params.get("outOrderNo").toString();
-            User user = userService.getById(userId);
-            if (user == null) {
-                return Result.error(404, "用户不存在");
-            }
-
-            // 查询支付分订单状态
-            PayScoreResult result = payScoreService.queryPayScoreOrder(outOrderNo);
-
-            if (result.isSuccess() && "ACCEPTED".equals(result.getState())) {
-                // 用户已授权,更新状态
-                updateUserPayscoreStatus(user);
-
-                Map<String, Object> data = new HashMap<>();
-                data.put("enabled", true);
-                data.put("userId", userId);
+            Map<String, Object> data = payScoreService.confirmEnablePayscore(userId, outOrderNo);
 
+            if (data != null) {
                 log.info("用户 {} 确认开通支付分成功", userId);
                 return Result.success("开通成功", data);
             } else {
-                log.warn("用户 {} 开通支付分失败,state: {}", userId, result != null ? result.getState() : "null");
-                return Result.error(500, "开通失败,请重试");
+                log.warn("用户 {} 开通支付分失败", userId);
+                return ResponseEnum.OPERATION_FAILED.toResult("开通失败,请重试");
             }
-
         } catch (Exception e) {
             log.error("确认开通支付分失败 - userId: {}", userId, e);
             return Result.error("开通失败:" + e.getMessage());
         }
     }
 
-    /**
-     * 判断用户是否已开通支付分
-     *
-     * @param user 用户对象
-     * @return true-已开通,false-未开通
-     */
-    private boolean isPayscoreEnabled(User user) {
-        return user.getPayscoreEnabled() != null && user.getPayscoreEnabled() == PAYSCORE_ENABLED;
-    }
-
-    /**
-     * 构建开通支付分所需的数据
-     *
-     * @param userId 用户 ID
-     * @param outOrderNo 微信商户订单号
-     * @return 开通数据
-     */
-    private Map<String, Object> buildEnableData(Long userId, String outOrderNo) {
-        Map<String, Object> data = new HashMap<>();
-        data.put("enabled", false);
-        data.put("userId", userId);
-        data.put("outOrderNo", outOrderNo);
-        // todo 微信支付开通好后放开
-//        data.put("serviceId", wxPayConfig != null ? wxPayConfig.getServiceId() : "");
-//        data.put("appId", wxPayConfig != null ? wxPayConfig.getAppId() : "");
-        return data;
-    }
-
-    /**
-     * 生成支付分订单号
-     */
-    private String generatePayscoreOrderNo(Long userId) {
-        return "PS" + System.currentTimeMillis() + String.format("%04d", userId % 10000);
-    }
-
-    /**
-     * 更新用户支付分开通状态
-     *
-     * @param user 用户对象
-     */
-    private void updateUserPayscoreStatus(User user) {
-        user.setPayscoreEnabled(PAYSCORE_ENABLED);
-        user.setUpdateTime(java.time.LocalDateTime.now());
-        boolean updated = userService.updateById(user);
-
-        if (!updated) {
-            throw new RuntimeException("更新用户状态失败");
-        }
-    }
-
     /**
      * 创建支付分服务订单
-     * POST /api/payscore/create
-     *
-     * @param params 请求参数
-     *   - orderId: 订单ID(必填)
-     *   - openId: 用户微信openId(必填)
-     *   - riskFundAmount: 风险金额(可选,默认99元)
-     *   - riskFundName: 风险金名称(可选,DEPOSIT/ADVANCE/CASH_DEPOSIT)
-     * @return 支付分结果(含小程序调起支付分所需的package参数)
      */
     @PostMapping("/create")
     public Result<Map<String, Object>> createPayScoreOrder(@RequestBody Map<String, Object> params) {
@@ -231,23 +109,15 @@ public class PayScoreController {
             log.info("用户 {} 请求创建支付分服务订单", userId);
 
             if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
             }
             if (!params.containsKey("openId")) {
-                return Result.error(400, "参数错误:openId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:openId 不能为空");
             }
 
             Long orderId = Long.valueOf(params.get("orderId").toString());
             String openId = params.get("openId").toString();
 
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-            if (!order.getUserId().equals(userId)) {
-                return Result.error(403, "无权操作该订单");
-            }
-
             BigDecimal riskFundAmount = null;
             if (params.containsKey("riskFundAmount")) {
                 riskFundAmount = new BigDecimal(params.get("riskFundAmount").toString());
@@ -258,45 +128,24 @@ public class PayScoreController {
                 riskFundName = params.get("riskFundName").toString();
             }
 
-            PayScoreResult result;
-            if (riskFundAmount != null || riskFundName != null) {
-                result = payScoreService.createPayScoreOrder(orderId, openId, riskFundAmount, riskFundName);
-            } else {
-                result = payScoreService.createPayScoreOrder(orderId, openId);
-            }
-
-            if (result.isSuccess()) {
-                Map<String, Object> data = new HashMap<>();
-                data.put("outOrderNo", result.getOutOrderNo());
-                data.put("state", result.getState());
-                data.put("package", result.getPackageStr());
-                log.info("创建支付分服务订单成功 - orderId: {}, outOrderNo: {}", orderId, result.getOutOrderNo());
+            Map<String, Object> data = payScoreService.createUserPayScoreOrder(userId, orderId, openId, riskFundAmount, riskFundName);
+            if (data != null) {
+                log.info("创建支付分服务订单成功 - orderId: {}", orderId);
                 return Result.success("创建成功", data);
             } else {
-                log.warn("创建支付分服务订单失败 - orderId: {}, errorCode: {}, errorMsg: {}",
-                        orderId, result.getErrorCode(), result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult("创建支付分服务订单失败");
             }
-
         } catch (NumberFormatException e) {
             log.error("参数格式错误", e);
-            return Result.error(400, "参数格式错误");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult();
         } catch (Exception e) {
             log.error("创建支付分服务订单失败", e);
-            return Result.error("创建失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("创建失败:" + e.getMessage());
         }
     }
 
     /**
      * 完结支付分服务订单
-     * POST /api/payscore/complete
-     *
-     * @param params 请求参数
-     *   - orderId: 订单ID(必填)
-     *   - totalAmount: 实际扣款总金额(必填)
-     *   - payments: 后付费项目列表(可选)
-     *   - discounts: 商户优惠列表(可选)
-     * @return 支付分结果
      */
     @PostMapping("/complete")
     public Result<Map<String, Object>> completePayScoreOrder(@RequestBody Map<String, Object> params) {
@@ -305,23 +154,15 @@ public class PayScoreController {
             log.info("用户 {} 请求完结支付分服务订单", userId);
 
             if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
             }
             if (!params.containsKey("totalAmount")) {
-                return Result.error(400, "参数错误:totalAmount 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:totalAmount 不能为空");
             }
 
             Long orderId = Long.valueOf(params.get("orderId").toString());
             BigDecimal totalAmount = new BigDecimal(params.get("totalAmount").toString());
 
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-            if (!order.getUserId().equals(userId)) {
-                return Result.error(403, "无权操作该订单");
-            }
-
             List<PostPayment> payments = null;
             if (params.containsKey("payments")) {
                 payments = JSON.parseArray(params.get("payments").toString(), PostPayment.class);
@@ -332,37 +173,24 @@ public class PayScoreController {
                 discounts = JSON.parseArray(params.get("discounts").toString(), PostDiscount.class);
             }
 
-            PayScoreResult result = payScoreService.completePayScoreOrder(orderId, totalAmount, payments, discounts);
-
-            if (result.isSuccess()) {
-                Map<String, Object> data = new HashMap<>();
-                data.put("outOrderNo", result.getOutOrderNo());
-                data.put("state", result.getState());
-                log.info("完结支付分服务订单成功 - orderId: {}, state: {}", orderId, result.getState());
+            Map<String, Object> data = payScoreService.completeUserPayScoreOrder(userId, orderId, totalAmount, payments, discounts);
+            if (data != null) {
+                log.info("完结支付分服务订单成功 - orderId: {}", orderId);
                 return Result.success("完结成功", data);
             } else {
-                log.warn("完结支付分服务订单失败 - orderId: {}, errorCode: {}, errorMsg: {}",
-                        orderId, result.getErrorCode(), result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult("完结支付分服务订单失败");
             }
-
         } catch (NumberFormatException e) {
             log.error("参数格式错误", e);
-            return Result.error(400, "参数格式错误");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult();
         } catch (Exception e) {
             log.error("完结支付分服务订单失败", e);
-            return Result.error("完结失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("完结失败:" + e.getMessage());
         }
     }
 
     /**
      * 取消支付分服务订单
-     * POST /api/payscore/cancel
-     *
-     * @param params 请求参数
-     *   - orderId: 订单ID(必填)
-     *   - reason: 取消原因(可选)
-     * @return 支付分结果
      */
     @PostMapping("/cancel")
     public Result<Map<String, Object>> cancelPayScoreOrder(@RequestBody Map<String, Object> params) {
@@ -371,49 +199,30 @@ public class PayScoreController {
             log.info("用户 {} 请求取消支付分服务订单", userId);
 
             if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
             }
 
             Long orderId = Long.valueOf(params.get("orderId").toString());
             String reason = params.containsKey("reason") ? params.get("reason").toString() : "用户取消";
 
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-            if (!order.getUserId().equals(userId)) {
-                return Result.error(403, "无权操作该订单");
-            }
-
-            PayScoreResult result = payScoreService.cancelPayScoreOrder(orderId, reason);
-
-            if (result.isSuccess()) {
-                Map<String, Object> data = new HashMap<>();
-                data.put("outOrderNo", result.getOutOrderNo());
-                data.put("state", result.getState());
+            Map<String, Object> data = payScoreService.cancelUserPayScoreOrder(userId, orderId, reason);
+            if (data != null) {
                 log.info("取消支付分服务订单成功 - orderId: {}", orderId);
                 return Result.success("取消成功", data);
             } else {
-                log.warn("取消支付分服务订单失败 - orderId: {}, errorCode: {}, errorMsg: {}",
-                        orderId, result.getErrorCode(), result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult("取消支付分服务订单失败");
             }
-
         } catch (NumberFormatException e) {
             log.error("参数格式错误", e);
-            return Result.error(400, "参数格式错误");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult();
         } catch (Exception e) {
             log.error("取消支付分服务订单失败", e);
-            return Result.error("取消失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("取消失败:" + e.getMessage());
         }
     }
 
     /**
      * 查询支付分服务订单状态
-     * GET /api/payscore/query/{orderId}
-     *
-     * @param orderId 订单ID
-     * @return 支付分订单状态
      */
     @GetMapping("/query/{orderId}")
     public Result<Map<String, Object>> queryPayScoreOrder(@PathVariable Long orderId) {
@@ -421,45 +230,21 @@ public class PayScoreController {
             Long userId = StpUtil.getLoginIdAsLong();
             log.info("用户 {} 查询支付分服务订单状态 - orderId: {}", userId, orderId);
 
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-            if (!order.getUserId().equals(userId)) {
-                return Result.error(403, "无权访问该订单");
-            }
-
-            if (order.getPayScoreOrderId() == null) {
-                return Result.error(400, "该订单未创建支付分服务订单");
-            }
-
-            PayScoreResult result = payScoreService.queryPayScoreOrder(order.getPayScoreOrderId());
-
-            if (result.isSuccess()) {
-                Map<String, Object> data = new HashMap<>();
-                data.put("outOrderNo", result.getOutOrderNo());
-                data.put("state", result.getState());
-                data.put("totalAmount", result.getTotalAmount());
-                log.info("查询支付分服务订单成功 - orderId: {}, state: {}", orderId, result.getState());
+            Map<String, Object> data = payScoreService.queryUserPayScoreOrder(userId, orderId);
+            if (data != null) {
+                log.info("查询支付分服务订单成功 - orderId: {}", orderId);
                 return Result.success("查询成功", data);
             } else {
-                log.warn("查询支付分服务订单失败 - orderId: {}, errorCode: {}, errorMsg: {}",
-                        orderId, result.getErrorCode(), result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.ORDER_NOT_FOUND.toResult("订单不存在或未创建支付分服务订单");
             }
-
         } catch (Exception e) {
             log.error("查询支付分服务订单失败", e);
-            return Result.error("查询失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("查询失败:" + e.getMessage());
         }
     }
 
     /**
      * 同步订单支付分状态
-     * POST /api/payscore/sync/{orderId}
-     *
-     * @param orderId 订单ID
-     * @return 操作结果
      */
     @PostMapping("/sync/{orderId}")
     public Result<Void> syncPayScoreStatus(@PathVariable Long orderId) {
@@ -467,37 +252,21 @@ public class PayScoreController {
             Long userId = StpUtil.getLoginIdAsLong();
             log.info("用户 {} 同步支付分状态 - orderId: {}", userId, orderId);
 
-            Order order = orderService.getById(orderId);
-            if (order == null) {
-                return Result.error(404, "订单不存在");
-            }
-            if (!order.getUserId().equals(userId)) {
-                return Result.error(403, "无权操作该订单");
-            }
-
-            boolean success = payScoreService.syncPayScoreStatus(orderId);
-
+            boolean success = payScoreService.syncUserPayScoreStatus(userId, orderId);
             if (success) {
                 log.info("同步支付分状态成功 - orderId: {}", orderId);
                 return Result.success("同步成功", null);
             } else {
-                return Result.error(500, "同步失败");
+                return ResponseEnum.OPERATION_FAILED.toResult("同步失败");
             }
-
         } catch (Exception e) {
             log.error("同步支付分状态失败", e);
-            return Result.error("同步失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("同步失败:" + e.getMessage());
         }
     }
 
     /**
      * 支付分回调通知
-     * POST /api/payscore/callback
-     *
-     * 注意:回调接口不需要 token 验证
-     *
-     * @param request HTTP请求
-     * @return 回调响应
      */
     @SaIgnore
     @PostMapping("/callback")
@@ -505,42 +274,21 @@ public class PayScoreController {
         try {
             log.info("收到支付分回调通知");
 
-            StringBuilder sb = new StringBuilder();
-            try (BufferedReader reader = request.getReader()) {
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    sb.append(line);
-                }
-            }
-            String body = sb.toString();
-
-            Map<String, Object> params = new HashMap<>();
-            params.put("body", body);
-            params.put("Wechatpay-Timestamp", request.getHeader("Wechatpay-Timestamp"));
-            params.put("Wechatpay-Nonce", request.getHeader("Wechatpay-Nonce"));
-            params.put("Wechatpay-Signature", request.getHeader("Wechatpay-Signature"));
-            params.put("Wechatpay-Serial", request.getHeader("Wechatpay-Serial"));
-            params.put("Wechatpay-Signature-Type", request.getHeader("Wechatpay-Signature-Type"));
-
-            log.info("支付分回调请求头: Timestamp={}, Nonce={}, Serial={}",
-                    params.get("Wechatpay-Timestamp"),
-                    params.get("Wechatpay-Nonce"),
-                    params.get("Wechatpay-Serial"));
+            Map<String, Object> params = RequestParseUtil.parseWechatPayCallbackParams(request);
 
             PayScoreCallbackResult result = payScoreService.handlePayScoreCallback(params);
 
             if (result.isSuccess()) {
                 log.info("支付分回调处理成功 - outOrderNo: {}, eventType: {}, state: {}",
                         result.getOutOrderNo(), result.getEventType(), result.getState());
-                return "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
+                return CallbackConstants.WECHAT_PAYSCORE_SUCCESS;
             } else {
                 log.warn("支付分回调处理失败 - errorMsg: {}", result.getErrorMsg());
-                return "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+                return CallbackConstants.WECHAT_PAYSCORE_FAIL;
             }
-
         } catch (Exception e) {
             log.error("处理支付分回调失败", e);
-            return "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+            return CallbackConstants.WECHAT_PAYSCORE_FAIL;
         }
     }
 }

+ 30 - 123
haha-miniapp/src/main/java/com/haha/miniapp/controller/PaymentController.java

@@ -2,7 +2,10 @@ package com.haha.miniapp.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
 import com.alibaba.fastjson2.JSON;
+import com.haha.common.constant.CallbackConstants;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.enums.PaymentChannel;
+import com.haha.common.utils.RequestParseUtil;
 import com.haha.common.vo.Result;
 import com.haha.service.payment.PaymentCallbackResult;
 import com.haha.service.payment.PaymentResult;
@@ -11,11 +14,10 @@ import com.haha.service.payment.RefundResult;
 import com.haha.service.payment.payscore.PayScoreCallbackResult;
 import com.haha.service.payment.payscore.PayScoreService;
 import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.BufferedReader;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -26,15 +28,13 @@ import java.util.stream.Collectors;
  * 提供统一的支付API,支持多渠道支付(微信、支付宝等)
  */
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/payment")
 public class PaymentController {
 
-    @Autowired
-    private PaymentService paymentService;
-
-    @Autowired
-    private PayScoreService payScoreService;
+    private final PaymentService paymentService;
+    private final PayScoreService payScoreService;
 
     /**
      * 创建支付
@@ -54,10 +54,10 @@ public class PaymentController {
         try {
             // 1. 提取参数
             if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
             }
             if (!params.containsKey("channel")) {
-                return Result.error(400, "参数错误:channel 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:channel 不能为空");
             }
 
             Long orderId = Long.valueOf(params.get("orderId").toString());
@@ -66,7 +66,7 @@ public class PaymentController {
             // 2. 转换 channel 字符串为 PaymentChannel 枚举
             PaymentChannel channel = PaymentChannel.fromCode(channelCode);
             if (channel == null) {
-                return Result.error(400, "不支持的支付渠道: " + channelCode);
+                return ResponseEnum.PARAM_FORMAT_ERROR.toResult("不支持的支付渠道: " + channelCode);
             }
 
             // 3. 构建 extra Map
@@ -89,15 +89,15 @@ public class PaymentController {
                 return Result.success("创建支付成功", result);
             } else {
                 log.warn("创建支付失败 - 订单ID: {}, 错误: {}", orderId, result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
             }
 
         } catch (NumberFormatException e) {
             log.error("参数格式错误", e);
-            return Result.error(400, "参数格式错误:orderId 必须为数字");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult("参数格式错误:orderId 必须为数字");
         } catch (Exception e) {
             log.error("创建支付失败", e);
-            return Result.error("创建支付失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("创建支付失败:" + e.getMessage());
         }
     }
 
@@ -121,59 +121,27 @@ public class PaymentController {
         try {
             log.info("收到支付回调 - 渠道: {}", channel);
 
-            Map<String, Object> params = new HashMap<>();
+            Map<String, Object> params;
 
             if (PaymentChannel.WECHAT_PAYSCORE.getCode().equalsIgnoreCase(channel)) {
-                StringBuilder sb = new StringBuilder();
-                try (BufferedReader reader = request.getReader()) {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        sb.append(line);
-                    }
-                }
-                String body = sb.toString();
-
-                params.put("body", body);
-                params.put("Wechatpay-Timestamp", request.getHeader("Wechatpay-Timestamp"));
-                params.put("Wechatpay-Nonce", request.getHeader("Wechatpay-Nonce"));
-                params.put("Wechatpay-Signature", request.getHeader("Wechatpay-Signature"));
-                params.put("Wechatpay-Serial", request.getHeader("Wechatpay-Serial"));
-                params.put("Wechatpay-Signature-Type", request.getHeader("Wechatpay-Signature-Type"));
-
-                log.info("微信支付分回调 - Timestamp: {}, Nonce: {}, Serial={}", 
-                        params.get("Wechatpay-Timestamp"), 
-                        params.get("Wechatpay-Nonce"), 
-                        params.get("Wechatpay-Serial"));
+                params = RequestParseUtil.parseWechatPayCallbackParams(request);
 
                 PayScoreCallbackResult result = payScoreService.handlePayScoreCallback(params);
 
                 if (result.isSuccess()) {
                     log.info("支付分回调处理成功 - outOrderNo: {}, eventType: {}, state: {}", 
                             result.getOutOrderNo(), result.getEventType(), result.getState());
-                    return "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
+                    return CallbackConstants.WECHAT_PAYSCORE_SUCCESS;
                 } else {
                     log.warn("支付分回调处理失败 - errorMsg: {}", result.getErrorMsg());
-                    return "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+                    return CallbackConstants.WECHAT_PAYSCORE_FAIL;
                 }
             }
 
             if ("wechat".equalsIgnoreCase(channel)) {
-                StringBuilder sb = new StringBuilder();
-                try (BufferedReader reader = request.getReader()) {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        sb.append(line);
-                    }
-                }
-                String body = sb.toString();
-                
-                params.put("body", body);
-                params.put("Wechatpay-Timestamp", request.getHeader("Wechatpay-Timestamp"));
-                params.put("Wechatpay-Nonce", request.getHeader("Wechatpay-Nonce"));
-                params.put("Wechatpay-Signature", request.getHeader("Wechatpay-Signature"));
-                params.put("Wechatpay-Serial", request.getHeader("Wechatpay-Serial"));
-                params.put("Wechatpay-Signature-Type", request.getHeader("Wechatpay-Signature-Type"));
+                params = RequestParseUtil.parseWechatPayCallbackParams(request);
                 
+                String body = (String) params.get("body");
                 if (body != null && !body.isEmpty()) {
                     try {
                         Map<String, Object> jsonParams = JSON.parseObject(body, Map.class);
@@ -181,12 +149,8 @@ public class PaymentController {
                     } catch (Exception ignored) {
                     }
                 }
-                log.info("微信V3回调 - Timestamp: {}, Nonce: {}, Serial: {}", 
-                        params.get("Wechatpay-Timestamp"), 
-                        params.get("Wechatpay-Nonce"), 
-                        params.get("Wechatpay-Serial"));
             } else {
-                params = parseRequestParams(request, requestParams);
+                params = RequestParseUtil.parseRequestParams(request, requestParams);
             }
             log.info("支付回调参数: {}", JSON.toJSONString(params));
 
@@ -228,7 +192,7 @@ public class PaymentController {
         try {
             // 提取 orderId, reason
             if (!params.containsKey("orderId")) {
-                return Result.error(400, "参数错误:orderId 不能为空");
+                return ResponseEnum.PARAM_REQUIRED.toResult("参数错误:orderId 不能为空");
             }
 
             Long orderId = Long.valueOf(params.get("orderId").toString());
@@ -244,15 +208,15 @@ public class PaymentController {
                 return Result.success("退款成功", result);
             } else {
                 log.warn("退款失败 - 订单ID: {}, 错误: {}", orderId, result.getErrorMsg());
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
             }
 
         } catch (NumberFormatException e) {
             log.error("参数格式错误", e);
-            return Result.error(400, "参数格式错误:orderId 必须为数字");
+            return ResponseEnum.PARAM_FORMAT_ERROR.toResult("参数格式错误:orderId 必须为数字");
         } catch (Exception e) {
             log.error("退款失败", e);
-            return Result.error("退款失败:" + e.getMessage());
+            return ResponseEnum.OPERATION_FAILED.toResult("退款失败:" + e.getMessage());
         }
     }
 
@@ -305,7 +269,7 @@ public class PaymentController {
             if (result.isSuccess()) {
                 return Result.success("查询成功", result);
             } else {
-                return Result.error(500, result.getErrorMsg());
+                return ResponseEnum.OPERATION_FAILED.toResult(result.getErrorMsg());
             }
 
         } catch (Exception e) {
@@ -314,63 +278,6 @@ public class PaymentController {
         }
     }
 
-    /**
-     * 解析请求参数,支持 JSON 和 form-urlencoded 两种格式
-     *
-     * @param request       HTTP请求对象
-     * @param requestParams form表单参数
-     * @return 参数Map
-     */
-    private Map<String, Object> parseRequestParams(HttpServletRequest request, Map<String, String> requestParams) {
-        Map<String, Object> params = new HashMap<>();
-
-        String contentType = request.getContentType();
-        log.debug("请求Content-Type: {}", contentType);
-
-        try {
-            // 判断 Content-Type
-            if (contentType != null && contentType.toLowerCase().contains("application/json")) {
-                // JSON 格式:从 request body 读取
-                StringBuilder sb = new StringBuilder();
-                try (BufferedReader reader = request.getReader()) {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        sb.append(line);
-                    }
-                }
-                String body = sb.toString();
-                if (body != null && !body.isEmpty()) {
-                    params = JSON.parseObject(body, Map.class);
-                    log.debug("解析JSON参数: {}", params.size());
-                }
-            } else if (contentType != null && contentType.toLowerCase().contains("text/xml")) {
-                // XML 格式(微信支付回调):从 request body 读取原始XML
-                StringBuilder sb = new StringBuilder();
-                try (BufferedReader reader = request.getReader()) {
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        sb.append(line);
-                    }
-                }
-                String body = sb.toString();
-                if (body != null && !body.isEmpty()) {
-                    params.put("xmlBody", body);
-                    log.debug("解析XML参数");
-                }
-            } else {
-                // form-urlencoded 格式:使用 @RequestParam 捕获的参数
-                if (requestParams != null && !requestParams.isEmpty()) {
-                    params.putAll(requestParams);
-                    log.debug("解析表单参数: {}", params.size());
-                }
-            }
-        } catch (Exception e) {
-            log.error("解析请求参数失败", e);
-        }
-
-        return params;
-    }
-
     /**
      * 构建回调成功响应
      * 根据不同支付渠道返回不同格式的成功响应
@@ -381,13 +288,13 @@ public class PaymentController {
     private String buildCallbackSuccessResponse(PaymentChannel channel) {
         if (channel == PaymentChannel.WECHAT) {
             // 微信支付 V3 返回 JSON 格式
-            return "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
+            return CallbackConstants.WECHAT_V3_SUCCESS;
         } else if (channel == PaymentChannel.ALIPAY || channel == PaymentChannel.ALIPAY_CREDIT) {
             // 支付宝返回 "success" 字符串
-            return "success";
+            return CallbackConstants.ALIPAY_SUCCESS;
         } else {
             // 其他渠道默认返回 "success"
-            return "success";
+            return CallbackConstants.ALIPAY_SUCCESS;
         }
     }
 
@@ -400,9 +307,9 @@ public class PaymentController {
     private String buildCallbackErrorResponse(String channelCode) {
         if ("wechat".equalsIgnoreCase(channelCode)) {
             // 微信支付 V3 返回 JSON 格式
-            return "{\"code\": \"FAIL\", \"message\": \"处理失败\"}";
+            return CallbackConstants.WECHAT_V3_FAIL;
         } else {
-            return "fail";
+            return CallbackConstants.FAIL;
         }
     }
 }

+ 28 - 108
haha-miniapp/src/main/java/com/haha/miniapp/controller/StatusQueryController.java

@@ -1,59 +1,37 @@
 package com.haha.miniapp.controller;
 
 import cn.dev33.satoken.annotation.SaIgnore;
+import com.haha.common.constant.ResponseEnum;
 import com.haha.common.vo.Result;
+import com.haha.service.StatusQueryService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
 import java.util.Map;
 
 @Slf4j
+@RequiredArgsConstructor
 @RestController
 @RequestMapping("/status")
 @SaIgnore
 public class StatusQueryController {
 
-    @Autowired
-    private StringRedisTemplate redisTemplate;
-
-    private static final String DEVICE_STATUS_KEY = "haha:device:status:";
-    private static final String RECOGNIZE_RESULT_KEY = "haha:recognize:result:";
-    private static final String ORDER_INFO_KEY = "haha:order:info:";
+    private final StatusQueryService statusQueryService;
 
     @PostMapping("/device")
     public Result<Map<String, String>> queryDeviceStatus(@RequestBody Map<String, String> params) {
         String deviceId = params.get("deviceId");
         if (deviceId == null || deviceId.isEmpty()) {
-            log.warn("[状态查询] 查询设备状态失败 - 设备ID为空");
-            return Result.error(400, "设备ID不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("设备ID不能为空");
         }
-        
+
         log.debug("[状态查询] 查询设备状态 - deviceId: {}", deviceId);
-        
-        String statusKey = DEVICE_STATUS_KEY + deviceId;
-        Map<Object, Object> statusData = redisTemplate.opsForHash().entries(statusKey);
-        
-        if (statusData.isEmpty()) {
-            log.debug("[状态查询] 设备状态暂无数据 - deviceId: {}", deviceId);
-            Map<String, String> emptyResult = new HashMap<>();
-            emptyResult.put("deviceId", deviceId);
-            emptyResult.put("doorStatus", "unknown");
-            return Result.success("暂无状态数据", emptyResult);
+        Map<String, String> result = statusQueryService.queryDeviceStatus(deviceId);
+
+        if (result.containsKey("doorStatus") && "unknown".equals(result.get("doorStatus"))) {
+            return Result.success("暂无状态数据", result);
         }
-        
-        Map<String, String> result = new HashMap<>();
-        result.put("deviceId", statusData.getOrDefault("deviceId", "").toString());
-        result.put("activityId", statusData.getOrDefault("activityId", "").toString());
-        result.put("doorStatus", statusData.getOrDefault("doorStatus", "unknown").toString());
-        result.put("openType", statusData.getOrDefault("openType", "").toString());
-        result.put("userId", statusData.getOrDefault("userId", "").toString());
-        result.put("timestamp", statusData.getOrDefault("timestamp", "").toString());
-        
-        log.debug("[状态查询] 设备状态查询成功 - deviceId: {}, doorStatus: {}", deviceId, result.get("doorStatus"));
-        
         return Result.success("查询成功", result);
     }
 
@@ -61,25 +39,15 @@ public class StatusQueryController {
     public Result<Map<String, String>> queryRecognizeResult(@RequestBody Map<String, String> params) {
         String activityId = params.get("activityId");
         if (activityId == null || activityId.isEmpty()) {
-            log.warn("[状态查询] 查询识别结果失败 - 活动ID为空");
-            return Result.error(400, "活动ID不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("活动ID不能为空");
         }
-        
+
         log.info("[状态查询] 查询识别结果 - activityId: {}", activityId);
-        
-        String resultKey = RECOGNIZE_RESULT_KEY + activityId;
-        Map<Object, Object> resultData = redisTemplate.opsForHash().entries(resultKey);
-        
-        if (resultData.isEmpty()) {
-            log.debug("[状态查询] 识别结果尚未生成 - activityId: {}", activityId);
-            return Result.error(404, "识别结果尚未生成,请稍后重试");
+        Map<String, String> result = statusQueryService.queryRecognizeResult(activityId);
+
+        if (result == null) {
+            return ResponseEnum.NOT_FOUND.toResult("识别结果尚未生成,请稍后重试");
         }
-        
-        Map<String, String> result = new HashMap<>();
-        resultData.forEach((k, v) -> result.put(k.toString(), v != null ? v.toString() : ""));
-        
-        log.info("[状态查询] 识别结果查询成功 - activityId: {}, nobuy: {}", activityId, result.get("nobuy"));
-        
         return Result.success("查询成功", result);
     }
 
@@ -87,28 +55,17 @@ public class StatusQueryController {
     public Result<Map<String, String>> queryOrderInfo(@RequestBody Map<String, String> params) {
         String orderId = params.get("orderId");
         String activityId = params.get("activityId");
-        
+
         if ((orderId == null || orderId.isEmpty()) && (activityId == null || activityId.isEmpty())) {
-            log.warn("[状态查询] 查询订单信息失败 - 订单ID和活动ID同时为空");
-            return Result.error(400, "订单ID或活动ID不能同时为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("订单ID或活动ID不能同时为空");
         }
-        
-        String queryKey = orderId != null && !orderId.isEmpty() ? orderId : activityId;
+
         log.debug("[状态查询] 查询订单信息 - orderId: {}, activityId: {}", orderId, activityId);
-        
-        String orderKey = ORDER_INFO_KEY + queryKey;
-        Map<Object, Object> orderData = redisTemplate.opsForHash().entries(orderKey);
-        
-        if (orderData.isEmpty()) {
-            log.debug("[状态查询] 订单信息尚未生成 - queryKey: {}", queryKey);
-            return Result.error(404, "订单信息尚未生成,请稍后重试");
+        Map<String, String> result = statusQueryService.queryOrderInfo(orderId, activityId);
+
+        if (result == null) {
+            return ResponseEnum.NOT_FOUND.toResult("订单信息尚未生成,请稍后重试");
         }
-        
-        Map<String, String> result = new HashMap<>();
-        orderData.forEach((k, v) -> result.put(k.toString(), v != null ? v.toString() : ""));
-        
-        log.debug("[状态查询] 订单信息查询成功 - queryKey: {}, totalAmount: {}", queryKey, result.get("totalAmount"));
-        
         return Result.success("查询成功", result);
     }
 
@@ -116,48 +73,11 @@ public class StatusQueryController {
     public Result<Map<String, Object>> queryAllStatus(@RequestBody Map<String, String> params) {
         String deviceId = params.get("deviceId");
         if (deviceId == null || deviceId.isEmpty()) {
-            log.warn("[状态查询] 综合状态查询失败 - 设备ID为空");
-            return Result.error(400, "设备ID不能为空");
+            return ResponseEnum.PARAM_REQUIRED.toResult("设备ID不能为空");
         }
-        
+
         log.debug("[状态查询] 综合状态查询 - deviceId: {}", deviceId);
-        
-        Map<String, Object> result = new HashMap<>();
-        
-        String statusKey = DEVICE_STATUS_KEY + deviceId;
-        Map<Object, Object> statusData = redisTemplate.opsForHash().entries(statusKey);
-        if (!statusData.isEmpty()) {
-            Map<String, String> deviceStatus = new HashMap<>();
-            statusData.forEach((k, v) -> deviceStatus.put(k.toString(), v != null ? v.toString() : ""));
-            result.put("deviceStatus", deviceStatus);
-            
-            String activityId = deviceStatus.get("activityId");
-            if (activityId != null && !activityId.isEmpty()) {
-                String recognizeKey = RECOGNIZE_RESULT_KEY + activityId;
-                Map<Object, Object> recognizeData = redisTemplate.opsForHash().entries(recognizeKey);
-                if (!recognizeData.isEmpty()) {
-                    Map<String, String> recognizeResult = new HashMap<>();
-                    recognizeData.forEach((k, v) -> recognizeResult.put(k.toString(), v != null ? v.toString() : ""));
-                    result.put("recognizeResult", recognizeResult);
-                }
-                
-                String orderKey = ORDER_INFO_KEY + activityId;
-                Map<Object, Object> orderData = redisTemplate.opsForHash().entries(orderKey);
-                if (!orderData.isEmpty()) {
-                    Map<String, String> orderInfo = new HashMap<>();
-                    orderData.forEach((k, v) -> orderInfo.put(k.toString(), v != null ? v.toString() : ""));
-                    result.put("orderInfo", orderInfo);
-                }
-            }
-        } else {
-            Map<String, String> emptyStatus = new HashMap<>();
-            emptyStatus.put("deviceId", deviceId);
-            emptyStatus.put("doorStatus", "unknown");
-            result.put("deviceStatus", emptyStatus);
-        }
-        
-        log.debug("[状态查询] 综合状态查询成功 - deviceId: {}, 包含数据: {}", deviceId, result.keySet());
-        
+        Map<String, Object> result = statusQueryService.queryAllStatus(deviceId);
         return Result.success("查询成功", result);
     }
-}
+}

+ 9 - 0
haha-service/src/main/java/com/haha/service/CheckinRecordService.java

@@ -64,6 +64,15 @@ public interface CheckinRecordService extends IService<CheckinRecord> {
      */
     Map<String, Object> syncOfflineCheckins(List<CheckinRecord> records);
 
+    /**
+     * 从离线数据Map构建签到记录并同步
+     *
+     * @param recordsData 离线签到数据列表
+     * @param userId 用户ID
+     * @return 同步结果
+     */
+    Map<String, Object> syncOfflineCheckinsFromData(List<Map<String, Object>> recordsData, Long userId);
+
     /**
      * 导出签到记录
      *

+ 16 - 17
haha-service/src/main/java/com/haha/service/DictService.java

@@ -1,7 +1,6 @@
 package com.haha.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.haha.common.vo.Result;
 import com.haha.entity.DictData;
 import com.haha.entity.DictType;
 
@@ -13,33 +12,33 @@ import java.util.Map;
  */
 public interface DictService extends IService<DictType> {
 
-    Result<Map<String, Object>> getDictTypeList(Map<String, Object> params);
+    Map<String, Object> getDictTypeList(Map<String, Object> params);
 
-    Result<DictType> getDictTypeById(Long id);
+    DictType getDictTypeById(Long id);
 
-    Result<DictType> getDictTypeByCode(String dictCode);
+    DictType getDictTypeByCode(String dictCode);
 
-    Result<Void> addDictType(DictType dictType);
+    void addDictType(DictType dictType);
 
-    Result<Void> updateDictType(DictType dictType);
+    void updateDictType(DictType dictType);
 
-    Result<Void> deleteDictType(Long id);
+    void deleteDictType(Long id);
 
-    Result<Void> batchDeleteDictType(List<Long> ids);
+    void batchDeleteDictType(List<Long> ids);
 
-    Result<List<DictData>> getDictDataList(String dictCode);
+    List<DictData> getDictDataList(String dictCode);
 
-    Result<Map<String, Object>> getDictDataPage(Map<String, Object> params);
+    Map<String, Object> getDictDataPage(Map<String, Object> params);
 
-    Result<DictData> getDictDataById(Long id);
+    DictData getDictDataById(Long id);
 
-    Result<Void> addDictData(DictData dictData);
+    void addDictData(DictData dictData);
 
-    Result<Void> updateDictData(DictData dictData);
+    void updateDictData(DictData dictData);
 
-    Result<Void> deleteDictData(Long id);
+    void deleteDictData(Long id);
 
-    Result<Void> batchDeleteDictData(List<Long> ids);
+    void batchDeleteDictData(List<Long> ids);
 
     Map<String, List<DictData>> getAllDictData();
 
@@ -51,7 +50,7 @@ public interface DictService extends IService<DictType> {
 
     String getDictValue(String dictCode, String itemLabel);
 
-    Result<Void> exportDictData(String dictCode);
+    void exportDictData(String dictCode);
 
-    Result<Void> importDictData(List<DictData> dataList);
+    void importDictData(List<DictData> dataList);
 }

+ 29 - 0
haha-service/src/main/java/com/haha/service/OrderService.java

@@ -112,4 +112,33 @@ public interface OrderService extends IService<Order> {
      * @return 是否成功
      */
     boolean completeOrderWithPayScore(Long orderId, BigDecimal totalAmount);
+
+    /**
+     * 获取用户订单列表(带商品信息)
+     *
+     * @param userId 用户ID
+     * @param status 订单状态(可选)
+     * @return 订单列表Map
+     */
+    List<Map<String, Object>> getUserOrderListWithProducts(Long userId, Integer status);
+
+    /**
+     * 获取用户订单详情(带商品信息和状态文本)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @param orderNo 订单号
+     * @param outTradeNo 商户订单号
+     * @return 订单详情Map,不存在返回null
+     */
+    Map<String, Object> getUserOrderDetail(Long userId, Long orderId, String orderNo, String outTradeNo);
+
+    /**
+     * 取消订单(含权限和状态校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @return 是否成功
+     */
+    boolean cancelUserOrder(Long userId, Long orderId);
 }

+ 43 - 0
haha-service/src/main/java/com/haha/service/StatusQueryService.java

@@ -0,0 +1,43 @@
+package com.haha.service;
+
+import java.util.Map;
+
+/**
+ * 状态查询服务接口
+ * 封装设备状态、识别结果、订单信息的Redis查询逻辑
+ */
+public interface StatusQueryService {
+
+    /**
+     * 查询设备状态
+     *
+     * @param deviceId 设备ID
+     * @return 设备状态数据
+     */
+    Map<String, String> queryDeviceStatus(String deviceId);
+
+    /**
+     * 查询识别结果
+     *
+     * @param activityId 活动ID
+     * @return 识别结果数据
+     */
+    Map<String, String> queryRecognizeResult(String activityId);
+
+    /**
+     * 查询订单信息
+     *
+     * @param orderId    订单ID(可为空)
+     * @param activityId 活动ID(可为空,与orderId至少提供一个)
+     * @return 订单信息数据
+     */
+    Map<String, String> queryOrderInfo(String orderId, String activityId);
+
+    /**
+     * 综合查询设备所有状态(设备状态+识别结果+订单信息)
+     *
+     * @param deviceId 设备ID
+     * @return 综合状态数据
+     */
+    Map<String, Object> queryAllStatus(String deviceId);
+}

+ 57 - 9
haha-service/src/main/java/com/haha/service/impl/CheckinRecordServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.haha.common.constant.CheckinConstants;
 import com.haha.entity.dto.CheckinQueryDTO;
 import com.haha.entity.dto.CheckinSubmitDTO;
 import com.haha.entity.CheckinRecord;
@@ -195,10 +196,10 @@ public class CheckinRecordServiceImpl extends ServiceImpl<CheckinRecordMapper, C
         List<CheckinRecord> todayRecords = checkinRecordMapper.selectTodayCheckinByUser(userId);
 
         for (CheckinRecord record : todayRecords) {
-            if ("inventory_tally".equals(record.getCheckinType())) {
+            if (CheckinConstants.TYPE_INVENTORY_TALLY.equals(record.getCheckinType())) {
                 result.put("hasInventoryTally", true);
                 result.put("inventoryTallyTime", formatDateTime(record.getCheckinTime()));
-            } else if ("delivery_replenish".equals(record.getCheckinType())) {
+            } else if (CheckinConstants.TYPE_REPLENISHMENT.equals(record.getCheckinType())) {
                 result.put("hasDeliveryReplenish", true);
                 result.put("deliveryReplenishTime", formatDateTime(record.getCheckinTime()));
             }
@@ -227,7 +228,7 @@ public class CheckinRecordServiceImpl extends ServiceImpl<CheckinRecordMapper, C
                     }
                 }
 
-                record.setStatus("synced");
+                record.setStatus(CheckinConstants.STATUS_SYNCED);
                 record.setSyncedAt(LocalDateTime.now());
                 record.setUpdateTime(LocalDateTime.now());
 
@@ -266,6 +267,58 @@ public class CheckinRecordServiceImpl extends ServiceImpl<CheckinRecordMapper, C
         return checkinRecordMapper.countTodayCheckinByUserAndType(userId, checkinType) > 0;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> syncOfflineCheckinsFromData(List<Map<String, Object>> recordsData, Long userId) {
+        List<CheckinRecord> records = new ArrayList<>();
+        for (Map<String, Object> data : recordsData) {
+            CheckinRecord record = new CheckinRecord();
+            record.setCheckinType((String) data.get("type"));
+            record.setUserId(userId);
+            record.setUserName((String) data.get("userName"));
+            record.setUserNo((String) data.get("userNo"));
+            record.setShopId(data.get("shopId") != null ? Long.valueOf(data.get("shopId").toString()) : null);
+            record.setDeviceId((String) data.get("deviceId"));
+
+            @SuppressWarnings("unchecked")
+            Map<String, Object> location = (Map<String, Object>) data.get("location");
+            if (location != null) {
+                record.setLatitude(new java.math.BigDecimal(location.get("latitude").toString()));
+                record.setLongitude(new java.math.BigDecimal(location.get("longitude").toString()));
+                record.setAddress((String) location.get("address"));
+                record.setAccuracy(location.get("accuracy") != null ? Integer.valueOf(location.get("accuracy").toString()) : null);
+            }
+
+            @SuppressWarnings("unchecked")
+            List<Map<String, Object>> photos = (List<Map<String, Object>>) data.get("photos");
+            if (photos != null) {
+                record.setPhotos(JSON.toJSONString(photos));
+            }
+
+            record.setRemark((String) data.get("remark"));
+            record.setOfflineId((String) data.get("offlineId"));
+            record.setStatus(CheckinConstants.STATUS_PENDING);
+
+            String createdAt = (String) data.get("createdAt");
+            if (createdAt != null) {
+                try {
+                    record.setCheckinTime(LocalDateTime.parse(createdAt.replace(" ", "T")));
+                    record.setCreateTime(record.getCheckinTime());
+                } catch (Exception e) {
+                    record.setCheckinTime(LocalDateTime.now());
+                    record.setCreateTime(LocalDateTime.now());
+                }
+            } else {
+                record.setCheckinTime(LocalDateTime.now());
+                record.setCreateTime(LocalDateTime.now());
+            }
+
+            records.add(record);
+        }
+
+        return syncOfflineCheckins(records);
+    }
+
     private void processCheckinRecord(Map<String, Object> record) {
         record.put("typeName", getTypeName((String) record.get("checkin_type")));
 
@@ -295,12 +348,7 @@ public class CheckinRecordServiceImpl extends ServiceImpl<CheckinRecordMapper, C
     }
 
     private String getTypeName(String type) {
-        if ("inventory_tally".equals(type)) {
-            return "理货盘点签到";
-        } else if ("delivery_replenish".equals(type)) {
-            return "补货确认签到";
-        }
-        return "未知类型";
+        return CheckinConstants.getTypeName(type);
     }
 
     private String formatDateTime(Object dateTime) {

+ 202 - 340
haha-service/src/main/java/com/haha/service/impl/DictServiceImpl.java

@@ -4,7 +4,10 @@ import com.alibaba.fastjson2.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.haha.common.vo.Result;
+import com.haha.common.constant.ResponseEnum;
+import com.haha.common.constant.RedisConstants;
+import com.haha.common.exception.BusinessException;
+import com.haha.common.utils.PageUtil;
 import com.haha.entity.DictData;
 import com.haha.entity.DictLog;
 import com.haha.entity.DictType;
@@ -12,8 +15,8 @@ import com.haha.mapper.DictDataMapper;
 import com.haha.mapper.DictLogMapper;
 import com.haha.mapper.DictTypeMapper;
 import com.haha.service.DictService;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -24,6 +27,7 @@ import java.util.*;
 import java.util.concurrent.TimeUnit;
 
 @Slf4j
+@RequiredArgsConstructor
 @Service
 public class DictServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements DictService {
 
@@ -31,401 +35,270 @@ public class DictServiceImpl extends ServiceImpl<DictTypeMapper, DictType> imple
     private static final String DICT_ALL_CACHE_KEY = "dict:data:all";
     private static final long CACHE_EXPIRE_HOURS = 24;
 
-    @Autowired
-    private DictTypeMapper dictTypeMapper;
-
-    @Autowired
-    private DictDataMapper dictDataMapper;
-
-    @Autowired
-    private DictLogMapper dictLogMapper;
-
-    @Autowired
-    private StringRedisTemplate redisTemplate;
+    private final DictTypeMapper dictTypeMapper;
+    private final DictDataMapper dictDataMapper;
+    private final DictLogMapper dictLogMapper;
+    private final StringRedisTemplate redisTemplate;
 
     @Override
-    public Result<Map<String, Object>> getDictTypeList(Map<String, Object> params) {
-        try {
-            int page = Integer.parseInt(params.getOrDefault("page", 1).toString());
-            int pageSize = Integer.parseInt(params.getOrDefault("pageSize", 10).toString());
-            String dictCode = (String) params.get("dictCode");
-            String dictName = (String) params.get("dictName");
-            Integer status = params.get("status") != null ? Integer.parseInt(params.get("status").toString()) : null;
-
-            LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
-            if (StringUtils.hasText(dictCode)) {
-                wrapper.like(DictType::getDictCode, dictCode);
-            }
-            if (StringUtils.hasText(dictName)) {
-                wrapper.like(DictType::getDictName, dictName);
-            }
-            if (status != null) {
-                wrapper.eq(DictType::getStatus, status);
-            }
-            wrapper.orderByAsc(DictType::getSortOrder);
-            wrapper.orderByDesc(DictType::getCreateTime);
-
-            Page<DictType> pageObj = new Page<>(page, pageSize);
-            Page<DictType> result = dictTypeMapper.selectPage(pageObj, wrapper);
+    public Map<String, Object> getDictTypeList(Map<String, Object> params) {
+        int[] pageParams = PageUtil.parsePageParams(params);
+        int page = pageParams[0];
+        int pageSize = pageParams[1];
+        String dictCode = (String) params.get("dictCode");
+        String dictName = (String) params.get("dictName");
+        Integer status = params.get("status") != null ? Integer.parseInt(params.get("status").toString()) : null;
+
+        LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.hasText(dictCode)) {
+            wrapper.like(DictType::getDictCode, dictCode);
+        }
+        if (StringUtils.hasText(dictName)) {
+            wrapper.like(DictType::getDictName, dictName);
+        }
+        if (status != null) {
+            wrapper.eq(DictType::getStatus, status);
+        }
+        wrapper.orderByAsc(DictType::getSortOrder);
+        wrapper.orderByDesc(DictType::getCreateTime);
 
-            Map<String, Object> data = new HashMap<>();
-            data.put("list", result.getRecords());
-            data.put("total", result.getTotal());
-            data.put("pageSize", pageSize);
-            data.put("currentPage", page);
+        Page<DictType> pageObj = new Page<>(page, pageSize);
+        Page<DictType> result = dictTypeMapper.selectPage(pageObj, wrapper);
 
-            return Result.success("查询成功", data);
-        } catch (Exception e) {
-            log.error("查询字典类型列表失败", e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+        return PageUtil.buildPageResult(result, page, pageSize);
     }
 
     @Override
-    public Result<DictType> getDictTypeById(Long id) {
-        try {
-            DictType dictType = dictTypeMapper.selectById(id);
-            if (dictType == null) {
-                return Result.error(404, "字典类型不存在");
-            }
-            return Result.success("查询成功", dictType);
-        } catch (Exception e) {
-            log.error("查询字典类型失败, id={}", id, e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+    public DictType getDictTypeById(Long id) {
+        DictType dictType = dictTypeMapper.selectById(id);
+        ResponseEnum.DICT_TYPE_NOT_FOUND.assertNotNull(dictType);
+        return dictType;
     }
 
     @Override
-    public Result<DictType> getDictTypeByCode(String dictCode) {
-        try {
-            LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(DictType::getDictCode, dictCode);
-            DictType dictType = dictTypeMapper.selectOne(wrapper);
-            if (dictType == null) {
-                return Result.error(404, "字典类型不存在");
-            }
-            return Result.success("查询成功", dictType);
-        } catch (Exception e) {
-            log.error("查询字典类型失败, dictCode={}", dictCode, e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+    public DictType getDictTypeByCode(String dictCode) {
+        LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DictType::getDictCode, dictCode);
+        DictType dictType = dictTypeMapper.selectOne(wrapper);
+        ResponseEnum.DICT_TYPE_NOT_FOUND.assertNotNull(dictType);
+        return dictType;
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> addDictType(DictType dictType) {
-        try {
-            LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(DictType::getDictCode, dictType.getDictCode());
-            if (dictTypeMapper.selectCount(wrapper) > 0) {
-                return Result.error(400, "字典编码已存在");
-            }
-
-            dictType.setCreateTime(LocalDateTime.now());
-            dictType.setUpdateTime(LocalDateTime.now());
-            dictTypeMapper.insert(dictType);
+    public void addDictType(DictType dictType) {
+        LambdaQueryWrapper<DictType> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DictType::getDictCode, dictType.getDictCode());
+        if (dictTypeMapper.selectCount(wrapper) > 0) {
+            throw new BusinessException(ResponseEnum.DICT_CODE_DUPLICATE);
+        }
 
-            saveDictLog(dictType, null, "insert", "新增字典类型");
+        dictType.setCreateTime(LocalDateTime.now());
+        dictType.setUpdateTime(LocalDateTime.now());
+        dictTypeMapper.insert(dictType);
 
-            return Result.success("添加成功");
-        } catch (Exception e) {
-            log.error("添加字典类型失败", e);
-            return Result.error(500, "添加失败: " + e.getMessage());
-        }
+        saveDictLog(dictType, null, "insert", "新增字典类型");
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> updateDictType(DictType dictType) {
-        try {
-            DictType oldDictType = dictTypeMapper.selectById(dictType.getId());
-            if (oldDictType == null) {
-                return Result.error(404, "字典类型不存在");
-            }
+    public void updateDictType(DictType dictType) {
+        DictType oldDictType = dictTypeMapper.selectById(dictType.getId());
+        ResponseEnum.DICT_TYPE_NOT_FOUND.assertNotNull(oldDictType);
 
-            dictType.setUpdateTime(LocalDateTime.now());
-            dictTypeMapper.updateById(dictType);
+        dictType.setUpdateTime(LocalDateTime.now());
+        dictTypeMapper.updateById(dictType);
 
-            saveDictLog(dictType, oldDictType, "update", "修改字典类型");
-
-            return Result.success("修改成功");
-        } catch (Exception e) {
-            log.error("修改字典类型失败", e);
-            return Result.error(500, "修改失败: " + e.getMessage());
-        }
+        saveDictLog(dictType, oldDictType, "update", "修改字典类型");
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> deleteDictType(Long id) {
-        try {
-            DictType dictType = dictTypeMapper.selectById(id);
-            if (dictType == null) {
-                return Result.error(404, "字典类型不存在");
-            }
+    public void deleteDictType(Long id) {
+        DictType dictType = dictTypeMapper.selectById(id);
+        ResponseEnum.DICT_TYPE_NOT_FOUND.assertNotNull(dictType);
 
-            if (dictType.getIsSystem() != null && dictType.getIsSystem() == 1) {
-                return Result.error(400, "系统内置字典不允许删除");
-            }
-
-            dictDataMapper.deleteByDictCode(dictType.getDictCode());
-            dictTypeMapper.deleteById(id);
+        if (dictType.getIsSystem() != null && dictType.getIsSystem() == 1) {
+            throw new BusinessException(ResponseEnum.DICT_SYSTEM_NO_DELETE);
+        }
 
-            clearDictCache(dictType.getDictCode());
+        dictDataMapper.deleteByDictCode(dictType.getDictCode());
+        dictTypeMapper.deleteById(id);
 
-            saveDictLog(dictType, null, "delete", "删除字典类型");
+        clearDictCache(dictType.getDictCode());
 
-            return Result.success("删除成功");
-        } catch (Exception e) {
-            log.error("删除字典类型失败", e);
-            return Result.error(500, "删除失败: " + e.getMessage());
-        }
+        saveDictLog(dictType, null, "delete", "删除字典类型");
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> batchDeleteDictType(List<Long> ids) {
-        try {
-            for (Long id : ids) {
-                DictType dictType = dictTypeMapper.selectById(id);
-                if (dictType != null && (dictType.getIsSystem() == null || dictType.getIsSystem() != 1)) {
-                    dictDataMapper.deleteByDictCode(dictType.getDictCode());
-                    dictTypeMapper.deleteById(id);
-                    clearDictCache(dictType.getDictCode());
-                }
+    public void batchDeleteDictType(List<Long> ids) {
+        for (Long id : ids) {
+            DictType dictType = dictTypeMapper.selectById(id);
+            if (dictType != null && (dictType.getIsSystem() == null || dictType.getIsSystem() != 1)) {
+                dictDataMapper.deleteByDictCode(dictType.getDictCode());
+                dictTypeMapper.deleteById(id);
+                clearDictCache(dictType.getDictCode());
             }
-            return Result.success("批量删除成功");
-        } catch (Exception e) {
-            log.error("批量删除字典类型失败", e);
-            return Result.error(500, "批量删除失败: " + e.getMessage());
         }
     }
 
     @Override
-    public Result<List<DictData>> getDictDataList(String dictCode) {
-        try {
-            List<DictData> dataList = getDictDataByCode(dictCode);
-            return Result.success("查询成功", dataList);
-        } catch (Exception e) {
-            log.error("查询字典数据列表失败, dictCode={}", dictCode, e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+    public List<DictData> getDictDataList(String dictCode) {
+        return getDictDataByCode(dictCode);
     }
 
     @Override
-    public Result<Map<String, Object>> getDictDataPage(Map<String, Object> params) {
-        try {
-            int page = Integer.parseInt(params.getOrDefault("page", 1).toString());
-            int pageSize = Integer.parseInt(params.getOrDefault("pageSize", 10).toString());
-            String dictCode = (String) params.get("dictCode");
-            String itemLabel = (String) params.get("itemLabel");
-            Integer status = params.get("status") != null ? Integer.parseInt(params.get("status").toString()) : null;
-
-            LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
-            if (StringUtils.hasText(dictCode)) {
-                wrapper.eq(DictData::getDictCode, dictCode);
-            }
-            if (StringUtils.hasText(itemLabel)) {
-                wrapper.like(DictData::getItemLabel, itemLabel);
-            }
-            if (status != null) {
-                wrapper.eq(DictData::getStatus, status);
-            }
-            wrapper.orderByAsc(DictData::getSortOrder);
-            wrapper.orderByDesc(DictData::getCreateTime);
-
-            Page<DictData> pageObj = new Page<>(page, pageSize);
-            Page<DictData> result = dictDataMapper.selectPage(pageObj, wrapper);
+    public Map<String, Object> getDictDataPage(Map<String, Object> params) {
+        int[] pageParams = PageUtil.parsePageParams(params);
+        int page = pageParams[0];
+        int pageSize = pageParams[1];
+        String dictCode = (String) params.get("dictCode");
+        String itemLabel = (String) params.get("itemLabel");
+        Integer status = params.get("status") != null ? Integer.parseInt(params.get("status").toString()) : null;
+
+        LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.hasText(dictCode)) {
+            wrapper.eq(DictData::getDictCode, dictCode);
+        }
+        if (StringUtils.hasText(itemLabel)) {
+            wrapper.like(DictData::getItemLabel, itemLabel);
+        }
+        if (status != null) {
+            wrapper.eq(DictData::getStatus, status);
+        }
+        wrapper.orderByAsc(DictData::getSortOrder);
+        wrapper.orderByDesc(DictData::getCreateTime);
 
-            Map<String, Object> data = new HashMap<>();
-            data.put("list", result.getRecords());
-            data.put("total", result.getTotal());
-            data.put("pageSize", pageSize);
-            data.put("currentPage", page);
+        Page<DictData> pageObj = new Page<>(page, pageSize);
+        Page<DictData> result = dictDataMapper.selectPage(pageObj, wrapper);
 
-            return Result.success("查询成功", data);
-        } catch (Exception e) {
-            log.error("查询字典数据列表失败", e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+        return PageUtil.buildPageResult(result, page, pageSize);
     }
 
     @Override
-    public Result<DictData> getDictDataById(Long id) {
-        try {
-            DictData dictData = dictDataMapper.selectById(id);
-            if (dictData == null) {
-                return Result.error(404, "字典数据不存在");
-            }
-            return Result.success("查询成功", dictData);
-        } catch (Exception e) {
-            log.error("查询字典数据失败, id={}", id, e);
-            return Result.error(500, "查询失败: " + e.getMessage());
-        }
+    public DictData getDictDataById(Long id) {
+        DictData dictData = dictDataMapper.selectById(id);
+        ResponseEnum.DICT_DATA_NOT_FOUND.assertNotNull(dictData);
+        return dictData;
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> addDictData(DictData dictData) {
-        try {
-            LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(DictData::getDictCode, dictData.getDictCode());
-            wrapper.eq(DictData::getItemValue, dictData.getItemValue());
-            if (dictDataMapper.selectCount(wrapper) > 0) {
-                return Result.error(400, "该字典下已存在相同的字典项值");
-            }
-
-            dictData.setCreateTime(LocalDateTime.now());
-            dictData.setUpdateTime(LocalDateTime.now());
-            dictDataMapper.insert(dictData);
+    public void addDictData(DictData dictData) {
+        LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(DictData::getDictCode, dictData.getDictCode());
+        wrapper.eq(DictData::getItemValue, dictData.getItemValue());
+        if (dictDataMapper.selectCount(wrapper) > 0) {
+            throw new BusinessException(ResponseEnum.DICT_ITEM_VALUE_DUPLICATE);
+        }
 
-            clearDictCache(dictData.getDictCode());
+        dictData.setCreateTime(LocalDateTime.now());
+        dictData.setUpdateTime(LocalDateTime.now());
+        dictDataMapper.insert(dictData);
 
-            return Result.success("添加成功");
-        } catch (Exception e) {
-            log.error("添加字典数据失败", e);
-            return Result.error(500, "添加失败: " + e.getMessage());
-        }
+        clearDictCache(dictData.getDictCode());
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> updateDictData(DictData dictData) {
-        try {
-            DictData oldDictData = dictDataMapper.selectById(dictData.getId());
-            if (oldDictData == null) {
-                return Result.error(404, "字典数据不存在");
-            }
+    public void updateDictData(DictData dictData) {
+        DictData oldDictData = dictDataMapper.selectById(dictData.getId());
+        ResponseEnum.DICT_DATA_NOT_FOUND.assertNotNull(oldDictData);
 
-            if (!oldDictData.getItemValue().equals(dictData.getItemValue())) {
-                LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
-                wrapper.eq(DictData::getDictCode, oldDictData.getDictCode());
-                wrapper.eq(DictData::getItemValue, dictData.getItemValue());
-                wrapper.ne(DictData::getId, dictData.getId());
-                if (dictDataMapper.selectCount(wrapper) > 0) {
-                    return Result.error(400, "该字典下已存在相同的字典项值");
-                }
+        if (!oldDictData.getItemValue().equals(dictData.getItemValue())) {
+            LambdaQueryWrapper<DictData> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(DictData::getDictCode, oldDictData.getDictCode());
+            wrapper.eq(DictData::getItemValue, dictData.getItemValue());
+            wrapper.ne(DictData::getId, dictData.getId());
+            if (dictDataMapper.selectCount(wrapper) > 0) {
+                throw new BusinessException(ResponseEnum.DICT_ITEM_VALUE_DUPLICATE);
             }
+        }
 
-            dictData.setUpdateTime(LocalDateTime.now());
-            dictDataMapper.updateById(dictData);
-
-            clearDictCache(oldDictData.getDictCode());
+        dictData.setUpdateTime(LocalDateTime.now());
+        dictDataMapper.updateById(dictData);
 
-            return Result.success("修改成功");
-        } catch (Exception e) {
-            log.error("修改字典数据失败", e);
-            return Result.error(500, "修改失败: " + e.getMessage());
-        }
+        clearDictCache(oldDictData.getDictCode());
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> deleteDictData(Long id) {
-        try {
-            DictData dictData = dictDataMapper.selectById(id);
-            if (dictData == null) {
-                return Result.error(404, "字典数据不存在");
-            }
+    public void deleteDictData(Long id) {
+        DictData dictData = dictDataMapper.selectById(id);
+        ResponseEnum.DICT_DATA_NOT_FOUND.assertNotNull(dictData);
 
-            dictDataMapper.deleteById(id);
+        dictDataMapper.deleteById(id);
 
-            clearDictCache(dictData.getDictCode());
-
-            return Result.success("删除成功");
-        } catch (Exception e) {
-            log.error("删除字典数据失败", e);
-            return Result.error(500, "删除失败: " + e.getMessage());
-        }
+        clearDictCache(dictData.getDictCode());
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> batchDeleteDictData(List<Long> ids) {
-        try {
-            Set<String> dictCodes = new HashSet<>();
-            for (Long id : ids) {
-                DictData dictData = dictDataMapper.selectById(id);
-                if (dictData != null) {
-                    dictCodes.add(dictData.getDictCode());
-                    dictDataMapper.deleteById(id);
-                }
-            }
-
-            for (String dictCode : dictCodes) {
-                clearDictCache(dictCode);
+    public void batchDeleteDictData(List<Long> ids) {
+        Set<String> dictCodes = new HashSet<>();
+        for (Long id : ids) {
+            DictData dictData = dictDataMapper.selectById(id);
+            if (dictData != null) {
+                dictCodes.add(dictData.getDictCode());
+                dictDataMapper.deleteById(id);
             }
+        }
 
-            return Result.success("批量删除成功");
-        } catch (Exception e) {
-            log.error("批量删除字典数据失败", e);
-            return Result.error(500, "批量删除失败: " + e.getMessage());
+        for (String dictCode : dictCodes) {
+            clearDictCache(dictCode);
         }
     }
 
     @Override
     public Map<String, List<DictData>> getAllDictData() {
-        try {
-            String cachedJson = redisTemplate.opsForValue().get(DICT_ALL_CACHE_KEY);
-            if (cachedJson != null) {
-                return JSON.parseObject(cachedJson, Map.class);
-            }
+        String cachedJson = redisTemplate.opsForValue().get(DICT_ALL_CACHE_KEY);
+        if (cachedJson != null) {
+            return JSON.parseObject(cachedJson, Map.class);
+        }
 
-            LambdaQueryWrapper<DictType> typeWrapper = new LambdaQueryWrapper<>();
-            typeWrapper.eq(DictType::getStatus, 1);
-            typeWrapper.orderByAsc(DictType::getSortOrder);
-            List<DictType> dictTypes = dictTypeMapper.selectList(typeWrapper);
+        LambdaQueryWrapper<DictType> typeWrapper = new LambdaQueryWrapper<>();
+        typeWrapper.eq(DictType::getStatus, 1);
+        typeWrapper.orderByAsc(DictType::getSortOrder);
+        List<DictType> dictTypes = dictTypeMapper.selectList(typeWrapper);
 
-            Map<String, List<DictData>> cachedData = new LinkedHashMap<>();
+        Map<String, List<DictData>> cachedData = new LinkedHashMap<>();
 
-            for (DictType dictType : dictTypes) {
-                List<DictData> dataList = getDictDataByCode(dictType.getDictCode());
-                cachedData.put(dictType.getDictCode(), dataList);
-            }
+        for (DictType dictType : dictTypes) {
+            List<DictData> dataList = getDictDataByCode(dictType.getDictCode());
+            cachedData.put(dictType.getDictCode(), dataList);
+        }
 
-            redisTemplate.opsForValue().set(DICT_ALL_CACHE_KEY, JSON.toJSONString(cachedData), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
+        redisTemplate.opsForValue().set(DICT_ALL_CACHE_KEY, JSON.toJSONString(cachedData), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
 
-            return cachedData;
-        } catch (Exception e) {
-            log.error("获取所有字典数据失败", e);
-            return new HashMap<>();
-        }
+        return cachedData;
     }
 
     @Override
     public List<DictData> getDictDataByCode(String dictCode) {
-        try {
-            String cacheKey = DICT_CACHE_KEY + dictCode;
-            String cachedJson = redisTemplate.opsForValue().get(cacheKey);
-            if (cachedJson != null) {
-                return JSON.parseArray(cachedJson, DictData.class);
-            }
+        String cacheKey = DICT_CACHE_KEY + dictCode;
+        String cachedJson = redisTemplate.opsForValue().get(cacheKey);
+        if (cachedJson != null) {
+            return JSON.parseArray(cachedJson, DictData.class);
+        }
 
-            List<DictData> dataList = dictDataMapper.selectByDictCode(dictCode);
+        List<DictData> dataList = dictDataMapper.selectByDictCode(dictCode);
 
-            redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(dataList), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
+        redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(dataList), CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
 
-            return dataList;
-        } catch (Exception e) {
-            log.error("获取字典数据失败, dictCode={}", dictCode, e);
-            return new ArrayList<>();
-        }
+        return dataList;
     }
 
     @Override
     public void refreshCache() {
-        try {
-            Set<String> keys = redisTemplate.keys(DICT_CACHE_KEY + "*");
-            if (keys != null && !keys.isEmpty()) {
-                redisTemplate.delete(keys);
-            }
-            if (Boolean.TRUE.equals(redisTemplate.hasKey(DICT_ALL_CACHE_KEY))) {
-                redisTemplate.delete(DICT_ALL_CACHE_KEY);
-            }
-            log.info("字典缓存已刷新");
-        } catch (Exception e) {
-            log.error("刷新字典缓存失败", e);
+        Set<String> keys = redisTemplate.keys(DICT_CACHE_KEY + "*");
+        if (keys != null && !keys.isEmpty()) {
+            redisTemplate.delete(keys);
         }
+        if (Boolean.TRUE.equals(redisTemplate.hasKey(DICT_ALL_CACHE_KEY))) {
+            redisTemplate.delete(DICT_ALL_CACHE_KEY);
+        }
+        log.info("字典缓存已刷新");
     }
 
     @Override
@@ -457,58 +330,47 @@ public class DictServiceImpl extends ServiceImpl<DictTypeMapper, DictType> imple
     }
 
     @Override
-    public Result<Void> exportDictData(String dictCode) {
-        return Result.success("导出成功");
+    public void exportDictData(String dictCode) {
+        // 导出功能暂未实现
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public Result<Void> importDictData(List<DictData> dataList) {
-        try {
-            if (dataList == null || dataList.isEmpty()) {
-                return Result.error(400, "导入数据不能为空");
-            }
-
-            Set<String> dictCodes = new HashSet<>();
-            for (DictData data : dataList) {
-                data.setCreateTime(LocalDateTime.now());
-                data.setUpdateTime(LocalDateTime.now());
-                dictDataMapper.insert(data);
-                dictCodes.add(data.getDictCode());
-            }
+    public void importDictData(List<DictData> dataList) {
+        if (dataList == null || dataList.isEmpty()) {
+            throw new BusinessException(ResponseEnum.IMPORT_DATA_EMPTY);
+        }
 
-            for (String code : dictCodes) {
-                clearDictCache(code);
-            }
+        Set<String> dictCodes = new HashSet<>();
+        for (DictData data : dataList) {
+            data.setCreateTime(LocalDateTime.now());
+            data.setUpdateTime(LocalDateTime.now());
+            dictDataMapper.insert(data);
+            dictCodes.add(data.getDictCode());
+        }
 
-            return Result.success("导入成功");
-        } catch (Exception e) {
-            log.error("导入字典数据失败", e);
-            return Result.error(500, "导入失败: " + e.getMessage());
+        for (String code : dictCodes) {
+            clearDictCache(code);
         }
     }
 
     private void clearDictCache(String dictCode) {
-        try {
-            String cacheKey = DICT_CACHE_KEY + dictCode;
-            redisTemplate.delete(cacheKey);
-            redisTemplate.delete(DICT_ALL_CACHE_KEY);
-        } catch (Exception e) {
-            log.error("清除字典缓存失败, dictCode={}", dictCode, e);
-        }
+        String cacheKey = DICT_CACHE_KEY + dictCode;
+        redisTemplate.delete(cacheKey);
+        redisTemplate.delete(DICT_ALL_CACHE_KEY);
     }
 
     private void saveDictLog(DictType dictType, DictType oldDictType, String operationType, String operationDesc) {
         try {
-            DictLog log = new DictLog();
-            log.setDictCode(dictType.getDictCode());
-            log.setDictName(dictType.getDictName());
-            log.setOperationType(operationType);
-            log.setOperationDesc(operationDesc);
-            log.setBeforeData(oldDictType != null ? JSON.toJSONString(oldDictType) : null);
-            log.setAfterData(JSON.toJSONString(dictType));
-            log.setCreateTime(LocalDateTime.now());
-            dictLogMapper.insert(log);
+            DictLog logEntry = new DictLog();
+            logEntry.setDictCode(dictType.getDictCode());
+            logEntry.setDictName(dictType.getDictName());
+            logEntry.setOperationType(operationType);
+            logEntry.setOperationDesc(operationDesc);
+            logEntry.setBeforeData(oldDictType != null ? JSON.toJSONString(oldDictType) : null);
+            logEntry.setAfterData(JSON.toJSONString(dictType));
+            logEntry.setCreateTime(LocalDateTime.now());
+            dictLogMapper.insert(logEntry);
         } catch (Exception e) {
             log.error("保存字典日志失败", e);
         }

+ 6 - 8
haha-service/src/main/java/com/haha/service/impl/HahaCallbackServiceImpl.java

@@ -3,6 +3,8 @@ package com.haha.service.impl;
 import com.alibaba.fastjson2.JSON;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
+import com.haha.common.config.CommonConfig;
+import com.haha.common.constant.RedisConstants;
 import com.haha.common.enums.DeviceDoorStatus;
 import com.haha.common.enums.PayScoreState;
 import com.haha.common.enums.PaymentChannel;
@@ -87,10 +89,6 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
     @Autowired
     private DeviceAlertProperties alertProperties;
 
-    private static final String DEVICE_STATUS_KEY = "haha:device:status:";
-    private static final String RECOGNIZE_RESULT_KEY = "haha:recognize:result:";
-    private static final String ORDER_INFO_KEY = "haha:order:info:";
-
     @Override
     public void handleMessage(Map<String, Object> params) {
         String notifyType = extractParam(params, "notify_type");
@@ -510,7 +508,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
 
     private void saveDeviceStatusToRedis(String deviceId, String activityId, String doorStatus, String openType, String outUserId) {
         try {
-            String statusKey = DEVICE_STATUS_KEY + deviceId;
+            String statusKey = RedisConstants.HAHA_DEVICE_STATUS_KEY + deviceId;
             Map<String, String> statusData = new HashMap<>();
             statusData.put("deviceId", deviceId != null ? deviceId : "");
             statusData.put("activityId", activityId != null ? activityId : "");
@@ -534,7 +532,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
      */
     private void saveRecognizeResultToRedis(String activityId, Map<String, Object> params) {
         try {
-            String resultKey = RECOGNIZE_RESULT_KEY + activityId;
+            String resultKey = RedisConstants.HAHA_RECOGNIZE_RESULT_KEY + activityId;
             Map<String, String> recognizeData = new HashMap<>();
             recognizeData.put("activityId", activityId != null ? activityId : "");
             recognizeData.put("deviceId", params.get("device_id") != null ? String.valueOf(params.get("device_id")) : "");
@@ -559,7 +557,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
      */
     private void saveOrderInfoToRedis(Order order, String activityId) {
         try {
-            String orderKey = ORDER_INFO_KEY + activityId;
+            String orderKey = RedisConstants.HAHA_ORDER_INFO_KEY + activityId;
 
             stringRedisTemplate.delete(orderKey);
 
@@ -592,7 +590,7 @@ public class HahaCallbackServiceImpl implements HahaCallbackService {
      */
     private void saveOrderInfoToRedis(Order order, String activityId, String orderId, Object orderMoney, String orderDetail) {
         try {
-            String orderKey = ORDER_INFO_KEY + activityId;
+            String orderKey = RedisConstants.HAHA_ORDER_INFO_KEY + activityId;
 
             stringRedisTemplate.delete(orderKey);
 

+ 5 - 4
haha-service/src/main/java/com/haha/service/impl/NewProductApplyServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.haha.common.enums.ApplyStatus;
 import com.haha.common.exception.BusinessException;
 import com.haha.entity.NewProductApply;
 import com.haha.mapper.NewProductApplyMapper;
@@ -161,7 +162,7 @@ public class NewProductApplyServiceImpl extends ServiceImpl<NewProductApplyMappe
         } catch (HahaException e) {
             log.error("新品申请提交到哈哈平台失败: {}", e.getMessage());
             // 提交失败,更新状态为待提交
-            apply.setStatus(0);
+            apply.setStatus(ApplyStatus.DRAFT.getCode());
             apply.setUpdateTime(LocalDateTime.now());
             updateById(apply);
             throw new BusinessException(500, "新品申请提交失败: " + e.getMessage());
@@ -201,17 +202,17 @@ public class NewProductApplyServiceImpl extends ServiceImpl<NewProductApplyMappe
         
         // 审核中
         long pending = count(new LambdaQueryWrapper<NewProductApply>()
-                .eq(NewProductApply::getStatus, 1));
+                .eq(NewProductApply::getStatus, ApplyStatus.PENDING.getCode()));
         stats.put("pending", pending);
         
         // 已通过
         long passed = count(new LambdaQueryWrapper<NewProductApply>()
-                .eq(NewProductApply::getStatus, 2));
+                .eq(NewProductApply::getStatus, ApplyStatus.APPROVED.getCode()));
         stats.put("passed", passed);
         
         // 已拒绝
         long rejected = count(new LambdaQueryWrapper<NewProductApply>()
-                .eq(NewProductApply::getStatus, 3));
+                .eq(NewProductApply::getStatus, ApplyStatus.REJECTED.getCode()));
         stats.put("rejected", rejected);
         
         return stats;

+ 129 - 3
haha-service/src/main/java/com/haha/service/impl/OrderServiceImpl.java

@@ -11,7 +11,7 @@ import com.haha.common.constant.OrderConstants;
 import com.haha.common.enums.OrderStatus;
 import com.haha.common.enums.PayStatus;
 import com.haha.common.enums.PaymentChannel;
-import com.haha.common.exception.BusinessException;
+import com.haha.common.config.CommonConfig;
 import com.haha.common.utils.EntityLabelUtils;
 import com.haha.common.utils.OrderUtils;
 import com.haha.common.vo.OrderItemVO;
@@ -42,6 +42,7 @@ import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -53,6 +54,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
 
     private final DeviceMapper deviceMapper;
     private final ShopMapper shopMapper;
+    private final CommonConfig commonConfig;
 
     @Autowired
     @Lazy
@@ -260,13 +262,13 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
             return lambdaQuery()
                 .eq(Order::getUserId, userId)
                 .eq(Order::getStatus, status)
-                .ne(Order::getOrderType, "IN")
+                .ne(Order::getOrderType, OrderConstants.ORDER_TYPE_IN)
                 .orderByDesc(Order::getId)
                 .list();
         } else {
             return lambdaQuery()
                 .eq(Order::getUserId, userId)
-                .ne(Order::getOrderType, "IN")
+                .ne(Order::getOrderType, OrderConstants.ORDER_TYPE_IN)
                 .orderByDesc(Order::getId)
                 .list();
         }
@@ -564,4 +566,128 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
             log.error("[邀请激活] 处理订单完成事件时发生异常 - orderId: {}, userId: {}", orderId, userId, e);
         }
     }
+
+    // ==================== 用户端订单业务方法 ====================
+
+    @Override
+    public List<Map<String, Object>> getUserOrderListWithProducts(Long userId, Integer status) {
+        List<Order> orders = getOrderListByUserId(userId, status);
+        List<Map<String, Object>> orderList = new ArrayList<>();
+        for (Order order : orders) {
+            orderList.add(buildOrderMap(order));
+        }
+        return orderList;
+    }
+
+    @Override
+    public Map<String, Object> getUserOrderDetail(Long userId, Long orderId, String orderNo, String outTradeNo) {
+        Order order = null;
+
+        if (orderId != null) {
+            order = this.getById(orderId);
+        } else if (orderNo != null && !orderNo.isEmpty()) {
+            order = this.lambdaQuery()
+                .eq(Order::getOrderNo, orderNo)
+                .one();
+        } else if (outTradeNo != null && !outTradeNo.isEmpty()) {
+            order = this.getOrderByOutTradeNo(outTradeNo);
+        }
+
+        if (order == null) {
+            return null;
+        }
+
+        if (!order.getUserId().equals(userId)) {
+            return null;
+        }
+
+        // IN类型订单不在用户端展示
+        if (OrderConstants.ORDER_TYPE_IN.equals(order.getOrderType())) {
+            return null;
+        }
+
+        Map<String, Object> detail = buildOrderMap(order);
+        detail.put("statusText", OrderConstants.getStatusDesc(order.getStatus()));
+        return detail;
+    }
+
+    @Override
+    public boolean cancelUserOrder(Long userId, Long orderId) {
+        Order order = this.getById(orderId);
+        if (order == null) {
+            return false;
+        }
+        if (!order.getUserId().equals(userId)) {
+            return false;
+        }
+        if (order.getStatus() != OrderConstants.STATUS_PENDING_PAYMENT) {
+            return false;
+        }
+        return cancelOrder(orderId);
+    }
+
+    /**
+     * 构建订单Map(含商品信息)
+     */
+    private Map<String, Object> buildOrderMap(Order order) {
+        Map<String, Object> orderMap = new HashMap<>();
+        orderMap.put("id", order.getId());
+        orderMap.put("orderNo", order.getOrderNo());
+        orderMap.put("orderName", order.getOrderName() != null ? order.getOrderName() : "");
+        orderMap.put("outTradeNo", order.getOutTradeNo());
+        orderMap.put("deviceId", order.getDeviceId());
+        orderMap.put("totalAmount", order.getTotalAmount());
+        orderMap.put("discountAmount", order.getDiscountAmount() != null ? order.getDiscountAmount() : 0);
+        orderMap.put("paidAmount", order.getPaidAmount() != null ? order.getPaidAmount() : order.getTotalAmount());
+        orderMap.put("payStatus", order.getPayStatus());
+        orderMap.put("status", order.getStatus());
+        orderMap.put("createTime", order.getCreateTime());
+        orderMap.put("payTime", order.getPayTime());
+        orderMap.put("confidence", order.getConfidence());
+        orderMap.put("products", getProductsFromDatabase(order.getId()));
+        return orderMap;
+    }
+
+    /**
+     * 从数据库查询订单商品信息
+     */
+    private List<Map<String, Object>> getProductsFromDatabase(Long orderId) {
+        List<Map<String, Object>> products = new ArrayList<>();
+        if (orderId == null) {
+            return products;
+        }
+        try {
+            List<OrderItemVO> goodsList = orderGoodsService.getVOByOrderId(orderId);
+            if (goodsList != null && !goodsList.isEmpty()) {
+                for (OrderItemVO goods : goodsList) {
+                    Map<String, Object> product = new HashMap<>();
+                    product.put("id", goods.getId());
+                    product.put("name", goods.getProductName());
+                    product.put("price", goods.getPrice());
+                    product.put("quantity", goods.getProductNum());
+                    product.put("image", normalizeImageUrl(goods.getPic()));
+                    product.put("subtotal", goods.getPrice() != null && goods.getProductNum() != null
+                        ? goods.getPrice().multiply(new BigDecimal(goods.getProductNum()))
+                        : new BigDecimal(0));
+                    products.add(product);
+                }
+            }
+        } catch (Exception e) {
+            log.error("查询订单 {} 的商品信息失败:{}", orderId, e.getMessage());
+        }
+        return products;
+    }
+
+    /**
+     * 标准化图片URL
+     */
+    private String normalizeImageUrl(String picUrl) {
+        if (picUrl == null || picUrl.isEmpty()) {
+            return picUrl;
+        }
+        if (picUrl.startsWith("http://") || picUrl.startsWith("https://")) {
+            return picUrl;
+        }
+        return commonConfig.getImageDomainPrefix() + picUrl;
+    }
 }

+ 108 - 0
haha-service/src/main/java/com/haha/service/impl/StatusQueryServiceImpl.java

@@ -0,0 +1,108 @@
+package com.haha.service.impl;
+
+import com.haha.common.constant.RedisConstants;
+import com.haha.service.StatusQueryService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 状态查询服务实现
+ * 封装设备状态、识别结果、订单信息的Redis查询逻辑
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class StatusQueryServiceImpl implements StatusQueryService {
+
+    private final StringRedisTemplate redisTemplate;
+
+    @Override
+    public Map<String, String> queryDeviceStatus(String deviceId) {
+        String statusKey = RedisConstants.HAHA_DEVICE_STATUS_KEY + deviceId;
+        Map<Object, Object> statusData = redisTemplate.opsForHash().entries(statusKey);
+
+        if (statusData.isEmpty()) {
+            Map<String, String> emptyResult = new HashMap<>();
+            emptyResult.put("deviceId", deviceId);
+            emptyResult.put("doorStatus", "unknown");
+            return emptyResult;
+        }
+
+        Map<String, String> result = new HashMap<>();
+        result.put("deviceId", statusData.getOrDefault("deviceId", "").toString());
+        result.put("activityId", statusData.getOrDefault("activityId", "").toString());
+        result.put("doorStatus", statusData.getOrDefault("doorStatus", "unknown").toString());
+        result.put("openType", statusData.getOrDefault("openType", "").toString());
+        result.put("userId", statusData.getOrDefault("userId", "").toString());
+        result.put("timestamp", statusData.getOrDefault("timestamp", "").toString());
+
+        log.debug("[状态查询] 设备状态查询成功 - deviceId: {}, doorStatus: {}", deviceId, result.get("doorStatus"));
+        return result;
+    }
+
+    @Override
+    public Map<String, String> queryRecognizeResult(String activityId) {
+        String resultKey = RedisConstants.HAHA_RECOGNIZE_RESULT_KEY + activityId;
+        Map<Object, Object> resultData = redisTemplate.opsForHash().entries(resultKey);
+
+        if (resultData.isEmpty()) {
+            return null;
+        }
+
+        Map<String, String> result = new HashMap<>();
+        resultData.forEach((k, v) -> result.put(k.toString(), v != null ? v.toString() : ""));
+
+        log.info("[状态查询] 识别结果查询成功 - activityId: {}, nobuy: {}", activityId, result.get("nobuy"));
+        return result;
+    }
+
+    @Override
+    public Map<String, String> queryOrderInfo(String orderId, String activityId) {
+        String queryKey = (orderId != null && !orderId.isEmpty()) ? orderId : activityId;
+        String orderKey = RedisConstants.HAHA_ORDER_INFO_KEY + queryKey;
+        Map<Object, Object> orderData = redisTemplate.opsForHash().entries(orderKey);
+
+        if (orderData.isEmpty()) {
+            return null;
+        }
+
+        Map<String, String> result = new HashMap<>();
+        orderData.forEach((k, v) -> result.put(k.toString(), v != null ? v.toString() : ""));
+
+        log.debug("[状态查询] 订单信息查询成功 - queryKey: {}, totalAmount: {}", queryKey, result.get("totalAmount"));
+        return result;
+    }
+
+    @Override
+    public Map<String, Object> queryAllStatus(String deviceId) {
+        Map<String, Object> result = new HashMap<>();
+
+        Map<String, String> deviceStatus = queryDeviceStatus(deviceId);
+        if (!deviceStatus.containsKey("doorStatus") || !"unknown".equals(deviceStatus.get("doorStatus"))) {
+            result.put("deviceStatus", deviceStatus);
+
+            String activityId = deviceStatus.get("activityId");
+            if (activityId != null && !activityId.isEmpty()) {
+                Map<String, String> recognizeResult = queryRecognizeResult(activityId);
+                if (recognizeResult != null) {
+                    result.put("recognizeResult", recognizeResult);
+                }
+
+                Map<String, String> orderInfo = queryOrderInfo(null, activityId);
+                if (orderInfo != null) {
+                    result.put("orderInfo", orderInfo);
+                }
+            }
+        } else {
+            result.put("deviceStatus", deviceStatus);
+        }
+
+        log.debug("[状态查询] 综合状态查询成功 - deviceId: {}, 包含数据: {}", deviceId, result.keySet());
+        return result;
+    }
+}

+ 80 - 0
haha-service/src/main/java/com/haha/service/payment/payscore/PayScoreService.java

@@ -88,4 +88,84 @@ public interface PayScoreService {
      * @return 是否同步成功
      */
     boolean syncPayScoreStatus(Long orderId);
+
+    /**
+     * 检查用户支付分开通状态
+     *
+     * @param userId 用户ID
+     * @return 包含 enabled 和 userId 的Map
+     */
+    Map<String, Object> checkPayscoreEnabled(Long userId);
+
+    /**
+     * 开通支付分(生成商户订单号和跳转数据)
+     *
+     * @param userId 用户ID
+     * @return 包含 enabled、userId、outOrderNo 的Map;如已开通则 enabled=true
+     */
+    Map<String, Object> enablePayscore(Long userId);
+
+    /**
+     * 确认开通支付分(用户完成授权后)
+     *
+     * @param userId 用户ID
+     * @param outOrderNo 微信商户订单号
+     * @return 包含 enabled 和 userId 的Map
+     */
+    Map<String, Object> confirmEnablePayscore(Long userId, String outOrderNo);
+
+    /**
+     * 创建支付分服务订单(含权限校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @param openId 用户微信openId
+     * @param riskFundAmount 风险金额(可选)
+     * @param riskFundName 风险金名称(可选)
+     * @return 包含 outOrderNo、state、package 的Map
+     */
+    Map<String, Object> createUserPayScoreOrder(Long userId, Long orderId, String openId,
+                                                  BigDecimal riskFundAmount, String riskFundName);
+
+    /**
+     * 完结支付分服务订单(含权限校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @param totalAmount 实际扣款金额
+     * @param payments 后付费项目列表(可选)
+     * @param discounts 优惠列表(可选)
+     * @return 包含 outOrderNo、state 的Map
+     */
+    Map<String, Object> completeUserPayScoreOrder(Long userId, Long orderId, BigDecimal totalAmount,
+                                                    List<PostPayment> payments,
+                                                    List<PayScoreCompleteRequest.PostDiscount> discounts);
+
+    /**
+     * 取消支付分服务订单(含权限校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @param reason 取消原因
+     * @return 包含 outOrderNo、state 的Map
+     */
+    Map<String, Object> cancelUserPayScoreOrder(Long userId, Long orderId, String reason);
+
+    /**
+     * 查询支付分服务订单状态(含权限校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @return 包含 outOrderNo、state、totalAmount 的Map
+     */
+    Map<String, Object> queryUserPayScoreOrder(Long userId, Long orderId);
+
+    /**
+     * 同步支付分状态(含权限校验)
+     *
+     * @param userId 用户ID
+     * @param orderId 订单ID
+     * @return 是否同步成功
+     */
+    boolean syncUserPayScoreStatus(Long userId, Long orderId);
 }

+ 165 - 0
haha-service/src/main/java/com/haha/service/payment/payscore/impl/PayScoreServiceImpl.java

@@ -6,7 +6,9 @@ import com.haha.common.enums.PayScoreState;
 import com.haha.common.enums.PayStatus;
 import com.haha.common.enums.PaymentChannel;
 import com.haha.entity.Order;
+import com.haha.entity.User;
 import com.haha.service.OrderService;
+import com.haha.service.UserService;
 import com.haha.service.payment.config.WxPayConfig;
 import com.haha.service.payment.payscore.*;
 import com.haha.service.payment.payscore.PayScoreCreateRequest.PostPayment;
@@ -20,6 +22,7 @@ import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -37,11 +40,15 @@ public class PayScoreServiceImpl implements PayScoreService {
     @Autowired
     private OrderService orderService;
 
+    @Autowired
+    private UserService userService;
+
     @Autowired(required = false)
     private WxPayConfig wxPayConfig;
 
     private static final BigDecimal DEFAULT_RISK_FUND_AMOUNT = new BigDecimal("99.00");
     private static final String DEFAULT_RISK_FUND_NAME = "DEPOSIT";
+    private static final int PAYSCORE_ENABLED = 1;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -351,4 +358,162 @@ public class PayScoreServiceImpl implements PayScoreService {
     private String formatDateTime(LocalDateTime dateTime) {
         return dateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
     }
+
+    // ==================== 用户端支付分业务方法 ====================
+
+    @Override
+    public Map<String, Object> checkPayscoreEnabled(Long userId) {
+        User user = userService.getById(userId);
+        boolean isEnabled = isPayscoreEnabled(user);
+        Map<String, Object> data = new HashMap<>();
+        data.put("enabled", isEnabled);
+        data.put("userId", userId);
+        return data;
+    }
+
+    @Override
+    public Map<String, Object> enablePayscore(Long userId) {
+        User user = userService.getById(userId);
+        if (isPayscoreEnabled(user)) {
+            Map<String, Object> data = new HashMap<>();
+            data.put("enabled", true);
+            data.put("userId", userId);
+            return data;
+        }
+
+        String outOrderNo = generatePayscoreOrderNo(userId);
+        Map<String, Object> data = new HashMap<>();
+        data.put("enabled", false);
+        data.put("userId", userId);
+        data.put("outOrderNo", outOrderNo);
+        return data;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> confirmEnablePayscore(Long userId, String outOrderNo) {
+        User user = userService.getById(userId);
+        PayScoreResult result = queryPayScoreOrder(outOrderNo);
+
+        if (result.isSuccess() && "ACCEPTED".equals(result.getState())) {
+            updateUserPayscoreStatus(user);
+            Map<String, Object> data = new HashMap<>();
+            data.put("enabled", true);
+            data.put("userId", userId);
+            return data;
+        }
+        return null; // 开通失败
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> createUserPayScoreOrder(Long userId, Long orderId, String openId,
+                                                        BigDecimal riskFundAmount, String riskFundName) {
+        Order order = orderService.getById(orderId);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return null;
+        }
+
+        PayScoreResult result;
+        if (riskFundAmount != null || riskFundName != null) {
+            result = createPayScoreOrder(orderId, openId, riskFundAmount, riskFundName);
+        } else {
+            result = createPayScoreOrder(orderId, openId);
+        }
+
+        if (result.isSuccess()) {
+            Map<String, Object> data = new HashMap<>();
+            data.put("outOrderNo", result.getOutOrderNo());
+            data.put("state", result.getState());
+            data.put("package", result.getPackageStr());
+            return data;
+        }
+        return null;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> completeUserPayScoreOrder(Long userId, Long orderId, BigDecimal totalAmount,
+                                                          List<PostPayment> payments,
+                                                          List<PostDiscount> discounts) {
+        Order order = orderService.getById(orderId);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return null;
+        }
+
+        PayScoreResult result = completePayScoreOrder(orderId, totalAmount, payments, discounts);
+        if (result.isSuccess()) {
+            Map<String, Object> data = new HashMap<>();
+            data.put("outOrderNo", result.getOutOrderNo());
+            data.put("state", result.getState());
+            return data;
+        }
+        return null;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> cancelUserPayScoreOrder(Long userId, Long orderId, String reason) {
+        Order order = orderService.getById(orderId);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return null;
+        }
+
+        PayScoreResult result = cancelPayScoreOrder(orderId, reason);
+        if (result.isSuccess()) {
+            Map<String, Object> data = new HashMap<>();
+            data.put("outOrderNo", result.getOutOrderNo());
+            data.put("state", result.getState());
+            return data;
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> queryUserPayScoreOrder(Long userId, Long orderId) {
+        Order order = orderService.getById(orderId);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return null;
+        }
+        if (order.getPayScoreOrderId() == null) {
+            return null;
+        }
+
+        PayScoreResult result = queryPayScoreOrder(order.getPayScoreOrderId());
+        if (result.isSuccess()) {
+            Map<String, Object> data = new HashMap<>();
+            data.put("outOrderNo", result.getOutOrderNo());
+            data.put("state", result.getState());
+            data.put("totalAmount", result.getTotalAmount());
+            return data;
+        }
+        return null;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean syncUserPayScoreStatus(Long userId, Long orderId) {
+        Order order = orderService.getById(orderId);
+        if (order == null || !order.getUserId().equals(userId)) {
+            return false;
+        }
+        return syncPayScoreStatus(orderId);
+    }
+
+    private boolean isPayscoreEnabled(User user) {
+        return user != null && user.getPayscoreEnabled() != null && user.getPayscoreEnabled() == PAYSCORE_ENABLED;
+    }
+
+    private void updateUserPayscoreStatus(User user) {
+        user.setPayscoreEnabled(PAYSCORE_ENABLED);
+        user.setUpdateTime(LocalDateTime.now());
+        boolean updated = userService.updateById(user);
+        if (!updated) {
+            throw new RuntimeException("更新用户状态失败");
+        }
+    }
+
+    private String generatePayscoreOrderNo(Long userId) {
+        return "PS" + System.currentTimeMillis() + String.format("%04d", userId % 10000);
+    }
 }