diff --git a/cash-api/market-server/src/main/java/com/czg/controller/admin/RechargeRedemptionController.java b/cash-api/market-server/src/main/java/com/czg/controller/admin/RechargeRedemptionController.java new file mode 100644 index 00000000..816c7cb7 --- /dev/null +++ b/cash-api/market-server/src/main/java/com/czg/controller/admin/RechargeRedemptionController.java @@ -0,0 +1,118 @@ +package com.czg.controller.admin; + +import com.czg.annotation.SaAdminCheckPermission; +import com.czg.annotation.SaCheckMainShop; +import com.czg.constant.TableValueConstant; +import com.czg.market.dto.MkRechargeRedemptionConfigDTO; +import com.czg.market.entity.MkRechargeRedemptionConfig; +import com.czg.market.service.MkEnableConfigService; +import com.czg.market.service.MkRechargeRedemptionConfigService; +import com.czg.market.vo.MkRechargeRedemptionCodeVO; +import com.czg.market.vo.MkRechargeRedemptionConfigVO; +import com.czg.resp.CzgResult; +import com.czg.sa.StpKit; +import com.czg.validator.group.UpdateGroup; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.groups.Default; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * + * 充值兑换相关 + * @author Administrator + */ +@RestController +@RequestMapping("/admin/rechargeRedemption") +public class RechargeRedemptionController { + @Resource + private MkRechargeRedemptionConfigService configService; + @Resource + private MkEnableConfigService enableConfigService; + + /** + * 配置开关 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:enable", name = "充值兑换状态修改") + @PutMapping("/{enable}") + public CzgResult upEnable(@PathVariable Integer enable) { + return CzgResult.success(enableConfigService.upEnable(StpKit.USER.getMainShopId(),StpKit.USER.getLoginIdAsLong(), enable, TableValueConstant.EnableConfig.Type.RECHARGE_REDEMPTION)); + } + + /** + * 开关状态 + */ + @GetMapping("/enable/status") + public CzgResult upEnable() { + return CzgResult.success(enableConfigService.detail(StpKit.USER.getMainShopId(), StpKit.USER.getLoginIdAsLong(), TableValueConstant.EnableConfig.Type.RECHARGE_REDEMPTION)); + } + + /** + * 配置信息详情 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:detail", name = "充值兑换列表") + @GetMapping + public CzgResult detail(@RequestParam Integer id) { + return CzgResult.success(configService.getOneAs(new QueryWrapper().eq(MkRechargeRedemptionConfig::getId, id) + .eq(MkRechargeRedemptionConfig::getMainShopId, StpKit.USER.getMainShopId()), MkRechargeRedemptionConfigVO.class)); + } + + /** + * 配置信息获取 列表 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:list", name = "充值兑换列表") + @GetMapping("/list") + public CzgResult> list(@RequestParam(required = false, defaultValue = "-1") Integer status) { + return CzgResult.success(configService.pageInfo(StpKit.USER.getMainShopId(), status)); + } + + /** + * 配置信息添加 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:add", name = "充值兑换配置添加") + @PostMapping + @SaCheckMainShop + public CzgResult add(@Validated @RequestBody MkRechargeRedemptionConfigDTO dto) { + return CzgResult.success(configService.add(StpKit.USER.getMainShopId(), dto)); + } + + /** + * 配置信息修改 + * + * @return 是否成功 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:edit", name = "充值兑换修改") + @SaCheckMainShop + @PutMapping + public CzgResult edit(@Validated({UpdateGroup.class, Default.class}) @RequestBody MkRechargeRedemptionConfigDTO dto) { + return CzgResult.success(configService.edit(StpKit.USER.getShopId(), dto)); + } + + /** + * 充值兑换码列表 + * + * @return 是否成功 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:codeList", name = "充值兑换码列表") + @SaCheckMainShop + @GetMapping("/code/list") + public CzgResult> codeList(@RequestParam Long redemptionId, @RequestParam(required = false) String code, @RequestParam(required = false) Integer status) { + return CzgResult.success(configService.codeList(StpKit.USER.getMainShopId(), redemptionId, code, status)); + } + + /** + * 充值兑换码导出 + */ + @SaAdminCheckPermission(value = "rechargeRedemption:codeExport", name = "充值兑换码列表导出") + @SaCheckMainShop + @GetMapping("/code/export") + public void exportCodeList(@RequestParam Long redemptionId, @RequestParam(required = false) String code, @RequestParam(required = false) Integer status, + HttpServletResponse response, HttpServletRequest request) { + configService.exportCodeList(StpKit.USER.getMainShopId(), redemptionId, code, status, response, request); + } + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkRechargeRedemptionConfigDTO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkRechargeRedemptionConfigDTO.java new file mode 100644 index 00000000..7d77de42 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/dto/MkRechargeRedemptionConfigDTO.java @@ -0,0 +1,67 @@ +package com.czg.market.dto; + +import com.czg.market.entity.ShopCoupon; +import com.czg.validator.group.UpdateGroup; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.*; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author Administrator + */ +@Data +public class MkRechargeRedemptionConfigDTO implements Serializable { + + + @NotNull(message = "id不能为空", groups = UpdateGroup.class) + private Long id; + + /** + * 名称 + */ + @NotBlank(message = "名称不能为空") + private String name; + + /** + * 赠送金额 + */ + @NotNull(message = "赠送金额不能为空") + @DecimalMin(value = "0.01", message = "赠送金额不能小于0.01") + private BigDecimal amount; + + /** + * 库存 + */ + + private Integer stock; + + /** + * 总数 + */ + @Min(value = 0, message = "总数不能小于0") + @NotNull(message = "总数不能为空") + @Max(value = 1000, message = "总数不能大于1000") + private Integer total; + + /** + * 可用开始时间 + */ + private LocalDateTime startTime; + + /** + * 可用结束时间 + */ + private LocalDateTime endTime; +} + diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkEnableConfig.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkEnableConfig.java new file mode 100644 index 00000000..f3b9be72 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkEnableConfig.java @@ -0,0 +1,62 @@ +package com.czg.market.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 兑换码明细 实体类。 + * + * @author zs + * @since 2025-10-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_enable_config") +public class MkEnableConfig implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 主店id + */ + private Long mainShopId; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 模块类型 + */ + private String type; + + private Integer isEnable; + + private Long shopId; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionCode.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionCode.java new file mode 100644 index 00000000..a0a42b3c --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionCode.java @@ -0,0 +1,85 @@ +package com.czg.market.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * 兑换码明细 实体类。 + * + * @author zs + * @since 2025-10-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_recharge_redemption_code") +@Accessors(chain = true) +public class MkRechargeRedemptionCode implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 兑换配置id + */ + private Long redemptionId; + + /** + * 主店id + */ + private Long mainShopId; + + /** + * 兑换时间 + */ + private LocalDateTime redemptionTime; + + /** + * 0未兑换 1已兑换 + */ + private Integer status; + + /** + * 店铺用户id + */ + private Long shopUserId; + + /** + * 用户id + */ + private Long userId; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 兑换码 + */ + private String code; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionConfig.java b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionConfig.java new file mode 100644 index 00000000..d8e2d023 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/entity/MkRechargeRedemptionConfig.java @@ -0,0 +1,88 @@ +package com.czg.market.entity; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import java.io.Serial; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +/** + * 充值优惠券修改 实体类。 + * + * @author zs + * @since 2025-10-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Table("mk_recharge_redemption_config") +@Accessors(chain = true) +public class MkRechargeRedemptionConfig implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 赠送金额 + */ + private BigDecimal amount; + + /** + * 库存 + */ + private Integer stock; + + /** + * 总数 + */ + private Integer total; + + /** + * 可用开始时间 + */ + private LocalDateTime startTime; + + /** + * 可用结束时间 + */ + private LocalDateTime endTime; + + /** + * 门店id + */ + private Long mainShopId; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + + @Column(ignore = true) + private Integer status; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkEnableConfigService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkEnableConfigService.java new file mode 100644 index 00000000..58c3dff6 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkEnableConfigService.java @@ -0,0 +1,17 @@ +package com.czg.market.service; + +import com.czg.constant.TableValueConstant; +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkEnableConfig; + +/** + * 兑换码明细 服务层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkEnableConfigService extends IService { + + Boolean upEnable(Long mainShopId, Long shopId, Integer enable, TableValueConstant.EnableConfig.Type type); + Integer detail(Long mainShopId, Long shopId, TableValueConstant.EnableConfig.Type type); +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionCodeService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionCodeService.java new file mode 100644 index 00000000..47eae45e --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionCodeService.java @@ -0,0 +1,14 @@ +package com.czg.market.service; + +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkRechargeRedemptionCode; + +/** + * 兑换码明细 服务层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkRechargeRedemptionCodeService extends IService { + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionConfigService.java b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionConfigService.java new file mode 100644 index 00000000..4877e269 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/service/MkRechargeRedemptionConfigService.java @@ -0,0 +1,31 @@ +package com.czg.market.service; + +import com.czg.market.dto.MkRechargeRedemptionConfigDTO; +import com.czg.market.vo.MkRechargeRedemptionCodeVO; +import com.czg.market.vo.MkRechargeRedemptionConfigVO; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.service.IService; +import com.czg.market.entity.MkRechargeRedemptionConfig; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * 充值优惠券修改 服务层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkRechargeRedemptionConfigService extends IService { + + MkRechargeRedemptionConfigVO detail(Long mainShopId); + + Boolean edit(Long shopId, MkRechargeRedemptionConfigDTO dto); + + boolean add(Long mainShopId, MkRechargeRedemptionConfigDTO dto); + + Page pageInfo(Long mainShopId, Integer status); + + Page codeList(Long mainShopId, Long id, String code, Integer status); + + void exportCodeList(Long mainShopId, Long redemptionId, String code, Integer status, HttpServletResponse response, HttpServletRequest request); +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionCodeVO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionCodeVO.java new file mode 100644 index 00000000..c7451c59 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionCodeVO.java @@ -0,0 +1,89 @@ +package com.czg.market.vo; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.KeyType; +import com.mybatisflex.annotation.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serial; +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 兑换码明细 实体类。 + * + * @author zs + * @since 2025-10-21 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class MkRechargeRedemptionCodeVO implements Serializable { + + @Id(keyType = KeyType.Auto) + private Long id; + + /** + * 兑换配置id + */ + private Long redemptionId; + + /** + * 主店id + */ + private Long mainShopId; + + /** + * 兑换时间 + */ + private LocalDateTime redemptionTime; + + /** + * 0未兑换 1已兑换 + */ + private Integer status; + + /** + * 店铺用户id + */ + private Long shopUserId; + + /** + * 用户id + */ + private Long userId; + + /** + * 创建时间 + */ + @Column(onInsertValue = "now()") + private LocalDateTime createTime; + + /** + * 修改时间 + */ + @Column(onInsertValue = "now()", onUpdateValue = "now()") + private LocalDateTime updateTime; + + /** + * 兑换码 + */ + private String code; + + /** + * 用户昵称 + */ + private String nickName; + /** + * 用户手机号 + */ + private String phone; + +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionConfigVO.java b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionConfigVO.java new file mode 100644 index 00000000..0db0c2e3 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/market/vo/MkRechargeRedemptionConfigVO.java @@ -0,0 +1,25 @@ +package com.czg.market.vo; + +import com.czg.market.dto.MemberConfigDTO; +import com.czg.market.entity.MkRechargeRedemptionConfig; +import jakarta.validation.Valid; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author Administrator + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class MkRechargeRedemptionConfigVO extends MkRechargeRedemptionConfig implements Serializable { + +} diff --git a/cash-common/cash-common-tools/src/main/java/com/czg/constant/TableValueConstant.java b/cash-common/cash-common-tools/src/main/java/com/czg/constant/TableValueConstant.java index c769b7f8..4edd105e 100644 --- a/cash-common/cash-common-tools/src/main/java/com/czg/constant/TableValueConstant.java +++ b/cash-common/cash-common-tools/src/main/java/com/czg/constant/TableValueConstant.java @@ -22,6 +22,23 @@ public interface TableValueConstant { } } + } + interface EnableConfig { + @Getter + enum Type { + RECHARGE_REDEMPTION("RECHARGE_REDEMPTION", "充值兑换"), + PAY("PAY", "购买会员增积分"), + MEMBER_TASK("MEMBER_TASK", "会员周奖励"), + COST("COST", "消费增积分"); + private final String code; + private final String msg; + + Type(String code, String msg) { + this.code = code; + this.msg = msg; + } + } + } interface ConsumeDiscount { diff --git a/cash-dependencies/pom.xml b/cash-dependencies/pom.xml index f5bf5ea6..818ad28a 100644 --- a/cash-dependencies/pom.xml +++ b/cash-dependencies/pom.xml @@ -40,10 +40,16 @@ 3.5.3 3.8.0 2.5.1 + 2.9.10 + + com.github.javen205 + IJPay-All + ${IJPay.version} + com.belerweb pinyin4j diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkEnableConfigMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkEnableConfigMapper.java new file mode 100644 index 00000000..73436fb4 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkEnableConfigMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkEnableConfig; + +/** + * 兑换码明细 映射层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkEnableConfigMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionCodeMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionCodeMapper.java new file mode 100644 index 00000000..6cf3a54a --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionCodeMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkRechargeRedemptionCode; + +/** + * 兑换码明细 映射层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkRechargeRedemptionCodeMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionConfigMapper.java b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionConfigMapper.java new file mode 100644 index 00000000..22822da7 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/mapper/MkRechargeRedemptionConfigMapper.java @@ -0,0 +1,14 @@ +package com.czg.service.market.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.czg.market.entity.MkRechargeRedemptionConfig; + +/** + * 充值优惠券修改 映射层。 + * + * @author zs + * @since 2025-10-21 + */ +public interface MkRechargeRedemptionConfigMapper extends BaseMapper { + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkEnableConfigServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkEnableConfigServiceImpl.java new file mode 100644 index 00000000..7304edc6 --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkEnableConfigServiceImpl.java @@ -0,0 +1,48 @@ +package com.czg.service.market.service.impl; + +import com.czg.constant.TableValueConstant; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkEnableConfig; +import com.czg.market.service.MkEnableConfigService; +import com.czg.service.market.mapper.MkEnableConfigMapper; +import org.springframework.stereotype.Service; + +/** + * 兑换码明细 服务层实现。 + * + * @author zs + * @since 2025-10-21 + */ +@Service +public class MkEnableConfigServiceImpl extends ServiceImpl implements MkEnableConfigService{ + + @Override + public Integer detail(Long mainShopId, Long shopId, TableValueConstant.EnableConfig.Type type) { + MkEnableConfig one = getOne(new QueryWrapper().eq(MkEnableConfig::getMainShopId, mainShopId).eq(MkEnableConfig::getType, type.getCode())); + if (one == null) { + one = new MkEnableConfig(); + one.setMainShopId(mainShopId); + one.setIsEnable(1); + one.setShopId(shopId); + save(one); + } + return one.getIsEnable(); + } + + @Override + public Boolean upEnable(Long mainShopId, Long shopId, Integer enable, TableValueConstant.EnableConfig.Type type) { + MkEnableConfig one = getOne(new QueryWrapper().eq(MkEnableConfig::getMainShopId, mainShopId).eq(MkEnableConfig::getType, type.getCode())); + if (one == null) { + one = new MkEnableConfig(); + one.setMainShopId(mainShopId); + one.setIsEnable(enable); + one.setShopId(shopId); + save(one); + }else { + one.setIsEnable(enable); + updateById(one); + } + return true; + } +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionCodeServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionCodeServiceImpl.java new file mode 100644 index 00000000..a891583f --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionCodeServiceImpl.java @@ -0,0 +1,18 @@ +package com.czg.service.market.service.impl; + +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkRechargeRedemptionCode; +import com.czg.market.service.MkRechargeRedemptionCodeService; +import com.czg.service.market.mapper.MkRechargeRedemptionCodeMapper; +import org.springframework.stereotype.Service; + +/** + * 兑换码明细 服务层实现。 + * + * @author zs + * @since 2025-10-21 + */ +@Service +public class MkRechargeRedemptionCodeServiceImpl extends ServiceImpl implements MkRechargeRedemptionCodeService{ + +} diff --git a/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionConfigServiceImpl.java b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionConfigServiceImpl.java new file mode 100644 index 00000000..980c570e --- /dev/null +++ b/cash-service/market-service/src/main/java/com/czg/service/market/service/impl/MkRechargeRedemptionConfigServiceImpl.java @@ -0,0 +1,233 @@ +package com.czg.service.market.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.ExcelUtil; +import cn.hutool.poi.excel.ExcelWriter; +import com.czg.account.entity.ShopUser; +import com.czg.exception.CzgException; +import com.czg.market.dto.MkRechargeRedemptionConfigDTO; +import com.czg.market.entity.MkRechargeRedemptionCode; +import com.czg.market.service.MkRechargeRedemptionCodeService; +import com.czg.market.vo.MkRechargeRedemptionCodeVO; +import com.czg.market.vo.MkRechargeRedemptionConfigVO; +import com.czg.utils.AssertUtil; +import com.czg.utils.MyQueryWrapper; +import com.czg.utils.PageUtil; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.czg.market.entity.MkRechargeRedemptionConfig; +import com.czg.market.service.MkRechargeRedemptionConfigService; +import com.czg.service.market.mapper.MkRechargeRedemptionConfigMapper; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Service; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.*; + +/** + * 充值优惠券修改 服务层实现。 + * + * @author zs + * @since 2025-10-21 + */ +@Service +public class MkRechargeRedemptionConfigServiceImpl extends ServiceImpl implements MkRechargeRedemptionConfigService{ + @Resource + private MkRechargeRedemptionCodeService codeService; + + /** + * 生成指定活动的兑换码集合 + * @param activityId 活动ID + * @param count 生成数量(≤1000) + */ + public static Set generateCodes(long activityId, int count) { + Set codes = new HashSet<>(); + + String actPart = String.format("%03d", activityId % 1000); + + while (codes.size() < count) { + String patternPart = generatePatternNumber(); + String code = actPart + patternPart; + codes.add(code); + } + return codes; + } + + /** + * 生成“有规律”的9位数字串 + * 包含连续或重复数字,提升记忆性 + */ + private static String generatePatternNumber() { + // 随机选择模式类型 + int mode = RandomUtil.randomInt(1, 4); + + switch (mode) { + case 1: + // 连续上升(如 123456789, 456789123) + int start = RandomUtil.randomInt(0, 5); + StringBuilder sb1 = new StringBuilder(); + for (int i = 0; i < 9; i++) { + sb1.append((start + i) % 10); + } + return sb1.toString(); + + case 2: + // 连续下降(如 987654321, 654321987) + int down = RandomUtil.randomInt(3, 9); + StringBuilder sb2 = new StringBuilder(); + for (int i = 0; i < 9; i++) { + sb2.append((down - i + 10) % 10); + } + return sb2.toString(); + + case 3: + // 带重复数字(如 112233445, 778899001) + String base = RandomUtil.randomNumbers(3); + String repeat = "%s%s%s%s%s%s".formatted(base.charAt(0), base.charAt(0), base.charAt(1), base.charAt(1), base.charAt(2), base.charAt(2)); + // 补3位随机数 + return (repeat + RandomUtil.randomNumbers(3)).substring(0, 9); + + default: + return RandomUtil.randomNumbers(9); + } + } + + public static void main(String[] args) { + Set codes = generateCodes(12, 1000); + codes.forEach(System.out::println); + } + + + @Override + public MkRechargeRedemptionConfigVO detail(Long mainShopId) { + return getOneAs(new QueryWrapper().eq(MkRechargeRedemptionConfig::getMainShopId, mainShopId), MkRechargeRedemptionConfigVO.class); + } + + @Override + public Page pageInfo(Long mainShopId, Integer status) { + QueryWrapper queryWrapper = new QueryWrapper().eq(MkRechargeRedemptionConfig::getMainShopId, mainShopId); + switch (status) { + case 0: + queryWrapper.le(MkRechargeRedemptionConfig::getStartTime, DateUtil.date()).ge(MkRechargeRedemptionConfig::getEndTime, DateUtil.date()); + break; + case 1: + queryWrapper.gt(MkRechargeRedemptionConfig::getStartTime, DateUtil.date()).lt(MkRechargeRedemptionConfig::getEndTime, DateUtil.date()); + break; + } + Page page = page(PageUtil.buildPage(), queryWrapper); + page.getRecords().forEach(item -> { + if (item.getStartTime() != null && item.getEndTime() != null) { + item.setStatus(!item.getStartTime().isAfter(DateUtil.date().toLocalDateTime()) && item.getEndTime().isBefore(DateUtil.date().toLocalDateTime()) ? 0 : 1); + }else { + item.setStatus(0); + } + }); + + return page; + } + + @Override + public boolean add(Long mainShopId, MkRechargeRedemptionConfigDTO dto) { + long count = count(new QueryWrapper().eq(MkRechargeRedemptionConfig::getName, dto.getName()).eq(MkRechargeRedemptionConfig::getMainShopId, mainShopId)); + AssertUtil.isTrue(count > 0, "名称已存在"); + MkRechargeRedemptionConfig config = BeanUtil.copyProperties(dto, MkRechargeRedemptionConfig.class); + config.setMainShopId(mainShopId); + save(config); + + ArrayList codeArrayList = new ArrayList<>(); + generateCodes(config.getId(), config.getTotal()).forEach(code -> { + codeArrayList.add(new MkRechargeRedemptionCode().setRedemptionId(config.getId()) + .setMainShopId(mainShopId).setCode(code)); + }); + + return codeService.saveBatch(codeArrayList); + } + + @Override + public Boolean edit(Long shopId, MkRechargeRedemptionConfigDTO dto) { + MkRechargeRedemptionConfig config = getOne(new QueryWrapper().eq(MkRechargeRedemptionConfig::getMainShopId, shopId).eq(MkRechargeRedemptionConfig::getId, dto.getId())); + AssertUtil.isNull(config, "活动不存在"); + if (dto.getStock() != null) { + if (config.getStock() < dto.getStock()) { + throw new CzgException("库存仅允许删减"); + } + int subStock = config.getStock() - dto.getStock(); + List subCodeList = codeService.list(new QueryWrapper().eq(MkRechargeRedemptionCode::getRedemptionId, config.getId()).eq(MkRechargeRedemptionCode::getStatus, 0).limit(subStock)); + subCodeList.forEach(item -> item.setStatus(1)); + codeService.updateBatch(subCodeList); + } + + BeanUtil.copyProperties(dto, config, "total", "amount", "startTime", "endTime"); + return updateById(config); + } + + @Override + public Page codeList(Long mainShopId, Long id, String code, Integer status) { + QueryWrapper queryWrapper = new MyQueryWrapper() + .selectAll(MkRechargeRedemptionCode.class) + .select(ShopUser::getNickName, ShopUser::getPhone) + .eq(MkRechargeRedemptionCode::getMainShopId, mainShopId) + .eq(MkRechargeRedemptionCode::getRedemptionId, id); + queryWrapper.eq(MkRechargeRedemptionCode::getStatus, status); + if (StrUtil.isNotBlank(code)) { + queryWrapper.like(MkRechargeRedemptionCode::getCode, code); + } + queryWrapper.leftJoin(ShopUser.class).on(ShopUser::getId, MkRechargeRedemptionCode::getShopUserId); + return codeService.pageAs(PageUtil.buildPage(), queryWrapper, MkRechargeRedemptionCodeVO.class); + } + + @Override + public void exportCodeList(Long mainShopId, Long redemptionId, String code, Integer status, HttpServletResponse response, HttpServletRequest request) { + QueryWrapper queryWrapper = new MyQueryWrapper() + .selectAll(MkRechargeRedemptionCode.class) + .select(ShopUser::getNickName, ShopUser::getPhone) + .eq(MkRechargeRedemptionCode::getMainShopId, mainShopId) + .eq(MkRechargeRedemptionCode::getRedemptionId, redemptionId); + queryWrapper.eq(MkRechargeRedemptionCode::getStatus, status); + if (StrUtil.isNotBlank(code)) { + queryWrapper.like(MkRechargeRedemptionCode::getCode, code); + } + queryWrapper.leftJoin(ShopUser.class).on(ShopUser::getId, MkRechargeRedemptionCode::getShopUserId); + List mkRechargeRedemptionCodeVOS = codeService.listAs(queryWrapper, MkRechargeRedemptionCodeVO.class); + + List> list = mkRechargeRedemptionCodeVOS.stream() + .map(item -> { + Map map = new HashMap<>(); + map.put("code", item.getCode()); + map.put("redemptionTime", item.getRedemptionTime()); + map.put("userInfo", item.getShopUserId() == null ? "" : item.getNickName() + " " + item.getPhone()); + return map; + }) + .toList(); + // 1. 创建 ExcelWriter + ExcelWriter writer = ExcelUtil.getWriter(true); + + // 2. 自定义标题别名(可选) + + // 3. 写入数据 + + // 4. 设置响应头,告诉浏览器下载文件 + try (writer) { + writer.addHeaderAlias("code", "兑换码"); + writer.addHeaderAlias("redemptionTime", "兑换时间"); + writer.addHeaderAlias("userInfo", "用户信息"); + writer.write(list, true); + response.setContentType("application/vnd.ms-excel;charset=utf-8"); + String fileName; + fileName = URLEncoder.encode("兑换码", StandardCharsets.UTF_8); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); + // 5. 输出到浏览器 + writer.flush(response.getOutputStream(), true); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } +} diff --git a/cash-service/market-service/src/main/resources/mapper/MkEnableConfigMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkEnableConfigMapper.xml new file mode 100644 index 00000000..735d0a10 --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkEnableConfigMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionCodeMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionCodeMapper.xml new file mode 100644 index 00000000..c4ce4100 --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionCodeMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionConfigMapper.xml b/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionConfigMapper.xml new file mode 100644 index 00000000..6ffbb7d0 --- /dev/null +++ b/cash-service/market-service/src/main/resources/mapper/MkRechargeRedemptionConfigMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/cash-service/pay-service/pom.xml b/cash-service/pay-service/pom.xml index 98a2bdfd..92db9799 100644 --- a/cash-service/pay-service/pom.xml +++ b/cash-service/pay-service/pom.xml @@ -17,6 +17,10 @@ UTF-8 + + com.github.javen205 + IJPay-All + com.czg czg-pay @@ -24,4 +28,4 @@ - \ No newline at end of file + diff --git a/cash-service/pay-service/src/main/java/com/czg/service/WxService.java b/cash-service/pay-service/src/main/java/com/czg/service/WxService.java new file mode 100644 index 00000000..227c341c --- /dev/null +++ b/cash-service/pay-service/src/main/java/com/czg/service/WxService.java @@ -0,0 +1,554 @@ +//package com.czg.service; +// +//import cn.hutool.core.util.IdUtil; +//import cn.hutool.core.util.StrUtil; +//import cn.hutool.http.HttpRequest; +//import cn.hutool.http.HttpUtil; +//import com.alibaba.fastjson.JSONObject; +//import com.czg.exception.CzgException; +//import com.ijpay.core.IJPayHttpResponse; +//import com.ijpay.core.enums.RequestMethodEnum; +//import com.ijpay.core.enums.SignType; +//import com.ijpay.core.kit.AesUtil; +//import com.ijpay.core.kit.PayKit; +//import com.ijpay.core.kit.RsaKit; +//import com.ijpay.core.kit.WxPayKit; +//import com.ijpay.wxpay.WxPayApi; +//import com.ijpay.wxpay.enums.WxDomainEnum; +//import com.ijpay.wxpay.enums.v3.BasePayApiEnum; +//import com.ijpay.wxpay.enums.v3.OtherApiEnum; +//import com.ijpay.wxpay.enums.v3.ProfitSharingApiEnum; +//import com.ijpay.wxpay.enums.v3.TransferApiEnum; +//import com.ijpay.wxpay.model.ReceiverModel; +//import com.ijpay.wxpay.model.v3.*; +//import jakarta.annotation.PostConstruct; +//import jakarta.annotation.Resource; +//import jakarta.servlet.http.HttpServletRequest; +//import lombok.extern.slf4j.Slf4j; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.stereotype.Component; +// +//import java.math.BigDecimal; +//import java.math.RoundingMode; +//import java.nio.charset.StandardCharsets; +//import java.security.cert.X509Certificate; +//import java.util.Base64; +//import java.util.List; +//import java.util.Locale; +//import java.util.Map; +// +//@Component +//@Slf4j +//public class WxService { +// +// @Value("${wx.appId}") +// private String appIdInstance; +// @Value("${wx.appSecret}") +// private String appSecretInstance; +// @Value("${wx.pay.certPath}") +// private String certPathInstance; +// @Value("${wx.pay.certKeyPath}") +// private String certKeyPathInstance; +// @Value("${wx.pay.pubKey}") +// private String pubKeyInstance; +// @Value("${wx.pay.platformCertPath}") +// private String platformCertPathInstance; +// @Value("${wx.pay.platformCertNo}") +// private String platformCertNoInstance; +// @Value("${wx.pay.mchId}") +// private String mchIdInstance; +// @Value("${wx.pay.apiV3Key}") +// private String apiV3KeyInstance; +// @Value("${wx.pay.apiV2Key}") +// private String apiV2KeyInstance; +// @Value("${wx.pay.notifyUrl}") +// private String notifyUrlInstance; +// @Value("${wx.pay.refundNotifyUrl}") +// private String refundNotifyUrlInstance; +// @Value("${wx.pay.transferNotifyUrl}") +// private String transferNotifyUrlInstance; +// +// @Resource +// private RedisService autoRedisService; +// private static RedisService redisService; +// +// @PostConstruct +// public void init() { +// appId = appIdInstance; +// appSecret = appSecretInstance; +// certPath = certPathInstance; +// pubKey = pubKeyInstance; +// certKeyPath = certKeyPathInstance; +// platformCertPath = platformCertPathInstance; +// platformCertNo = platformCertNoInstance; +// mchId = mchIdInstance; +// apiV3Key = apiV3KeyInstance; +// apiV2Key = apiV2KeyInstance; +// notifyUrl = notifyUrlInstance; +// refundNotifyUrl = refundNotifyUrlInstance; +// transferNotifyUrl = transferNotifyUrlInstance; +// redisService = this.autoRedisService; +// } +// +// // static copies for use in static methods +// private static String appId; +// private static String appSecret; +// private static String certPath; +// private static String pubKey; +// private static String certKeyPath; +// private static String platformCertPath; +// private static String platformCertNo; +// private static String mchId; +// private static String apiV3Key; +// private static String apiV2Key; +// private static String notifyUrl; +// private static String refundNotifyUrl; +// private static String transferNotifyUrl; +// +// private static String getAccessToken(boolean refresh) { +// Object token = redisService.get("access_token"); +// if (!refresh && token instanceof String) { +// return (String) token; +// } +// +// String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", +// Map.of("grant_type", "client_credential", "appid", appId, "secret", appSecret) +// ); +// +// log.info("获取access_token响应: {}", response); +// JSONObject jsonObject = JSONObject.parseObject(response); +// String accessToken = jsonObject.getString("access_token"); +// if (accessToken == null) { +// throw new RuntimeException("获取access_token失败"); +// } +// Long expiresIn = jsonObject.getLong("expires_in"); +// if (expiresIn == null) { +// expiresIn = 7200L; +// } +// redisService.set("access_token", accessToken, expiresIn - 200); +// return accessToken; +// } +// +// public static String getPhone(String code) { +// String requestBody = JSONObject.toJSONString(Map.of("code", code)); +// String response = HttpUtil.post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + getAccessToken(false), requestBody); +// log.info("获取手机号响应: {}", response); +// JSONObject jsonObject = JSONObject.parseObject(response); +// Integer errCode = jsonObject.getInteger("errcode"); +// +// if (Integer.valueOf(0).equals(errCode)) { +// return jsonObject.getJSONObject("phone_info").getString("phoneNumber"); +// } else if (Integer.valueOf(40001).equals(errCode)) { +// getAccessToken(true); +// } +// throw new RuntimeException("获取手机号失败"); +// } +// +// public static String getOpenId(String code) { +// String response = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session", +// Map.of("appid", appId, "secret", appSecret, "js_code", code, "grant_type", "authorization_code") +// ); +// log.info("获取openId响应: {}", response); +// JSONObject jsonObject = JSONObject.parseObject(response); +// String openId = jsonObject.getString("openid"); +// if (openId != null && !openId.isBlank()) { +// return openId; +// } +// throw new RuntimeException("获取openId失败"); +// } +// +// /** +// * 使用微信支付平台证书公钥加密敏感信息(OAEP) +// */ +// private static String encryptByPlatformCert(String content) { +// try (var certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(platformCertPath)) { +// if (certStream == null) { +// throw new RuntimeException("未找到微信支付平台证书文件: " + platformCertPath); +// } +// X509Certificate certificate = PayKit.getCertificate(certStream); +// if (certificate == null) throw new RuntimeException("读取证书失败"); +// return PayKit.rsaEncryptOAEP(content, certificate); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// } +// +// private static String getSerialNumber() { +// try (var certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(certPath)) { +// X509Certificate certificate = PayKit.getCertificate(certStream); +// if (certificate != null) { +// String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(Locale.getDefault()); +// boolean isValid = PayKit.checkCertificateIsValid(certificate, mchId, -2); +// log.info("证书是否可用 {} 证书有效期为 {}", isValid, certificate.getNotAfter()); +// log.info("证书序列号: {}", serialNo); +// return serialNo; +// } +// } catch (Exception e) { +// log.error("读取证书失败", e); +// } +// return null; +// } +// +// private static String getPlatSerialNumber() { +// try (var certStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(platformCertNo)) { +// X509Certificate certificate = PayKit.getCertificate(certStream); +// if (certificate != null) { +// String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(Locale.getDefault()); +// boolean isValid = PayKit.checkCertificateIsValid(certificate, mchId, -2); +// log.info("平台证书是否可用 {} 证书有效期为 {}", isValid, certificate.getNotAfter()); +// log.info("平台证书序列号: {}", serialNo); +// return serialNo; +// } +// } catch (Exception e) { +// log.error("读取平台证书失败", e); +// } +// return null; +// } +// +// public static JSONObject verifySignature(HttpServletRequest request) { +// try { +// log.info("开始校验签名并解密"); +// String timestamp = request.getHeader("Wechatpay-Timestamp"); +// String nonce = request.getHeader("Wechatpay-Nonce"); +// String serialNo = request.getHeader("Wechatpay-Serial"); +// String signature = request.getHeader("Wechatpay-Signature"); +// String result = request.getReader().lines().reduce((a, b) -> a + b).orElse(""); +// String resp = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, apiV3Key, platformCertPath); +// log.info("解密明文{}", resp); +// return JSONObject.parseObject(resp); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// } +// +// public static void getPlatCert() throws Exception { +// String response = WxPayApi.v3( +// RequestMethodEnum.GET, +// WxDomainEnum.CHINA.toString(), +// OtherApiEnum.GET_CERTIFICATES.toString(), +// mchId, +// getSerialNumber(), +// null, +// certKeyPath, +// "" +// ).getBody(); +// +// JSONObject jsonObject = JSONObject.parseObject(response); +// var dataArray = jsonObject.getJSONArray("data"); +// var encryptObject = dataArray.getJSONObject(0); +// var encryptCertificate = encryptObject.getJSONObject("encrypt_certificate"); +// String associatedData = encryptCertificate.getString("associated_data"); +// String cipherText = encryptCertificate.getString("ciphertext"); +// String nonce = encryptCertificate.getString("nonce"); +// AesUtil aesUtil = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8)); +// String publicKey = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText); +// log.info(publicKey); +// } +// +// public static Map pay(String openId, BigDecimal amount, String desc, String tradeNo, String type) throws Exception { +// if (desc == null) desc = "订单支付"; +// UnifiedOrderModel model = new UnifiedOrderModel(); +// model.setAppid(appId); +// model.setMchid(mchId); +// model.setDescription(desc); +// model.setOut_trade_no(tradeNo); +// int total = amount.setScale(2, RoundingMode.UP).multiply(new BigDecimal(100)).intValueExact(); +// model.setAmount(new Amount(total, "CNY")); +// model.setNotify_url(notifyUrl + "/" + type); +// model.setPayer(new Payer(openId, null, null)); +// +// String payInfo = JSONObject.toJSONString(model); +// log.info("统一下单参数: {}", payInfo); +// +// var resp = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// BasePayApiEnum.JS_API_PAY.toString(), +// mchId, +// getSerialNumber(), +// getSerialNumber(), +// certKeyPath, +// payInfo +// ); +// +// log.info("统一下单响应: {}", resp); +// String body = resp.getBody(); +// JSONObject jsonObject = JSONObject.parseObject(body); +// String prepayId = jsonObject.getString("prepay_id"); +// if (StrUtil.isBlank(prepayId)) { +// throw new RuntimeException(jsonObject.getString("message")); +// } +// try { +// return WxPayKit.jsApiCreateSign(appId, prepayId, certKeyPath); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// } +// +// public static Map v2Pay(String openId, BigDecimal amount, String desc, String tradeNo) { +// Map payModel = com.ijpay.wxpay.model.UnifiedOrderModel.builder() +// .appid(appId) +// .mch_id(mchId) +// .body(desc) +// .out_trade_no(tradeNo) +// .total_fee(amount.setScale(2, RoundingMode.UP).multiply(new BigDecimal(100)).intValueExact() + "") +// .fee_type("CNY") +// .notify_url(notifyUrl) +// .openid(openId) +// .trade_type("JSAPI") +// .build() +// .createSign(apiV2Key, SignType.MD5); +// +// log.info("统一下单参数: {}", payModel); +// String resp = WxPayApi.pushOrder(false, payModel); +// log.info("统一下单响应: {}", resp); +// +// Map resultMap = WxPayKit.xmlToMap(resp); +// String returnCode = resultMap.get("return_code"); +// String returnMsg = resultMap.get("return_msg"); +// if (!WxPayKit.codeIsOk(returnCode)) { +// throw new CzgException(returnMsg); +// } +// String resultCode = resultMap.get("result_code"); +// if (!WxPayKit.codeIsOk(resultCode)) { +// throw new CzgException(returnMsg); +// } +// String prepayId = resultMap.get("prepay_id"); +// return WxPayKit.prepayIdCreateSign(prepayId, appId, appSecret, SignType.MD5); +// } +// +// public static String refund(String tradeNo, String refundTradeNo, BigDecimal amount) { +// int finalAmount = amount.multiply(new BigDecimal(100)).intValueExact(); +// RefundModel model = new RefundModel(); +// model.setOut_trade_no(tradeNo); +// model.setOut_refund_no(refundTradeNo); +// model.setAmount(new RefundAmount(finalAmount, "CNY", finalAmount)); +// model.setNotify_url(refundNotifyUrl); +// +// String info = JSONObject.toJSONString(model); +// log.info("统一退款参数: {}", info); +// IJPayHttpResponse response; +// try { +// response = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// BasePayApiEnum.REFUND.toString(), +// mchId, +// getSerialNumber(), +// getSerialNumber(), +// certKeyPath, +// info +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// log.info("统一退款响应 {}", response); +// String body = response.getBody(); +// JSONObject jsonObject = JSONObject.parseObject(body); +// if ("ABNORMAL".equals(jsonObject.getString("status")) || response.getStatus() != 200) { +// throw new CzgException("退款异常," + jsonObject.getString("message")); +// } +// return jsonObject.getString("refund_id"); +// } +// +// public static String genCode(int shopId, int id, String path) { +// Map params = Map.of( +// "scene", "id=" + id + "&shopId=" + shopId, +// "page", path, +// "width", 430 +// ); +// var response = HttpRequest.post("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + getAccessToken(false)) +// .body(JSONObject.toJSONString(params)) +// .execute(); +// +// byte[] bodyBytes = response.bodyBytes(); +// String str = new String(bodyBytes); +// if (str.contains("errmsg")) { +// JSONObject json = JSONObject.parseObject(str); +// throw new CzgException(json.getString("errmsg")); +// } +// return "data:image/png;base64," + Base64.getEncoder().encodeToString(bodyBytes); +// } +// +// public static String addProfitSharingUser(AddReceivers params) throws Exception { +// getPlatCert(); +// params.setAppid(appId); +// if (params.getName() != null && !params.getName().isBlank()) { +// params.setName(encryptByPlatformCert(params.getName())); +// } else { +// params.setName(null); +// } +// log.info("添加分账方参数: {}", JSONObject.toJSONString(params)); +// var response = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// ProfitSharingApiEnum.PROFIT_SHARING_RECEIVERS_ADD.toString(), +// mchId, +// getSerialNumber(), +// platformCertNo, +// certKeyPath, +// JSONObject.toJSONString(params) +// ); +// log.info("添加分账方响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("分账添加失败" + resp.getString("message")); +// } +// return resp.getString("account"); +// } +// +// public static JSONObject getMchConfig(String mchIdParam) throws Exception { +// var response = WxPayApi.v3( +// RequestMethodEnum.GET, +// WxDomainEnum.CHINA.toString(), +// String.format(ProfitSharingApiEnum.PROFIT_SHARING_MERCHANT_CONFIGS.toString(), mchIdParam), +// mchId, +// getSerialNumber(), +// getSerialNumber(), +// certKeyPath, +// "" +// ); +// log.info("查询分账响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("分账查询失败" + resp.getString("message")); +// } +// return resp; +// } +// +// /** +// * 获取可分账金额 +// */ +// public static BigDecimal getRemainAmount(String transactionId) { +// IJPayHttpResponse response; +// try { +// response = WxPayApi.v3( +// RequestMethodEnum.GET, +// WxDomainEnum.CHINA.toString(), +// String.format(ProfitSharingApiEnum.PROFIT_SHARING_UNFREEZE_QUERY.toString(), transactionId), +// mchId, +// getSerialNumber(), +// getSerialNumber(), +// certKeyPath, +// "" +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// log.info("查询可分账响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("分账查询失败" + resp.getString("message")); +// } +// return resp.getBigDecimal("unsplit_amount"); +// } +// +// public static void profitSharing(String transactionId, ReceiverModel... receivers) { +// for (ReceiverModel r : receivers) { +// if (r.getName() != null && !r.getName().isBlank()) { +// r.setName(encryptByPlatformCert(r.getName())); +// } +// } +// String tradeNo = IdUtil.simpleUUID(); +// ProfitSharingModel model = new ProfitSharingModel(); +// model.setAppid(appId); +// model.setTransaction_id(transactionId); +// model.setReceivers(List.of(receivers)); +// model.setUnfreeze_unsplit(true); +// model.setOut_order_no(tradeNo); +// +// String params = JSONObject.toJSONString(model); +// log.info("分账参数: {}", params); +// IJPayHttpResponse response; +// try { +// response = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// ProfitSharingApiEnum.PROFIT_SHARING_ORDERS.toString(), +// mchId, +// getSerialNumber(), +// platformCertNo, +// certKeyPath, +// params +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// log.info("分账响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("分账失败" + resp.getString("message") + ", 响应: " + resp.toJSONString()); +// } +// } +// +// public static void unFreezeSharing(String transactionId, String orderNo) { +// com.ijpay.wxpay.model.ProfitSharingModel paramsModel = new com.ijpay.wxpay.model.ProfitSharingModel(); +// paramsModel.setTransaction_id(transactionId); +// paramsModel.setOut_order_no(orderNo); +// paramsModel.setDescription("分账解冻"); +// String params = JSONObject.toJSONString(paramsModel); +// log.info("分账解冻参数: {}", params); +// IJPayHttpResponse response; +// try { +// response = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// ProfitSharingApiEnum.PROFIT_SHARING_UNFREEZE.toString(), +// mchId, +// getSerialNumber(), +// platformCertNo, +// certKeyPath, +// params +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// log.info("分账解冻响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("分账解冻失败" + resp.getString("message") + ", 响应: " + resp.toJSONString()); +// } +// } +// +// public static JSONObject transferBalance(String openId, String name, BigDecimal amount, String remarkTxt, String billNoTxt) { +// String remark = remarkTxt == null ? "佣金" : remarkTxt; +// String billNo = billNoTxt == null ? IdUtil.simpleUUID() : billNoTxt; +// Map params = Map.of( +// "appid", appId, +// "out_bill_no", billNo, +// "transfer_scene_id", "1005", +// "openid", openId, +// "user_name", encryptByPlatformCert(name), +// "transfer_amount", amount.multiply(BigDecimal.valueOf(100)).intValue(), +// "transfer_remark", remark, +// "notify_url", transferNotifyUrl, +// "transfer_scene_report_infos", new Object[]{ +// Map.of("info_type", "岗位类型", "info_content", "加盟商"), +// Map.of("info_type", "报酬说明", "info_content", "测试") +// } +// ); +// log.info("转账到零钱参数: {}", JSONObject.toJSONString(params)); +// IJPayHttpResponse response = null; +// try { +// response = WxPayApi.v3( +// RequestMethodEnum.POST, +// WxDomainEnum.CHINA.toString(), +// "/v3/fund-app/mch-transfer/transfer-bills", +// mchId, +// getSerialNumber(), +// platformCertNo, +// certKeyPath, +// JSONObject.toJSONString(params) +// ); +// } catch (Exception e) { +// throw new RuntimeException(e); +// } +// log.info("转账到零钱响应 {}", response.getBody()); +// JSONObject resp = JSONObject.parseObject(response.getBody()); +// if (resp.containsKey("code")) { +// throw new CzgException("转账到零钱失败" + resp.getString("message") + ", 响应: " + resp.toJSONString()); +// } +// return resp; +// } +//} +//