Merge remote-tracking branch 'origin/test' into test
This commit is contained in:
commit
a07ee3f58b
|
|
@ -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<Boolean> 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<Integer> 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<MkRechargeRedemptionConfigVO> 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<Page<MkRechargeRedemptionConfig>> 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<Boolean> add(@Validated @RequestBody MkRechargeRedemptionConfigDTO dto) {
|
||||
return CzgResult.success(configService.add(StpKit.USER.getMainShopId(), dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置信息修改
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
@SaAdminCheckPermission(value = "rechargeRedemption:edit", name = "充值兑换修改")
|
||||
@SaCheckMainShop
|
||||
@PutMapping
|
||||
public CzgResult<Boolean> 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<Page<MkRechargeRedemptionCodeVO>> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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<MkEnableConfig> {
|
||||
|
||||
Boolean upEnable(Long mainShopId, Long shopId, Integer enable, TableValueConstant.EnableConfig.Type type);
|
||||
Integer detail(Long mainShopId, Long shopId, TableValueConstant.EnableConfig.Type type);
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionCode> {
|
||||
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionConfig> {
|
||||
|
||||
MkRechargeRedemptionConfigVO detail(Long mainShopId);
|
||||
|
||||
Boolean edit(Long shopId, MkRechargeRedemptionConfigDTO dto);
|
||||
|
||||
boolean add(Long mainShopId, MkRechargeRedemptionConfigDTO dto);
|
||||
|
||||
Page<MkRechargeRedemptionConfig> pageInfo(Long mainShopId, Integer status);
|
||||
|
||||
Page<MkRechargeRedemptionCodeVO> codeList(Long mainShopId, Long id, String code, Integer status);
|
||||
|
||||
void exportCodeList(Long mainShopId, Long redemptionId, String code, Integer status, HttpServletResponse response, HttpServletRequest request);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -40,10 +40,16 @@
|
|||
<zxing.version>3.5.3</zxing.version>
|
||||
<weixin.java.miniapp.version>3.8.0</weixin.java.miniapp.version>
|
||||
<pinyin.version>2.5.1</pinyin.version>
|
||||
<IJPay.version>2.9.10</IJPay.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-All</artifactId>
|
||||
<version>${IJPay.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.belerweb</groupId>
|
||||
<artifactId>pinyin4j</artifactId>
|
||||
|
|
|
|||
|
|
@ -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<MkEnableConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionCode> {
|
||||
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionConfig> {
|
||||
|
||||
}
|
||||
|
|
@ -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<MkEnableConfigMapper, MkEnableConfig> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionCodeMapper, MkRechargeRedemptionCode> implements MkRechargeRedemptionCodeService{
|
||||
|
||||
}
|
||||
|
|
@ -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<MkRechargeRedemptionConfigMapper, MkRechargeRedemptionConfig> implements MkRechargeRedemptionConfigService{
|
||||
@Resource
|
||||
private MkRechargeRedemptionCodeService codeService;
|
||||
|
||||
/**
|
||||
* 生成指定活动的兑换码集合
|
||||
* @param activityId 活动ID
|
||||
* @param count 生成数量(≤1000)
|
||||
*/
|
||||
public static Set<String> generateCodes(long activityId, int count) {
|
||||
Set<String> 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<String> 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<MkRechargeRedemptionConfig> 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<MkRechargeRedemptionConfig> 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<MkRechargeRedemptionCode> 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<MkRechargeRedemptionCode> 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<MkRechargeRedemptionCodeVO> 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<MkRechargeRedemptionCodeVO> mkRechargeRedemptionCodeVOS = codeService.listAs(queryWrapper, MkRechargeRedemptionCodeVO.class);
|
||||
|
||||
List<Map<String, Object>> list = mkRechargeRedemptionCodeVOS.stream()
|
||||
.map(item -> {
|
||||
Map<String, Object> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.market.mapper.MkEnableConfigMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.market.mapper.MkRechargeRedemptionCodeMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.czg.service.market.mapper.MkRechargeRedemptionConfigMapper">
|
||||
|
||||
</mapper>
|
||||
|
|
@ -17,6 +17,10 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-All</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.czg</groupId>
|
||||
<artifactId>czg-pay</artifactId>
|
||||
|
|
@ -24,4 +28,4 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<String, String> 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<String, String> v2Pay(String openId, BigDecimal amount, String desc, String tradeNo) {
|
||||
// Map<String, String> 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<String, String> 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<String, Object> 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<String, Object> 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;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
Loading…
Reference in New Issue