Administrator
2025-07-03 4b95f906abd287452324c39bcfa114617720eab1
feat(mall): 添加设计衣服订单功能

- 新增 ApiClothesOrderController 控制器
- 添加草稿保存、订单创建、取消订单、删除订单、支付订单等接口
- 新增相关 DTO 和 VO 类
- 实现 ApiClothesOrderService 接口
- 在 AgentConsumer 中添加订单自动取消的消费逻辑
- 在 AgentProducer 中添加发送订单自动取消消息的方法
16 files modified
25 files added
1670 ■■■■■ changed files
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java 34 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderItemEnum.java 23 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderPayTypeEnum.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderStatusEnum.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/clothes/ApiClothesController.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/controller/clothes/ApiClothesOrderController.java 95 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java 4 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/PayOrderDto.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderDraftDto.java 16 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderInfoDto.java 39 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderItemInfoDto.java 27 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderPayDto.java 25 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiMyDraftPageDto.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiMyDraftSaveDto.java 49 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrder.java 68 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrderDraft.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrderItem.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderDraftMapper.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderItemMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderMapper.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/quartz/WxxcxJob.java 56 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/ApiClothesOrderService.java 28 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/ApiClothesService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesOrderServiceImpl.java 680 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesServiceImpl.java 81 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiClothesOrderInfoVo.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiClothesOrderPayVo.java 15 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiMyDraftSaveVo.java 14 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiMyDraftVo.java 68 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/IPayService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/impl/PayServiceImpl.java 38 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java 36 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java 17 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java 11 ●●●●● patch | view | raw | blame | history
src/main/resources/application-test.yml 4 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/ClothesOrderDraftMapper.xml 16 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/ClothesOrderItemMapper.xml 7 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/ClothesOrderMapper.xml 7 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -46,6 +46,40 @@
        return BindingBuilder.bind(defaultQueue()).to(defaultExchange()).with(RouteKeyConstants.ROUTE_KEY_DEFAULT);
    }
    @Bean
    public DirectExchange delayTtlExchangeClothes() {
        return new DirectExchange(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY_TTL.getExchange());
    }
    @Bean
    public Queue orderDelayQueueTtlClothes() {
        return QueueBuilder.durable(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY_TTL.getQueue())
                //到期后转发的交换机
                .withArgument("x-dead-letter-exchange", RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY.getExchange())
                //到期后转发的路由键
                .withArgument("x-dead-letter-routing-key", RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY.getRoute())
                .build();
    }
    @Bean
    public Binding orderDelayBindTtlClothes() {
        return BindingBuilder.bind(orderDelayQueueTtlClothes()).to(delayTtlExchangeClothes()).with(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY_TTL.getRoute());
    }
    @Bean
    public DirectExchange orderDelayExchangeClothes() {
        return new DirectExchange(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY.getExchange());
    }
    @Bean
    public Queue orderDelayQueueClothes() {
        return new Queue(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY.getQueue());
    }
    @Bean
    public Binding orderDelayBindClothes() {
        return BindingBuilder.bind(orderDelayQueueClothes()).to(orderDelayExchangeClothes()).with(RabbitQueueEnum.CLOTHES_ORDER_CANCEL_DELAY.getRoute());
    }
    @Bean
    public DirectExchange delayTtlExchange() {
        return new DirectExchange(RabbitQueueEnum.ORDER_CANCEL_DELAY_TTL.getExchange());
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderItemEnum.java
New file
@@ -0,0 +1,23 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum ClothesOrderItemEnum {
    /**
     *   类型 1图案 2图案位置 3工艺 4布料 5尺码 6尺码自定义
     */
    CUSTOMIZE(6),
    SIZE(5),
    CLOTH(4),
    ART(3),
    LOCATION(2),
    PATTERN(1);
    private final int code;
    ClothesOrderItemEnum(int code) {
        this.code = code;
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderPayTypeEnum.java
New file
@@ -0,0 +1,22 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum ClothesOrderPayTypeEnum {
    WECHAT(1,"微信支付"),
    ALIPAY(2,"支付宝支付"),
    BALANCE(3,"余额支付")
    ;
    private Integer code;
    private String name;
    ClothesOrderPayTypeEnum(Integer code,String name) {
        this.code = code;
        this.name = name;
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/ClothesOrderStatusEnum.java
New file
@@ -0,0 +1,35 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum ClothesOrderStatusEnum {
    /**
     * 状态;1-待支付 2-待发货 3-待收货 4-已完成 5-已取消
     */
    WAIT_PAY(1),
    /**
     * 待发货
     */
    WAIT_SHIPPING(2),
    /**
     * 待收货
     */
    WAIT_FINISH(3),
    /**
     * 已完成
     */
    FINISH(4),
    /**
     * 已取消
     */
    CANCEL(5)
    ;
    private final int value;
    ClothesOrderStatusEnum(int value) {
        this.value = value;
    }
}
src/main/java/cc/mrbird/febs/mall/controller/clothes/ApiClothesController.java
@@ -136,4 +136,14 @@
        return clothesService.statureDel(dto);
    }
    @ApiOperation(value = "预览效果-保存至草稿", notes = "预览效果-保存至草稿")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMyDraftSaveVo.class)
    })
    @PostMapping(value = "/draftSave")
    public FebsResponse draftSave(@RequestBody @Validated ApiMyDraftSaveDto dto) {
        return clothesService.draftSave(dto);
    }
}
src/main/java/cc/mrbird/febs/mall/controller/clothes/ApiClothesOrderController.java
New file
@@ -0,0 +1,95 @@
package cc.mrbird.febs.mall.controller.clothes;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.OrderListDto;
import cc.mrbird.febs.mall.dto.PayOrderDto;
import cc.mrbird.febs.mall.dto.clothes.*;
import cc.mrbird.febs.mall.service.ApiClothesOrderService;
import cc.mrbird.febs.mall.service.ApiClothesService;
import cc.mrbird.febs.mall.vo.OrderListVo;
import cc.mrbird.febs.mall.vo.clothes.*;
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.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/clothes/order")
@Api(value = "ApiClothesOrderController", tags = "设计衣服订单")
public class ApiClothesOrderController {
    private final ApiClothesOrderService apiClothesOrderService;
    @ApiOperation(value = "我的草稿", notes = "我的草稿")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMyDraftVo.class)
    })
    @PostMapping(value = "/myDraft")
    public FebsResponse myDraft(@RequestBody @Validated ApiMyDraftPageDto dto) {
        return apiClothesOrderService.myDraft(dto);
    }
    @ApiOperation(value = "我的草稿-跳转到开始设计", notes = "我的草稿-跳转到开始设计")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiMyDraftVo.class)
    })
    @PostMapping(value = "/draftToDesign")
    public FebsResponse draftToDesign(@RequestBody @Validated ApiClothesOrderDraftDto dto) {
        return apiClothesOrderService.draftToDesign(dto);
    }
    @ApiOperation(value = "我的草稿-删除", notes = "我的草稿-删除")
    @PostMapping(value = "/draftDel")
    public FebsResponse draftDel(@RequestBody @Validated ApiClothesOrderDraftDto dto) {
        return apiClothesOrderService.draftDel(dto);
    }
    @ApiOperation(value = "创建订单", notes = "创建订单")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiClothesOrderInfoVo.class)
    })
    @PostMapping(value = "/createOrder")
    public FebsResponse createOrder(@RequestBody @Validated ApiClothesOrderInfoDto dto) {
        return apiClothesOrderService.createOrder(dto);
    }
    @ApiOperation(value = "取消订单", notes = "取消订单")
    @PostMapping(value = "/cancelOrder/{id}")
    public FebsResponse cancelOrder(@PathVariable("id") Long id) {
        return apiClothesOrderService.cancelOrder(id);
    }
    @ApiOperation(value = "删除订单", notes = "删除订单")
    @PostMapping(value = "/delOrder/{id}")
    public FebsResponse delOrder(@PathVariable("id") Long id) {
        return apiClothesOrderService.delOrder(id);
    }
    @ApiOperation(value = "支付订单", notes = "支付订单")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = ApiClothesOrderPayVo.class)
    })
    @PostMapping(value = "/payOrder")
    public FebsResponse payOrder(@RequestBody ApiClothesOrderPayDto dto) {
        return apiClothesOrderService.payOrder(dto);
    }
}
src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java
@@ -18,7 +18,7 @@
    @ApiModelProperty(value = "第几页", example = "1")
    private Integer pageNum;
    @ApiModelProperty(value = "搜索参数(姓名,电话,提货码)", example = "1")
    @ApiModelProperty(value = "搜索参数(姓名,电话)", example = "1")
    private String query;
    @ApiModelProperty(value = "订单状态", example = "0-全部 1-待付款 2-待发货(待确认) 3-待收货(待提货) 4-已完成 5-已取消")
@@ -27,6 +27,4 @@
    @ApiModelProperty(hidden = true)
    private Long memberId;
    @ApiModelProperty(value = "1-普通订单, 2-积分订单", example = "1")
    private Integer orderType;
}
src/main/java/cc/mrbird/febs/mall/dto/PayOrderDto.java
@@ -20,7 +20,7 @@
    private Long id;
    @NotBlank(message = "参数不能为空")
    @ApiModelProperty(value = "支付类型", example = "1微信2支付宝3余额4积分")
    @ApiModelProperty(value = "支付类型", example = "1微信2支付宝3余额")
    private String type;
    @ApiModelProperty(value = "支付密码", example = "如果选择余额支付需要输入")
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderDraftDto.java
New file
@@ -0,0 +1,16 @@
package cc.mrbird.febs.mall.dto.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiClothesOrderDraftDto", description = "参数")
public class ApiClothesOrderDraftDto {
    @NotNull(message = "草稿不能为空")
    @ApiModelProperty(value = "草稿ID")
    private Long id;
}
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderInfoDto.java
New file
@@ -0,0 +1,39 @@
package cc.mrbird.febs.mall.dto.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
@Data
@ApiModel(value = "ApiClothesOrderInfoDto", description = "参数")
public class ApiClothesOrderInfoDto {
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "地址ID", example = "1")
    private Long addressId;
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "类型ID", example = "1")
    private Long typeId;
    @ApiModelProperty(value = "备注")
    private String remark;
    @ApiModelProperty(value = "快递费")
    private BigDecimal deliveryAmount;
    @ApiModelProperty(value = "会员优惠卷ID")
    private Long memberCouponId;
    @NotNull(message = "数量不能为空")
    @ApiModelProperty(value = "数量", example = "2")
    private Integer cnt;
    @ApiModelProperty(value = "商品明细")
    private List<ApiClothesOrderItemInfoDto> items;
}
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderItemInfoDto.java
New file
@@ -0,0 +1,27 @@
package cc.mrbird.febs.mall.dto.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiClothesOrderItemInfoDto", description = "参数")
public class ApiClothesOrderItemInfoDto {
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "id", example = "1")
    private Long skuId;
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "数量", example = "2")
    private Integer cnt;
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "类型 1图案 2图案位置 3工艺 4布料 5尺码 6尺码自定义", example = "2")
    private Integer type;
    @ApiModelProperty(value = "自定义图案内容", example = "2")
    private String patternRemark;
}
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiClothesOrderPayDto.java
New file
@@ -0,0 +1,25 @@
package cc.mrbird.febs.mall.dto.clothes;
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 = "ApiClothesOrderPayDto", description = "参数")
public class ApiClothesOrderPayDto {
    @NotNull(message = "参数不能为空")
    @ApiModelProperty(value = "订单ID")
    private Long id;
    @NotBlank(message = "参数不能为空")
    @ApiModelProperty(value = "支付类型", example = "1微信2支付宝3余额")
    private Integer type;
    @ApiModelProperty(value = "支付密码", example = "如果选择余额支付需要输入")
    private String tradePwd;
}
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiMyDraftPageDto.java
New file
@@ -0,0 +1,24 @@
package cc.mrbird.febs.mall.dto.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiMyDraftPageDto", description = "参数")
public class ApiMyDraftPageDto {
    @NotNull(message = "页码不能为空")
    @ApiModelProperty(value = "页码", example = "1")
    private Integer pageNow;
    @NotNull(message = "每页数量不能为空")
    @ApiModelProperty(value = "每页数量", example = "10")
    private Integer pageSize;
    @ApiModelProperty(hidden = true)
    private Long memberId;
}
src/main/java/cc/mrbird/febs/mall/dto/clothes/ApiMyDraftSaveDto.java
New file
@@ -0,0 +1,49 @@
package cc.mrbird.febs.mall.dto.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel(value = "ApiMyDraftSaveDto", description = "参数")
public class ApiMyDraftSaveDto {
    @NotNull(message = "类型不能为空")
    @ApiModelProperty(value = "类型ID")
    private Long typeId;
    @NotNull(message = "工艺不能为空")
    @ApiModelProperty(value = "工艺ID")
    private Long artId;
    @NotNull(message = "尺码不能为空")
    @ApiModelProperty(value = "尺码ID")
    private Long sizeId;
    @NotNull(message = "图案不能为空")
    @ApiModelProperty(value = "图案ID")
    private Long patternId;
    @ApiModelProperty(value = "自定义内容")
    private String patternRemark;
    @NotNull(message = "图案位置不能为空")
    @ApiModelProperty(value = "图案位置ID")
    private Long locationId;
    @NotNull(message = "布料不能为空")
    @ApiModelProperty(value = "布料ID")
    private Long clothId;
    @ApiModelProperty(value = "身材数据ID")
    private Long statureId;
}
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrder.java
New file
@@ -0,0 +1,68 @@
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;
import java.util.Date;
@Data
@TableName("clothes_order_graft")
public class ClothesOrder extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL,
     `order_no` varchar(32) DEFAULT NULL COMMENT '订单号',
     `order_time` datetime DEFAULT NULL COMMENT '下单时间',
     `goods_cnt` int(11) DEFAULT NULL COMMENT '数量',
     `amount` decimal(20,2) DEFAULT NULL COMMENT '订单金额',
     `pay_time` datetime DEFAULT NULL COMMENT '支付时间',
     `pay_method` varchar(32) DEFAULT NULL COMMENT '支付方式',
     `pay_order_no` text COMMENT '支付订单号',
     `pay_result` int(11) DEFAULT NULL COMMENT '支付结果 1-成功 0-未成功',
     `status` int(11) DEFAULT NULL COMMENT '状态;1-待支付 2-待发货 3-待收货 4-已完成 5-已取消',
     `name` varchar(32) DEFAULT NULL COMMENT '联系人',
     `phone` varchar(32) DEFAULT NULL COMMENT '联系方式',
     `address_id` bigint(20) DEFAULT NULL COMMENT '地址ID',
     `address` text COMMENT '收货地址',
     `longitude` varchar(255) DEFAULT NULL COMMENT '经度',
     `latitude` varchar(255) DEFAULT NULL COMMENT '纬度',
     `carriage` decimal(4,2) DEFAULT '0.00' COMMENT '运费',
     `comment_state` int(11) DEFAULT '1' COMMENT '评价状态 1:待评价 2:已评价',
     `remark` text COMMENT '备注',
     `member_coupon_id` bigint(20) DEFAULT NULL COMMENT '会员优惠卷ID',
     */
    private Long memberId;
    private Long memberCouponId;
    private Long typeId;
    private String orderNo;
    private Date orderTime;
    private Integer goodsCnt;
    private Integer status;
    private String remark;
    private Date payTime;
    private String payMethod;
    private String payOrderNo;
    private Integer payResult;
    private Long addressId;
    private Integer deliveryState;
    private String name;
    private String phone;
    private String address;
    private String longitude;
    private String latitude;
    private BigDecimal amount;
    private BigDecimal discountAmount;
    private BigDecimal carriage;
    private BigDecimal realAmount;
    private Integer commentState;
    private Integer delFlag;
}
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrderDraft.java
New file
@@ -0,0 +1,35 @@
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("clothes_order_draft")
public class ClothesOrderDraft extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL,
     `type_id` bigint(20) DEFAULT NULL COMMENT '类别',
     `art_id` bigint(20) DEFAULT NULL,
     `stature_id` bigint(20) DEFAULT NULL,
     `size_id` bigint(20) DEFAULT NULL,
     `pattern_id` bigint(20) DEFAULT NULL,
     `location_id` bigint(20) DEFAULT NULL,
     `cloth_id` bigint(20) DEFAULT NULL,
     `pattern_remark` varchar(200) DEFAULT NULL,
     */
    private Long memberId;
    private Long typeId;
    private Long artId;
    private Long statureId;
    private Long sizeId;
    private Long patternId;
    private Long locationId;
    private Long clothId;
    private Integer delFlag;
    private String patternRemark;
}
src/main/java/cc/mrbird/febs/mall/entity/ClothesOrderItem.java
New file
@@ -0,0 +1,31 @@
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("clothes_order_item")
public class ClothesOrderItem  extends BaseEntity {
    /**
     *
     `member_id` bigint(20) DEFAULT NULL,
     `order_id` bigint(20) DEFAULT NULL,
     `name` varchar(200) DEFAULT NULL,
     `price` decimal(20,2) DEFAULT NULL,
     `item_cnt` int(11) DEFAULT NULL,
     `amount` decimal(20,2) DEFAULT NULL,
     `type` int(11) DEFAULT NULL COMMENT '类型 1图案 2图案位置 3工艺 4布料 5尺码',
     `remark` varchar(200) DEFAULT NULL,
     */
    private Long memberId;
    private Long orderId;
    private String name;
    private BigDecimal price;
    private Integer itemCnt;
    private BigDecimal amount;
    private Integer type;
    private String remark;
}
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderDraftMapper.java
New file
@@ -0,0 +1,12 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.dto.clothes.ApiMyDraftPageDto;
import cc.mrbird.febs.mall.entity.ClothesOrderDraft;
import cc.mrbird.febs.mall.vo.clothes.ApiMyDraftVo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
public interface ClothesOrderDraftMapper  extends BaseMapper<ClothesOrderDraft> {
    Page<ApiMyDraftVo> selectPageInDraft(Page<ApiMyDraftVo> page, @Param("record")ApiMyDraftPageDto dto);
}
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderItemMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.ClothesOrderItem;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface ClothesOrderItemMapper extends BaseMapper<ClothesOrderItem> {
}
src/main/java/cc/mrbird/febs/mall/mapper/ClothesOrderMapper.java
New file
@@ -0,0 +1,7 @@
package cc.mrbird.febs.mall.mapper;
import cc.mrbird.febs.mall.entity.ClothesOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface ClothesOrderMapper extends BaseMapper<ClothesOrder> {
}
src/main/java/cc/mrbird/febs/mall/quartz/WxxcxJob.java
@@ -48,34 +48,34 @@
     * 获取access_token
     * 有效期两小时
     */
//    @Scheduled(cron = "0 0 0/1 * * ? ")
//    public void getAccessToken() throws IOException {
//        log.info("执行access_token刷新");
//        String appId = xcxProperties.getXcxAppid();
//        String appSecret = xcxProperties.getXcxSecret();
//        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
//        String jsonStr = restTemplate.getForObject(url, String.class);
//
//        /**
//         * 返回结果
//         * {"access_token":"ACCESS_TOKEN","expires_in":7200}
//         */
//        if (!jsonStr.contains("access_token")) {
//            System.out.println("获取微信access_token失败");
//        }
//
//        String accessTokenKey = WechatConfigure.WX_ACCESS_TOKEN_REDIS_KEY;
//        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
//        String accessToken = jsonObject.getString(accessTokenKey);
//        if (StrUtil.isEmpty(accessToken)) {
//            log.error("获取access token失败: {}" , jsonObject.getString("errmsg"));
//            throw new ApiException("获取access token失败");
//        } else {
//            log.info("wx access_token : {}",accessToken);
//            redisUtils.set(accessTokenKey,accessToken);
//        }
//
//    }
    @Scheduled(cron = "0 0 0/1 * * ? ")
    public void getAccessToken() throws IOException {
        log.info("执行access_token刷新");
        String appId = xcxProperties.getXcxAppid();
        String appSecret = xcxProperties.getXcxSecret();
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
        String jsonStr = restTemplate.getForObject(url, String.class);
        /**
         * 返回结果
         * {"access_token":"ACCESS_TOKEN","expires_in":7200}
         */
        if (!jsonStr.contains("access_token")) {
            System.out.println("获取微信access_token失败");
        }
        String accessTokenKey = WechatConfigure.WX_ACCESS_TOKEN_REDIS_KEY;
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String accessToken = jsonObject.getString(accessTokenKey);
        if (StrUtil.isEmpty(accessToken)) {
            log.error("获取access token失败: {}" , jsonObject.getString("errmsg"));
            throw new ApiException("获取access token失败");
        } else {
            log.info("wx access_token : {}",accessToken);
            redisUtils.set(accessTokenKey,accessToken);
        }
    }
    @Scheduled(cron = "0 0 0/1 * * ? ")
    public void expireCoupon() {
src/main/java/cc/mrbird/febs/mall/service/ApiClothesOrderService.java
New file
@@ -0,0 +1,28 @@
package cc.mrbird.febs.mall.service;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.mall.dto.clothes.ApiClothesOrderDraftDto;
import cc.mrbird.febs.mall.dto.clothes.ApiClothesOrderInfoDto;
import cc.mrbird.febs.mall.dto.clothes.ApiClothesOrderPayDto;
import cc.mrbird.febs.mall.dto.clothes.ApiMyDraftPageDto;
import cc.mrbird.febs.mall.entity.ClothesOrder;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ApiClothesOrderService extends IService<ClothesOrder> {
    FebsResponse myDraft(ApiMyDraftPageDto dto);
    FebsResponse draftToDesign(ApiClothesOrderDraftDto dto);
    FebsResponse draftDel(ApiClothesOrderDraftDto dto);
    FebsResponse createOrder(ApiClothesOrderInfoDto dto);
    void orderCancelDelayClothes(long parseLong);
    FebsResponse cancelOrder(Long id);
    FebsResponse delOrder(Long id);
    FebsResponse payOrder(ApiClothesOrderPayDto dto);
}
src/main/java/cc/mrbird/febs/mall/service/ApiClothesService.java
@@ -30,4 +30,6 @@
    FebsResponse statureUpdate(ApiClothesMemberStatureUpdateDto dto);
    FebsResponse statureDel(ApiClothesMemberStatureInfoDto dto);
    FebsResponse draftSave(ApiMyDraftSaveDto dto);
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesOrderServiceImpl.java
New file
@@ -0,0 +1,680 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.enumerates.*;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.MallUtils;
import cc.mrbird.febs.common.utils.ShareCodeUtil;
import cc.mrbird.febs.mall.dto.AddOrderItemDto;
import cc.mrbird.febs.mall.dto.clothes.*;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.*;
import cc.mrbird.febs.mall.service.ApiClothesOrderService;
import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
import cc.mrbird.febs.mall.vo.clothes.ApiClothesOrderInfoVo;
import cc.mrbird.febs.mall.vo.clothes.ApiClothesOrderPayVo;
import cc.mrbird.febs.mall.vo.clothes.ApiMyDraftVo;
import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
import cc.mrbird.febs.pay.service.IPayService;
import cc.mrbird.febs.pay.service.IXcxPayService;
import cc.mrbird.febs.rabbit.producter.AgentProducer;
import cn.hutool.core.collection.CollUtil;
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.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiClothesOrderServiceImpl extends ServiceImpl<ClothesOrderMapper, ClothesOrder> implements ApiClothesOrderService {
    private final ClothesOrderMapper clothesOrderMapper;
    private final ClothesOrderItemMapper clothesOrderItemMapper;
    private final ClothesOrderDraftMapper clothesOrderDraftMapper;
    private final ClothesTypeMapper clothesTypeMapper;
    private final ClothesTypeClothMapper clothesTypeClothMapper;
    private final ClothesTypePatternMapper clothesTypePatternMapper;
    private final ClothesTypeSizeMapper clothesTypeSizeMapper;
    private final ClothesSizeMapper clothesSizeMapper;
    private final ClothesTypeLocationMapper clothesTypeLocationMapper;
    private final ClothesTypeArtMapper clothesTypeArtMapper;
    private final ClothesMemberStatureMapper clothesMemberStatureMapper;
    private final ClothesPatternMapper clothesPatternMapper;
    private final ClothesLocationMapper clothesLocationMapper;
    private final ClothesClothMapper clothesClothMapper;
    private final ClothesArtMapper clothesArtMapper;
    private final MallAddressInfoMapper mallAddressInfoMapper;
    private final MallMemberCouponMapper mallMemberCouponMapper;
    private final MallGoodsCouponMapper mallGoodsCouponMapper;
    private final AgentProducer agentProducer;
    private final IXcxPayService iXcxPayService;
    private final IPayService payService;
    private final MallMemberMapper mallMemberMapper;
    private final IApiMallMemberWalletService apiMallMemberWalletService;
    private final IMallMoneyFlowService mallMoneyFlowService;
    @Override
    public FebsResponse myDraft(ApiMyDraftPageDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        dto.setMemberId(memberId);
        // 创建分页对象,传入当前页和每页大小
        Page<ApiMyDraftVo> page = new Page<>(dto.getPageNow(), dto.getPageSize());
        // 调用Mapper方法获取活动分页数据
        Page<ApiMyDraftVo> voPage = clothesOrderDraftMapper.selectPageInDraft(page, dto);
        if (CollUtil.isNotEmpty(voPage.getRecords())){
            List<ApiMyDraftVo> records = voPage.getRecords();
            for (ApiMyDraftVo record : records){
                Long typeId = record.getTypeId();
                ClothesType clothesType = clothesTypeMapper.selectById(typeId);
                record.setTypeName(clothesType.getName());
                record.setTypeImage(clothesType.getImage());
                Long sizeId = ObjectUtil.defaultIfNull(record.getSizeId(),0L);
                List<ClothesTypeSize> clothesTypeSizes = clothesTypeSizeMapper.selectList(Wrappers.<ClothesTypeSize>lambdaQuery().eq(ClothesTypeSize::getTypeId, typeId));
                if (CollUtil.isNotEmpty(clothesTypeSizes)){
                    Set<Long> collect = clothesTypeSizes.stream().map(ClothesTypeSize::getSizeId).collect(Collectors.toSet());
                    if(CollUtil.isNotEmpty( collect) && collect.contains(sizeId)){
                        ClothesSize clothesSize = clothesSizeMapper.selectById(sizeId);
                        if (ObjectUtil.isNotNull(clothesSize)){
                            record.setSizeName(clothesSize.getName());
                            record.setSizePrice(clothesSize.getPrice());
                        }
                    }
                }
                Long statureId = ObjectUtil.defaultIfNull(record.getStatureId(),0L);
                ClothesMemberStature clothesMemberStature = clothesMemberStatureMapper.selectById(statureId);
                if (ObjectUtil.isNotEmpty(clothesMemberStature)){
                    record.setStatureName(clothesMemberStature.getName());
                }
                Long patternId = ObjectUtil.defaultIfNull(record.getPatternId(),0L);
                List<ClothesTypePattern> clothesTypePatterns = clothesTypePatternMapper.selectList(Wrappers.<ClothesTypePattern>lambdaQuery().eq(ClothesTypePattern::getTypeId, typeId));
                if (CollUtil.isNotEmpty(clothesTypePatterns)){
                    Set<Long> patternIds = clothesTypePatterns.stream().map(ClothesTypePattern::getPatternId).collect(Collectors.toSet());
                    if(CollUtil.isNotEmpty( patternIds) && patternIds.contains(patternId)){
                        ClothesPattern clothesPattern = clothesPatternMapper.selectById(patternId);
                        if (ObjectUtil.isNotNull(clothesPattern)){
                            record.setPatternName(clothesPattern.getName());
                            record.setPatternPrice(clothesPattern.getPrice());
                        }
                    }
                }
                Long locationId = ObjectUtil.defaultIfNull(record.getLocationId(),0L);
                List<ClothesTypeLocation> clothesTypeLocations = clothesTypeLocationMapper.selectList(Wrappers.<ClothesTypeLocation>lambdaQuery().eq(ClothesTypeLocation::getTypeId, typeId));
                if (CollUtil.isNotEmpty(clothesTypeLocations)){
                    Set<Long> locationIds = clothesTypeLocations.stream().map(ClothesTypeLocation::getLocationId).collect(Collectors.toSet());
                    if(CollUtil.isNotEmpty( locationIds) && locationIds.contains(locationId)){
                        ClothesLocation clothesLocation = clothesLocationMapper.selectById(locationId);
                        if (ObjectUtil.isNotNull(clothesLocation)){
                            record.setLocationName(clothesLocation.getName());
                            record.setLocationPrice(clothesLocation.getPrice());
                        }
                    }
                }
                Long artId = ObjectUtil.defaultIfNull(record.getArtId(),0L);
                List<ClothesTypeArt> clothesTypeArts = clothesTypeArtMapper.selectList(Wrappers.lambdaQuery(ClothesTypeArt.class).eq(ClothesTypeArt::getTypeId, typeId));
                if(CollUtil.isNotEmpty(clothesTypeArts)){
                    Set<Long> artIds = clothesTypeArts.stream().map(ClothesTypeArt::getArtId).collect(Collectors.toSet());
                    if (CollUtil.isNotEmpty(artIds) && artIds.contains(artId)){
                        ClothesArt clothesArt = clothesArtMapper.selectById(artId);
                        if (ObjectUtil.isNotNull(clothesArt)){
                            record.setArtName(clothesArt.getName());
                            record.setArtPrice(clothesArt.getPrice());
                        }
                    }
                }
                Long clothId = ObjectUtil.defaultIfNull(record.getClothId(),0L);
                List<ClothesTypeCloth> clothesTypeCloths = clothesTypeClothMapper.selectList(Wrappers.lambdaQuery(ClothesTypeCloth.class).eq(ClothesTypeCloth::getTypeId, typeId));
                if(CollUtil.isNotEmpty(clothesTypeCloths)){
                    Set<Long> clothIds = clothesTypeCloths.stream().map(ClothesTypeCloth::getClothId).collect(Collectors.toSet());
                    if (CollUtil.isNotEmpty(clothIds) && clothIds.contains(clothId)){
                        ClothesCloth clothesCloth = clothesClothMapper.selectById(clothId);
                        if (ObjectUtil.isNotNull(clothesCloth)){
                            record.setClothName(clothesCloth.getName());
                            record.setClothPrice(clothesCloth.getPrice());
                        }
                    }
                }
                BigDecimal amount =
                        record.getClothPrice()
                                .add(record.getLocationPrice())
                                .add(record.getArtPrice())
                                .add(record.getSizePrice())
                                .add(record.getPatternPrice()).setScale(2, RoundingMode.DOWN);
                record.setAmount(amount);
            }
        }
        return new FebsResponse().success().data(voPage);
    }
    @Override
    public FebsResponse draftToDesign(ApiClothesOrderDraftDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        ApiMyDraftVo record = new ApiMyDraftVo();
        Long id = dto.getId();
        ClothesOrderDraft clothesOrderDraft = clothesOrderDraftMapper.selectById(id);
        if (ObjectUtil.isNotNull(clothesOrderDraft)){
            Long typeId = clothesOrderDraft.getTypeId();
            ClothesType clothesType = clothesTypeMapper.selectById(typeId);
            record.setTypeId(typeId);
            record.setTypeName(clothesType.getName());
            record.setTypeImage(clothesType.getImage());
            record.setPatternRemark(clothesOrderDraft.getPatternRemark());
            Long sizeId = ObjectUtil.defaultIfNull(clothesOrderDraft.getSizeId(),0L);
            List<ClothesTypeSize> clothesTypeSizes = clothesTypeSizeMapper.selectList(Wrappers.<ClothesTypeSize>lambdaQuery().eq(ClothesTypeSize::getTypeId, typeId));
            if (CollUtil.isNotEmpty(clothesTypeSizes)){
                Set<Long> collect = clothesTypeSizes.stream().map(ClothesTypeSize::getSizeId).collect(Collectors.toSet());
                if(CollUtil.isNotEmpty( collect) && collect.contains(sizeId)){
                    ClothesSize clothesSize = clothesSizeMapper.selectById(sizeId);
                    if(ObjectUtil.isNotNull(clothesSize)){
                        record.setSizeId(sizeId);
                        record.setSizeName(clothesSize.getName());
                        record.setSizePrice(clothesSize.getPrice());
                    }
                }
            }
            Long statureId = ObjectUtil.defaultIfNull(clothesOrderDraft.getStatureId(),0L);
            ClothesMemberStature clothesMemberStature = clothesMemberStatureMapper.selectById(statureId);
            if (ObjectUtil.isNotNull(clothesMemberStature)){
                record.setStatureId(clothesMemberStature.getId());
                record.setStatureName(clothesMemberStature.getName());
            }
            Long patternId = ObjectUtil.defaultIfNull(clothesOrderDraft.getPatternId(),0L);
            List<ClothesTypePattern> clothesTypePatterns = clothesTypePatternMapper.selectList(Wrappers.<ClothesTypePattern>lambdaQuery().eq(ClothesTypePattern::getTypeId, typeId));
            if (CollUtil.isNotEmpty(clothesTypePatterns)){
                Set<Long> patternIds = clothesTypePatterns.stream().map(ClothesTypePattern::getPatternId).collect(Collectors.toSet());
                if(CollUtil.isNotEmpty( patternIds) && patternIds.contains(patternId)){
                    ClothesPattern clothesPattern = clothesPatternMapper.selectById(patternId);
                    if (ObjectUtil.isNotNull(clothesPattern)){
                        record.setPatternId(patternId);
                        record.setPatternName(clothesPattern.getName());
                        record.setPatternPrice(clothesPattern.getPrice());
                    }
                }
            }
            Long locationId = ObjectUtil.defaultIfNull(clothesOrderDraft.getLocationId(),0L);
            List<ClothesTypeLocation> clothesTypeLocations = clothesTypeLocationMapper.selectList(Wrappers.<ClothesTypeLocation>lambdaQuery().eq(ClothesTypeLocation::getTypeId, typeId));
            if (CollUtil.isNotEmpty(clothesTypeLocations)){
                Set<Long> locationIds = clothesTypeLocations.stream().map(ClothesTypeLocation::getLocationId).collect(Collectors.toSet());
                if(CollUtil.isNotEmpty( locationIds) && locationIds.contains(locationId)){
                    ClothesLocation clothesLocation = clothesLocationMapper.selectById(locationId);
                    if (ObjectUtil.isNotNull(clothesLocation)){
                        record.setLocationId(locationId);
                        record.setLocationName(clothesLocation.getName());
                        record.setLocationPrice(clothesLocation.getPrice());
                    }
                }
            }
            Long artId = ObjectUtil.defaultIfNull(clothesOrderDraft.getArtId(),0L);
            List<ClothesTypeArt> clothesTypeArts = clothesTypeArtMapper.selectList(Wrappers.lambdaQuery(ClothesTypeArt.class).eq(ClothesTypeArt::getTypeId, typeId));
            if(CollUtil.isNotEmpty(clothesTypeArts)){
                Set<Long> artIds = clothesTypeArts.stream().map(ClothesTypeArt::getArtId).collect(Collectors.toSet());
                if (CollUtil.isNotEmpty(artIds) && artIds.contains(artId)){
                    ClothesArt clothesArt = clothesArtMapper.selectById(artId);
                    if (ObjectUtil.isNotNull(clothesArt)){
                        record.setArtId(artId);
                        record.setArtName(clothesArt.getName());
                        record.setArtPrice(clothesArt.getPrice());
                    }
                }
            }
            Long clothId = ObjectUtil.defaultIfNull(clothesOrderDraft.getClothId(),0L);
            List<ClothesTypeCloth> clothesTypeCloths = clothesTypeClothMapper.selectList(Wrappers.lambdaQuery(ClothesTypeCloth.class).eq(ClothesTypeCloth::getTypeId, typeId));
            if(CollUtil.isNotEmpty(clothesTypeCloths)){
                Set<Long> clothIds = clothesTypeCloths.stream().map(ClothesTypeCloth::getClothId).collect(Collectors.toSet());
                if (CollUtil.isNotEmpty(clothIds) && clothIds.contains(clothId)){
                    ClothesCloth clothesCloth = clothesClothMapper.selectById(clothId);
                    if (ObjectUtil.isNotNull(clothesCloth)){
                        record.setClothId(clothId);
                        record.setClothName(clothesCloth.getName());
                        record.setClothPrice(clothesCloth.getPrice());
                    }
                }
            }
            BigDecimal amount =
                    record.getClothPrice()
                            .add(record.getLocationPrice())
                            .add(record.getArtPrice())
                            .add(record.getSizePrice())
                            .add(record.getPatternPrice()).setScale(2, RoundingMode.DOWN);
            record.setAmount(amount);
        }
        return new FebsResponse().success().data(record);
    }
    @Override
    public FebsResponse draftDel(ApiClothesOrderDraftDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        clothesOrderDraftMapper.update(null,
                Wrappers.lambdaUpdate(ClothesOrderDraft.class)
                        .set(ClothesOrderDraft::getDelFlag, ClothesEnum.UP.getCode())
                        .eq(ClothesOrderDraft::getId, dto.getId())
                        .eq(ClothesOrderDraft::getMemberId, memberId)
        );
        return new FebsResponse().success().message("操作成功");
    }
    private BigDecimal getCouponAmountReduce(BigDecimal totalAmount, Long memberCouponId) {
        BigDecimal reduceAmount = BigDecimal.ZERO;
        HashMap<Long, BigDecimal> couponAmountMap = new HashMap<>();
        // 获取优惠券信息
        Optional<MallMemberCoupon> optionalMallMemberCoupon = Optional.ofNullable(mallMemberCouponMapper.selectById(memberCouponId));
        MallMemberCoupon mallMemberCoupon = optionalMallMemberCoupon.orElse(null);
        if (ObjectUtil.isNull(mallMemberCoupon) || mallMemberCoupon.getState() != 1) {
            return reduceAmount;
        }
        Optional<MallGoodsCoupon> optionalMallGoodsCoupon = Optional.ofNullable(mallGoodsCouponMapper.selectById(mallMemberCoupon.getCouponId()));
        MallGoodsCoupon mallGoodsCoupon = optionalMallGoodsCoupon.orElse(null);
        if (ObjectUtil.isNull(mallGoodsCoupon)) {
            return reduceAmount;
        }
        BigDecimal costAmount = mallGoodsCoupon.getCostAmount();
        BigDecimal realAmount = mallGoodsCoupon.getRealAmount();
        Integer type = mallGoodsCoupon.getType();
        if (MallGoodsCoupon.TYPE_ONE == type) {
            reduceAmount = mallGoodsCoupon.getRealAmount();
        } else if (MallGoodsCoupon.TYPE_TWO == type) {
            BigDecimal divideTime = totalAmount.divide(costAmount, 0, RoundingMode.DOWN); // 累计减免次数
            reduceAmount = divideTime.multiply(realAmount); // 实际减免金额
        }
        return reduceAmount;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FebsResponse createOrder(ApiClothesOrderInfoDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        if (CollUtil.isEmpty(dto.getItems())) {
            throw new FebsException("参数错误");
        }
        //选择了地址才允许下单
        Long addressId = dto.getAddressId();
        MallAddressInfo address = mallAddressInfoMapper.selectAddressInfoByMemberIdAndId(memberId, addressId);
        if(ObjectUtil.isNull( address)){
            throw new FebsException("请选择收货地址");
        }
        if (StrUtil.isBlank(address.getLatitude())||StrUtil.isBlank(address.getLongitude())) {
            throw new FebsException("请添加地址");
        }
        Long typeId = dto.getTypeId();
        ClothesType clothesType = clothesTypeMapper.selectById(typeId);
        if(ObjectUtil.isNull( clothesType)){
            throw new FebsException("请选择商品");
        }
        if(ClothesEnum.UP.getCode() != clothesType.getState()){
            throw new FebsException("商品已下架");
        }
        String orderNo = MallUtils.getOrderNum("CL");
        ClothesOrder orderInfo = new ClothesOrder();
        orderInfo.setMemberId(memberId);
        orderInfo.setTypeId(typeId);
        orderInfo.setOrderNo(orderNo);
        orderInfo.setOrderTime(new Date());
        orderInfo.setGoodsCnt(dto.getCnt());
        orderInfo.setStatus(ClothesOrderStatusEnum.WAIT_PAY.getValue());
        orderInfo.setRemark(dto.getRemark());
        orderInfo.setAddressId(addressId);
        orderInfo.setName(address.getName());
        orderInfo.setPhone(address.getPhone());
        orderInfo.setAddress(address.getProvince() + address.getCity() + address.getArea() + address.getAddress());
        orderInfo.setLatitude(address.getLatitude());
        orderInfo.setLongitude(address.getLongitude());
        clothesOrderMapper.insert(orderInfo);
        Long orderId = orderInfo.getId();
        /**
         * 创建订单子表
         */
        BigDecimal total = BigDecimal.ZERO;
        for (ApiClothesOrderItemInfoDto item : dto.getItems()) {
            ClothesOrderItem orderItem = new ClothesOrderItem();
            orderItem.setMemberId(memberId);
            orderItem.setOrderId(orderId);
            orderItem.setType(item.getType());
            if (ClothesOrderItemEnum.CLOTH.getCode() == item.getType()) {
                ClothesCloth cloth = clothesClothMapper.selectById(item.getSkuId());
                if (ObjectUtil.isNull(cloth)) {
                    throw new FebsException("请选择布料");
                }
                orderItem.setName(cloth.getName());
                orderItem.setPrice(cloth.getPrice());
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(cloth.getPrice().multiply(new BigDecimal(item.getCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else if (ClothesOrderItemEnum.SIZE.getCode() == item.getType()) {
                ClothesSize size = clothesSizeMapper.selectById(item.getSkuId());
                if (ObjectUtil.isNull(size)) {
                    throw new FebsException("请选择尺寸");
                }
                orderItem.setName(size.getName());
                orderItem.setPrice(size.getPrice());
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(orderItem.getPrice().multiply(new BigDecimal(orderItem.getItemCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else if (ClothesOrderItemEnum.LOCATION.getCode() == item.getType()) {
                ClothesLocation location = clothesLocationMapper.selectById(item.getSkuId());
                if (ObjectUtil.isNull(location)) {
                    throw new FebsException("请选择图案位置");
                }
                orderItem.setName(location.getName());
                orderItem.setPrice(location.getPrice());
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(orderItem.getPrice().multiply(new BigDecimal(orderItem.getItemCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else if (ClothesOrderItemEnum.PATTERN.getCode() == item.getType()) {
                ClothesPattern pattern = clothesPatternMapper.selectById(item.getSkuId());
                if (ObjectUtil.isNull(pattern)) {
                    throw new FebsException("请选择图案");
                }
                orderItem.setRemark(item.getPatternRemark());
                orderItem.setName(pattern.getName());
                orderItem.setPrice(pattern.getPrice());
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(orderItem.getPrice().multiply(new BigDecimal(orderItem.getItemCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else if (ClothesOrderItemEnum.ART.getCode() == item.getType()) {
                ClothesArt art = clothesArtMapper.selectById(item.getSkuId());
                if (ObjectUtil.isNull(art)) {
                    throw new FebsException("请选择工艺");
                }
                orderItem.setName(art.getName());
                orderItem.setPrice(art.getPrice());
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(orderItem.getPrice().multiply(new BigDecimal(orderItem.getItemCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else if (ClothesOrderItemEnum.CUSTOMIZE.getCode() == item.getType()) {
                ClothesMemberStature clothesMemberStature = clothesMemberStatureMapper.selectById(item.getSkuId());
                orderItem.setName(clothesMemberStature.getName());
                orderItem.setPrice(BigDecimal.ZERO);
                orderItem.setItemCnt(item.getCnt());
                orderItem.setAmount(orderItem.getPrice().multiply(new BigDecimal(orderItem.getItemCnt())).setScale(2, RoundingMode.DOWN));
                clothesOrderItemMapper.insert(orderItem);
                total = total.add(orderItem.getAmount());
                continue;
            } else {
                throw new FebsException("详情参数错误");
            }
        }
        /**
         *  计算优惠金额、运费和实际支付金额
         */
        BigDecimal discountAmount = BigDecimal.ZERO;
        MallMemberCoupon mallMemberCoupon = new MallMemberCoupon();
        if(ObjectUtil.isNotEmpty(dto.getMemberCouponId())){
            Long memberCouponId = dto.getMemberCouponId();
            mallMemberCoupon = mallMemberCouponMapper.selectById(memberCouponId);
            if(ObjectUtil.isEmpty(mallMemberCoupon)){
                throw new FebsException(mallMemberCoupon.getCouponName()+"无法使用");
            }
            Integer state = mallMemberCoupon.getState();
            if(1 != state){
                throw new FebsException(mallMemberCoupon.getCouponName()+"无法使用");
            }
            List<ApiClothesOrderItemInfoDto> items = dto.getItems();
            discountAmount = getCouponAmountReduce(total, memberCouponId);
            // 优惠金额大于0,则更新优惠卷
            if(discountAmount.compareTo(BigDecimal.ZERO) > 0){
                mallMemberCoupon.setState(2);
                mallMemberCouponMapper.updateById(mallMemberCoupon);
                orderInfo.setMemberCouponId(memberCouponId);
            }
        }
        BigDecimal deliveryAmount = dto.getDeliveryAmount() == null ? BigDecimal.ZERO : dto.getDeliveryAmount();
        orderInfo.setAmount(total);
        orderInfo.setDiscountAmount(discountAmount);
        orderInfo.setCarriage(deliveryAmount);
        BigDecimal realAmount = total.subtract(discountAmount).add(deliveryAmount);
        orderInfo.setRealAmount(realAmount);
        clothesOrderMapper.updateById(orderInfo);
        //过期时间修改成24小时
        agentProducer.sendClothesOrderCancelDelayMsg(orderInfo.getId(),  24 * 60 * 60 * 1000L);
        ApiClothesOrderInfoVo apiClothesOrderInfoVo = new ApiClothesOrderInfoVo();
        apiClothesOrderInfoVo.setOrderId(orderInfo.getId());
        return new FebsResponse().success().data(apiClothesOrderInfoVo);
    }
    @Override
    public void orderCancelDelayClothes(long id) {
        ClothesOrder orderInfo = clothesOrderMapper.selectById(id);
        if (ObjectUtil.isNull(orderInfo)) {
            log.error("自动取消订单参数错误:{}", id);
            return;
        }
        if (orderInfo.getStatus() == ClothesOrderStatusEnum.WAIT_PAY.getValue()) {
            log.info("自动取消订单:{},{}", orderInfo.getMemberId(), id);
            clothesOrderMapper.update(null,
                    Wrappers.lambdaUpdate(ClothesOrder.class)
                    .set(ClothesOrder::getStatus, ClothesOrderStatusEnum.CANCEL.getValue())
                    .set(ClothesOrder::getUpdatedTime, new Date())
                    .eq(ClothesOrder::getId, id)
            );
        }
    }
    @Override
    public FebsResponse cancelOrder(Long id) {
        ClothesOrder clothesOrder = clothesOrderMapper.selectById(id);
        if(
                ObjectUtil.isNotNull(clothesOrder)
                        && ClothesEnum.DOWN.getCode() == clothesOrder.getDelFlag()
                        && ClothesOrderStatusEnum.WAIT_PAY.getValue() == clothesOrder.getStatus()
        ){
            clothesOrderMapper.update(null,
                    Wrappers.lambdaUpdate(ClothesOrder.class)
                            .set(ClothesOrder::getStatus, ClothesOrderStatusEnum.CANCEL.getValue())
                            .set(ClothesOrder::getUpdatedTime, new Date())
                            .eq(ClothesOrder::getId, id)
            );
            Long memberCouponId = ObjectUtil.defaultIfNull(clothesOrder.getMemberCouponId(), 0L);
            MallMemberCoupon mallMemberCoupon = mallMemberCouponMapper.selectById(memberCouponId);
            if(ObjectUtil.isNotNull(mallMemberCoupon)){
                mallMemberCoupon.setState(1);
                mallMemberCouponMapper.updateById(mallMemberCoupon);
            }
        }
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    public FebsResponse delOrder(Long id) {
        ClothesOrder clothesOrder = clothesOrderMapper.selectById(id);
        if(
                ObjectUtil.isNotNull(clothesOrder)
                && ClothesEnum.DOWN.getCode() == clothesOrder.getDelFlag()
        ){
            clothesOrderMapper.update(null,
                    Wrappers.lambdaUpdate(ClothesOrder.class)
                            .set(ClothesOrder::getDelFlag, ClothesEnum.UP.getCode())
                            .set(ClothesOrder::getUpdatedTime, new Date())
                            .eq(ClothesOrder::getId, id)
            );
        }
        return new FebsResponse().success().message("操作成功");
    }
    private String balancePay(ClothesOrder orderInfo, String tradePwd, String field) {
        if (StrUtil.isBlank(tradePwd)) {
            throw new FebsException("支付密码错误");
        }
        MallMember mallMember = mallMemberMapper.selectById(orderInfo.getMemberId());
        if (StrUtil.isBlank(mallMember.getTradePassword())) {
            throw new FebsException("未设置支付密码");
        }
        if (!SecureUtil.md5(tradePwd).equals(mallMember.getTradePassword())) {
            throw new FebsException("支付密码错误");
        }
        int reduce = apiMallMemberWalletService.reduce(orderInfo.getAmount(), mallMember.getId(), field);
        if (reduce == 2) {
            throw new FebsException("余额不足");
        }
        return orderInfo.getOrderNo();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FebsResponse payOrder(ApiClothesOrderPayDto dto) {
        MallMember member = LoginUserUtil.getLoginUser();
        ClothesOrder clothesOrder = clothesOrderMapper.selectById(dto.getId());
        if (ObjectUtil.isNull(clothesOrder)){
            throw new FebsException("订单不存在");
        }
        if (ClothesEnum.DOWN.getCode() != clothesOrder.getDelFlag()) {
            throw new FebsException("订单不存在");
        }
        if (ClothesOrderStatusEnum.WAIT_PAY.getValue() != clothesOrder.getStatus()) {
            throw new FebsException("订单不是待支付状态");
        }
        if(
                ClothesOrderPayTypeEnum.WECHAT.getCode() != dto.getType()
                && ClothesOrderPayTypeEnum.ALIPAY.getCode() != dto.getType()
                && ClothesOrderPayTypeEnum.BALANCE.getCode() != dto.getType()
        ){
            throw new FebsException("支付方式不支持");
        }
        String payResultStr = "";
        String wxResultStr = "";
        switch (dto.getType()) {
            case 1:
                BrandWCPayRequestData brandWCPayRequestData = null;
                try {
                    brandWCPayRequestData = iXcxPayService.startPayment(clothesOrder);
                } catch (Exception e) {
                    throw new FebsException("支付失败");
                }
                wxResultStr = JSONUtil.toJsonStr(brandWCPayRequestData);
                payResultStr = brandWCPayRequestData.getPrepay_id();
                clothesOrder.setPayMethod(ClothesOrderPayTypeEnum.WECHAT.getName());
                break;
            case 2:
                if (StrUtil.isNotBlank(clothesOrder.getPayOrderNo())) {
                    payResultStr = clothesOrder.getPayOrderNo();
                } else {
                    payResultStr = payService.aliPay(clothesOrder);
                }
                clothesOrder.setPayOrderNo(payResultStr);
                clothesOrder.setPayMethod(ClothesOrderPayTypeEnum.ALIPAY.getName());
                break;
            case 3:
                Date date = new Date();
                payResultStr = balancePay(clothesOrder, dto.getTradePwd(), "balance");
                clothesOrder.setPayOrderNo(clothesOrder.getOrderNo());
                clothesOrder.setPayMethod(ClothesOrderPayTypeEnum.BALANCE.getName());
                clothesOrder.setStatus(ClothesOrderStatusEnum.WAIT_SHIPPING.getValue());
                clothesOrder.setPayTime(date);
                clothesOrder.setPayResult(1);
                clothesOrder.setDeliveryState(OrderDeliveryStateEnum.DELIVERY_WAIT.getValue());
                mallMoneyFlowService.addMoneyFlow(
                        member.getId(),
                        clothesOrder.getRealAmount().negate(),
                        ScoreFlowTypeEnum.PAY_BALANCE.getValue(),
                        clothesOrder.getOrderNo(),
                        FlowTypeEnum.BALANCE.getValue(),
                        StrUtil.format(ScoreFlowTypeEnum.PAY_BALANCE.getDesc(),clothesOrder.getRealAmount()),
                        2
                );
                Long memberCouponId = ObjectUtil.defaultIfNull(clothesOrder.getMemberCouponId(), 0L);
                MallMemberCoupon mallMemberCoupon = mallMemberCouponMapper.selectById(memberCouponId);
                if(ObjectUtil.isNotNull(mallMemberCoupon)){
                    mallMemberCoupon.setState(2);
                    mallMemberCouponMapper.updateById(mallMemberCoupon);
                }
                break;
            default:
        }
        clothesOrderMapper.updateById(clothesOrder);
        Map<String, Object> map = new HashMap<>();
        map.put("orderInfo", payResultStr);
        map.put("orderNo", clothesOrder.getOrderNo());
        map.put("orderId", clothesOrder.getId());
        map.put("wxResultStr", wxResultStr);
        ApiClothesOrderPayVo apiClothesOrderPayVo = new ApiClothesOrderPayVo();
        apiClothesOrderPayVo.setOrder(map);
        apiClothesOrderPayVo.setType(dto.getType());
        return new FebsResponse().success().data(apiClothesOrderPayVo).message("支付成功");
    }
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiClothesServiceImpl.java
@@ -3,6 +3,7 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.enumerates.ClothesEnum;
import cc.mrbird.febs.common.enumerates.StateUpDownEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.mall.dto.clothes.*;
import cc.mrbird.febs.mall.entity.*;
@@ -12,6 +13,7 @@
import cc.mrbird.febs.mall.vo.clothes.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -19,6 +21,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@@ -35,9 +38,14 @@
    private final ClothesTypePatternMapper clothesTypePatternMapper;
    private final ClothesTypeSizeMapper clothesTypeSizeMapper;
    private final ClothesSizeMapper clothesSizeMapper;
    private final ClothesPatternMapper clothesPatternMapper;
    private final ClothesLocationMapper clothesLocationMapper;
    private final ClothesClothMapper clothesClothMapper;
    private final ClothesArtMapper clothesArtMapper;
    private final ClothesTypeLocationMapper clothesTypeLocationMapper;
    private final ClothesTypeArtMapper clothesTypeArtMapper;
    private final ClothesMemberStatureMapper clothesMemberStatureMapper;
    private final ClothesOrderDraftMapper clothesOrderDraftMapper;
    @Override
    public FebsResponse clothesType() {
@@ -254,15 +262,82 @@
    @Override
    public FebsResponse statureDel(ApiClothesMemberStatureInfoDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        clothesMemberStatureMapper.delete(
        clothesMemberStatureMapper.update(null,
                Wrappers.lambdaUpdate(ClothesMemberStature.class)
                        .set(ClothesMemberStature::getDelFlag, ClothesEnum.UP.getCode())
                        .eq(ClothesMemberStature::getId, dto.getId())
                        .eq(ClothesMemberStature::getMemberId, memberId)
                        .eq(ClothesMemberStature::getDelFlag, ClothesEnum.DOWN.getCode())
        );
        return new FebsResponse().success().message("操作成功");
    }
    @Override
    @Transactional
    public FebsResponse draftSave(ApiMyDraftSaveDto dto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
        ClothesOrderDraft clothesOrderDraft = new ClothesOrderDraft();
        clothesOrderDraft.setMemberId(memberId);
        Long typeId = ObjectUtil.defaultIfNull(dto.getTypeId(),0L);
        ClothesType clothesType = clothesTypeMapper.selectById(typeId);
        if (ObjectUtil.isNull(clothesType)){
            throw new FebsException("请选择商品");
        }
        if (ClothesEnum.UP.getCode() != clothesType.getState()){
            throw new FebsException("商品已下架");
        }
        clothesOrderDraft.setTypeId(typeId);
        Long sizeId = ObjectUtil.defaultIfNull(dto.getSizeId(),0L);
        ClothesSize clothesSize = clothesSizeMapper.selectById(sizeId);
        if (ObjectUtil.isNull(clothesSize)){
            throw new FebsException("请选择尺码");
        }
        clothesOrderDraft.setSizeId(sizeId);
        Long patternId = ObjectUtil.defaultIfNull(dto.getPatternId(),0L);
        ClothesPattern pattern = clothesPatternMapper.selectById(patternId);
        if (ObjectUtil.isNull(pattern)){
            throw new FebsException("请选择图案");
        }
        clothesOrderDraft.setPatternId(patternId);
        if(StrUtil.isNotBlank(dto.getPatternRemark())){
            clothesOrderDraft.setPatternRemark(dto.getPatternRemark());
        }
        Long locationId = ObjectUtil.defaultIfNull(dto.getLocationId(),0L);
        ClothesLocation clothesLocation = clothesLocationMapper.selectById(locationId);
        if (ObjectUtil.isNull(clothesLocation)){
            throw new FebsException("请选择图案位置");
        }
        clothesOrderDraft.setLocationId(locationId);
        Long clothId = ObjectUtil.defaultIfNull(dto.getClothId(),0L);
        ClothesCloth clothesCloth = clothesClothMapper.selectById(clothId);
        if (ObjectUtil.isNull(clothesCloth)){
            throw new FebsException("请选择布料");
        }
        clothesOrderDraft.setClothId(clothId);
        Long artId = ObjectUtil.defaultIfNull(dto.getArtId(),0L);
        ClothesArt clothesArt = clothesArtMapper.selectById(artId);
        if (ObjectUtil.isNull(clothesArt)){
            throw new FebsException("请选择工艺");
        }
        clothesOrderDraft.setArtId(artId);
        Long statureId = ObjectUtil.defaultIfNull(dto.getStatureId(),0L);
        ClothesMemberStature clothesMemberStature = clothesMemberStatureMapper.selectById(statureId);
        if (ObjectUtil.isNull(clothesMemberStature)){
            throw new FebsException("请选择身材数据");
        }
        clothesOrderDraft.setStatureId(clothesMemberStature.getId());
        clothesOrderDraftMapper.insert(clothesOrderDraft);
        return new FebsResponse().success().message("操作成功");
    }
}
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiClothesOrderInfoVo.java
New file
@@ -0,0 +1,15 @@
package cc.mrbird.febs.mall.vo.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiMyDraftVo", description = "参数")
public class ApiClothesOrderInfoVo {
    @ApiModelProperty(value = "订单ID")
    private Long orderId;
}
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiClothesOrderPayVo.java
New file
@@ -0,0 +1,15 @@
package cc.mrbird.febs.mall.vo.clothes;
import io.swagger.annotations.ApiModel;
import lombok.Data;
import java.util.Map;
@Data
@ApiModel(value = "ApiClothesOrderPayVo", description = "参数")
public class ApiClothesOrderPayVo {
    private Map<String, Object> order;
    private Integer type;
}
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiMyDraftSaveVo.java
New file
@@ -0,0 +1,14 @@
package cc.mrbird.febs.mall.vo.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "ApiMyDraftSaveVo", description = "参数")
public class ApiMyDraftSaveVo {
    @ApiModelProperty(value = "草稿ID")
    private Long id;
}
src/main/java/cc/mrbird/febs/mall/vo/clothes/ApiMyDraftVo.java
New file
@@ -0,0 +1,68 @@
package cc.mrbird.febs.mall.vo.clothes;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
@ApiModel(value = "ApiMyDraftVo", description = "参数")
public class ApiMyDraftVo {
    @ApiModelProperty(value = "草稿ID")
    private Long id;
    @ApiModelProperty(value = "总价")
    private BigDecimal amount = BigDecimal.ZERO;
    @ApiModelProperty(value = "类型ID")
    private Long typeId;
    @ApiModelProperty(value = "类型名称")
    private String typeName;
    @ApiModelProperty(value = "类型图片")
    private String typeImage;
    @ApiModelProperty(value = "工艺ID")
    private Long artId;
    @ApiModelProperty(value = "工艺名称")
    private String artName;
    @ApiModelProperty(value = "工艺价格")
    private BigDecimal artPrice = BigDecimal.ZERO;
    @ApiModelProperty(value = "尺码ID")
    private Long sizeId;
    @ApiModelProperty(value = "尺码名称")
    private String sizeName;
    @ApiModelProperty(value = "尺码价格")
    private BigDecimal sizePrice = BigDecimal.ZERO;
    @ApiModelProperty(value = "图案ID")
    private Long patternId;
    @ApiModelProperty(value = "图案名称")
    private String patternName;
    @ApiModelProperty(value = "图案价格")
    private BigDecimal patternPrice = BigDecimal.ZERO;
    @ApiModelProperty(value = "自定义内容")
    private String patternRemark;
    @ApiModelProperty(value = "图案位置ID")
    private Long locationId;
    @ApiModelProperty(value = "图案位置")
    private String locationName;
    @ApiModelProperty(value = "图案位置价格")
    private BigDecimal locationPrice = BigDecimal.ZERO;
    @ApiModelProperty(value = "布料ID")
    private Long clothId;
    @ApiModelProperty(value = "布料名称")
    private String clothName;
    @ApiModelProperty(value = "布料价格")
    private BigDecimal clothPrice = BigDecimal.ZERO;
    @ApiModelProperty(value = "身材数据ID")
    private Long statureId;
    @ApiModelProperty(value = "身材数据")
    private String statureName;
}
src/main/java/cc/mrbird/febs/pay/service/IPayService.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.pay.service;
import cc.mrbird.febs.mall.entity.ClothesOrder;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import java.util.Map;
@@ -11,6 +12,7 @@
public interface IPayService {
    String aliPay(MallOrderInfo orderInfo);
    String aliPay(ClothesOrder orderInfo);
    void aliCallback(Map<String, String> params);
}
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.ClothesOrder;
import cc.mrbird.febs.mall.entity.HappyActivityOrder;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
@@ -20,6 +21,7 @@
     * 发起支付(创建预付订单)
     */
    BrandWCPayRequestData startPayment(MallOrderInfo mallOrderInfo) throws Exception;
    BrandWCPayRequestData startPayment(ClothesOrder orderInfo) throws Exception;
    /**
     * 发起支付(创建预付订单)
src/main/java/cc/mrbird/febs/pay/service/impl/PayServiceImpl.java
@@ -5,8 +5,12 @@
import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum;
import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.mall.entity.ClothesOrder;
import cc.mrbird.febs.mall.entity.ClothesType;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.mapper.ClothesOrderMapper;
import cc.mrbird.febs.mall.mapper.ClothesTypeMapper;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cc.mrbird.febs.mall.service.IApiMallMemberService;
import cc.mrbird.febs.mall.service.IApiMallOrderInfoService;
@@ -46,6 +50,8 @@
    @Autowired
    private MallOrderInfoMapper orderInfoMapper;
    @Autowired
    private ClothesTypeMapper clothesTypeMapper;
    @Autowired
    private AgentProducer agentProducer;
    @Value("${spring.profiles.active}")
@@ -82,6 +88,38 @@
    }
    @Override
    public String aliPay(ClothesOrder orderInfo) {
        ClothesType clothesType = clothesTypeMapper.selectById(orderInfo.getTypeId());
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setSubject(clothesType.getName());
        model.setBody(orderInfo.getName());
        model.setOutTradeNo(orderInfo.getOrderNo());
        model.setTimeoutExpress("15m");
        if ("dev".equals(active) || "test".equals(active)) {
            model.setTotalAmount("0.01");
        } else {
            model.setTotalAmount(orderInfo.getRealAmount().toString());
        }
        AliPayPassbackModel passbackModel = new AliPayPassbackModel();
        passbackModel.setOrderId(orderInfo.getId());
        passbackModel.setMemberId(orderInfo.getMemberId());
        model.setPassbackParams(JSONObject.toJSONString(passbackModel));
        model.setProductCode("QUICK_MSECURITY_PAY");
        AlipayTradeAppPayResponse resp = null;
        try {
            resp = AliPayApi.appPayToResponse(model, aliPayProperties.getNoticeUrl());
        } catch (AlipayApiException e) {
            log.error("支付宝支付异常", e);
            throw new FebsException("支付宝支付异常");
        }
        return resp.getBody();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void aliCallback(Map<String, String> params) {
        String modelStr = params.get("passback_params");
src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java
@@ -23,6 +23,7 @@
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
@@ -41,10 +42,7 @@
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
@Slf4j
@Service
@@ -70,6 +68,8 @@
    @Autowired
    private MallMemberWithdrawMapper mallMemberWithdrawMapper;
    private final IMallMoneyFlowService mallMoneyFlowService;
    private final ClothesTypeMapper clothesTypeMapper;
    private final ClothesOrderMapper clothesOrderMapper;
    @Autowired
    RedisUtils redisUtils;
@@ -212,6 +212,34 @@
    }
    @Override
    public BrandWCPayRequestData startPayment(ClothesOrder orderInfo) throws Exception {
        BigDecimal unit = new BigDecimal("100");
        BigDecimal money = new BigDecimal(orderInfo.getRealAmount().toString());
        BrandWCPayRequestData payData;
        ClothesType clothesType = clothesTypeMapper.selectById(orderInfo.getTypeId());
        String productNames = clothesType.getName();
        MallMember mallMember = mallMemberMapper.selectById(orderInfo.getMemberId());
        Boolean debug = xcxProperties.getDebug();
        if (debug) {
            payData = weixinServiceUtil.createOrder("[测试]" + productNames, orderInfo.getOrderNo(),
                    1, mallMember.getOpenId(), String.valueOf(orderInfo.getId()));
        } else {
            payData = weixinServiceUtil.createOrder(productNames, orderInfo.getOrderNo(),
                    unit.multiply(money).intValue(),mallMember.getOpenId(), String.valueOf(orderInfo.getId()));
        }
        orderInfo.setPayOrderNo(payData.getPrepay_id());
        clothesOrderMapper.update(null,
                Wrappers.lambdaUpdate(ClothesOrder.class)
                .set(ClothesOrder::getPayOrderNo, payData.getPrepay_id())
                .set(ClothesOrder::getUpdatedTime, new Date())
                .eq(ClothesOrder::getId, orderInfo.getId())
                );
        return payData;
    }
    @Override
    public BrandWCPayRequestData startPaymentActivity(HappyActivityOrder dto) throws Exception {
        BigDecimal unit = new BigDecimal("100");
        BigDecimal money = new BigDecimal(dto.getAmount().toString());
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -17,4 +17,7 @@
    public static final String GET_SCORE_MSG = "queue_get_score_msg";
    public static final String VIP_LEVEL_UP = "queue_vip_level_up";
    public static final String SALE_LEVEL_UP = "queue_sale_level_up";
    ;
    public static final String CLOTHES_ORDER_CANCEL_DELAY = "queue_order_delay_qay_clothes";
}
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -1,9 +1,6 @@
package cc.mrbird.febs.rabbit.consumer;
import cc.mrbird.febs.mall.service.HappyActivityService;
import cc.mrbird.febs.mall.service.IAgentService;
import cc.mrbird.febs.mall.service.IApiMallOrderInfoService;
import cc.mrbird.febs.mall.service.IMemberProfitService;
import cc.mrbird.febs.mall.service.*;
import cc.mrbird.febs.rabbit.constants.QueueConstants;
import cc.mrbird.febs.rabbit.enumerates.RabbitQueueEnum;
import cc.mrbird.febs.vip.service.IVipCommonService;
@@ -26,6 +23,9 @@
    @Autowired
    private IApiMallOrderInfoService orderInfoService;
    @Autowired
    private ApiClothesOrderService apiClothesOrderService;
    @Autowired
    private IAgentService agentService;
    @Autowired
@@ -38,6 +38,15 @@
        log.info("消费者:{}", new String(message.getBody()));
    }
    @RabbitListener(queues = QueueConstants.CLOTHES_ORDER_CANCEL_DELAY)
    public void orderCancelDelayClothes(String id) {
        try {
            apiClothesOrderService.orderCancelDelayClothes(Long.parseLong(id));
        } catch (Exception e) {
            log.error("订单超时支付异常", e);
        }
    }
    @RabbitListener(queues = "queue_order_delay_qay")
    public void orderCancelDelay(String id) {
        try {
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -14,6 +14,9 @@
    ORDER_CANCEL_DELAY_TTL("exchange_order_delay_ttl_qay", "route_key_order_delay_ttl_qay", "queue_order_delay_ttl_qay"),
    ORDER_CANCEL_DELAY("exchange_order_delay_qay", "route_key_order_delay_qay", "queue_order_delay_qay"),
    CLOTHES_ORDER_CANCEL_DELAY_TTL("exchange_order_delay_ttl_qay_clothes", "route_key_order_delay_ttl_qay_clothes", "queue_order_delay_ttl_qay_clothes"),
    CLOTHES_ORDER_CANCEL_DELAY("exchange_order_delay_qay_clothes", "route_key_order_delay_qay_clothes", QueueConstants.CLOTHES_ORDER_CANCEL_DELAY),
    AGENT_REUTRN_MONEY("exchange_agent_return_money_qay", "route_key_agent_return_money_qay", "queue_agent_return_money_qay"),
    ORDER_RETURN_MONEY("exchange_order_return_money_qay", "route_key_order_return_money_qay", "queue_order_return_money_qay"),
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -62,6 +62,17 @@
        });
    }
    public void sendClothesOrderCancelDelayMsg(Long id, Long times) {
        log.info("发送自动取消订单消息:{}, {}", id, times);
        rabbitTemplate.convertAndSend(RabbitQueueEnum.ORDER_CANCEL_DELAY_TTL.getExchange(), RabbitQueueEnum.ORDER_CANCEL_DELAY_TTL.getRoute(), id, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration(String.valueOf(times));
                return message;
            }
        });
    }
    /**
     * 发送代理自动升级消息
     *
src/main/resources/application-test.yml
@@ -70,8 +70,8 @@
#  wecharpaySecret: CSxc168888CSxc168888CSxc168888xc
xcx:
  wechar_login_url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
  xcx_appid: wxe8454293f5c4c143
  xcx_secret: 33c3ad513344cf6c16904e5d528b70ea
  xcx_appid: wx5cc58f796224af61
  xcx_secret: 0c2715d0c23c6b9959edd2b2eac81b80
  debug: true
  wecharPaynotifyUrl: http://happy.csxuncong.com/api/xcxPay/wxpayCallback
  wecharActivityPaynotifyUrl: http://happy.csxuncong.com/api/xcxPay/activityOrderCallback
src/main/resources/mapper/modules/ClothesOrderDraftMapper.xml
New file
@@ -0,0 +1,16 @@
<?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.ClothesOrderDraftMapper">
    <select id="selectPageInDraft" resultType="cc.mrbird.febs.mall.vo.clothes.ApiMyDraftVo">
        select
            a.*
        from clothes_order_draft a
        left join clothes_type b on a.type_id = b.id
        where a.member_id = #{record.memberId}
        and a.del_flag = 0
        and b.state = 1
        order by a.CREATED_TIME asc
    </select>
</mapper>
src/main/resources/mapper/modules/ClothesOrderItemMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.ClothesOrderItemMapper">
</mapper>
src/main/resources/mapper/modules/ClothesOrderMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.ClothesOrderMapper">
</mapper>