mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-14 13:42:07 +08:00
1、产品管理、定价规则接口完善;2、支付测试;
This commit is contained in:
+12
-11
@@ -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.ProductSaveReqVO;
|
||||
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 io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -30,36 +31,36 @@ public class ProductsController {
|
||||
@Resource
|
||||
private ProductsService productsService;
|
||||
|
||||
@PostMapping("")
|
||||
@PutMapping("")
|
||||
@Operation(summary = "新建产品")
|
||||
// @PreAuthorize("@ss.hasPermission('base:products:create')")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:create')")
|
||||
public CommonResult<Long> createProducts(@RequestParam("productName") String productName) {
|
||||
return success(productsService.create(productName));
|
||||
}
|
||||
|
||||
@PutMapping("")
|
||||
@PostMapping("")
|
||||
@Operation(summary = "更新产品")
|
||||
// @PreAuthorize("@ss.hasPermission('base:products:update')")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:update')")
|
||||
public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) {
|
||||
ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class);
|
||||
productsService.update(productsDO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/freeze")
|
||||
@PostMapping("/freeze")
|
||||
@Operation(summary = "下架产品")
|
||||
// @PreAuthorize("@ss.hasPermission('base:products:freeze')")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:freeze')")
|
||||
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);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PutMapping("/melt")
|
||||
@PostMapping("/melt")
|
||||
@Operation(summary = "上架产品")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:melt')")
|
||||
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);
|
||||
return success(true);
|
||||
}
|
||||
@@ -75,7 +76,7 @@ public class ProductsController {
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "获得产品")
|
||||
@Operation(summary = "查询产品")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:query')")
|
||||
public CommonResult<ProductRespVO> getProducts(@PathVariable("id") Long id) {
|
||||
@@ -84,7 +85,7 @@ public class ProductsController {
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品分页")
|
||||
@Operation(summary = "查询产品分页")
|
||||
@PreAuthorize("@ss.hasPermission('base:products:query')")
|
||||
public CommonResult<PageResult<ProductRespVO>> getProductsPage(@Valid ProductPageReqVO pageReqVO) {
|
||||
PageResult<ProductsDO> pageResult = productsService.getPage(pageReqVO);
|
||||
|
||||
+4
-4
@@ -30,14 +30,14 @@ public class ProductsDetailController {
|
||||
@Resource
|
||||
private ProductsDetailService productDetailsService;
|
||||
|
||||
@PostMapping("")
|
||||
@PutMapping("")
|
||||
@Operation(summary = "新建产品明细")
|
||||
@PreAuthorize("@ss.hasPermission('base:productDetails:create')")
|
||||
public CommonResult<Long> createProducts(@Valid @RequestBody ProductDetailsSaveReqVO createReqVO) {
|
||||
return success(productDetailsService.create(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("")
|
||||
@PostMapping("")
|
||||
@Operation(summary = "更新产品明细")
|
||||
@PreAuthorize("@ss.hasPermission('base:productDetails:update')")
|
||||
public CommonResult<Boolean> updateProducts(@Valid @RequestBody ProductDetailsSaveReqVO updateReqVO) {
|
||||
@@ -55,7 +55,7 @@ public class ProductsDetailController {
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "获得产品明细")
|
||||
@Operation(summary = "查询产品明细")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('base:productDetails:query')")
|
||||
public CommonResult<List<ProductsDetailDO>> getProducts(@PathVariable("id") Long id) {
|
||||
@@ -64,7 +64,7 @@ public class ProductsDetailController {
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得产品明细分页")
|
||||
@Operation(summary = "查询产品明细分页")
|
||||
@PreAuthorize("@ss.hasPermission('base:productDetails:query')")
|
||||
public CommonResult<PageResult<ProductDetailsRespVO>> getProductsPage(@Valid ProductDetailsPageReqVO pageReqVO) {
|
||||
PageResult<ProductsDetailDO> pageResult = productDetailsService.getPage(pageReqVO);
|
||||
|
||||
+1
-17
@@ -6,11 +6,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
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")
|
||||
@Data
|
||||
@@ -24,18 +19,7 @@ public class ProductPageReqVO extends PageParam {
|
||||
@Schema(description = "产品名称", example = "赵六")
|
||||
private String productName;
|
||||
|
||||
@Schema(description = "产品状态", example = "0待上架 1已上架 2已下架")
|
||||
@Schema(description = "产品状态", example = "0")
|
||||
@ProductStatus
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
+2
@@ -1,5 +1,6 @@
|
||||
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 lombok.Data;
|
||||
|
||||
@@ -17,6 +18,7 @@ public class ProductSaveReqVO {
|
||||
private String productName;
|
||||
|
||||
@Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ProductStatus
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "软件id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
||||
+5
-16
@@ -6,12 +6,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
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")
|
||||
@Data
|
||||
@@ -23,19 +19,19 @@ public class ProductDetailsPageReqVO extends PageParam {
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "产品ID", example = "1")
|
||||
private String productId;
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "购买方式", example = "购买方式:0时长;1产量")
|
||||
@Schema(description = "购买方式", example = "0")
|
||||
@ProductType
|
||||
private Integer purchaseType;
|
||||
|
||||
@Schema(description = "正常时间", example = "半个月")
|
||||
@Schema(description = "产品时长", example = "1")
|
||||
private String duration;
|
||||
|
||||
@Schema(description = "正常产量", example = "")
|
||||
private BigDecimal output;
|
||||
|
||||
@Schema(description = "赠送时间", example = "半个月")
|
||||
@Schema(description = "赠送市场", example = "1")
|
||||
private String giftDuration;
|
||||
|
||||
@Schema(description = "赠送产量", example = "")
|
||||
@@ -50,14 +46,7 @@ public class ProductDetailsPageReqVO extends PageParam {
|
||||
@Schema(description = "产品现价", example = "80")
|
||||
private BigDecimal currentPrice;
|
||||
|
||||
@Schema(description = "是否特惠", example = "是")
|
||||
@Schema(description = "是否特惠", example = "0")
|
||||
private Boolean isDiscounted;
|
||||
|
||||
@Schema(description = "操作时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] updateTime;
|
||||
|
||||
@Schema(description = "是否删除")
|
||||
private Integer deleted;
|
||||
|
||||
}
|
||||
|
||||
+19
-6
@@ -1,6 +1,8 @@
|
||||
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.TimeUnitValid;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -18,35 +20,46 @@ public class ProductDetailsSaveReqVO {
|
||||
@NotNull(message = "产品名称不能为空")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "购买方式:0时长;1产量")
|
||||
@Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
|
||||
@NotNull(message = "购买方式不能为空")
|
||||
@ProductType
|
||||
private Integer purchaseType;
|
||||
|
||||
@Schema(description = "产品时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1month")
|
||||
@Schema(description = "产品时间,格式:时长值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private String duration;
|
||||
|
||||
@Schema(description = "产品时长单位,0:年、1:月、2:日", example = "1")
|
||||
@TimeUnitValid
|
||||
private Integer durationUnit;
|
||||
|
||||
@Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
private BigDecimal output;
|
||||
//
|
||||
@Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "半个月")
|
||||
@Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private String giftDuration;
|
||||
|
||||
@Schema(description = "赠送时长单位,0:年、1:月、2:日", example = "1")
|
||||
@TimeUnitValid
|
||||
private Integer giftDurationUnit;
|
||||
|
||||
@Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
|
||||
private BigDecimal giftOutput;
|
||||
|
||||
@Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
|
||||
@NotNull(message = "产品时间不能为空")
|
||||
@NotNull(message = "产品原价不能为空")
|
||||
@NumberValid(name = "产品原价")
|
||||
private BigDecimal originalPrice;
|
||||
|
||||
@Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8")
|
||||
@NumberValid(name = "折扣", integer = 4, fraction = 2)
|
||||
private BigDecimal discount;
|
||||
|
||||
@Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80")
|
||||
@NotNull(message = "产品时间不能为空")
|
||||
@NotNull(message = "产品现价不能为空")
|
||||
@NumberValid(name = "产品现价")
|
||||
private BigDecimal currentPrice;
|
||||
|
||||
@Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "是")
|
||||
@Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||
private Boolean isDiscounted;
|
||||
|
||||
}
|
||||
|
||||
+14
-6
@@ -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.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 io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -36,13 +37,20 @@ public class PayController {
|
||||
@Resource
|
||||
private PayOrderService payOrderService;
|
||||
|
||||
@PostMapping()
|
||||
@Operation(summary = "创建支付订单")
|
||||
public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayOrderUnifiedReqVO payOrderUnifiedReqVO) throws Throwable {
|
||||
PayOrderRespDTO payOrderRespDTO = payOrderService.initiatePay(payOrderUnifiedReqVO);
|
||||
@PostMapping("/recharge")
|
||||
@Operation(summary = "创建充值支付订单")
|
||||
public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayRechargeOrderReqVO payRechargeOrderReqVO) {
|
||||
PayOrderRespDTO payOrderRespDTO = payOrderService.rechargePay(payRechargeOrderReqVO);
|
||||
return success(payOrderRespDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/product")
|
||||
@Operation(summary = "创建产品支付订单")
|
||||
public CommonResult<PayOrderRespDTO> initiatePay(@RequestBody PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO) {
|
||||
payOrderService.productPay(payProductOrderUnifiedReqVO);
|
||||
return success(null);
|
||||
}
|
||||
|
||||
@GetMapping("/order/{channelCode}/{outTradeNo}")
|
||||
@Operation(summary = "查询支付订单")
|
||||
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,
|
||||
@RequestParam(required = false) Map<String, String> params,
|
||||
@RequestBody(required = false) String body) {
|
||||
log.debug("[notifyOrder][channelCode({}) 回调数据({}/{})]", channelCode, params, body);
|
||||
log.info("[notifyOrder][channelCode({}) 回调数据({}/{})]", channelCode, params, body);
|
||||
payOrderService.doOrderNotify(channelCode, params, body);
|
||||
// 支付接口回调相应必须是"success"
|
||||
return "success";
|
||||
|
||||
+30
@@ -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;
|
||||
}
|
||||
+35
@@ -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;
|
||||
}
|
||||
+12
-2
@@ -14,8 +14,8 @@ import java.math.BigDecimal;
|
||||
*
|
||||
* @author 晨丰科技
|
||||
*/
|
||||
@TableName("products_detail")
|
||||
@KeySequence("products_detail_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@TableName("products_details")
|
||||
@KeySequence("products_details_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@@ -45,6 +45,11 @@ public class ProductsDetailDO extends BaseDO {
|
||||
*/
|
||||
private String duration;
|
||||
|
||||
/**
|
||||
* 产品时长单位
|
||||
*/
|
||||
private Integer durationUnit;
|
||||
|
||||
/**
|
||||
* 正常产量,不加赠送产量
|
||||
*/
|
||||
@@ -56,6 +61,11 @@ public class ProductsDetailDO extends BaseDO {
|
||||
*/
|
||||
private String giftDuration;
|
||||
|
||||
/**
|
||||
* 赠送时间单位
|
||||
*/
|
||||
private Integer giftDurationUnit;
|
||||
|
||||
/**
|
||||
* 赠送产量
|
||||
*/
|
||||
|
||||
+5
-4
@@ -34,13 +34,14 @@ public interface ProductsDetailMapper extends BaseMapperX<ProductsDetailDO> {
|
||||
|
||||
|
||||
// 时长查重,添加productId为查询条件
|
||||
default int selectCountByDuration(String duration, Long productId) {
|
||||
default int selectCountByDuration(Long productId, Long productDetailId, String duration, Integer durationUnit) {
|
||||
LambdaQueryWrapperX<ProductsDetailDO> queryWrapper = new LambdaQueryWrapperX<>();
|
||||
queryWrapper.eq(ProductsDetailDO::getProductId, productId)
|
||||
.eq(ProductsDetailDO::getDeleted, false)
|
||||
.eq(ProductsDetailDO::getDuration, duration);
|
||||
.eq(ProductsDetailDO::getDeleted, false)
|
||||
.eq(ProductsDetailDO::getDuration, duration)
|
||||
.eq(ProductsDetailDO::getDurationUnit, durationUnit)
|
||||
.neIfPresent(ProductsDetailDO::getId, productDetailId);
|
||||
return Math.toIntExact(selectCount(queryWrapper));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+53
@@ -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;
|
||||
}
|
||||
}
|
||||
+15
@@ -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 jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -51,4 +52,18 @@ public interface ProductsDetailService {
|
||||
*/
|
||||
PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 校验产品明细是否存在
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
ProductsDetailDO validateProductDetailsExists(Long id);
|
||||
|
||||
/**
|
||||
* 校验产品是否存在和时效性
|
||||
*
|
||||
* @param productId
|
||||
*/
|
||||
void validateProductExist(Long productId);
|
||||
}
|
||||
|
||||
+75
-112
@@ -1,7 +1,7 @@
|
||||
package com.cf.imes.module.system.service.funds.products;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
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.util.Assert.AssertUtils;
|
||||
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.mysql.funds.products.ProductsDetailMapper;
|
||||
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.ProductsPurchaseTypeEnum;
|
||||
import com.cf.imes.module.system.util.SnowflakeIdWorker3rd;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.List;
|
||||
|
||||
import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@@ -41,57 +40,37 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
|
||||
@Resource
|
||||
private ProductsMapper productsMapper;
|
||||
|
||||
@Resource
|
||||
private SnowflakeIdWorker3rd idWorker;
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Long create(ProductDetailsSaveReqVO createReqVO) {
|
||||
|
||||
// 校验是否有这个产品
|
||||
validateProductExist(createReqVO.getProductId());
|
||||
|
||||
if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) {
|
||||
|
||||
String duration = createReqVO.getDuration();
|
||||
|
||||
AssertUtils.notEmpty(duration,PRODUCTS_DURATION_NOT_NULL);
|
||||
|
||||
if (ProductsPurchaseTypeEnum.DURATION.getStatus().equals(createReqVO.getPurchaseType())) {
|
||||
// 校验时长
|
||||
duration = checkDuration(duration);
|
||||
|
||||
String giftDuration = null;
|
||||
if (createReqVO.getGiftDuration() != null) {
|
||||
giftDuration = checkDuration(createReqVO.getGiftDuration());
|
||||
checkDuration(createReqVO.getDuration(), createReqVO.getDurationUnit());
|
||||
// 校验赠送时长
|
||||
String giftDuration = createReqVO.getGiftDuration();
|
||||
if (StringUtils.isNotEmpty(giftDuration)) {
|
||||
checkDuration(giftDuration, createReqVO.getGiftDurationUnit());
|
||||
}
|
||||
|
||||
createReqVO.setDuration(duration)
|
||||
.setGiftDuration(giftDuration);
|
||||
|
||||
// 校验现价计算是否正确
|
||||
calculateDiscount(createReqVO.getOriginalPrice(), createReqVO.getCurrentPrice(), createReqVO.getDiscount());
|
||||
// 查询是否有重复的定价
|
||||
checkProductDetails(createReqVO);
|
||||
|
||||
} else if (createReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
|
||||
if (StringUtils.isBlank(createReqVO.getDuration())) {
|
||||
throw exception(PRODUCTS_OUTPUT_NOT_NULL);
|
||||
}
|
||||
// todo 暂不支持产量
|
||||
throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
|
||||
}
|
||||
|
||||
Long id = idWorker.nextId();
|
||||
createReqVO.setId(id);
|
||||
ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class).setId(id);
|
||||
ProductsDetailDO productDetailsDO = BeanUtils.toBean(createReqVO, ProductsDetailDO.class);
|
||||
productDetailsMapper.insert(productDetailsDO);
|
||||
return id;
|
||||
|
||||
return productDetailsDO.getId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void update(ProductDetailsSaveReqVO updateReqVO) {
|
||||
|
||||
@@ -100,45 +79,25 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
|
||||
validateProductDetailsExists(updateReqVO.getId());
|
||||
|
||||
if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) {
|
||||
|
||||
if (StringUtils.isBlank(updateReqVO.getDuration())) {
|
||||
throw exception(PRODUCTS_DURATION_NOT_NULL);
|
||||
}
|
||||
// 校验时长
|
||||
String duration = checkDuration(updateReqVO.getDuration());
|
||||
String giftDuration = null;
|
||||
if (updateReqVO.getGiftDuration() != null) {
|
||||
giftDuration = checkDuration(updateReqVO.getGiftDuration());
|
||||
checkDuration(updateReqVO.getDuration(), updateReqVO.getDurationUnit());
|
||||
// 校验赠送时长
|
||||
String giftDuration = updateReqVO.getGiftDuration();
|
||||
if (StringUtils.isNotEmpty(giftDuration)) {
|
||||
checkDuration(giftDuration, updateReqVO.getGiftDurationUnit());
|
||||
}
|
||||
updateReqVO.setDuration(duration).setGiftDuration(giftDuration);
|
||||
|
||||
// 校验现价计算是否正确
|
||||
calculateDiscount(updateReqVO.getOriginalPrice(), updateReqVO.getCurrentPrice(), updateReqVO.getDiscount());
|
||||
// 校验同时长是否还有其他的定价规则
|
||||
checkProductDetails(updateReqVO);
|
||||
|
||||
|
||||
} else if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.OUTPUT.getStatus())) {
|
||||
if (StringUtils.isBlank(updateReqVO.getDuration())) {
|
||||
throw exception(PRODUCTS_OUTPUT_NOT_NULL);
|
||||
}
|
||||
// todo 暂不支持产量
|
||||
throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT);
|
||||
}
|
||||
|
||||
ProductsDetailDO productDetailsDO = 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);
|
||||
productDetailsMapper.updateById(BeanUtils.toBean(updateReqVO, ProductsDetailDO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,12 +119,12 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
|
||||
|
||||
@Override
|
||||
public PageResult<ProductsDetailDO> getPage(ProductDetailsPageReqVO pageReqVO) {
|
||||
return productDetailsMapper.selectPage(pageReqVO.setDeleted(0));
|
||||
return productDetailsMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private ProductsDetailDO validateProductDetailsExists(Long id) {
|
||||
@Override
|
||||
public ProductsDetailDO validateProductDetailsExists(Long id) {
|
||||
if (id == null) {
|
||||
throw exception(PRODUCTS_DETAIL_NO_EXIST);
|
||||
}
|
||||
@@ -182,75 +141,64 @@ public class ProductsDetailServiceImpl implements ProductsDetailService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 时长校验
|
||||
private String checkDuration(String duration){
|
||||
|
||||
if (duration == null || !duration.contains("-")) {
|
||||
throw new IllegalArgumentException("格式错误,格式为:时长值-单位,例如 10-月");
|
||||
}
|
||||
|
||||
String[] parts = duration.split("-", 2);
|
||||
String valueStr = parts[0].trim();
|
||||
String timeUnit = parts[1].trim();
|
||||
/**
|
||||
* 校验时长
|
||||
*
|
||||
* @param duration
|
||||
* @param timeUnit
|
||||
* @return
|
||||
*/
|
||||
private void checkDuration(String duration, Integer timeUnit) {
|
||||
AssertUtils.notEmpty(duration, PRODUCTS_DURATION_NOT_NULL);
|
||||
AssertUtils.notEmpty(timeUnit, PRODUCTS_DURATION_NOT_NULL);
|
||||
|
||||
// 校验时长值
|
||||
if (valueStr.isEmpty() || !valueStr.matches("^\\d+$")) {
|
||||
if (!duration.matches("^\\d+$")) {
|
||||
throw exception(PRODUCTS_DURATION_INT_ERR);
|
||||
}
|
||||
|
||||
// 去除前导 0
|
||||
valueStr = valueStr.replaceFirst("^0+(?!$)", "");
|
||||
|
||||
int timeValue = Integer.parseInt(valueStr);
|
||||
int timeValue = Integer.parseInt(duration);
|
||||
if (timeValue <= 0) {
|
||||
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>()
|
||||
.eq(ProductsDO::getId, productId)
|
||||
.eq(ProductsDO::getDeleted, false));
|
||||
|
||||
AssertUtils.notEmpty(productsDO,PRODUCTS_NO_EXIST);
|
||||
AssertUtils.notEmpty(productsDO, PRODUCTS_NO_EXIST);
|
||||
|
||||
if(productsDO.getStatus().equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())){
|
||||
if (productsDO.getStatus().equals(ProductStatusEnum.PRODUCT_UPDATES.getStatus())) {
|
||||
throw exception(PRODUCTS_DETAIL_NO_UPDATE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 时长/产量去重
|
||||
private void checkProductDetails(ProductDetailsSaveReqVO createReqVO){
|
||||
/**
|
||||
* 检查产品下是否有相同时长的规则
|
||||
*
|
||||
* @param createReqVO
|
||||
*/
|
||||
private void checkProductDetails(ProductDetailsSaveReqVO createReqVO) {
|
||||
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) {
|
||||
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) {
|
||||
//产量去重
|
||||
count = productDetailsMapper.selectCountByOutput(createReqVO.getOutput(), createReqVO.getProductId());
|
||||
if (count > 0) {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+41
-27
@@ -1,6 +1,5 @@
|
||||
package com.cf.imes.module.system.service.funds.products;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.cf.imes.framework.common.pojo.PageResult;
|
||||
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.mysql.funds.products.ProductsMapper;
|
||||
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.validation.annotation.Validated;
|
||||
|
||||
@@ -27,44 +26,42 @@ import static com.cf.imes.module.system.enums.ErrorCodeConstants.*;
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductsServiceImpl implements ProductsService{
|
||||
public class ProductsServiceImpl implements ProductsService {
|
||||
|
||||
@Resource
|
||||
private ProductsMapper productsMapper;
|
||||
|
||||
@Resource
|
||||
private SnowflakeIdWorker3rd idWorker;
|
||||
|
||||
@Override
|
||||
public Long create(String productName) {
|
||||
// 校验产品名称唯一
|
||||
validateProductNameUnique(null, productName);
|
||||
|
||||
List<ProductsDO> productsDOS = productsMapper.selectList(new LambdaQueryWrapperX<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)
|
||||
.setStatus(ProductStatusEnum.PRODUCT_WAITING_UPDATES.getStatus())
|
||||
.setSoftwareId(0)
|
||||
);
|
||||
return id;
|
||||
ProductsDO productsDO = new ProductsDO()
|
||||
.setProductName(productName)
|
||||
.setStatus(ProductStatusEnum.PRODUCT_WAITING_UPDATES.getStatus())
|
||||
.setSoftwareId(0);
|
||||
productsMapper.insert(productsDO);
|
||||
return productsDO.getId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
productsMapper.updateById(updateReqVO);
|
||||
@@ -99,8 +96,12 @@ public class ProductsServiceImpl implements ProductsService{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 校验产品id是否存在
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
private ProductsDO validateProductPlateExists(Long id) {
|
||||
ProductsDO productsDO = productsMapper.selectOne(new LambdaQueryWrapperX<ProductsDO>()
|
||||
.eq(ProductsDO::getId, id)
|
||||
@@ -112,6 +113,19 @@ public class ProductsServiceImpl implements ProductsService{
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-7
@@ -1,8 +1,8 @@
|
||||
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.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;
|
||||
|
||||
@@ -14,13 +14,18 @@ import java.util.Map;
|
||||
*/
|
||||
public interface PayOrderService {
|
||||
/**
|
||||
* 发起支付
|
||||
* 产品支付
|
||||
*
|
||||
* @param payOrderUnifiedReqVO
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
* @param payProductOrderUnifiedReqVO
|
||||
*/
|
||||
PayOrderRespDTO initiatePay(PayOrderUnifiedReqVO payOrderUnifiedReqVO);
|
||||
void productPay(PayProductOrderUnifiedReqVO payProductOrderUnifiedReqVO);
|
||||
|
||||
/**
|
||||
* 账户充值支付
|
||||
*
|
||||
* @param payRechargeOrderReqVO
|
||||
*/
|
||||
PayOrderRespDTO rechargePay(PayRechargeOrderReqVO payRechargeOrderReqVO);
|
||||
|
||||
/**
|
||||
* 查询支付订单支付状态
|
||||
|
||||
+52
-17
@@ -10,18 +10,26 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import com.cf.imes.framework.common.exception.ServiceException;
|
||||
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.validation.ValidationUtils;
|
||||
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
|
||||
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.PayOrderUnifiedReqDTO;
|
||||
import com.cf.imes.framework.common.exception.PayException;
|
||||
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.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.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.mysql.pay.PayOrderMapper;
|
||||
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.validation.Validator;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
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_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_RECHARGE_ORDER_ORGANID_CHECK_ERROR;
|
||||
|
||||
/**
|
||||
* 支付订单接口 实现类
|
||||
@@ -69,18 +80,43 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
@Resource
|
||||
private ChenfengAlipayConfig alipayConfig;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public PayOrderRespDTO initiatePay(PayOrderUnifiedReqVO payOrderUnifiedReqVO) {
|
||||
// 主动校验一次入参
|
||||
ValidationUtils.validate(validator, payOrderUnifiedReqVO);
|
||||
@Resource
|
||||
private ChenfengPayConfig payConfig;
|
||||
|
||||
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);
|
||||
|
||||
// 创建支付订单
|
||||
PayOrderDO payOrder = createPayOrder(payOrderUnifiedReqVO);
|
||||
PayOrderDO payOrder = createPayOrder(payRechargeOrderReqVO.getPrice(), "imes充值", channelCode);
|
||||
payOrderMapper.insert(payOrder);
|
||||
|
||||
// 发起渠道方支付
|
||||
@@ -99,23 +135,22 @@ public class PayOrderServiceImpl implements PayOrderService {
|
||||
/**
|
||||
* 创建支付订单
|
||||
*
|
||||
* @param payOrderUnifiedReqVO
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
private PayOrderDO createPayOrder(PayOrderUnifiedReqVO payOrderUnifiedReqVO) {
|
||||
private PayOrderDO createPayOrder(BigDecimal price, String subject, Integer channelCode) {
|
||||
PayOrderDO payOrderDO = new PayOrderDO();
|
||||
|
||||
// 校验获取组织id
|
||||
Long organId = validOrganId();
|
||||
|
||||
Long payOrderId = IdUtil.getSnowflake(0, 0).nextId();
|
||||
Long organId = SecurityFrameworkUtils.getUserOrganId();
|
||||
|
||||
payOrderDO.setId(payOrderId);
|
||||
payOrderDO.setPayNo(String.format(PAY_ORDER_PREFIX_FORMAT, organId, payOrderId, DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN)));
|
||||
payOrderDO.setStatus(PayOrderStatusEnum.WAITING);
|
||||
payOrderDO.setExpireTime(payOrderUnifiedReqVO.getExpireTime());
|
||||
payOrderDO.setPrice(payOrderUnifiedReqVO.getPrice());
|
||||
payOrderDO.setSubject(payOrderUnifiedReqVO.getSubject());
|
||||
payOrderDO.setChannelCode(PayChannelCodeEnum.fromType(payOrderUnifiedReqVO.getChannelCode()));
|
||||
payOrderDO.setExpireTime(LocalDateTime.now().plus(payConfig.getPayExpireTime()));
|
||||
payOrderDO.setPrice(price);
|
||||
payOrderDO.setSubject(subject);
|
||||
payOrderDO.setChannelCode(PayChannelCodeEnum.fromType(channelCode));
|
||||
payOrderDO.setOrganId(organId);
|
||||
return payOrderDO;
|
||||
}
|
||||
|
||||
+8
@@ -5,6 +5,7 @@ import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.CharSequenceUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.hutool.http.Method;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayTradePagePayModel;
|
||||
@@ -27,6 +28,7 @@ import jakarta.annotation.Resource;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
@@ -60,6 +62,12 @@ public class AlipayPcPayHandler extends AbstractPayHandler {
|
||||
model.setProductCode(alipayConfig.getProductCode());
|
||||
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 请求
|
||||
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
|
||||
request.setBizModel(model);
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import java.lang.annotation.Target;
|
||||
validatedBy = {PayChannelCodeValidator.class}
|
||||
)
|
||||
public @interface PayChannelCodeValid {
|
||||
String message() default "不支持的支付渠道,0:支付宝、1:微信";
|
||||
String message() default "不支持的支付渠道";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
|
||||
+31
@@ -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 {};
|
||||
}
|
||||
+27
@@ -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;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ import java.lang.annotation.*;
|
||||
)
|
||||
public @interface ProductType {
|
||||
|
||||
String message() default "购买方式:0 时长;1 产量";
|
||||
String message() default "购买方式不合法:0 时长;1 产量";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
|
||||
+32
@@ -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 {};
|
||||
}
|
||||
+30
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user