feat 钱包支持预冻结额度操作, 新增个人钱包, 储值卡调试

This commit is contained in:
xxm1995
2023-06-27 16:19:34 +08:00
parent 16bcbc0d52
commit 42a45016f7
19 changed files with 308 additions and 164 deletions

View File

@@ -9,7 +9,6 @@
<version>1.3.0</version>
</parent>
<groupId>cn.bootx.platform</groupId>
<artifactId>dax-pay</artifactId>
<properties>

View File

@@ -20,6 +20,9 @@ public interface PayWayExtraCode {
/** 钱包ID */
String WALLET_ID = "wallet_id";
/** 用户ID */
String USER_ID = "user_id";
/** 同步通知路径 支付完成跳转的页面地址 */
String RETURN_URL = "return_url";

View File

@@ -9,38 +9,38 @@ package cn.bootx.platform.daxpay.code.paymodel;
public interface VoucherCode {
/**
* 状态-启用
* 状态-正常
*/
int STATUS_NORMAL = 1;
String STATUS_NORMAL = "normal";
/**
* 状态-停用
*/
int STATUS_FORBIDDEN = 2;
String STATUS_FORBIDDEN = "forbidden";
/**
* 储值卡日志-开通
*/
int LOG_ACTIVE = 1;
String LOG_ACTIVE = "active";
/**
* 储值卡日志-支付
*/
int LOG_PAY = 2;
String LOG_PAY = "pay";
/**
* 储值卡日志-退款
*/
int LOG_CLOSE = 3;
String LOG_CLOSE = "close";
/**
* 储值卡日志-退款
*/
int LOG_REFUND = 4;
String LOG_REFUND = "refund";
/**
* 储值卡日志-Admin余额变动
*/
int LOG_ADMIN_CHANGER = 4;
String LOG_ADMIN_CHANGER = "changer";
}

View File

@@ -0,0 +1,106 @@
package cn.bootx.platform.daxpay.controller;
import cn.bootx.platform.common.core.annotation.OperateLog;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletService;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletQueryService;
import cn.bootx.platform.daxpay.dto.channel.wallet.WalletDto;
import cn.bootx.platform.daxpay.dto.channel.wallet.WalletInfoDto;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletPayParam;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletRechargeParam;
import cn.bootx.platform.iam.dto.user.UserInfoDto;
import cn.bootx.platform.iam.param.user.UserInfoParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 钱包
*
* @author xxm
* @since 2021/2/24
*/
@Tag(name = "钱包相关的接口")
@RestController
@RequestMapping("/wallet/admin")
@AllArgsConstructor
public class WalletAdminController {
private final WalletService walletService;
private final WalletQueryService walletQueryService;
@Operation(summary = "开通用户钱包操作")
@PostMapping("/createWallet")
public ResResult<Void> createWallet(Long userId) {
walletService.createWallet(userId);
return Res.ok();
}
@Operation(summary = "批量开通用户钱包操作")
@PostMapping("/createWalletBatch")
public ResResult<Void> createWalletBatch(@RequestBody List<Long> userIds) {
walletService.createWalletBatch(userIds);
return Res.ok();
}
@Operation(summary = "解锁钱包")
@OperateLog(title = "解锁钱包", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/unlock")
public ResResult<Void> unlock(Long walletId) {
walletService.unlock(walletId);
return Res.ok();
}
@Operation(summary = "锁定钱包")
@OperateLog(title = "锁定钱包", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/lock")
public ResResult<Void> lock(Long walletId) {
walletService.lock(walletId);
return Res.ok();
}
@Operation(summary = "充值操作(增减余额)")
@PostMapping("/changerBalance")
public ResResult<Void> changerBalance(@RequestBody WalletRechargeParam param) {
walletService.changerBalance(param);
return Res.ok();
}
@Operation(summary = "分页")
@GetMapping("/page")
public ResResult<PageResult<WalletDto>> page(PageParam pageParam, WalletPayParam param) {
return Res.ok(walletQueryService.page(pageParam, param));
}
@Operation(summary = "分页(未开通钱包的用户)")
@GetMapping("/pageByNotWallet")
public ResResult<PageResult<UserInfoDto>> pageByNotWallet(PageParam pageParam, UserInfoParam param) {
return Res.ok(walletQueryService.pageByNotWallet(pageParam, param));
}
@Operation(summary = "根据用户ID查询钱包")
@GetMapping("/findByUserId")
public ResResult<WalletDto> findByUserId(Long userId) {
return Res.ok(walletQueryService.findByUserId(userId));
}
@Operation(summary = "根据钱包ID查询钱包")
@GetMapping("/findById")
public ResResult<WalletDto> findById(Long walletId) {
return Res.ok(walletQueryService.findById(walletId));
}
@Operation(summary = "获取钱包综合信息")
@GetMapping("/getWalletInfo")
public ResResult<WalletInfoDto> getWalletInfo(Long walletId) {
return Res.ok(walletQueryService.getWalletInfo(walletId));
}
}

View File

@@ -1,89 +1,26 @@
package cn.bootx.platform.daxpay.controller;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletQueryService;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletService;
import cn.bootx.platform.daxpay.dto.channel.wallet.WalletDto;
import cn.bootx.platform.daxpay.dto.channel.wallet.WalletInfoDto;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletPayParam;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletRechargeParam;
import cn.bootx.platform.common.core.annotation.OperateLog;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.Res;
import cn.bootx.platform.common.core.rest.ResResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.iam.dto.user.UserInfoDto;
import cn.bootx.platform.iam.param.user.UserInfoParam;
import cn.bootx.platform.starter.auth.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 钱包
*
* @author xxm
* @since 2021/2/24
*/
@Tag(name = "钱包相关的接口")
@RestController
@RequestMapping("/wallet")
@AllArgsConstructor
public class WalletController {
private final WalletService walletService;
private final WalletQueryService walletQueryService;
@Operation(summary = "开通用户钱包操作")
@PostMapping("createWallet")
public ResResult<Void> createWallet(Long userId) {
walletService.createWallet(userId);
return Res.ok();
}
@Operation(summary = "批量开通用户钱包操作")
@PostMapping("createWalletBatch")
public ResResult<Void> createWalletBatch(@RequestBody List<Long> userIds) {
walletService.createWalletBatch(userIds);
return Res.ok();
}
@Operation(summary = "解锁钱包")
@OperateLog(title = "解锁钱包", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/unlock")
public ResResult<Void> unlock(Long walletId) {
walletService.unlock(walletId);
return Res.ok();
}
@Operation(summary = "锁定钱包")
@OperateLog(title = "锁定钱包", businessType = OperateLog.BusinessType.UPDATE, saveParam = true)
@PostMapping("/lock")
public ResResult<Void> lock(Long walletId) {
walletService.lock(walletId);
return Res.ok();
}
@Operation(summary = "充值操作(增减余额)")
@PostMapping("/changerBalance")
public ResResult<Void> changerBalance(@RequestBody WalletRechargeParam param) {
walletService.changerBalance(param);
return Res.ok();
}
@Operation(summary = "分页")
@GetMapping("/page")
public ResResult<PageResult<WalletDto>> page(PageParam pageParam, WalletPayParam param) {
return Res.ok(walletQueryService.page(pageParam, param));
}
@Operation(summary = "分页")
@GetMapping("/pageByNotWallet")
public ResResult<PageResult<UserInfoDto>> pageByNotWallet(PageParam pageParam, UserInfoParam param) {
return Res.ok(walletQueryService.pageByNotWallet(pageParam, param));
}
private final WalletService walletService;
@Operation(summary = "根据用户查询钱包")
@GetMapping("/findByUser")
@@ -91,16 +28,11 @@ public class WalletController {
return Res.ok(walletQueryService.findByUser());
}
@Operation(summary = "根据钱包ID查询钱包")
@GetMapping("/findById")
public ResResult<WalletDto> findById(Long walletId) {
return Res.ok(walletQueryService.findById(walletId));
@Operation(summary = "开通用户钱包操作")
@PostMapping("/createWallet")
public ResResult<Void> createWallet() {
Long userId = SecurityUtil.getUserId();
walletService.createWallet(userId);
return Res.ok();
}
@Operation(summary = "获取钱包综合信息")
@GetMapping("/getWalletInfo")
public ResResult<WalletInfoDto> getWalletInfo(Long walletId) {
return Res.ok(walletQueryService.getWalletInfo(walletId));
}
}

View File

@@ -79,7 +79,6 @@ public class CashierService {
map.put(PayWayExtraCode.AUTH_CODE, param.getAuthCode());
map.put(PayWayExtraCode.OPEN_ID, param.getOpenId());
map.put(PayWayExtraCode.VOUCHER_NO, param.getVoucherNo());
map.put(PayWayExtraCode.WALLET_ID, param.getWalletId());
String extraParamsJson = PayWaylUtil.buildExtraParamsJson(param.getPayChannel(), map);
payWayParam.setExtraParamsJson(extraParamsJson);

View File

@@ -20,7 +20,7 @@ public class VoucherLogManager extends BaseManager<VoucherLogMapper, VoucherLog>
/**
* 根据支付id和类型进行查询
*/
public List<VoucherLog> findByPaymentIdAndType(Long paymentId, int type) {
public List<VoucherLog> findByPaymentIdAndType(Long paymentId, String type) {
return lambdaQuery().eq(VoucherLog::getPaymentId, paymentId).eq(VoucherLog::getType, type).list();
}

View File

@@ -1,5 +1,9 @@
package cn.bootx.platform.daxpay.core.channel.voucher.entity;
import cn.bootx.mybatis.table.modify.annotation.DbColumn;
import cn.bootx.mybatis.table.modify.annotation.DbComment;
import cn.bootx.mybatis.table.modify.annotation.DbTable;
import cn.bootx.mybatis.table.modify.mybatis.mysq.annotation.DbMySqlIndex;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.platform.daxpay.code.paymodel.VoucherCode;
@@ -21,36 +25,51 @@ import java.time.LocalDateTime;
*/
@EqualsAndHashCode(callSuper = true)
@Data
@DbTable(comment = "储值卡")
@Accessors(chain = true)
@TableName("pay_voucher")
public class Voucher extends MpBaseEntity implements EntityBaseFunction<VoucherDto> {
/** 卡号 */
@DbComment("卡号")
@DbMySqlIndex(comment = "卡号索引")
private String cardNo;
/** 生成批次号 */
@DbComment("生成批次号")
private Long batchNo;
/** 面值 */
@DbComment("面值")
private BigDecimal faceValue;
/** 余额 */
@DbComment("余额")
private BigDecimal balance;
/** 预冻结额度 */
@DbColumn(comment = "预冻结额度")
private BigDecimal freezeBalance;
/** 是否长期有效 */
private Boolean enduring;
@DbComment("是否长期有效")
private boolean enduring;
/** 开始时间 */
@DbComment("开始时间")
private LocalDateTime startTime;
/** 结束时间 */
@DbComment("结束时间")
private LocalDateTime endTime;
/**
* 状态
* @see VoucherCode
* @see VoucherCode#STATUS_FORBIDDEN
*/
private Integer status;
@DbComment("状态")
private String status;
@Override
public VoucherDto toDto() {

View File

@@ -32,9 +32,9 @@ public class VoucherLog extends MpBaseEntity {
/**
* 类型
* @see VoucherCode
* @see VoucherCode#LOG_PAY
*/
private Integer type;
private String type;
/** 交易记录ID */
private Long paymentId;

View File

@@ -5,15 +5,15 @@ import cn.bootx.platform.common.core.util.BigDecimalUtil;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.daxpay.code.paymodel.VoucherCode;
import cn.bootx.platform.daxpay.core.channel.voucher.dao.VoucherLogManager;
import cn.bootx.platform.daxpay.core.payment.entity.Payment;
import cn.bootx.platform.daxpay.core.channel.voucher.dao.VoucherManager;
import cn.bootx.platform.daxpay.core.channel.voucher.dao.VoucherPaymentManager;
import cn.bootx.platform.daxpay.core.channel.voucher.entity.Voucher;
import cn.bootx.platform.daxpay.core.channel.voucher.entity.VoucherLog;
import cn.bootx.platform.daxpay.core.channel.voucher.entity.VoucherPayment;
import cn.bootx.platform.daxpay.core.payment.entity.Payment;
import cn.bootx.platform.daxpay.exception.payment.PayFailureException;
import cn.bootx.platform.daxpay.param.pay.PayWayParam;
import cn.bootx.platform.daxpay.param.channel.voucher.VoucherPayParam;
import cn.bootx.platform.daxpay.param.pay.PayWayParam;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONUtil;
@@ -82,11 +82,25 @@ public class VoucherPayService {
throw new PayFailureException("储值卡余额不足");
}
return vouchers;
return sort(vouchers);
}
/**
* 支付 TODO 有期限的在前面, 同样有期限到期时间短的在前面, 同样到期日金额小的在前面
* 支付前冻结余额
*/
public void freezeBalance(BigDecimal amount, Payment payment, List<Voucher> vouchers){
}
/**
* 支付成功
*/
public void paySuccess(Long paymentId){
}
/**
* 直接支付
*/
public void pay(BigDecimal amount, Payment payment, List<Voucher> vouchers) {
vouchers.sort((o1, o2) -> BigDecimalUtil.compareTo(o1.getBalance(), o2.getBalance()));
@@ -122,15 +136,17 @@ public class VoucherPayService {
voucherLogManager.saveAll(voucherLogs);
}
/**
* 取消支付
* 取消支付, 可配置解除冻结金额
* @param freeze 是否是冻结模式, 是的话对冻结金额进行解冻, 不是的话返还扣减的金额
*/
public void close(Long paymentId) {
public void close(Long paymentId,boolean freeze) {
// 查找支付记录日志
List<VoucherLog> voucherLogs = voucherLogManager.findByPaymentIdAndType(paymentId, VoucherCode.LOG_PAY);
// 查出关联的储值卡
Map<Long, VoucherLog> voucherLogMap = voucherLogs.stream()
.collect(Collectors.toMap(VoucherLog::getVoucherId, Function.identity()));
.collect(Collectors.toMap(VoucherLog::getVoucherId, Function.identity()));
List<Voucher> vouchers = voucherManager.findAllByIds(voucherLogMap.keySet());
// 执行退款并记录日志
List<VoucherLog> logs = new ArrayList<>();
@@ -138,11 +154,11 @@ public class VoucherPayService {
VoucherLog voucherLog = voucherLogMap.get(voucher.getId());
voucher.setBalance(voucher.getBalance().add(voucherLog.getAmount()));
VoucherLog log = new VoucherLog().setAmount(voucherLog.getAmount())
.setPaymentId(paymentId)
.setBusinessId(voucherLog.getBusinessId())
.setVoucherId(voucher.getId())
.setVoucherNo(voucher.getCardNo())
.setType(VoucherCode.LOG_CLOSE);
.setPaymentId(paymentId)
.setBusinessId(voucherLog.getBusinessId())
.setVoucherId(voucher.getId())
.setVoucherNo(voucher.getCardNo())
.setType(VoucherCode.LOG_CLOSE);
logs.add(log);
}
voucherManager.updateAllById(vouchers);
@@ -177,9 +193,51 @@ public class VoucherPayService {
private boolean check(List<Voucher> vouchers) {
// 判断有效期
return vouchers.stream()
.filter(voucher -> !Objects.equals(voucher.getEnduring(), true))
.filter(voucher -> !Objects.equals(voucher.isEnduring(), true))
.allMatch(voucher -> LocalDateTimeUtil.between(LocalDateTime.now(), voucher.getStartTime(),
voucher.getEndTime()));
}
/**
* 对储值卡进行排序
* 有期限的在前面, 同样有期限到期时间短的在前面, 同样到期日余额小的在前面, 金额一样id小的前面
*/
private List<Voucher> sort(List<Voucher> vouchers){
vouchers.sort(this::compareTime);
return vouchers;
}
/**
* 比较储值卡的期限
*/
private int compareTime(Voucher v1,Voucher v2){
// 期限对比, 都为长期
if (v1.isEnduring()&&v2.isEnduring()){
// 比较余额
return compareBalance(v1,v2);
}
// 都不为长期, 且金额一致
if (Objects.equals(v1.getEndTime(),v2.getEndTime())){
// 比较余额
return compareBalance(v1,v2);
}
// 期限对比 其中一个为长期
if (v1.isEnduring()^v2.isEnduring()){
return v1.isEnduring()?1:-1;
}
// 比较期限
return v1.getEndTime().compareTo(v2.getEndTime());
}
/**
* 比较储值卡的余额, 余额一致比较主键
*/
private int compareBalance(Voucher v1,Voucher v2) {
int i = BigDecimalUtil.compareTo(v1.getBalance(), v2.getBalance());
if (i==0){
return Long.compare(v1.getId(),v2.getId());
}
return i;
}
}

View File

@@ -45,6 +45,7 @@ public class Wallet extends MpBaseEntity implements EntityBaseFunction<WalletDto
* 状态
* @see WalletCode#STATUS_FORBIDDEN
*/
@DbColumn(comment = "状态")
private String status;
@Override

View File

@@ -38,7 +38,7 @@ public class WalletPayService {
private final WalletLogManager walletLogManager;
/**
* 支付前冻结余额操作
* 支付前冻结余额
* @param amount 付款金额
* @param payment 支付记录
* @param wallet 钱包
@@ -63,9 +63,9 @@ public class WalletPayService {
}
/**
* 支付成功更新
* 支付成功, 进行扣款
*/
public void success(Long paymentId){
public void paySuccess(Long paymentId){
// 钱包支付记录
walletPaymentManager.findByPaymentId(paymentId).ifPresent(walletPayment -> {
Optional<Wallet> walletOpt = walletManager.findById(walletPayment.getWalletId());

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.daxpay.core.channel.wallet.service;
import cn.bootx.platform.common.core.entity.UserDetail;
import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
@@ -18,6 +19,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* 钱包
*
@@ -34,18 +37,26 @@ public class WalletQueryService {
private final UserQueryService userQueryService;
/**
* 根据ID查询Wallet
* 根据钱包ID查询Wallet
*/
public WalletDto findById(Long walletId) {
return walletManager.findById(walletId).map(Wallet::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 根据用户ID查询钱包
*/
public WalletDto findByUserId(Long userId) {
return walletManager.findByUser(userId).map(Wallet::toDto).orElseThrow(DataNotExistException::new);
}
/**
* 根据用户ID查询钱包
*/
public WalletDto findByUser() {
Long userId = SecurityUtil.getUserId();
return walletManager.findByUser(userId).map(Wallet::toDto).orElseThrow(DataNotExistException::new);
return walletManager.findByUser(userId).map(Wallet::toDto).orElse(null);
}
/**
@@ -74,4 +85,26 @@ public class WalletQueryService {
return MpUtil.convert2DtoPageResult(walletManager.pageByNotWallet(pageParam, userInfoParam));
}
/**
* 获取钱包, 获取顺序: 1. 显式传入的钱包ID 2. 显式传入的用户ID 3. 从系统中获取到的用户ID
*
*/
public Wallet getWallet(Long walletId,Long userId){
Wallet wallet = null;
// 首先根据钱包ID查询
if (Objects.nonNull(walletId)) {
wallet = walletManager.findById(walletId).orElseThrow(null);
}
if (Objects.nonNull(wallet)){
return wallet;
}
// 根据用户id查询
if (Objects.isNull(userId)){
userId = SecurityUtil.getCurrentUser().map(UserDetail::getId).orElse(null);
}
return walletManager.findByUser(userId).orElse(null);
}
}

View File

@@ -8,8 +8,6 @@ import cn.bootx.platform.daxpay.core.channel.wallet.dao.WalletLogManager;
import cn.bootx.platform.daxpay.core.channel.wallet.dao.WalletManager;
import cn.bootx.platform.daxpay.core.channel.wallet.entity.Wallet;
import cn.bootx.platform.daxpay.core.channel.wallet.entity.WalletLog;
import cn.bootx.platform.daxpay.exception.waller.WalletBannedException;
import cn.bootx.platform.daxpay.exception.waller.WalletNotExistsException;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletRechargeParam;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -18,14 +16,12 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 钱包的相关操作
*
* @author xxm
* @since 2020/12/8
* @since 2023/6/26
*/
@Slf4j
@Service
@@ -79,8 +75,8 @@ public class WalletService {
.setUserId(wallet.getUserId())
.setAmount(BigDecimal.ZERO)
.setType(WalletCode.LOG_ACTIVE)
.setRemark("激活钱包")
.setOperationSource(WalletCode.OPERATION_SOURCE_USER))
.setRemark("批量开通钱包")
.setOperationSource(WalletCode.OPERATION_SOURCE_ADMIN))
.collect(Collectors.toList());
walletLogManager.saveAll(walletLogs);
}
@@ -142,30 +138,4 @@ public class WalletService {
.setOperationSource(WalletCode.OPERATION_SOURCE_ADMIN);
walletLogManager.save(walletLog);
}
/**
* 查询钱包,如果钱包不存在或者钱包被禁用将抛出异常
*/
public Wallet getNormalWalletById(Long walletId) {
// 查询Wallet
Wallet wallet = walletManager.findById(walletId).orElseThrow(WalletNotExistsException::new);
// 是否被禁用
if (Objects.equals(WalletCode.STATUS_FORBIDDEN, wallet.getStatus())) {
throw new WalletBannedException();
}
return wallet;
}
/**
* 查询钱包,如果钱包不存在或者钱包被禁用将抛出异常
*/
public Wallet getNormalWalletByUserId(Long userId) {
// 查询Wallet
Wallet wallet = walletManager.findByUser(userId).orElseThrow(WalletNotExistsException::new);
// 是否被禁用
if (Objects.equals(WalletCode.STATUS_FORBIDDEN, wallet.getStatus())) {
throw new WalletBannedException();
}
return wallet;
}
}

View File

@@ -45,7 +45,7 @@ public class VoucherStrategy extends AbsPayStrategy {
*/
@Override
public void doBeforePayHandler() {
// 获取并校验余额
// 获取并校验储值卡
this.vouchers = voucherPayService.getAndCheckVoucher(this.getPayWayParam());
}
@@ -54,8 +54,12 @@ public class VoucherStrategy extends AbsPayStrategy {
*/
@Override
public void doPayHandler() {
voucherPayService.pay(getPayWayParam().getAmount(), this.getPayment(), this.vouchers);
voucherPaymentService.savePayment(getPayment(), getPayParam(), getPayWayParam(), vouchers);
if (this.getPayment().isAsyncPayMode()){
voucherPayService.freezeBalance(this.getPayWayParam().getAmount(), this.getPayment(), this.vouchers);
} else {
voucherPayService.pay(this.getPayWayParam().getAmount(), this.getPayment(), this.vouchers);
}
voucherPaymentService.savePayment(this.getPayment(), getPayParam(), getPayWayParam(), vouchers);
}
/**
@@ -63,6 +67,9 @@ public class VoucherStrategy extends AbsPayStrategy {
*/
@Override
public void doSuccessHandler() {
if (this.getPayment().isAsyncPayMode()){
voucherPayService.paySuccess(this.getPayment().getId());
}
voucherPaymentService.updateSuccess(this.getPayment().getId());
}
@@ -71,7 +78,7 @@ public class VoucherStrategy extends AbsPayStrategy {
*/
@Override
public void doCloseHandler() {
voucherPayService.close(this.getPayment().getId());
voucherPayService.close(this.getPayment().getId(), this.getPayment().isAsyncPayMode());
voucherPaymentService.updateClose(this.getPayment().getId());
}

View File

@@ -2,13 +2,15 @@ package cn.bootx.platform.daxpay.core.pay.strategy;
import cn.bootx.platform.common.core.util.BigDecimalUtil;
import cn.bootx.platform.daxpay.code.pay.PayChannelEnum;
import cn.bootx.platform.daxpay.code.paymodel.WalletCode;
import cn.bootx.platform.daxpay.core.channel.wallet.entity.Wallet;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPayService;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPaymentService;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletService;
import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletQueryService;
import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy;
import cn.bootx.platform.daxpay.core.payment.service.PaymentService;
import cn.bootx.platform.daxpay.exception.payment.PayFailureException;
import cn.bootx.platform.daxpay.exception.waller.WalletBannedException;
import cn.bootx.platform.daxpay.exception.waller.WalletLackOfBalanceException;
import cn.bootx.platform.daxpay.param.channel.wallet.WalletPayParam;
import cn.hutool.core.util.StrUtil;
@@ -18,6 +20,8 @@ import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.Objects;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
/**
@@ -35,7 +39,7 @@ public class WalletPayStrategy extends AbsPayStrategy {
private final WalletPayService walletPayService;
private final WalletService walletService;
private final WalletQueryService walletQueryService;
private final PaymentService paymentService;
@@ -51,17 +55,22 @@ public class WalletPayStrategy extends AbsPayStrategy {
*/
@Override
public void doBeforePayHandler() {
WalletPayParam walletPayParam = new WalletPayParam();
try {
// 钱包参数验证
String extraParamsJson = this.getPayWayParam().getExtraParamsJson();
if (StrUtil.isNotBlank(extraParamsJson)) {
WalletPayParam walletPayParam = JSONUtil.toBean(extraParamsJson, WalletPayParam.class);
this.wallet = walletService.getNormalWalletById(walletPayParam.getWalletId());
walletPayParam = JSONUtil.toBean(extraParamsJson, WalletPayParam.class);
}
}
catch (JSONException e) {
} catch (JSONException e) {
throw new PayFailureException("支付参数错误");
}
// 获取钱包
this.wallet = walletQueryService.getWallet(walletPayParam.getWalletId(),walletPayParam.getUserId());
// 是否被禁用
if (Objects.equals(WalletCode.STATUS_FORBIDDEN, this.wallet.getStatus())) {
throw new WalletBannedException();
}
// 判断余额
if (BigDecimalUtil.compareTo(this.wallet.getBalance(), getPayWayParam().getAmount()) < 0) {
throw new WalletLackOfBalanceException();
@@ -88,7 +97,7 @@ public class WalletPayStrategy extends AbsPayStrategy {
@Override
public void doSuccessHandler() {
if (this.getPayment().isAsyncPayMode()){
walletPayService.success(this.getPayment().getId());
walletPayService.paySuccess(this.getPayment().getId());
}
walletPaymentService.updateSuccess(this.getPayment().getId());
}
@@ -99,7 +108,7 @@ public class WalletPayStrategy extends AbsPayStrategy {
@Override
public void doCloseHandler() {
if (this.getPayment().isAsyncPayMode()){
walletPayService.success(this.getPayment().getId());
walletPayService.paySuccess(this.getPayment().getId());
}
walletPayService.close(this.getPayment().getId(),this.getPayment().isAsyncPayMode());
walletPaymentService.updateClose(this.getPayment().getId());

View File

@@ -42,9 +42,9 @@ public class VoucherDto extends BaseDto {
private LocalDateTime endTime;
/**
* @see VoucherCode
* @see VoucherCode#STATUS_FORBIDDEN
*/
@Schema(description = "状态")
private Integer status;
private String status;
}

View File

@@ -22,4 +22,8 @@ public class WalletPayParam implements Serializable {
@Schema(description = "钱包ID")
private Long walletId;
@Schema(description = "用户ID")
private Long userId;
}

View File

@@ -101,7 +101,11 @@ public class PayWaylUtil {
}
case WALLET: {
String walletId = map.get(PayWayExtraCode.WALLET_ID);
return JSONUtil.toJsonStr(new WalletPayParam().setWalletId(Long.valueOf(walletId)));
String userId = map.get(PayWayExtraCode.USER_ID);
WalletPayParam walletPayParam = new WalletPayParam()
.setWalletId(Long.valueOf(walletId))
.setUserId(Long.valueOf(userId));
return JSONUtil.toJsonStr(walletPayParam);
}
default: {
return null;