1、产品管理、定价规则接口完善;2、支付测试;

This commit is contained in:
gaoqr
2025-08-12 16:44:07 +08:00
parent 280a3392aa
commit c985272d58
29 changed files with 563 additions and 244 deletions
@@ -1,7 +1,9 @@
package com.cf.imes.framework.common.util.Assert; package com.cf.imes.framework.common.util.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.exception.ErrorCode; import com.cf.imes.framework.common.exception.ErrorCode;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import java.util.List; import java.util.List;
@@ -38,6 +40,12 @@ public class AssertUtils {
} }
} }
public static void empty(List<?> array, ErrorCode errorCode, Object... params) {
if (!ObjectUtils.isEmpty(array)) {
throw ServiceExceptionUtil.exception(errorCode, params);
}
}
public static void empty(Object object, ErrorCode errorCode) { public static void empty(Object object, ErrorCode errorCode) {
if (object != null) { if (object != null) {
throw exception(errorCode); throw exception(errorCode);
@@ -64,4 +72,9 @@ public class AssertUtils {
} }
} }
public static void notEquals(Object obj1, Object obj2, ErrorCode errorCode) {
if (ObjectUtil.notEqual(obj1, obj2)) {
throw exception(errorCode);
}
}
} }
@@ -17,7 +17,7 @@ public class NumberValidator implements ConstraintValidator<NumberValid, Number>
private static final String GREATER_THAN_ZERO_NOTIFICATION = "%s必须大于0"; private static final String GREATER_THAN_ZERO_NOTIFICATION = "%s必须大于0";
private static final String FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION = "%s长度不合法,总长度不超过8位,小数点后不超过3"; private static final String FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION = "%s长度不合法,总长度不超过%d位,小数点后不超过%d";
private String name; private String name;
@@ -104,13 +104,13 @@ public class NumberValidator implements ConstraintValidator<NumberValid, Number>
int integerPartLength = split[0].length(); int integerPartLength = split[0].length();
// 获取小数点后的位数 // 获取小数点后的位数
int fractionalPartLength = 0; int fractionalPartLength = 0;
if (split.length > 2) { if (split.length == 2) {
fractionalPartLength = split[1].length(); fractionalPartLength = split[1].length();
} }
// 总位数不超过 8 位,小数点后位数不超过 3 位 // 总位数不超过 8 位,小数点后位数不超过 3 位
if (integerPartLength > integer || fractionalPartLength > fraction) { if (integerPartLength > integer || fractionalPartLength > fraction) {
return String.format(FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION, name); return String.format(FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION, name, integer, fraction);
} }
return null; return null;
} }
@@ -131,13 +131,13 @@ public class NumberValidator implements ConstraintValidator<NumberValid, Number>
int integerPartLength = split[0].length(); int integerPartLength = split[0].length();
// 获取小数点后的位数 // 获取小数点后的位数
int fractionalPartLength = 0; int fractionalPartLength = 0;
if (split.length > 2) { if (split.length == 2) {
fractionalPartLength = split[1].length(); fractionalPartLength = split[1].length();
} }
// 总位数不超过 8 位,小数点后位数不超过 3 位 // 总位数不超过 8 位,小数点后位数不超过 3 位
if (integerPartLength > integer || fractionalPartLength > fraction) { if (integerPartLength > integer || fractionalPartLength > fraction) {
return String.format(FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION, name); return String.format(FLOAT_NUMBER_LENGTH_ERROR_NOTIFICATION, name, integer, fraction);
} }
return null; return null;
} }
@@ -12,7 +12,7 @@ import org.springframework.context.annotation.Bean;
* @author 晨丰科技 * @author 晨丰科技
*/ */
@AutoConfiguration @AutoConfiguration
@EnableConfigurationProperties({ChenfengAlipayConfig.class, ChenfengWechatPayConfig.class}) @EnableConfigurationProperties({ChenfengAlipayConfig.class, ChenfengWechatPayConfig.class, ChenfengPayConfig.class})
public class ChenfengPayAutoConfiguration { public class ChenfengPayAutoConfiguration {
@Bean @Bean
@@ -0,0 +1,19 @@
package com.cf.imes.framework.pay.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.time.Duration;
/**
* @author Gqr
* @since 2025/8/12 15:55
*/
@ConfigurationProperties(prefix = "chenfeng.pay")
@Data
public class ChenfengPayConfig {
/**
* 支付超时时间
*/
private Duration payExpireTime = Duration.ofMinutes(5);
}
@@ -422,9 +422,9 @@ public class ErrorCodeConstants {
public static final ErrorCode INVOICE_TITLE_NO_EXIST = new ErrorCode(1_002_043_009, "发票抬头信息有误,请进行查看"); public static final ErrorCode INVOICE_TITLE_NO_EXIST = new ErrorCode(1_002_043_009, "发票抬头信息有误,请进行查看");
public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_010, "当前发票以开票,无法再次进行开票"); public static final ErrorCode THIS_INVOICE_IS_FAIL = new ErrorCode(1_002_043_010, "当前发票以开票,无法再次进行开票");
public static final ErrorCode THIS_INVOICE_IS_SUCCESS = new ErrorCode(1_002_043_011, "当前发票已经开票,无法再次进行开票"); public static final ErrorCode THIS_INVOICE_IS_SUCCESS = new ErrorCode(1_002_043_011, "当前发票已经开票,无法再次进行开票");
public static final ErrorCode PRODUCTS_IS_EXIST = new ErrorCode(1_002_043_012, "当前名称的产品已存在,无法新增产品"); public static final ErrorCode PRODUCTS_IS_EXIST = new ErrorCode(1_002_043_012, "产品【{}】已存在,请修改产品名称后再次操作");
public static final ErrorCode PRODUCTS_NO_DELETE = new ErrorCode(1_002_043_013, "当前产品上架,无法删除,请下架后再删除"); public static final ErrorCode PRODUCTS_NO_DELETE = new ErrorCode(1_002_043_013, "当前产品上架,无法删除,请下架后再删除");
public static final ErrorCode PRODUCTS_NO_UPDATE = new ErrorCode(1_002_043_014, "当前产品上架,无法进行修改"); public static final ErrorCode PRODUCTS_NO_UPDATE = new ErrorCode(1_002_043_014, "当前产品上架,无法进行修改");
public static final ErrorCode PRODUCTS_DETAIL_NO_UPDATE = new ErrorCode(1_002_043_016, "定价规则对应的产品已上架,无法进行修改"); public static final ErrorCode PRODUCTS_DETAIL_NO_UPDATE = new ErrorCode(1_002_043_016, "定价规则对应的产品已上架,无法进行修改");
public static final ErrorCode ADVERTISEMENT_START_TIME_ERROR = new ErrorCode(1_002_043_017, "广告开始时间选择有误,应等于或大于当日"); public static final ErrorCode ADVERTISEMENT_START_TIME_ERROR = new ErrorCode(1_002_043_017, "广告开始时间选择有误,应等于或大于当日");
public static final ErrorCode ADVERTISEMENT_TIME_ERROR = new ErrorCode(1_002_043_018, "时间选择有误,结束时间应大于或等于开始时间"); public static final ErrorCode ADVERTISEMENT_TIME_ERROR = new ErrorCode(1_002_043_018, "时间选择有误,结束时间应大于或等于开始时间");
@@ -441,17 +441,18 @@ public class ErrorCodeConstants {
public static final ErrorCode PAY_ORDER_NOTIFY_DATA_PARSE_ERROR = new ErrorCode(1_002_048_003, "解析支付回调数据异常"); public static final ErrorCode PAY_ORDER_NOTIFY_DATA_PARSE_ERROR = new ErrorCode(1_002_048_003, "解析支付回调数据异常");
public static final ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1_002_048_004, "支付订单不处于待支付"); public static final ErrorCode PAY_ORDER_STATUS_IS_NOT_WAITING = new ErrorCode(1_002_048_004, "支付订单不处于待支付");
public static final ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_002_048_005, "发起渠道支付异常,请联系客服"); public static final ErrorCode PAY_ORDER_SUBMIT_CHANNEL_ERROR = new ErrorCode(1_002_048_005, "发起渠道支付异常,请联系客服");
public static final ErrorCode PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR = new ErrorCode(1_002_048_006, "充值目标组织和当前操作人组织不同,发起充值支付失败");
//=========== 产品相关 1-002-045-000 ============ //=========== 产品相关 1-002-045-000 ============
public static final ErrorCode PRODUCTS_NO_EXIST = new ErrorCode(1_002_045_001, "当前产品不存在"); public static final ErrorCode PRODUCTS_NO_EXIST = new ErrorCode(1_002_045_001, "当前产品不存在");
public static final ErrorCode PRODUCTS_DETAIL_NO_EXIST = new ErrorCode(1_002_045_002, "当前产品的规则不存在"); public static final ErrorCode PRODUCTS_DETAIL_NO_EXIST = new ErrorCode(1_002_045_002, "当前产品的规则不存在");
public static final ErrorCode PRODUCTS_DURATION_NOT_NULL = new ErrorCode(1_002_045_003, "购买方式为时长时,需确定产品时长"); public static final ErrorCode PRODUCTS_DURATION_NOT_NULL = new ErrorCode(1_002_045_003, "当前购买方式为时长】,请填写产品时长");
public static final ErrorCode PRODUCTS_OUTPUT_NOT_NULL = new ErrorCode(1_002_045_004, "购买方式为产量时,需确定产量数量"); public static final ErrorCode PRODUCTS_OUTPUT_NOT_NULL = new ErrorCode(1_002_045_004, "购买方式为产量时,需确定产量数量");
public static final ErrorCode PRODUCTS_DETAIL_DURATION_EXIST = new ErrorCode(1_002_045_005, "存在当前时长的产品定价规则"); public static final ErrorCode PRODUCTS_DETAIL_DURATION_EXIST = new ErrorCode(1_002_045_005, "当前产品下已存在产品时长:【{}】、单位:【{}】的定价规则,请修改后重新操作");
public static final ErrorCode PRODUCTS_DETAIL_OUTPUT_EXIST = new ErrorCode(1_002_045_006, "存在当前产量的产品定价规则"); public static final ErrorCode PRODUCTS_DETAIL_OUTPUT_EXIST = new ErrorCode(1_002_045_006, "存在当前产量的产品定价规则");
public static final ErrorCode PRODUCTS_DURATION_NUM_ERR = new ErrorCode(1_002_045_007, "产品定价规则,时长数据设置有误"); public static final ErrorCode PRODUCTS_DETAIL_CURRENTPRICE_CALCULATE_ERROR = new ErrorCode(1_002_045_007, "产品现价计算错误,期望价格【{}】");
public static final ErrorCode PRODUCTS_DURATION_INT_ERR = new ErrorCode(1_002_045_008, "产品定价规则:时长必须为整数且大于 0"); public static final ErrorCode PRODUCTS_DURATION_INT_ERR = new ErrorCode(1_002_045_008, "产品定价规则:时长必须为整数且大于 0");
public static final ErrorCode PRODUCTS_DURATION_UNIT_ERR = new ErrorCode(1_002_045_009, "产品定价规则,时长单位设置有误"); public static final ErrorCode PRODUCTS_OUTPUT_NOT_SUPPORT = new ErrorCode(1_002_045_009, "暂不支持创建购买方式为【产量】的定价规则");
public static final ErrorCode RECHARGE_ACTIVE_NO_EXIST = new ErrorCode(1_002_045_010, "当前赠送金活动不存在"); public static final ErrorCode RECHARGE_ACTIVE_NO_EXIST = new ErrorCode(1_002_045_010, "当前赠送金活动不存在");
//=========== 广告相关 1-002-046-000 ============ //=========== 广告相关 1-002-046-000 ============
@@ -7,6 +7,7 @@ import com.cf.imes.module.system.controller.admin.funds.products.vo.product.Prod
import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductRespVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductRespVO;
import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductSaveReqVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductSaveReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.enums.products.ProductStatusEnum;
import com.cf.imes.module.system.service.funds.products.ProductsService; import com.cf.imes.module.system.service.funds.products.ProductsService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@@ -30,36 +31,36 @@ public class ProductsController {
@Resource @Resource
private ProductsService productsService; private ProductsService productsService;
@PostMapping("") @PutMapping("")
@Operation(summary = "新建产品") @Operation(summary = "新建产品")
// @PreAuthorize("@ss.hasPermission('base:products:create')") @PreAuthorize("@ss.hasPermission('base:products:create')")
public CommonResult<Long> createProducts(@RequestParam("productName") String productName) { public CommonResult<Long> createProducts(@RequestParam("productName") String productName) {
return success(productsService.create(productName)); return success(productsService.create(productName));
} }
@PutMapping("") @PostMapping("")
@Operation(summary = "更新产品") @Operation(summary = "更新产品")
// @PreAuthorize("@ss.hasPermission('base:products:update')") @PreAuthorize("@ss.hasPermission('base:products:update')")
public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) { public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) {
ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class); ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class);
productsService.update(productsDO); productsService.update(productsDO);
return success(true); return success(true);
} }
@PutMapping("/freeze") @PostMapping("/freeze")
@Operation(summary = "下架产品") @Operation(summary = "下架产品")
// @PreAuthorize("@ss.hasPermission('base:products:freeze')") @PreAuthorize("@ss.hasPermission('base:products:freeze')")
public CommonResult<Boolean> freezeProducts(@Valid Long id) { public CommonResult<Boolean> freezeProducts(@Valid Long id) {
ProductsDO productsDO = new ProductsDO().setId(id).setStatus(3); ProductsDO productsDO = new ProductsDO().setId(id).setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus());
productsService.update(productsDO); productsService.update(productsDO);
return success(true); return success(true);
} }
@PutMapping("/melt") @PostMapping("/melt")
@Operation(summary = "上架产品") @Operation(summary = "上架产品")
@PreAuthorize("@ss.hasPermission('base:products:melt')") @PreAuthorize("@ss.hasPermission('base:products:melt')")
public CommonResult<Boolean> meltProducts(@Valid Long id) { public CommonResult<Boolean> meltProducts(@Valid Long id) {
ProductsDO productsDO = new ProductsDO().setId(id).setStatus(2); ProductsDO productsDO = new ProductsDO().setId(id).setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus());
productsService.update(productsDO); productsService.update(productsDO);
return success(true); return success(true);
} }
@@ -75,7 +76,7 @@ public class ProductsController {
} }
@GetMapping("/{id}") @GetMapping("/{id}")
@Operation(summary = "获得产品") @Operation(summary = "查询产品")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('base:products:query')") @PreAuthorize("@ss.hasPermission('base:products:query')")
public CommonResult<ProductRespVO> getProducts(@PathVariable("id") Long id) { public CommonResult<ProductRespVO> getProducts(@PathVariable("id") Long id) {
@@ -84,7 +85,7 @@ public class ProductsController {
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得产品分页") @Operation(summary = "查询产品分页")
@PreAuthorize("@ss.hasPermission('base:products:query')") @PreAuthorize("@ss.hasPermission('base:products:query')")
public CommonResult<PageResult<ProductRespVO>> getProductsPage(@Valid ProductPageReqVO pageReqVO) { public CommonResult<PageResult<ProductRespVO>> getProductsPage(@Valid ProductPageReqVO pageReqVO) {
PageResult<ProductsDO> pageResult = productsService.getPage(pageReqVO); PageResult<ProductsDO> pageResult = productsService.getPage(pageReqVO);
@@ -30,14 +30,14 @@ public class ProductsDetailController {
@Resource @Resource
private ProductsDetailService productDetailsService; private ProductsDetailService productDetailsService;
@PostMapping("") @PutMapping("")
@Operation(summary = "新建产品明细") @Operation(summary = "新建产品明细")
@PreAuthorize("@ss.hasPermission('base:productDetails:create')") @PreAuthorize("@ss.hasPermission('base:productDetails:create')")
public CommonResult<Long> createProducts(@Valid @RequestBody ProductDetailsSaveReqVO createReqVO) { public CommonResult<Long> createProducts(@Valid @RequestBody ProductDetailsSaveReqVO createReqVO) {
return success(productDetailsService.create(createReqVO)); return success(productDetailsService.create(createReqVO));
} }
@PutMapping("") @PostMapping("")
@Operation(summary = "更新产品明细") @Operation(summary = "更新产品明细")
@PreAuthorize("@ss.hasPermission('base:productDetails:update')") @PreAuthorize("@ss.hasPermission('base:productDetails:update')")
public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductDetailsSaveReqVO updateReqVO) { public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductDetailsSaveReqVO updateReqVO) {
@@ -55,7 +55,7 @@ public class ProductsDetailController {
} }
@GetMapping("/{id}") @GetMapping("/{id}")
@Operation(summary = "获得产品明细") @Operation(summary = "查询产品明细")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('base:productDetails:query')") @PreAuthorize("@ss.hasPermission('base:productDetails:query')")
public CommonResult<List<ProductsDetailDO>> getProducts(@PathVariable("id") Long id) { public CommonResult<List<ProductsDetailDO>> getProducts(@PathVariable("id") Long id) {
@@ -64,7 +64,7 @@ public class ProductsDetailController {
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得产品明细分页") @Operation(summary = "查询产品明细分页")
@PreAuthorize("@ss.hasPermission('base:productDetails:query')") @PreAuthorize("@ss.hasPermission('base:productDetails:query')")
public CommonResult<PageResult<ProductDetailsRespVO>> getProductsPage(@Valid ProductDetailsPageReqVO pageReqVO) { public CommonResult<PageResult<ProductDetailsRespVO>> getProductsPage(@Valid ProductDetailsPageReqVO pageReqVO) {
PageResult<ProductsDetailDO> pageResult = productDetailsService.getPage(pageReqVO); PageResult<ProductsDetailDO> pageResult = productDetailsService.getPage(pageReqVO);
@@ -6,11 +6,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 产品表 products Request VO") @Schema(description = "管理后台 - 产品表 products Request VO")
@Data @Data
@@ -24,18 +19,7 @@ public class ProductPageReqVO extends PageParam {
@Schema(description = "产品名称", example = "赵六") @Schema(description = "产品名称", example = "赵六")
private String productName; private String productName;
@Schema(description = "产品状态", example = "0待上架 1已上架 2已下架") @Schema(description = "产品状态", example = "0")
@ProductStatus @ProductStatus
private Integer status; private Integer status;
@Schema(description = "软件id", example = "1")
private Long softwareId;
@Schema(description = "操作时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
@Schema(description = "是否删除")
private Integer deleted;
} }
@@ -1,5 +1,6 @@
package com.cf.imes.module.system.controller.admin.funds.products.vo.product; package com.cf.imes.module.system.controller.admin.funds.products.vo.product;
import com.cf.imes.module.system.validation.products.ProductStatus;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -17,6 +18,7 @@ public class ProductSaveReqVO {
private String productName; private String productName;
@Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED)
@ProductStatus
private Integer status; private Integer status;
@Schema(description = "软件id", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "软件id", requiredMode = Schema.RequiredMode.REQUIRED)
@@ -6,12 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 产品详情表 productDetails Request VO") @Schema(description = "管理后台 - 产品详情表 productDetails Request VO")
@Data @Data
@@ -23,19 +19,19 @@ public class ProductDetailsPageReqVO extends PageParam {
private Long id; private Long id;
@Schema(description = "产品ID", example = "1") @Schema(description = "产品ID", example = "1")
private String productId; private Long productId;
@Schema(description = "购买方式", example = "购买方式:0时长;1产量") @Schema(description = "购买方式", example = "0")
@ProductType @ProductType
private Integer purchaseType; private Integer purchaseType;
@Schema(description = "正常时间", example = "半个月") @Schema(description = "产品时长", example = "1")
private String duration; private String duration;
@Schema(description = "正常产量", example = "") @Schema(description = "正常产量", example = "")
private BigDecimal output; private BigDecimal output;
@Schema(description = "赠送时间", example = "半个月") @Schema(description = "赠送市场", example = "1")
private String giftDuration; private String giftDuration;
@Schema(description = "赠送产量", example = "") @Schema(description = "赠送产量", example = "")
@@ -50,14 +46,7 @@ public class ProductDetailsPageReqVO extends PageParam {
@Schema(description = "产品现价", example = "80") @Schema(description = "产品现价", example = "80")
private BigDecimal currentPrice; private BigDecimal currentPrice;
@Schema(description = "是否特惠", example = "") @Schema(description = "是否特惠", example = "0")
private Boolean isDiscounted; private Boolean isDiscounted;
@Schema(description = "操作时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
@Schema(description = "是否删除")
private Integer deleted;
} }
@@ -1,6 +1,8 @@
package com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails; package com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails;
import com.cf.imes.framework.common.validation.NumberValid;
import com.cf.imes.module.system.validation.products.ProductType; import com.cf.imes.module.system.validation.products.ProductType;
import com.cf.imes.module.system.validation.products.TimeUnitValid;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -18,35 +20,46 @@ public class ProductDetailsSaveReqVO {
@NotNull(message = "产品名称不能为空") @NotNull(message = "产品名称不能为空")
private Long productId; private Long productId;
@Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买方式:0时长;1产量") @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "购买方式不能为空") @NotNull(message = "购买方式不能为空")
@ProductType @ProductType
private Integer purchaseType; private Integer purchaseType;
@Schema(description = "产品时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1month") @Schema(description = "产品时间,格式:时长值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String duration; private String duration;
@Schema(description = "产品时长单位,0:年、1:月、2:日", example = "1")
@TimeUnitValid
private Integer durationUnit;
@Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") @Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private BigDecimal output; private BigDecimal output;
// //
@Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "半个月") @Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String giftDuration; private String giftDuration;
@Schema(description = "赠送时长单位,0:年、1:月、2:日", example = "1")
@TimeUnitValid
private Integer giftDurationUnit;
@Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") @Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private BigDecimal giftOutput; private BigDecimal giftOutput;
@Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") @Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "产品时间不能为空") @NotNull(message = "产品原价不能为空")
@NumberValid(name = "产品原价")
private BigDecimal originalPrice; private BigDecimal originalPrice;
@Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8")
@NumberValid(name = "折扣", integer = 4, fraction = 2)
private BigDecimal discount; private BigDecimal discount;
@Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") @Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80")
@NotNull(message = "产品时间不能为空") @NotNull(message = "产品现价不能为空")
@NumberValid(name = "产品现价")
private BigDecimal currentPrice; private BigDecimal currentPrice;
@Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "") @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean isDiscounted; private Boolean isDiscounted;
} }
@@ -2,7 +2,8 @@ package com.cf.imes.module.system.controller.admin.pay;
import com.cf.imes.framework.common.pojo.CommonResult; import com.cf.imes.framework.common.pojo.CommonResult;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO; import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayOrderUnifiedReqVO; import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import com.cf.imes.module.system.service.pay.PayOrderService; import com.cf.imes.module.system.service.pay.PayOrderService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -36,13 +37,20 @@ public class PayController {
@Resource @Resource
private PayOrderService payOrderService; private PayOrderService payOrderService;
@PostMapping() @PostMapping("/recharge")
@Operation(summary = "创建支付订单") @Operation(summary = "创建充值支付订单")
public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayOrderUnifiedReqVO payOrderUnifiedReqVO) throws Throwable { public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayRechargeOrderReqVO payRechargeOrderReqVO) {
PayOrderRespDTO payOrderRespDTO = payOrderService.initiatePay(payOrderUnifiedReqVO); PayOrderRespDTO payOrderRespDTO = payOrderService.rechargePay(payRechargeOrderReqVO);
return success(payOrderRespDTO); return success(payOrderRespDTO);
} }
@PostMapping("/product")
@Operation(summary = "创建产品支付订单")
public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
payOrderService.productPay(payProductOrderUnifiedReqVO);
return success(null);
}
@GetMapping("/order/{channelCode}/{outTradeNo}") @GetMapping("/order/{channelCode}/{outTradeNo}")
@Operation(summary = "查询支付订单") @Operation(summary = "查询支付订单")
public CommonResult<Boolean> queryPayOrder(@PathVariable("outTradeNo") String outTradeNo, @PathVariable("channelCode") int channelCode) { public CommonResult<Boolean> queryPayOrder(@PathVariable("outTradeNo") String outTradeNo, @PathVariable("channelCode") int channelCode) {
@@ -57,7 +65,7 @@ public class PayController {
public String notifyOrder(@PathVariable("channelCode") Integer channelCode, public String notifyOrder(@PathVariable("channelCode") Integer channelCode,
@RequestParam(required = false) Map<String, String> params, @RequestParam(required = false) Map<String, String> params,
@RequestBody(required = false) String body) { @RequestBody(required = false) String body) {
log.debug("[notifyOrder][channelCode({}) 回调数据({}/{})]", channelCode, params, body); log.info("[notifyOrder][channelCode({}) 回调数据({}/{})]", channelCode, params, body);
payOrderService.doOrderNotify(channelCode, params, body); payOrderService.doOrderNotify(channelCode, params, body);
// 支付接口回调相应必须是"success" // 支付接口回调相应必须是"success"
return "success"; return "success";
@@ -0,0 +1,30 @@
package com.cf.imes.module.system.controller.admin.pay.vo;
import com.cf.imes.module.system.validation.pay.PayProductChannelCodeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
/**
* 产品支付vo
*
* @author Gqr
* @since 2025/4/15 14:30
*/
@Data
@Valid
public class PayProductOrderUnifiedReqVO {
/**
* 产品定价规则编号
*/
@Schema(description = "产品定价规则编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotEmpty(message = "产品定价规则编号不能为空")
private Long productDetailsId;
@Schema(description = "支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@PayProductChannelCodeValid
@NotNull(message = "支付渠道编码不能为空")
private Integer channelCode;
}
@@ -0,0 +1,35 @@
package com.cf.imes.module.system.controller.admin.pay.vo;
import com.cf.imes.module.system.validation.pay.PayChannelCodeValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
/**
* 充值支付vo
*
* @author Gqr
* @since 2025/4/15 14:30
*/
@Data
@Valid
public class PayRechargeOrderReqVO {
@Schema(description = "组织编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "组织编号不能为空")
private Long organId;
@Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
private BigDecimal price;
@Schema(description = "支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@PayChannelCodeValid
@NotNull(message = "支付渠道编码不能为空")
private Integer channelCode;
}
@@ -14,8 +14,8 @@ import java.math.BigDecimal;
* *
* @author 晨丰科技 * @author 晨丰科技
*/ */
@TableName("products_detail") @TableName("products_details")
@KeySequence("products_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @KeySequence("products_details_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
@@ -45,6 +45,11 @@ public class ProductsDetailDO extends BaseDO {
*/ */
private String duration; private String duration;
/**
* 产品时长单位
*/
private Integer durationUnit;
/** /**
* 正常产量,不加赠送产量 * 正常产量,不加赠送产量
*/ */
@@ -56,6 +61,11 @@ public class ProductsDetailDO extends BaseDO {
*/ */
private String giftDuration; private String giftDuration;
/**
* 赠送时间单位
*/
private Integer giftDurationUnit;
/** /**
* 赠送产量 * 赠送产量
*/ */
@@ -34,13 +34,14 @@ public interface ProductsDetailMapper extends BaseMapperX<ProductsDetailDO> {
// 时长查重,添加productId为查询条件 // 时长查重,添加productId为查询条件
default int selectCountByDuration(String duration, Long productId) { default int selectCountByDuration(Long productId, Long productDetailId, String duration, Integer durationUnit) {
LambdaQueryWrapperX<ProductsDetailDO> queryWrapper = new LambdaQueryWrapperX<>(); LambdaQueryWrapperX<ProductsDetailDO> queryWrapper = new LambdaQueryWrapperX<>();
queryWrapper.eq(ProductsDetailDO::getProductId, productId) queryWrapper.eq(ProductsDetailDO::getProductId, productId)
.eq(ProductsDetailDO::getDeleted, false) .eq(ProductsDetailDO::getDeleted, false)
.eq(ProductsDetailDO::getDuration, duration); .eq(ProductsDetailDO::getDuration, duration)
.eq(ProductsDetailDO::getDurationUnit, durationUnit)
.neIfPresent(ProductsDetailDO::getId, productDetailId);
return Math.toIntExact(selectCount(queryWrapper)); return Math.toIntExact(selectCount(queryWrapper));
} }
@@ -0,0 +1,53 @@
package com.cf.imes.module.system.enums.pay;
import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 产品支付渠道编码
*
* @author Gqr
* @since 2024/7/5 9:25
*/
@Getter
@AllArgsConstructor
public enum PayProductChannelCodeEnum {
/**
* 支付宝
*/
ALIPAY_PC(0),
/**
* 微信
*/
WECHAT_NATIVE(1),
/**
* 账户余额
*/
BALANCE_ONLY(2),
/**
* 账户余额+支付宝
*/
BALANCE_AND_ALIPAY(3),
/**
* 账户余额+微信
*/
BALANCE_AND_WECHAT(4);
@EnumValue
private final Integer code;
@JsonCreator
public static PayProductChannelCodeEnum fromType(Integer type) {
for (PayProductChannelCodeEnum value : values()) {
if (value.getCode().equals(type)) {
return value;
}
}
return null;
}
}
@@ -6,6 +6,7 @@ import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetai
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List; import java.util.List;
/** /**
@@ -51,4 +52,18 @@ public interface ProductsDetailService {
*/ */
PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO); PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO);
/**
* 校验产品明细是否存在
*
* @param id
* @return
*/
ProductsDetailDO validateProductDetailsExists(Long id);
/**
* 校验产品是否存在和时效性
*
* @param productId
*/
void validateProductExist(Long productId);
} }
@@ -1,7 +1,7 @@
package com.cf.imes.module.system.service.funds.products; package com.cf.imes.module.system.service.funds.products;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.nacos.common.utils.StringUtils; import com.alibaba.nacos.common.utils.StringUtils;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils; import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.common.util.object.BeanUtils;
@@ -12,15 +12,14 @@ import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsDetailMapper;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper;
import com.cf.imes.module.system.enums.products.DurationUnitEnum;
import com.cf.imes.module.system.enums.products.ProductStatusEnum; import com.cf.imes.module.system.enums.products.ProductStatusEnum;
import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum; import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum;
import com.cf.imes.module.system.util.SnowflakeIdWorker3rd;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List; import java.util.List;
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -41,57 +40,37 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
@Resource @Resource
private ProductsMapper productsMapper; private ProductsMapper productsMapper;
@Resource
private SnowflakeIdWorker3rd idWorker;
@Override @Override
public Long create(ProductDetailsSaveReqVO createReqVO) { public Long create(ProductDetailsSaveReqVO createReqVO) {
// 校验是否有这个产品 // 校验是否有这个产品
validateProductExist(createReqVO.getProductId()); validateProductExist(createReqVO.getProductId());
if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) { if (ProductsPurchaseTypeEnum.DURATION.getStatus().equals(createReqVO.getPurchaseType())) {
String duration = createReqVO.getDuration();
AssertUtils.notEmpty(duration,PRODUCTS_DURATION_NOT_NULL);
// 校验时长 // 校验时长
duration = checkDuration(duration); checkDuration(createReqVO.getDuration(), createReqVO.getDurationUnit());
// 校验赠送时长
String giftDuration = null; String giftDuration = createReqVO.getGiftDuration();
if (createReqVO.getGiftDuration() != null) { if (StringUtils.isNotEmpty(giftDuration)) {
giftDuration = checkDuration(createReqVO.getGiftDuration()); checkDuration(giftDuration, createReqVO.getGiftDurationUnit());
} }
createReqVO.setDuration(duration) // 校验现价计算是否正确
.setGiftDuration(giftDuration); calculateDiscount(createReqVO.getOriginalPrice(), createReqVO.getCurrentPrice(), createReqVO.getDiscount());
// 查询是否有重复的定价 // 查询是否有重复的定价
checkProductDetails(createReqVO); checkProductDetails(createReqVO);
} else if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) { } else if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
if (StringUtils.isBlank(createReqVO.getDuration())) { // todo 暂不支持产量
throw exception(PRODUCTS_OUTPUT_NOT_NULL); throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
}
} }
Long id = idWorker.nextId(); ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class);
createReqVO.setId(id);
ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class).setId(id);
productDetailsMapper.insert(productDetailsDO); productDetailsMapper.insert(productDetailsDO);
return id; return productDetailsDO.getId();
} }
@Override @Override
public void update(ProductDetailsSaveReqVO updateReqVO) { public void update(ProductDetailsSaveReqVO updateReqVO) {
@@ -100,45 +79,25 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
validateProductDetailsExists(updateReqVO.getId()); validateProductDetailsExists(updateReqVO.getId());
if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) { if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) {
if (StringUtils.isBlank(updateReqVO.getDuration())) {
throw exception(PRODUCTS_DURATION_NOT_NULL);
}
// 校验时长 // 校验时长
String duration = checkDuration(updateReqVO.getDuration()); checkDuration(updateReqVO.getDuration(), updateReqVO.getDurationUnit());
String giftDuration = null; // 校验赠送时长
if (updateReqVO.getGiftDuration() != null) { String giftDuration = updateReqVO.getGiftDuration();
giftDuration = checkDuration(updateReqVO.getGiftDuration()); if (StringUtils.isNotEmpty(giftDuration)) {
checkDuration(giftDuration, updateReqVO.getGiftDurationUnit());
} }
updateReqVO.setDuration(duration).setGiftDuration(giftDuration);
// 校验现价计算是否正确
calculateDiscount(updateReqVO.getOriginalPrice(), updateReqVO.getCurrentPrice(), updateReqVO.getDiscount());
// 校验同时长是否还有其他的定价规则 // 校验同时长是否还有其他的定价规则
checkProductDetails(updateReqVO); checkProductDetails(updateReqVO);
} else if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) { } else if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
if (StringUtils.isBlank(updateReqVO.getDuration())) { // todo 暂不支持产量
throw exception(PRODUCTS_OUTPUT_NOT_NULL); throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
}
} }
ProductsDetailDO productDetailsDO = BeanUtils.toBean(updateReqVO, ProductsDetailDO.class) productDetailsMapper.updateById(BeanUtils.toBean(updateReqVO, ProductsDetailDO.class));
.setDiscount(getZeroBigDecimal(updateReqVO.getDiscount()))
.setOriginalPrice(getZeroBigDecimal(updateReqVO.getOriginalPrice()))
.setIsDiscounted(updateReqVO.getIsDiscounted());
productDetailsMapper.updateById(productDetailsDO);
}
/**
* value为空返回0.0
*
* @param value
* @return
*/
private BigDecimal getZeroBigDecimal(BigDecimal value) {
return ObjectUtil.defaultIfNull(value, BigDecimal.ZERO);
} }
@Override @Override
@@ -160,12 +119,12 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
@Override @Override
public PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO) { public PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO) {
return productDetailsMapper.selectPage(pageReqVO.setDeleted(0)); return productDetailsMapper.selectPage(pageReqVO);
} }
@Override
private ProductsDetailDO validateProductDetailsExists(Long id) { public ProductsDetailDO validateProductDetailsExists(Long id) {
if (id == null) { if (id == null) {
throw exception(PRODUCTS_DETAIL_NO_EXIST); throw exception(PRODUCTS_DETAIL_NO_EXIST);
} }
@@ -182,50 +141,36 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
} }
/**
* 校验时长
*
// 时长校验 * @param duration
private String checkDuration(String duration){ * @param timeUnit
* @return
if (duration == null || !duration.contains("-")) { */
throw new IllegalArgumentException("格式错误,格式为:时长值-单位,例如 10-月"); private void checkDuration(String duration, Integer timeUnit) {
} AssertUtils.notEmpty(duration, PRODUCTS_DURATION_NOT_NULL);
AssertUtils.notEmpty(timeUnit, PRODUCTS_DURATION_NOT_NULL);
String[] parts = duration.split("-", 2);
String valueStr = parts[0].trim();
String timeUnit = parts[1].trim();
// 校验时长值 // 校验时长值
if (valueStr.isEmpty() || !valueStr.matches("^\\d+$")) { if (!duration.matches("^\\d+$")) {
throw exception(PRODUCTS_DURATION_INT_ERR); throw exception(PRODUCTS_DURATION_INT_ERR);
} }
// 去除前导 0 int timeValue = Integer.parseInt(duration);
valueStr = valueStr.replaceFirst("^0+(?!$)", "");
int timeValue = Integer.parseInt(valueStr);
if (timeValue <= 0) { if (timeValue <= 0) {
throw exception(PRODUCTS_DURATION_INT_ERR); throw exception(PRODUCTS_DURATION_INT_ERR);
} }
// 校验时间单位
if (timeUnit.isEmpty()
|| !(timeUnit.equals(DurationUnitEnum.YEAR.getName())
|| timeUnit.equals(DurationUnitEnum.MONTH.getName())
|| timeUnit.equals(DurationUnitEnum.DAY.getName()))) {
throw exception(PRODUCTS_DURATION_UNIT_ERR);
}
return timeValue + timeUnit;
} }
/**
// 产品存在性校验 * 产品是否存在和时效性校验
private void validateProductExist(Long productId){ *
* @param productId
*/
@Override
public void validateProductExist(Long productId) {
ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>() ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>()
.eq(ProductsDO::getId, productId) .eq(ProductsDO::getId, productId)
.eq(ProductsDO::getDeleted, false)); .eq(ProductsDO::getDeleted, false));
@@ -235,20 +180,23 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
if (productsDO.getStatus().equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())) { if (productsDO.getStatus().equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())) {
throw exception(PRODUCTS_DETAIL_NO_UPDATE); throw exception(PRODUCTS_DETAIL_NO_UPDATE);
} }
} }
/**
* 检查产品下是否有相同时长的规则
// 时长/产量去重 *
* @param createReqVO
*/
private void checkProductDetails(ProductDetailsSaveReqVO createReqVO) { private void checkProductDetails(ProductDetailsSaveReqVO createReqVO) {
int count; int count;
if (createReqVO.getPurchaseType() == 0) { if (createReqVO.getPurchaseType() == 0) {
String duration = createReqVO.getDuration();
Integer durationUnit = createReqVO.getDurationUnit();
// 时长去重 // 时长去重
count = productDetailsMapper.selectCountByDuration(createReqVO.getDuration(), createReqVO.getProductId()); count = productDetailsMapper.selectCountByDuration(createReqVO.getProductId(), createReqVO.getId(), duration, durationUnit);
if (count > 0) { if (count > 0) {
throw exception(PRODUCTS_DETAIL_DURATION_EXIST); throw ServiceExceptionUtil.exception(PRODUCTS_DETAIL_DURATION_EXIST, duration, durationUnit);
} }
} else if (createReqVO.getPurchaseType() == 1) { } else if (createReqVO.getPurchaseType() == 1) {
//产量去重 //产量去重
@@ -260,6 +208,21 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
} }
/**
* 计算折扣是否正确
*
* @param originalPrice 原价
* @param currentPrice 当前价格
* @param discount 折扣(百分比)
*/
private void calculateDiscount(BigDecimal originalPrice, BigDecimal currentPrice, BigDecimal discount) {
// 校验当前价格是否正确
// 计算期望现价(保留2位小数,四舍五入)
BigDecimal expectedPrice = originalPrice.multiply(discount).setScale(2, RoundingMode.HALF_UP);
if (currentPrice.compareTo(expectedPrice) != 0) {
throw ServiceExceptionUtil.exception(PRODUCTS_DETAIL_CURRENTPRICE_CALCULATE_ERROR, expectedPrice);
}
}
} }
@@ -1,6 +1,5 @@
package com.cf.imes.module.system.service.funds.products; package com.cf.imes.module.system.service.funds.products;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.common.util.Assert.AssertUtils; import com.cf.imes.framework.common.util.Assert.AssertUtils;
@@ -9,7 +8,7 @@ import com.cf.imes.module.system.controller.admin.funds.products.vo.product.Prod
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO;
import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper;
import com.cf.imes.module.system.enums.products.ProductStatusEnum; import com.cf.imes.module.system.enums.products.ProductStatusEnum;
import com.cf.imes.module.system.util.SnowflakeIdWorker3rd; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@@ -32,39 +31,37 @@ public class ProductsServiceImpl implements ProductsService{
@Resource @Resource
private ProductsMapper productsMapper; private ProductsMapper productsMapper;
@Resource
private SnowflakeIdWorker3rd idWorker;
@Override @Override
public Long create(String productName) { public Long create(String productName) {
// 校验产品名称唯一
validateProductNameUnique(null, productName);
List<ProductsDO> productsDOS = productsMapper.selectList(new LambdaQueryWrapperX<ProductsDO>() ProductsDO productsDO = new ProductsDO()
.eq(ProductsDO::getDeleted, false)
.eq(ProductsDO::getProductName, productName)
.select(ProductsDO::getId));
AssertUtils.empty(productsDOS,PRODUCTS_IS_EXIST);
Long id = idWorker.nextId();
productsMapper.insert(
new ProductsDO()
.setId(id)
.setProductName(productName) .setProductName(productName)
.setStatus(ProductStatusEnum.PRODUCT_WAITING_UPDATES.getStatus()) .setStatus(ProductStatusEnum.PRODUCT_WAITING_UPDATES.getStatus())
.setSoftwareId(0) .setSoftwareId(0);
); productsMapper.insert(productsDO);
return id; return productsDO.getId();
} }
@Override @Override
public void update(ProductsDO updateReqVO) { public void update(ProductsDO updateReqVO) {
Integer status = validateProductPlateExists(updateReqVO.getId()).getStatus(); Long updateReqVOId = updateReqVO.getId();
String productName = updateReqVO.getProductName();
// 目标状态
Integer updateReqVOStatus = updateReqVO.getStatus();
// 校验产品是否存在
Integer status = validateProductPlateExists(updateReqVOId).getStatus();
// 校验产品名称唯一
if (StringUtils.isNotEmpty(productName)) {
validateProductNameUnique(updateReqVOId, productName);
}
if(status.equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())){ // 当前状态是上架状态 && 目标状态不是下架 的操作提示已上架
if (ProductStatusEnum.PRODUCT_UPDATES.getStatus().equals(status) && !ProductStatusEnum.isProductDelis(updateReqVOStatus)) {
throw exception(PRODUCTS_NO_UPDATE); throw exception(PRODUCTS_NO_UPDATE);
} }
productsMapper.updateById(updateReqVO); productsMapper.updateById(updateReqVO);
@@ -99,8 +96,12 @@ public class ProductsServiceImpl implements ProductsService{
} }
/**
* 校验产品id是否存在
*
* @param id
* @return
*/
private ProductsDO validateProductPlateExists(Long id) { private ProductsDO validateProductPlateExists(Long id) {
ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>() ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>()
.eq(ProductsDO::getId, id) .eq(ProductsDO::getId, id)
@@ -112,6 +113,19 @@ public class ProductsServiceImpl implements ProductsService{
return productsDO; return productsDO;
} }
/**
* 校验产品名称是否存在
*
* @param productName
*/
private void validateProductNameUnique(Long productId, String productName) {
List<ProductsDO> productsDOS = productsMapper.selectList(new LambdaQueryWrapperX<ProductsDO>()
.eq(ProductsDO::getDeleted, false)
.eq(ProductsDO::getProductName, productName)
.neIfPresent(ProductsDO::getId, productId)
.select(ProductsDO::getId));
AssertUtils.empty(productsDOS, PRODUCTS_IS_EXIST, productName);
}
} }
@@ -1,8 +1,8 @@
package com.cf.imes.module.system.service.pay; package com.cf.imes.module.system.service.pay;
import com.alipay.api.AlipayApiException;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO; import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayOrderUnifiedReqVO; import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import java.util.Map; import java.util.Map;
@@ -14,13 +14,18 @@ import java.util.Map;
*/ */
public interface PayOrderService { public interface PayOrderService {
/** /**
* 发起支付 * 产品支付
* *
* @param payOrderUnifiedReqVO * @param payProductOrderUnifiedReqVO
* @return
* @throws AlipayApiException
*/ */
PayOrderRespDTO initiatePay(PayOrderUnifiedReqVO payOrderUnifiedReqVO); void productPay(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO);
/**
* 账户充值支付
*
* @param payRechargeOrderReqVO
*/
PayOrderRespDTO rechargePay(PayRechargeOrderReqVO payRechargeOrderReqVO);
/** /**
* 查询支付订单支付状态 * 查询支付订单支付状态
@@ -10,18 +10,26 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants; import com.cf.imes.framework.common.exception.enums.GlobalErrorCodeConstants;
import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.json.JsonUtils; import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.common.util.validation.ValidationUtils; import com.cf.imes.framework.common.util.validation.ValidationUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder; import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.framework.pay.config.ChenfengAlipayConfig; import com.cf.imes.framework.pay.config.ChenfengAlipayConfig;
import com.cf.imes.framework.pay.config.ChenfengPayConfig;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO; import com.cf.imes.framework.pay.core.client.dto.order.PayOrderRespDTO;
import com.cf.imes.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import com.cf.imes.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import com.cf.imes.framework.common.exception.PayException; import com.cf.imes.framework.common.exception.PayException;
import com.cf.imes.framework.pay.core.enums.order.PayOrderStatusRespEnum; import com.cf.imes.framework.pay.core.enums.order.PayOrderStatusRespEnum;
import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
import com.cf.imes.module.system.controller.admin.funds.organamount.vo.OrganAmountRespVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayProductOrderUnifiedReqVO;
import com.cf.imes.module.system.controller.admin.pay.vo.PayRechargeOrderReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO;
import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum; import com.cf.imes.module.system.enums.pay.PayChannelCodeEnum;
import com.cf.imes.module.system.service.funds.organamount.OrganAmountService;
import com.cf.imes.module.system.service.funds.products.ProductsDetailService;
import com.cf.imes.module.system.service.pay.factory.impl.AbstractPayHandler; import com.cf.imes.module.system.service.pay.factory.impl.AbstractPayHandler;
import com.cf.imes.module.system.service.pay.factory.PayHandlerFactory; import com.cf.imes.module.system.service.pay.factory.PayHandlerFactory;
import com.cf.imes.module.system.controller.admin.pay.vo.PayOrderUnifiedReqVO;
import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO; import com.cf.imes.module.system.dal.dataobject.pay.PayOrderDO;
import com.cf.imes.module.system.dal.mysql.pay.PayOrderMapper; import com.cf.imes.module.system.dal.mysql.pay.PayOrderMapper;
import com.cf.imes.module.system.enums.pay.PayOrderStatusEnum; import com.cf.imes.module.system.enums.pay.PayOrderStatusEnum;
@@ -32,6 +40,8 @@ import org.springframework.validation.annotation.Validated;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -43,6 +53,7 @@ import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_NOTIF
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_NOT_EXIST; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_NOT_EXIST;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_STATUS_IS_NOT_WAITING;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_SUBMIT_CHANNEL_ERROR; import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_ORDER_SUBMIT_CHANNEL_ERROR;
import static com.cf.imes.module.system.enums.ErrorCodeConstants.PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR;
/** /**
* 支付订单接口 实现类 * 支付订单接口 实现类
@@ -69,18 +80,43 @@ public class PayOrderServiceImpl implements PayOrderService {
@Resource @Resource
private ChenfengAlipayConfig alipayConfig; private ChenfengAlipayConfig alipayConfig;
@Override @Resource
@Transactional(rollbackFor = Exception.class) private ChenfengPayConfig payConfig;
public PayOrderRespDTO initiatePay(PayOrderUnifiedReqVO payOrderUnifiedReqVO) {
// 主动校验一次入参
ValidationUtils.validate(validator, payOrderUnifiedReqVO);
Integer channelCode = payOrderUnifiedReqVO.getChannelCode(); @Resource
private ProductsDetailService productsDetailService;
@Resource
private OrganAmountService organAmountService;
@Override
public void productPay(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
// 主动校验一次入参
ValidationUtils.validate(validator, payProductOrderUnifiedReqVO);
// 校验产品和产品明细
ProductsDetailDO productsDetailDO = productsDetailService.validateProductDetailsExists(payProductOrderUnifiedReqVO.getProductDetailsId());
productsDetailService.validateProductExist(productsDetailDO.getProductId());
// 查询组织余额信息
OrganAmountRespVO organAmount = organAmountService.getOrganAmount(SecurityFrameworkUtils.getUserOrganId());
}
@Override
public PayOrderRespDTO rechargePay(PayRechargeOrderReqVO payRechargeOrderReqVO) {
// 主动校验一次入参
ValidationUtils.validate(validator, payRechargeOrderReqVO);
// 校验组织名称
AssertUtils.notEquals(payRechargeOrderReqVO.getOrganId(), SecurityFrameworkUtils.getUserOrganId(), PAY_RECHARGE_ORDER_ORGANID_CHECK_ERROR);
Integer channelCode = payRechargeOrderReqVO.getChannelCode();
// 获取渠道方处理器 // 获取渠道方处理器
AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode); AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode);
// 创建支付订单 // 创建支付订单
PayOrderDO payOrder = createPayOrder(payOrderUnifiedReqVO); PayOrderDO payOrder = createPayOrder(payRechargeOrderReqVO.getPrice(), "imes充值", channelCode);
payOrderMapper.insert(payOrder); payOrderMapper.insert(payOrder);
// 发起渠道方支付 // 发起渠道方支付
@@ -99,23 +135,22 @@ public class PayOrderServiceImpl implements PayOrderService {
/** /**
* 创建支付订单 * 创建支付订单
* *
* @param payOrderUnifiedReqVO * @param
* @return * @return
*/ */
private PayOrderDO createPayOrder(PayOrderUnifiedReqVO payOrderUnifiedReqVO) { private PayOrderDO createPayOrder(BigDecimal price, String subject, Integer channelCode) {
PayOrderDO payOrderDO = new PayOrderDO(); PayOrderDO payOrderDO = new PayOrderDO();
// 校验获取组织id
Long organId = validOrganId();
Long payOrderId = IdUtil.getSnowflake(0, 0).nextId(); Long payOrderId = IdUtil.getSnowflake(0, 0).nextId();
Long organId = SecurityFrameworkUtils.getUserOrganId();
payOrderDO.setId(payOrderId); payOrderDO.setId(payOrderId);
payOrderDO.setPayNo(String.format(PAY_ORDER_PREFIX_FORMAT, organId, payOrderId, DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN))); payOrderDO.setPayNo(String.format(PAY_ORDER_PREFIX_FORMAT, organId, payOrderId, DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN)));
payOrderDO.setStatus(PayOrderStatusEnum.WAITING); payOrderDO.setStatus(PayOrderStatusEnum.WAITING);
payOrderDO.setExpireTime(payOrderUnifiedReqVO.getExpireTime()); payOrderDO.setExpireTime(LocalDateTime.now().plus(payConfig.getPayExpireTime()));
payOrderDO.setPrice(payOrderUnifiedReqVO.getPrice()); payOrderDO.setPrice(price);
payOrderDO.setSubject(payOrderUnifiedReqVO.getSubject()); payOrderDO.setSubject(subject);
payOrderDO.setChannelCode(PayChannelCodeEnum.fromType(payOrderUnifiedReqVO.getChannelCode())); payOrderDO.setChannelCode(PayChannelCodeEnum.fromType(channelCode));
payOrderDO.setOrganId(organId); payOrderDO.setOrganId(organId);
return payOrderDO; return payOrderDO;
} }
@@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert;
import cn.hutool.core.text.CharSequenceUtil; import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method; import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient; import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel; import com.alipay.api.domain.AlipayTradePagePayModel;
@@ -27,6 +28,7 @@ import jakarta.annotation.Resource;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -60,6 +62,12 @@ public class AlipayPcPayHandler extends AbstractPayHandler {
model.setProductCode(alipayConfig.getProductCode()); model.setProductCode(alipayConfig.getProductCode());
model.setQrPayMode(alipayConfig.getQrPayMode()); model.setQrPayMode(alipayConfig.getQrPayMode());
Map<String, String> passbackMap = new HashMap<>();
passbackMap.put("test1", "1");
passbackMap.put("test2", "2");
passbackMap.put("test3", outTradeNo);
model.setPassbackParams(JSON.toJSONString(passbackMap));
// 1.2 构建 AlipayTradePagePayRequest 请求 // 1.2 构建 AlipayTradePagePayRequest 请求
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setBizModel(model); request.setBizModel(model);
@@ -22,7 +22,7 @@ import java.lang.annotation.Target;
validatedBy = {PayChannelCodeValidator.class} validatedBy = {PayChannelCodeValidator.class}
) )
public @interface PayChannelCodeValid { public @interface PayChannelCodeValid {
String message() default "不支持的支付渠道0:支付宝、1:微信"; String message() default "不支持的支付渠道";
Class<?>[] groups() default {}; Class<?>[] groups() default {};
@@ -0,0 +1,31 @@
package com.cf.imes.module.system.validation.pay;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 产品支付渠道编码校验注解
* @author Gqr
* @since 2025/4/18 10:21
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {PayProductChannelCodeValidator.class}
)
public @interface PayProductChannelCodeValid {
String message() default "不支持的支付渠道";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -0,0 +1,27 @@
package com.cf.imes.module.system.validation.pay;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
/**
* 产品支付渠道编码校验器
*
* @author Gqr
* @since 2025/4/18 10:22
*/
public class PayProductChannelCodeValidator implements ConstraintValidator<PayProductChannelCodeValid, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (PayProductChannelCodeEnum codeEnum : PayProductChannelCodeEnum.values()) {
if (ObjectUtil.equal(codeEnum.getCode(), value)) {
return true;
}
}
return false;
}
}
@@ -17,7 +17,7 @@ import java.lang.annotation.*;
) )
public @interface ProductType { public @interface ProductType {
String message() default "购买方式:0 时长;1 产量"; String message() default "购买方式不合法0 时长;1 产量";
Class<?>[] groups() default {}; Class<?>[] groups() default {};
@@ -0,0 +1,32 @@
package com.cf.imes.module.system.validation.products;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 时长单位校验注解
*
* @author Gqr
* @since 2025/8/11 14:18
*/
@Target({
ElementType.FIELD,
})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
validatedBy = {TimeUnitValidator.class}
)
public @interface TimeUnitValid {
String message() default "时长单位不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -0,0 +1,30 @@
package com.cf.imes.module.system.validation.products;
import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.module.system.enums.products.DurationUnitEnum;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.util.Objects;
/**
* 时长单位校验器
*
* @author Gqr
* @since 2025/8/11 14:19
*/
public class TimeUnitValidator implements ConstraintValidator<TimeUnitValid, Integer> {
@Override
public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) {
if (ObjectUtil.isNull(value)) {
return true;
}
for (DurationUnitEnum unitEnum : DurationUnitEnum.values()) {
if (Objects.equals(unitEnum.getStatus(), value)) {
return true;
}
}
return false;
}
}