Administrator
2025-04-22 c4a0a66f61e1ccfefb0793fba5a9b62ccb7818ae
feat(mall): 重构活动模块接口和数据结构

- 重新命名和调整了多个接口和数据传输对象的位置
- 新增了活动报名、订单创建和支付相关功能的接口和实体类
- 优化了活动信息展示和投票记录查询的SQL映射
- 调整了活动状态和支付状态的字段定义
1 files copied
13 files added
12 files renamed
14 files modified
988 ■■■■ changed files
src/main/java/cc/mrbird/febs/common/enumerates/StateUpDownEnum.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityCategoryController.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityController.java 39 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityOrderController.java 85 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiActivityDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiActivityInfoDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiConnectListDto.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiConnectSaveDto.java 29 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiCreateOrderDto.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateDoDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateRegisterActivityDto.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateRegisterUserDto.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateVoteDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiPayOrderDto.java 27 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/ApiVoteRecordInPageDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/HappyActivity.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityConnect.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityOrder.java 43 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityOrderItem.java 41 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityConnectMapper.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityMapper.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityOrderItemMapper.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityOrderMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/HappyActivityService.java 28 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityCategoryServiceImpl.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java 341 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityInfoVo.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityOptionListVo.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityOptionVo.java 5 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityVo.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiCategoryInfoVo.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiConnectListInPageVo.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/ApiVoteRecordInPageVo.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java 44 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java 4 ●●●● patch | view | raw | blame | history
src/main/resources/application-test.yml 7 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/HappyActivityMapper.xml 41 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/HappyActivityOptionMapper.xml 45 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/StateUpDownEnum.java
@@ -27,6 +27,27 @@
    VOTE_OPTION_STATE_AUDIT_REFUSE(2),
    /**
     * 支付状态 0-待支付 1-支付成功 2-支付失败
     */
    PAY_STATE_NOT_PAY(0),
    PAY_STATE_PAY_SUCCESS(1),
    PAY_STATE_PAY_FAIL(2),
    /**
     * 支付方式 1-余额支付 2-微信支付 3-积分支付 0-无需支付
     */
    PAY_METHOD_BALANCE(1),
    PAY_METHOD_WECHAT(2),
    PAY_METHOD_INTEGRAL(3),
    PAY_METHOD_NO_PAY(0),
    /**
     * 是否众筹 0-关闭 1-开启(开启代表收取参与费用)
     */
    ACTIVITY_CROWDFUNDING_STATE_CLOSE(0),
    ACTIVITY_CROWDFUNDING_STATE_OPEN(1),
    /**
     * 活动类型 1-普通活动 2-众筹活动 3-投票活动
     */
    ACTIVITY_TYPE_NORMAL(1),
@@ -43,6 +64,7 @@
     * 状态 0-未开启 1-已开启
     * 是否推荐到首页 0-不推荐 1-推荐
     * 删除标识 0-未删除 1-已删除
     * 使用状态 0-待使用 1-已使用
     */
    DOWN(0),
    UP(1);
src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java
@@ -17,6 +17,8 @@
    private String wecharPaynotifyUrl;
    private String wecharActivityPaynotifyUrl;
    private String wecharRechargePaynotifyUrl;
    //测试支付的开关,true:支付0.01元
    private Boolean debug;
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityCategoryController.java
@@ -2,7 +2,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.service.HappyActivityCategoryService;
import cc.mrbird.febs.mall.vo.api.activity.category.ApiCategoryInfoVo;
import cc.mrbird.febs.mall.vo.ApiCategoryInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
@@ -19,7 +19,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/happyCategory")
@Api(value = "ApiHappyActivityCategoryController", tags = "365活动")
@Api(value = "ApiHappyActivityCategoryController", tags = "365活动分类")
public class ApiHappyActivityCategoryController {
    private final HappyActivityCategoryService happyActivityCategoryService;
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityController.java
@@ -2,10 +2,9 @@
import cc.mrbird.febs.common.annotation.Limit;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.service.HappyActivityService;
import cc.mrbird.febs.mall.vo.api.activity.*;
import cc.mrbird.febs.mall.vo.api.activity.follow.ApiOperateDoDto;
import cc.mrbird.febs.mall.vo.api.activity.options.*;
import cc.mrbird.febs.mall.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
@@ -20,7 +19,7 @@
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/happyActivity")
@Api(value = "ApiHappyActivityController", tags = "365活动分类")
@Api(value = "ApiHappyActivityController", tags = "365活动")
public class ApiHappyActivityController{
    private final HappyActivityService happyActivityService;
@@ -45,7 +44,15 @@
        return happyActivityService.activityInfo(dto);
    }
    @ApiOperation(value = "投票活动选项列表", notes = "投票活动选项列表")
    @ApiOperation(value = "点赞关注转发", notes = "点赞关注转发")
    @PostMapping(value = "/operateDo")
    @Limit(key = "operateDo", period = 60, count = 1, name = "点赞关注转发接口", prefix = "limit")
    public FebsResponse operateDo(@RequestBody @Validated ApiOperateDoDto dto) {
        return happyActivityService.operateDo(dto);
    }
    @ApiOperation(value = "投票活动-选项列表", notes = "投票活动-选项列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiActivityOptionListVo.class)
    })
@@ -55,7 +62,7 @@
        return happyActivityService.voteOptionList(id);
    }
    @ApiOperation(value = "投票活动选项详情", notes = "投票活动选项详情")
    @ApiOperation(value = "投票活动-选项详情", notes = "投票活动-选项详情")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiActivityOptionVo.class)
    })
@@ -65,15 +72,7 @@
        return happyActivityService.voteOption(id);
    }
    @ApiOperation(value = "点赞关注转发", notes = "点赞关注转发")
    @PostMapping(value = "/operateDo")
    @Limit(key = "operateDo", period = 60, count = 1, name = "点赞关注转发接口", prefix = "limit")
    public FebsResponse operateDo(@RequestBody @Validated ApiOperateDoDto dto) {
        return happyActivityService.operateDo(dto);
    }
    @ApiOperation(value = "投票活动选项投票", notes = "投票活动选项投票")
    @ApiOperation(value = "投票活动-选项投票", notes = "投票活动-选项投票")
    @PostMapping(value = "/operateVote")
    @Limit(key = "operateVote", period = 60, count = 1, name = "投票接口", prefix = "limit")
    public FebsResponse operateVote(@RequestBody @Validated ApiOperateVoteDto dto) {
@@ -81,7 +80,7 @@
        return happyActivityService.operateVote(dto);
    }
    @ApiOperation(value = "投票活动选项投票记录", notes = "投票活动选项投票记录")
    @ApiOperation(value = "投票活动-选项投票记录", notes = "投票活动-选项投票记录")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiVoteRecordInPageVo.class)
    })
@@ -89,14 +88,6 @@
    public FebsResponse voteRecordInPage(@RequestBody @Validated ApiVoteRecordInPageDto dto) {
        return happyActivityService.voteRecordInPage(dto);
    }
    @ApiOperation(value = "活动报名", notes = "活动报名")
    @PostMapping(value = "/operateRegister")
    @Limit(key = "operateRegister", period = 60, count = 1, name = "活动报名接口", prefix = "limit")
    public FebsResponse operateRegister(@RequestBody @Validated ApiOperateRegisterActivityDto dto) {
        return happyActivityService.operateRegister(dto);
    }
}
src/main/java/cc/mrbird/febs/mall/controller/ApiHappyActivityOrderController.java
New file
@@ -0,0 +1,85 @@
package cc.mrbird.febs.mall.controller;
import cc.mrbird.febs.common.annotation.Limit;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.service.HappyActivityService;
import cc.mrbird.febs.mall.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/happyActivityOrder")
@Api(value = "ApiHappyActivityOrderController", tags = "365活动订单")
public class ApiHappyActivityOrderController {
    private final HappyActivityService happyActivityService;
    @ApiOperation(value = "活动报名-新增报名人", notes = "活动报名-新增报名人")
    @PostMapping(value = "/addConnect")
    @Limit(key = "addConnect", period = 60, count = 1, name = "活动报名-新增报名人", prefix = "limit")
    public FebsResponse addConnect(@RequestBody @Validated ApiOperateRegisterUserDto dto) {
        return happyActivityService.addConnect(dto);
    }
    @ApiOperation(value = "活动报名-报名人列表", notes = "活动报名-报名人列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiConnectListInPageVo.class)
    })
    @PostMapping(value = "/connectList")
    public FebsResponse connectList(@RequestBody @Validated ApiConnectListDto dto) {
        return happyActivityService.connectList(dto);
    }
    @ApiOperation(value = "活动报名-报名人详情", notes = "活动报名-报名人详情")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiConnectListInPageVo.class)
    })
    @GetMapping(value = "/connectInfo/{id}")
    public FebsResponse connectInfo(@PathVariable("id") Long id) {
        return happyActivityService.connectInfo(id);
    }
    @ApiOperation(value = "活动报名-报名人删除", notes = "活动报名-报名人删除")
    @GetMapping(value = "/connectDel/{id}")
    public FebsResponse connectDel(@PathVariable("id") Long id) {
        return happyActivityService.connectDel(id);
    }
    @ApiOperation(value = "活动报名-报名人保存", notes = "活动报名-报名人保存")
    @PostMapping(value = "/connectSave")
    public FebsResponse connectSave(@RequestBody @Validated ApiConnectSaveDto dto) {
        return happyActivityService.connectSave(dto);
    }
    @ApiOperation(value = "活动报名-报名-创建订单", notes = "活动报名-报名-创建订单")
    @PostMapping(value = "/createOrder")
    @Limit(key = "createOrder", period = 60, count = 1, name = "创建订单", prefix = "limit")
    public FebsResponse createOrder(@RequestBody @Validated ApiCreateOrderDto dto) {
        return happyActivityService.createOrder(dto);
    }
    @ApiOperation(value = "活动报名-报名-支付订单", notes = "活动报名-报名-支付订单")
    @PostMapping(value = "/payOrder")
    @Limit(key = "payOrder", period = 60, count = 1, name = "支付订单", prefix = "limit")
    public FebsResponse payOrder(@RequestBody @Validated ApiPayOrderDto dto) {
        return happyActivityService.payOrder(dto);
    }
}
src/main/java/cc/mrbird/febs/mall/dto/ApiActivityDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/ApiActivityDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/dto/ApiActivityInfoDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/ApiActivityInfoDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/dto/ApiConnectListDto.java
copy from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiVoteRecordInPageDto.java copy to src/main/java/cc/mrbird/febs/mall/dto/ApiConnectListDto.java
File was copied from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiVoteRecordInPageDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -7,9 +7,8 @@
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiVoteRecordInPageDto", description = "参数")
public class ApiVoteRecordInPageDto {
@ApiModel(value = "ApiConnectListDto", description = "参数")
public class ApiConnectListDto {
    @NotNull(message = "页码不能为空")
    @ApiModelProperty(value = "页码", example = "1")
@@ -19,8 +18,6 @@
    @ApiModelProperty(value = "每页数量", example = "10")
    private Integer pageSize;
    @NotNull(message = "选项ID不能为空")
    @ApiModelProperty(value = "选项ID")
    private Long sourceOptionId;
    @ApiModelProperty(hidden = true)
    private Long memberId;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiConnectSaveDto.java
New file
@@ -0,0 +1,29 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiConnectSaveDto", description = "参数")
public class ApiConnectSaveDto {
    @NotNull(message = "ID不能为空")
    @ApiModelProperty(value = "ID", example = "丽丽")
    private Long id;
    @NotBlank(message = "姓名不可为空")
    @ApiModelProperty(value = "姓名", example = "丽丽")
    private String name;
    @NotBlank(message = "电话不可为空")
    @ApiModelProperty(value = "电话", example = "丽丽")
    private String phone;
    @NotBlank(message = "地址不可为空")
    @ApiModelProperty(value = "地址", example = "丽丽")
    private String address;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiCreateOrderDto.java
New file
@@ -0,0 +1,26 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
@ApiModel(value = "ApiCreateOrderDto", description = "参数")
public class ApiCreateOrderDto {
    @NotNull(message = "活动ID不能为空")
    @ApiModelProperty(value = "活动ID", example = "1")
    private Long activityId;
    @NotNull(message = "数量不能为空")
    @ApiModelProperty(value = "数量", example = "1")
    private Integer numCnt;
    @NotNull(message = "报名人不能为空")
    @ApiModelProperty(value = "报名人ID列表", example = "1")
    private List<Long> connectIds;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateDoDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/follow/ApiOperateDoDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.follow;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateRegisterActivityDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/ApiOperateRegisterActivityDto.java
@@ -1,16 +1,17 @@
package cc.mrbird.febs.mall.vo.api.activity;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiOperateRegisterActivityDto", description = "参数")
public class ApiOperateRegisterActivityDto {
    @NotBlank(message = "活动ID不可为空")
    @NotNull(message = "活动ID不可为空")
    @ApiModelProperty(value = "活动ID", example = "1")
    private Long activityId;//投票活动ID
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateRegisterUserDto.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@ApiModel(value = "ApiOperateRegisterUserDto", description = "参数")
public class ApiOperateRegisterUserDto {
    @NotBlank(message = "姓名不可为空")
    @ApiModelProperty(value = "姓名", example = "丽丽")
    private String name;
    @NotBlank(message = "电话不可为空")
    @ApiModelProperty(value = "电话", example = "丽丽")
    private String phone;
    @NotBlank(message = "地址不可为空")
    @ApiModelProperty(value = "地址", example = "丽丽")
    private String address;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiOperateVoteDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiOperateVoteDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/dto/ApiPayOrderDto.java
New file
@@ -0,0 +1,27 @@
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiPayOrderDto", description = "参数")
public class ApiPayOrderDto {
    @NotNull(message = "订单ID不能为空")
    @ApiModelProperty(value = "订单ID", example = "1")
    private Long orderId;
    @NotNull(message = "支付方式不能为空")
    @ApiModelProperty(value = "支付方式 1-余额支付 2-微信支付 3-积分支付 0-无需支付", example = "1")
    private Integer payType;
    @NotBlank(message = "支付密码不能为空")
    @ApiModelProperty(value = "支付密码", example = "如果选择余额支付需要输入")
    private String tradePwd;
}
src/main/java/cc/mrbird/febs/mall/dto/ApiVoteRecordInPageDto.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiVoteRecordInPageDto.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/entity/HappyActivity.java
@@ -35,6 +35,7 @@
     `hot_state` int(11) DEFAULT '0' COMMENT '是否推荐到首页 0-不推荐 1-推荐',
     `back_img` varchar(500) DEFAULT NULL COMMENT '背景图片',
     `DELETE_FLAG` int(11) DEFAULT '0' COMMENT '删除标识 0-未删除 1-已删除',
     `vote_cnt` int(11) DEFAULT NULL COMMENT '投票数量',
     */
    private Long categoryId;
    private String code;
@@ -59,6 +60,7 @@
    private Integer hotState;
    private String backImg;
    private Integer deleteFlag;
    private Integer voteCnt;
}
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityConnect.java
New file
@@ -0,0 +1,22 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("happy_activity_connect")
public class HappyActivityConnect extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
     `name` varchar(100) DEFAULT NULL COMMENT '姓名',
     `phone` varchar(100) DEFAULT NULL COMMENT '电话',
     `address` varchar(200) DEFAULT NULL COMMENT '地址',
     */
    private Long memberId;
    private String name;
    private String phone;
    private String address;
}
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityOrder.java
New file
@@ -0,0 +1,43 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("happy_activity_order")
public class HappyActivityOrder extends BaseEntity {
    /**
     *
     `ID` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
     `member_id` bigint(20) DEFAULT NULL,
     `activity_id` bigint(20) DEFAULT NULL COMMENT '活动ID',
     `price` decimal(20,2) DEFAULT NULL COMMENT '单价',
     `num_cnt` int(11) DEFAULT NULL COMMENT '数量',
     `amount` decimal(20,2) DEFAULT NULL COMMENT '支付总金额',
     `pay_state` int(11) DEFAULT NULL COMMENT '支付状态 0-待支付 1-支付成功 2-支付失败',
     `pay_type` int(11) DEFAULT NULL COMMENT '支付方式 1-余额支付 2-微信支付 3-积分支付',
     `DELETE_FLAG` int(11) DEFAULT '0' COMMENT '删除标识 0-未删除 1-已删除',
     `order_no` varchar(32) DEFAULT NULL COMMENT '订单号',
     `pay_order_no` text COMMENT '支付订单号',
     `wx_order_no` varchar(100) DEFAULT NULL COMMENT '微信订单编号',
     */
    private Long memberId;
    private Long activityId;
    private BigDecimal price;
    private Integer numCnt;
    private BigDecimal amount;
    private Integer payState;
    private Integer payType;
    private Date payTime;
    private Integer deleteFlag;
    private String orderNo;
    private String payOrderNo;
    private String wxOrderNo;
}
src/main/java/cc/mrbird/febs/mall/entity/HappyActivityOrderItem.java
New file
@@ -0,0 +1,41 @@
package cc.mrbird.febs.mall.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("happy_activity_order_item")
public class HappyActivityOrderItem extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL,
     `activity_id` bigint(20) DEFAULT NULL COMMENT '活动ID',
     `order_id` bigint(20) DEFAULT NULL COMMENT '订单ID',
     `connect_id` bigint(20) DEFAULT NULL COMMENT '联系人ID',
     `code` varchar(100) DEFAULT NULL COMMENT '唯一票号',
     `price` decimal(20,2) DEFAULT NULL COMMENT '单价',
     `name` varchar(100) DEFAULT NULL COMMENT '姓名',
     `phone` varchar(100) DEFAULT NULL COMMENT '电话',
     `address` varchar(500) DEFAULT NULL COMMENT '地址',
     `state` int(11) DEFAULT '0' COMMENT '使用状态 0-待使用 1-已使用',
     `transfer_item_id` bigint(20) DEFAULT NULL COMMENT '转赠来源ID(接收转赠之后,更新成新增的订单子表ID)',
     `transfer_state` int(11) DEFAULT '0' COMMENT '是否转赠 0-未转赠 1-已转赠',
     `DELETE_FLAG` int(11) DEFAULT '0' COMMENT '删除标识 0-未删除 1-已删除',
     */
    private Long memberId;
    private Long activityId;
    private Long orderId;
    private Long connectId;
    private String code;
    private BigDecimal price;
    private String name;
    private String phone;
    private String address;
    private Integer state;
    private Long transferItemId;
    private Integer transferState;
    private Integer deleteFlag;
}
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityConnectMapper.java
New file
@@ -0,0 +1,14 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.dto.ApiConnectListDto;
import cc.mrbird.febs.mall.entity.HappyActivityConnect;
import cc.mrbird.febs.mall.vo.ApiConnectListInPageVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface HappyActivityConnectMapper extends BaseMapper<HappyActivityConnect> {
    Page<ApiConnectListInPageVo> selectConnectListPage(Page<ApiConnectListInPageVo> page, @Param("record")ApiConnectListDto dto);
}
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityMapper.java
@@ -1,10 +1,10 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.HappyActivity;
import cc.mrbird.febs.mall.vo.api.activity.ApiActivityInfoDto;
import cc.mrbird.febs.mall.vo.api.activity.ApiActivityInfoVo;
import cc.mrbird.febs.mall.vo.api.activity.options.ApiVoteRecordInPageDto;
import cc.mrbird.febs.mall.vo.api.activity.options.ApiVoteRecordInPageVo;
import cc.mrbird.febs.mall.dto.ApiActivityInfoDto;
import cc.mrbird.febs.mall.vo.ApiActivityInfoVo;
import cc.mrbird.febs.mall.dto.ApiVoteRecordInPageDto;
import cc.mrbird.febs.mall.vo.ApiVoteRecordInPageVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityOrderItemMapper.java
New file
@@ -0,0 +1,8 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.HappyActivityOrder;
import cc.mrbird.febs.mall.entity.HappyActivityOrderItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface HappyActivityOrderItemMapper extends BaseMapper<HappyActivityOrderItem> {
}
src/main/java/cc/mrbird/febs/mall/mapper/HappyActivityOrderMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.HappyActivityOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface HappyActivityOrderMapper extends BaseMapper<HappyActivityOrder> {
}
src/main/java/cc/mrbird/febs/mall/service/HappyActivityService.java
@@ -1,13 +1,11 @@
package cc.mrbird.febs.mall.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.HappyActivity;
import cc.mrbird.febs.mall.vo.api.activity.ApiActivityDto;
import cc.mrbird.febs.mall.vo.api.activity.ApiActivityInfoDto;
import cc.mrbird.febs.mall.vo.api.activity.ApiOperateRegisterActivityDto;
import cc.mrbird.febs.mall.vo.api.activity.follow.ApiOperateDoDto;
import cc.mrbird.febs.mall.vo.api.activity.options.ApiOperateVoteDto;
import cc.mrbird.febs.mall.vo.api.activity.options.ApiVoteRecordInPageDto;
import cc.mrbird.febs.mall.dto.ApiOperateDoDto;
import cc.mrbird.febs.mall.dto.ApiOperateVoteDto;
import cc.mrbird.febs.mall.dto.ApiVoteRecordInPageDto;
import com.baomidou.mybatisplus.extension.service.IService;
public interface HappyActivityService extends IService<HappyActivity> {
@@ -31,4 +29,22 @@
    FebsResponse voteRecordInPage(ApiVoteRecordInPageDto dto);
    FebsResponse operateRegister(ApiOperateRegisterActivityDto dto);
    FebsResponse addConnect(ApiOperateRegisterUserDto dto);
    FebsResponse connectList(ApiConnectListDto dto);
    FebsResponse connectInfo(Long id);
    FebsResponse connectDel(Long id);
    FebsResponse connectSave(ApiConnectSaveDto dto);
    FebsResponse createOrder(ApiCreateOrderDto dto);
    FebsResponse payOrder(ApiPayOrderDto dto);
    void addLikeCnt(Long sourceOptionId);
    void substructJoinCnt(Long activityId,Integer cnt);
}
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityCategoryServiceImpl.java
@@ -5,7 +5,7 @@
import cc.mrbird.febs.mall.entity.HappyActivityCategory;
import cc.mrbird.febs.mall.mapper.HappyActivityCategoryMapper;
import cc.mrbird.febs.mall.service.HappyActivityCategoryService;
import cc.mrbird.febs.mall.vo.api.activity.category.ApiCategoryInfoVo;
import cc.mrbird.febs.mall.vo.ApiCategoryInfoVo;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java
@@ -1,25 +1,28 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.enumerates.StateUpDownEnum;
import cc.mrbird.febs.common.enumerates.*;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.mall.entity.HappyActivity;
import cc.mrbird.febs.mall.entity.HappyActivityOption;
import cc.mrbird.febs.mall.entity.HappyFollow;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.mapper.HappyActivityMapper;
import cc.mrbird.febs.mall.mapper.HappyActivityOptionMapper;
import cc.mrbird.febs.mall.mapper.HappyFollowMapper;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.common.utils.MallUtils;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.*;
import cc.mrbird.febs.mall.service.HappyActivityService;
import cc.mrbird.febs.mall.vo.api.activity.*;
import cc.mrbird.febs.mall.vo.api.activity.follow.ApiOperateDoDto;
import cc.mrbird.febs.mall.vo.api.activity.options.*;
import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
import cc.mrbird.febs.mall.vo.*;
import cc.mrbird.febs.mall.dto.ApiOperateDoDto;
import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
import cc.mrbird.febs.pay.service.IXcxPayService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -28,6 +31,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -40,6 +45,11 @@
    private final HappyFollowMapper happyFollowMapper;
    private final MallMemberMapper mallMemberMapper;
    private final HappyActivityOptionMapper happyActivityOptionMapper;
    private final HappyActivityConnectMapper happyActivityConnectMapper;
    private final HappyActivityOrderMapper happyActivityOrderMapper;
    private final HappyActivityOrderItemMapper happyActivityOrderItemMapper;
    private final IXcxPayService iXcxPayService;
    private final IApiMallMemberWalletService iApiMallMemberWalletService;
    @Override
    public FebsResponse activityList(ApiActivityInfoDto dto) {
@@ -189,6 +199,7 @@
                        throw new FebsException("选项ID不能为空");
                    }
                    this.operateDoVote(memberId, StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode(), sourceId, sourceOptionId, type);
                    this.addLikeCnt(sourceOptionId);
                } else {
                    this.operateDo(memberId, StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode(), sourceId, type);
                }
@@ -235,6 +246,18 @@
        Integer sourceType = dto.getSourceType();
        Integer type = StateUpDownEnum.VOTE.getCode();
        HappyActivity happyActivity = this.baseMapper.selectById(sourceId);
        if(StateUpDownEnum.ACTIVITY_TYPE_VOTE.getCode() != happyActivity.getType()){
            throw new FebsException("当前活动无法投票");
        }
        HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId);
        if (happyActivityOption == null) {
            throw new FebsException("投票对象不存在");
        }
        if (StateUpDownEnum.VOTE_OPTION_STATE_AUDIT_SUCCESS.getCode() != happyActivityOption.getState()) {
            throw new FebsException("请重新选择投票对象");
        }
        //验证当前登录人员今日是否已经投票
        List<HappyFollow> happyFollows = happyFollowMapper.selectList(
                new LambdaQueryWrapper<HappyFollow>()
@@ -244,33 +267,11 @@
                        .eq(HappyFollow::getType, type)
                        .gt(HappyFollow::getCreatedTime, DateUtil.beginOfDay(new Date()))
        );
        if (CollUtil.isNotEmpty(happyFollows)){
        if (CollUtil.isNotEmpty(happyFollows) && happyFollows.size() >= happyActivity.getVoteCnt()){
            throw new FebsException("今日已经投票");
        }
        if (StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode() == sourceType) {
            HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId);
            if (happyActivityOption == null) {
                throw new FebsException("投票对象不存在");
            }
            if (StateUpDownEnum.VOTE_OPTION_STATE_AUDIT_SUCCESS.getCode() != happyActivityOption.getState()) {
                throw new FebsException("请重新选择投票对象");
            }
            Integer likesCnt = happyActivityOption.getLikesCnt();
            if (likesCnt == null) {
                likesCnt = 0;
            }
            likesCnt += 1;
            happyActivityOption.setLikesCnt(likesCnt);
            boolean updateSuccess = happyActivityOptionMapper.updateById(happyActivityOption) > 0;
            if (!updateSuccess) {
                throw new FebsException("更新票数失败");
            }
            this.operateDoVote(memberId, sourceType, sourceId, sourceOptionId, type);
        }
        this.operateDoVote(memberId, sourceType, sourceId, sourceOptionId, type);
        this.addLikeCnt(sourceOptionId);
        return new FebsResponse().success();
    }
@@ -307,9 +308,275 @@
    @Override
    public FebsResponse operateRegister(ApiOperateRegisterActivityDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        return null;
    }
    @Override
    public FebsResponse addConnect(ApiOperateRegisterUserDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        HappyActivityConnect happyActivityConnect = new HappyActivityConnect();
        happyActivityConnect.setMemberId(memberId);
        happyActivityConnect.setName(dto.getName());
        happyActivityConnect.setPhone(dto.getPhone());
        happyActivityConnect.setAddress(dto.getAddress());
        happyActivityConnectMapper.insert(happyActivityConnect);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse connectList(ApiConnectListDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        dto.setMemberId(memberId);
        // 创建分页对象,传入当前页和每页大小
        Page<ApiConnectListInPageVo> page = new Page<>(dto.getPageNow(), dto.getPageSize());
        Page<ApiConnectListInPageVo> voteRecordInPage = happyActivityConnectMapper.selectConnectListPage(page, dto);
        return new FebsResponse().success().data(voteRecordInPage);
    }
    @Override
    public FebsResponse connectInfo(Long id) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(id);
        ApiConnectListInPageVo apiConnectListInPageVo = new ApiConnectListInPageVo();
        BeanUtil.copyProperties(happyActivityConnect,apiConnectListInPageVo);
        return new FebsResponse().success().data(apiConnectListInPageVo);
    }
    @Override
    public FebsResponse connectDel(Long id) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        happyActivityConnectMapper.deleteById(id);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse connectSave(ApiConnectSaveDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        Long id = dto.getId();
        HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(id);
        if (happyActivityConnect == null) {
            throw new FebsException("记录不存在");
        }
        happyActivityConnect.setName(dto.getName());
        happyActivityConnect.setPhone(dto.getPhone());
        happyActivityConnect.setAddress(dto.getAddress());
        happyActivityConnectMapper.updateById(happyActivityConnect);
        return new FebsResponse().success();
    }
    @Override
    public FebsResponse createOrder(ApiCreateOrderDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        if(CollUtil.isEmpty(dto.getConnectIds())){
            throw new FebsException("请选择报名人");
        }
        List<Long> connectIds = dto.getConnectIds();
        Integer numCnt = dto.getNumCnt();
        if(numCnt != connectIds.size()){
            throw new FebsException("报名人数与票的数量不匹配");
        }
        Long activityId = dto.getActivityId();
        HappyActivity happyActivity = this.baseMapper.selectById(activityId);
        if (ObjectUtil.isEmpty(happyActivity)) {
            throw new FebsException("活动不存在");
        }
        Integer joinCnt = happyActivity.getJoinCnt();
        if(joinCnt < numCnt){
            throw new FebsException("报名额度剩下"+joinCnt+",请减少报名人数");
        }
        //支付总金额
        BigDecimal amount = happyActivity.getPayAmount().multiply(new BigDecimal(dto.getNumCnt())).setScale(2, RoundingMode.DOWN);
        if(amount.compareTo(BigDecimal.ZERO) < 0){
            throw new FebsException("支付金额错误");
        }
        HappyActivityOrder happyActivityOrder = new HappyActivityOrder();
        happyActivityOrder.setOrderNo(MallUtils.getOrderNum());
        happyActivityOrder.setMemberId(memberId);
        happyActivityOrder.setActivityId(dto.getActivityId());
        happyActivityOrder.setPrice(happyActivity.getPayAmount());
        happyActivityOrder.setNumCnt(dto.getNumCnt());
        happyActivityOrder.setAmount(amount);
        happyActivityOrder.setPayState(StateUpDownEnum.PAY_STATE_NOT_PAY.getCode());
        happyActivityOrderMapper.insert(happyActivityOrder);
        for(Long connectId : connectIds){
            HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(connectId);
            HappyActivityOrderItem happyActivityOrderItem = new HappyActivityOrderItem();
            happyActivityOrderItem.setMemberId(memberId);
            happyActivityOrderItem.setActivityId(dto.getActivityId());
            happyActivityOrderItem.setOrderId(happyActivityOrder.getId());
            happyActivityOrderItem.setConnectId(connectId);
            happyActivityOrderItem.setPrice(happyActivity.getPayAmount());
            happyActivityOrderItem.setName(happyActivityConnect.getName());
            happyActivityOrderItem.setPhone(happyActivityConnect.getPhone());
            happyActivityOrderItem.setAddress(happyActivityConnect.getAddress());
            happyActivityOrderItem.setState(StateUpDownEnum.DOWN.getCode());
            happyActivityOrderItemMapper.insert(happyActivityOrderItem);
        }
        this.substructJoinCnt(activityId, happyActivityOrder.getNumCnt());
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("orderId",happyActivityOrder.getId());
        stringObjectHashMap.put("amount",amount);
        return new FebsResponse().success().data(stringObjectHashMap);
    }
    /**
     * 支付订单函数,根据传入的支付订单数据对象处理不同支付类型的订单支付逻辑。
     *
     * @param dto 包含支付订单相关信息的数据传输对象,包括订单ID和支付类型等信息。
     *            - orderId: 订单ID,用于查询订单信息。
     *            - payType: 支付类型,决定支付逻辑的分支。
     *            - tradePwd: 交易密码(可选),用于余额或积分支付时验证。
     * @return FebsResponse 返回支付结果的响应对象,包含支付状态、订单信息等数据。
     *         - orderInfo: 支付结果信息,可能是预支付ID或其他支付相关数据。
     *         - orderNo: 订单编号。
     *         - orderId: 订单ID。
     *         - wxResultStr: 微信支付相关的结果字符串(仅在微信支付时返回)。
     * @throws FebsException 如果订单不存在、已支付、支付失败或支付类型不支持,则抛出异常。
     */
    @Override
    public FebsResponse payOrder(ApiPayOrderDto dto) {
        // 获取当前登录用户的ID
        Long memberId = LoginUserUtil.getLoginUser().getId();
        Long orderId = dto.getOrderId();
        Integer payType = dto.getPayType();
        // 查询订单信息,确保订单存在且未支付
        HappyActivityOrder happyActivityOrder = happyActivityOrderMapper.selectById(orderId);
        if (ObjectUtil.isEmpty(happyActivityOrder)) {
            throw new FebsException("订单不存在");
        }
        if (happyActivityOrder.getPayState() == StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()) {
            throw new FebsException("订单已支付");
        }
        String payResultStr = "";
        String wxResultStr = "";
        try {
            // 根据支付类型处理不同的支付逻辑
            if (StateUpDownEnum.PAY_METHOD_NO_PAY.getCode() == payType) {
                // 处理无需支付的订单逻辑
                processNoPayOrder(happyActivityOrder, orderId);
            } else if (StateUpDownEnum.PAY_METHOD_WECHAT.getCode() == payType) {
                // 处理微信支付逻辑,生成支付请求数据并更新订单状态
                BrandWCPayRequestData brandWCPayRequestData = iXcxPayService.startPaymentActivity(happyActivityOrder);
                wxResultStr = JSONUtil.toJsonStr(brandWCPayRequestData);
                payResultStr = brandWCPayRequestData.getPrepay_id();
                updateOrderState(happyActivityOrder, payType, StateUpDownEnum.PAY_STATE_NOT_PAY.getCode());
            } else if (StateUpDownEnum.PAY_METHOD_BALANCE.getCode() == payType ||
                       StateUpDownEnum.PAY_METHOD_INTEGRAL.getCode() == payType) {
                // 处理余额或积分支付逻辑,验证交易密码并完成支付
                String payMethod = StateUpDownEnum.PAY_METHOD_BALANCE.getCode() == payType ? "balance" : "prizeScore";
                payResultStr = balancePay(happyActivityOrder, dto.getTradePwd(), payMethod);
                processPaidOrder(happyActivityOrder, orderId, payType);
            } else {
                // 如果支付类型不支持,抛出异常
                throw new FebsException("不支持的支付类型");
            }
        } catch (Exception e) {
            // 捕获支付过程中的异常,记录日志并抛出自定义异常
            log.error("支付失败,订单ID:{},支付类型:{}", orderId, payType, e);
            throw new FebsException("支付失败:" + e.getMessage());
        }
        // todo 支付失败要把对应的人数加回来
        // 构造返回结果,包含支付相关信息
        Map<String, Object> map = new HashMap<>();
        map.put("orderInfo", payResultStr);
        map.put("orderNo", happyActivityOrder.getOrderNo());
        map.put("orderId", happyActivityOrder.getId());
        map.put("wxResultStr", wxResultStr);
        return new FebsResponse().success().data(map).message("支付成功");
    }
    @Override
    public void addLikeCnt(Long sourceOptionId) {
        HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId);
        happyActivityOption.setLikesCnt(happyActivityOption.getLikesCnt() + 1);
        happyActivityOptionMapper.updateById(happyActivityOption);
    }
    @Override
    public void substructJoinCnt(Long activityId, Integer numCnt) {
        HappyActivity happyActivity = this.baseMapper.selectById(activityId);
        if(ObjectUtil.isNotEmpty(happyActivity)){
            happyActivity.setJoinCnt(happyActivity.getJoinCnt() -numCnt);
            this.baseMapper.updateById(happyActivity);
        }
    }
    // 处理未支付订单
    private void processNoPayOrder(HappyActivityOrder order, Long orderId) {
        updateOrderState(order, StateUpDownEnum.PAY_METHOD_NO_PAY.getCode(), StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode());
        generateOrderItemCodes(orderId);
    }
    // 处理已支付订单
    private void processPaidOrder(HappyActivityOrder order, Long orderId, Integer payType) {
        updateOrderState(order, payType, StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode());
        generateOrderItemCodes(orderId);
    }
    // 更新订单状态
    private void updateOrderState(HappyActivityOrder order, Integer payType, Integer payState) {
        order.setPayState(payState);
        order.setPayType(payType);
        if (payState == StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()) {
            order.setPayTime(new Date());
        }
        happyActivityOrderMapper.updateById(order);
    }
    // 批量生成订单项编码
    private void generateOrderItemCodes(Long orderId) {
        List<HappyActivityOrderItem> items = happyActivityOrderItemMapper.selectList(
            new LambdaQueryWrapper<HappyActivityOrderItem>()
                .eq(HappyActivityOrderItem::getOrderId, orderId)
        );
        if (CollUtil.isNotEmpty(items)) {
            for (HappyActivityOrderItem item : items) {
                String code = ShareCodeUtil.toSerialCode(item.getOrderId()) + MallUtils.getRandomNum(8);
                item.setCode(code);
                happyActivityOrderItemMapper.updateById(item);
            }
        }
    }
    private String balancePay(HappyActivityOrder happyActivityOrder, String tradePwd, String field) {
        if (StrUtil.isBlank(tradePwd)) {
            throw new FebsException("支付密码错误");
        }
        MallMember mallMember = mallMemberMapper.selectById(happyActivityOrder.getMemberId());
        if (StrUtil.isBlank(mallMember.getTradePassword())) {
            throw new FebsException("未设置支付密码");
        }
        if (!SecureUtil.md5(tradePwd).equals(mallMember.getTradePassword())) {
            throw new FebsException("支付密码错误");
        }
        int reduce = iApiMallMemberWalletService.reduce(happyActivityOrder.getAmount(), mallMember.getId(), field);
        if (reduce == 2) {
            throw new FebsException("余额不足");
        }
        return happyActivityOrder.getOrderNo();
    }
    public static void main(String[] args) {
        Date date = new Date();
        //获取今日的凌晨的时间
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityInfoVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/ApiActivityInfoVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity;
package cc.mrbird.febs.mall.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityOptionListVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiActivityOptionListVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityOptionVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiActivityOptionVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -40,4 +40,7 @@
    @ApiModelProperty(value = "是否签约mcn机构 0否 1是")
    private Integer mcnState;
    @ApiModelProperty(value = "投票数量")
    private Integer voteCnt;
}
src/main/java/cc/mrbird/febs/mall/vo/ApiActivityVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/ApiActivityVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity;
package cc.mrbird.febs.mall.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
src/main/java/cc/mrbird/febs/mall/vo/ApiCategoryInfoVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/category/ApiCategoryInfoVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.category;
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
src/main/java/cc/mrbird/febs/mall/vo/ApiConnectListInPageVo.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.mall.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiConnectListInPageVo", description = "参数")
public class ApiConnectListInPageVo {
    @ApiModelProperty(value = "ID", example = "丽丽")
    private Long id;
    @ApiModelProperty(value = "姓名", example = "丽丽")
    private String name;
    @ApiModelProperty(value = "电话", example = "丽丽")
    private String phone;
    @ApiModelProperty(value = "地址", example = "丽丽")
    private String address;
}
src/main/java/cc/mrbird/febs/mall/vo/ApiVoteRecordInPageVo.java
File was renamed from src/main/java/cc/mrbird/febs/mall/vo/api/activity/options/ApiVoteRecordInPageVo.java
@@ -1,4 +1,4 @@
package cc.mrbird.febs.mall.vo.api.activity.options;
package cc.mrbird.febs.mall.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java
@@ -3,6 +3,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.ApiRechargeWalletDto;
import cc.mrbird.febs.mall.dto.RechargeWalletMessageSendDto;
import cc.mrbird.febs.mall.entity.HappyActivityOrder;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
import cc.mrbird.febs.pay.model.MemberWithdrawalDto;
@@ -21,6 +22,11 @@
    BrandWCPayRequestData startPayment(MallOrderInfo mallOrderInfo) throws Exception;
    /**
     * 发起支付(创建预付订单)
     */
    BrandWCPayRequestData startPaymentActivity(HappyActivityOrder dto) throws Exception;
    /**
     * 发送订单送达消息
     */
    void pushOrderToAddress(OrderStateDto info);
src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java
@@ -52,6 +52,12 @@
public class XcxPayServiceImpl implements IXcxPayService {
    @Autowired
    private HappyActivityOrderMapper happyActivityOrderMapper;
    @Autowired
    private HappyActivityMapper happyActivityMapper;
    @Autowired
    private MallOrderInfoMapper mallOrderInfoMapper;
    @Autowired
    private MallMemberMapper mallMemberMapper;
@@ -202,6 +208,27 @@
        }
        mallOrderInfo.setWxOrderNo(payData.getPrepay_id());
        mallOrderInfoMapper.updateById(mallOrderInfo);
        return payData;
    }
    @Override
    public BrandWCPayRequestData startPaymentActivity(HappyActivityOrder dto) throws Exception {
        BigDecimal unit = new BigDecimal("100");
        BigDecimal money = new BigDecimal(dto.getAmount().toString());
        BrandWCPayRequestData payData;
        HappyActivity happyActivity = happyActivityMapper.selectById(dto.getActivityId());
        String productNames = getActivityNames(happyActivity.getId(),dto.getNumCnt());
        MallMember mallMember = mallMemberMapper.selectById(dto.getMemberId());
        Boolean debug = xcxProperties.getDebug();
        if (debug) {
            payData = weixinServiceUtil.createActivityOrder("[测试]" + productNames, dto.getOrderNo(),
                    1, mallMember.getOpenId(), String.valueOf(dto.getId()));
        } else {
            payData = weixinServiceUtil.createActivityOrder(productNames, dto.getOrderNo(),
                    unit.multiply(money).intValue(),mallMember.getOpenId(), String.valueOf(dto.getId()));
        }
        dto.setWxOrderNo(payData.getPrepay_id());
        happyActivityOrderMapper.updateById(dto);
        return payData;
    }
@@ -509,4 +536,21 @@
        }
        return productNames;
    }
    /**
     * 根据用户ID和订单ID获取所购买商品名称
     * @return 所含商品名称(多个以","隔开)
     */
    public String getActivityNames(Long activityId,Integer numCnt) {
        HappyActivity happyActivity = happyActivityMapper.selectById(activityId);
        StringBuffer productNameBuffer = new StringBuffer();
        Integer maxLength = 25;
        String goodsName = happyActivity.getName();
        if (goodsName.length() > maxLength) {
            productNameBuffer.append(goodsName.substring(0, maxLength) + "*"+numCnt);
        }else{
            productNameBuffer.append(goodsName+"*"+numCnt);
        }
        return productNameBuffer.toString();
    }
}
src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java
@@ -37,6 +37,10 @@
     * @return 预支付订单返回的结果对象(该结果对象已封装),在H5页面使用该对象信息
     * @throws Exception
     */
    public BrandWCPayRequestData createActivityOrder(String desc, String outTradeNo, int price, String openId, String attach) throws Exception {
        String wecharActivityPaynotifyUrl = xcxProperties.getWecharActivityPaynotifyUrl();
        return buildBrandWCPayRequestData(desc, outTradeNo, price, openId, attach, wecharActivityPaynotifyUrl);
    }
    public BrandWCPayRequestData createOrder(String desc, String outTradeNo, int price, String openId, String attach) throws Exception {
        String wecharPaynotifyUrl = xcxProperties.getWecharPaynotifyUrl();
        return buildBrandWCPayRequestData(desc, outTradeNo, price, openId, attach, wecharPaynotifyUrl);
src/main/resources/application-test.yml
@@ -15,10 +15,10 @@
      datasource:
        # 数据源-1,名称为 base
        base:
          username: db_blnka
          password: blnka!@#123
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://121.37.162.173:3306/db_blnka?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
          url: jdbc:mysql://localhost:3306/happy_community_365?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8
  redis:
    # Redis数据库索引(默认为 0)
@@ -74,6 +74,7 @@
  xcx_secret: 9bb58d655bff419feec3a6d948ca8b8d1
  debug: true
  wecharPaynotifyUrl: http://blnka.csxuncong.com/api/xcxPay/wxpayCallback
  wecharActivityPaynotifyUrl: http://blnka.csxuncong.com/api/xcxPay/wxpayCallback
  wecharRechargePaynotifyUrl: http://blnka.csxuncong.com/api/xcxPay/rechargeCallBack
  certLocalPath: /home/blnkaCert/apiclient_cert.p12
  wecharpayMchid: 1658958205
src/main/resources/mapper/modules/HappyActivityMapper.xml
@@ -1,44 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.mrbird.febs.mall.mapper.HappyActivityMapper">
<mapper namespace="cc.mrbird.febs.mall.mapper.HappyActivityConnectMapper">
    <select id="selectActivityPage" resultType="cc.mrbird.febs.mall.vo.api.activity.ApiActivityInfoVo">
    <select id="selectConnectListPage" resultType="cc.mrbird.febs.mall.vo.ApiConnectListInPageVo">
        select
            a.id,
            a.index_img,
            a.code,
            a.name,
            a.state,
            a.join_cnt,
            a.start_time,
            a.end_time
        from happy_activity a
        <where>
            a.state != 0
            and a.DELETE_FLAG = 0
            <if test="record != null">
                <if test="record.query != null and record.query != ''">
                    and a.name like CONCAT('%', CONCAT(#{record.query}, '%'))
                </if>
                <if test="record.hotState != null">
                    and a.hot_state=#{record.hotState}
                </if>
                <if test="record.categoryId != null">
                    and a.category_id=#{record.categoryId}
                </if>
            </if>
        </where>
        order by a.order_cnt asc, a.id desc
    </select>
    <select id="getVoteRecordInPage" resultType="cc.mrbird.febs.mall.vo.api.activity.options.ApiVoteRecordInPageVo">
        select
            a.member_id as memberId,
                a.created_time as createdTime
        from happy_follow a
            a.*
        from happy_activity_connect a
        where
            a.type = 4
            and a.source_option_id = #{record.sourceOptionId}
            a.member_id = #{record.memberId}
        order by a.id desc
    </select>
src/main/resources/mapper/modules/HappyActivityOptionMapper.xml
New file
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.mrbird.febs.mall.mapper.HappyActivityMapper">
    <select id="selectActivityPage" resultType="cc.mrbird.febs.mall.vo.ApiActivityInfoVo">
        select
            a.id,
            a.index_img,
            a.code,
            a.name,
            a.state,
            a.join_cnt,
            a.start_time,
            a.end_time
        from happy_activity a
        <where>
            a.state != 0
            and a.DELETE_FLAG = 0
            <if test="record != null">
                <if test="record.query != null and record.query != ''">
                    and a.name like CONCAT('%', CONCAT(#{record.query}, '%'))
                </if>
                <if test="record.hotState != null">
                    and a.hot_state=#{record.hotState}
                </if>
                <if test="record.categoryId != null">
                    and a.category_id=#{record.categoryId}
                </if>
            </if>
        </where>
        order by a.order_cnt asc, a.id desc
    </select>
    <select id="getVoteRecordInPage" resultType="cc.mrbird.febs.mall.vo.ApiVoteRecordInPageVo">
        select
            a.member_id as memberId,
                a.created_time as createdTime
        from happy_follow a
        where
            a.type = 4
            and a.source_option_id = #{record.sourceOptionId}
        order by a.id desc
    </select>
</mapper>