feat:退款的回调
This commit is contained in:
1 parent
44b26ffc6b
commit
87e5e30b78
3 files changed
+116
-19
No files matched your search
+5
-5
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.member.controller.admin.opentype;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -53,11 +54,10 @@ public class OpenTypeController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/refund")
|
||||
@Operation(summary = "发起钱包充值退款")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<Boolean> refundWalletRecharge(@RequestParam("id") Long id) {
|
||||
openTypeService.refundWalletRecharge(id, getClientIP());
|
||||
@PostMapping("/update-refunded")
|
||||
@Operation(summary = "更新钱包充值为已退款")
|
||||
public CommonResult<Boolean> updateWalletRechargeRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
|
||||
openTypeService.updateWalletRechargeRefunded(Long.valueOf(notifyReqDTO.getMerchantOrderId()), notifyReqDTO.getPayRefundId());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -51,6 +51,11 @@ public interface OpenTypeService {
|
||||
*/
|
||||
Long payOpenType(AppPayOpenReqType dto);
|
||||
|
||||
/**
|
||||
* 发起退款
|
||||
*/
|
||||
void refundWalletRecharge(Long id, String ip);
|
||||
|
||||
/**
|
||||
* 当前用户是否是会员
|
||||
*/
|
||||
@@ -86,5 +91,5 @@ public interface OpenTypeService {
|
||||
/**
|
||||
* 退款的回调
|
||||
*/
|
||||
void refundWalletRecharge(Long id, String ip);
|
||||
void updateWalletRechargeRefunded(Long merchantOrderId, Long payRefundId);
|
||||
}
|
||||
+105
-13
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.member.service.opentype;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.member.client.service.ChatApi;
|
||||
import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotalMessageTotalReqVO;
|
||||
@@ -11,22 +10,22 @@ import cn.iocoder.yudao.module.member.client.vo.chat.privatemsg.ChatPrivateTotal
|
||||
import cn.iocoder.yudao.module.member.controller.app.opentype.vo.AppPayOpenReqType;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.config.MemberConfigDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.opentype.OpenTypeUserDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberRecentTagDO;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeUserMapper;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberRecentTagMapper;
|
||||
import cn.iocoder.yudao.module.member.enums.MemberErrorCode;
|
||||
import cn.iocoder.yudao.module.member.enums.opentype.OpenTypeUserStatusEnum;
|
||||
import cn.iocoder.yudao.module.member.enums.tag.MemberRecentTagEnum;
|
||||
import cn.iocoder.yudao.module.member.service.config.MemberConfigService;
|
||||
import cn.iocoder.yudao.module.member.service.opentype.BO.OpenTypeExtBO;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberRecentTagService;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -45,7 +44,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.opentype.OpenTypeMapper;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -56,6 +54,7 @@ import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.add
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum.*;
|
||||
|
||||
/**
|
||||
* 会员类型 Service 实现类
|
||||
@@ -81,6 +80,8 @@ public class OpenTypeServiceImpl implements OpenTypeService {
|
||||
private ChatApi chatApi;
|
||||
@Resource
|
||||
private PayOrderApi payOrderApi;
|
||||
@Resource
|
||||
private PayRefundApi payRefundApi;
|
||||
|
||||
|
||||
/**
|
||||
@@ -189,6 +190,38 @@ public class OpenTypeServiceImpl implements OpenTypeService {
|
||||
return payOrderId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起退款
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void refundWalletRecharge(Long id, String clientIP) {
|
||||
OpenTypeUserDO openTypeUserDO = openTypeUserMapper.selectById(id);
|
||||
if (ObjectUtil.isEmpty(openTypeUserDO)) {
|
||||
log.error("[会员开通退款][recharge({}) clientIP({}) 不存在开通会员的订单,请进行处理!]", id, clientIP);
|
||||
throw exception(MemberErrorCode.EMPTY, "会员开通记录不存在");
|
||||
}
|
||||
// 校验钱包充值是否可以发起退款
|
||||
validateOpenTypeCanRefund(openTypeUserDO);
|
||||
String walletRechargeId = String.valueOf(id);
|
||||
String refundId = walletRechargeId + "-refund";
|
||||
// 创建退款订单
|
||||
PayRefundCreateReqDTO refundDto = new PayRefundCreateReqDTO();
|
||||
refundDto.setAppKey("vip");
|
||||
refundDto.setUserIp(clientIP);
|
||||
refundDto.setMerchantOrderId(String.valueOf(openTypeUserDO.getId()));
|
||||
refundDto.setMerchantRefundId(refundId + "-refund");
|
||||
refundDto.setReason("想退钱");
|
||||
refundDto.setPrice(openTypeUserDO.getPayPrice());
|
||||
Long payOrderRefundId = payRefundApi.createRefund(refundDto);
|
||||
// 更新订单
|
||||
OpenTypeUserDO updateObj = new OpenTypeUserDO();
|
||||
updateObj.setId(openTypeUserDO.getId());
|
||||
updateObj.setRefundStatus(WAITING.getStatus());
|
||||
updateObj.setPayRefundId(payOrderRefundId);
|
||||
openTypeUserMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前用户是否是会员
|
||||
*/
|
||||
@@ -312,7 +345,7 @@ public class OpenTypeServiceImpl implements OpenTypeService {
|
||||
// 查询订单
|
||||
PayOrderRespDTO payOrder = validatePayOrderPaid(openTypeUserDO, payOrderId);
|
||||
|
||||
// 更新钱包充值的支付状态
|
||||
// 更新会员开通的支付状态
|
||||
LambdaUpdateWrapper<OpenTypeUserDO> updateWrapper = new LambdaUpdateWrapper<OpenTypeUserDO>()
|
||||
.set(OpenTypeUserDO::getPayChannelCode, payOrder.getChannelCode())
|
||||
.set(OpenTypeUserDO::getPayStatus, true)
|
||||
@@ -330,16 +363,33 @@ public class OpenTypeServiceImpl implements OpenTypeService {
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void refundWalletRecharge(Long id, String clientIP) {
|
||||
public void updateWalletRechargeRefunded(Long id, Long payRefundId) {
|
||||
OpenTypeUserDO openTypeUserDO = openTypeUserMapper.selectById(id);
|
||||
if (ObjectUtil.isEmpty(openTypeUserDO)) {
|
||||
log.error("[会员开通退款][recharge({}) clientIP({}) 不存在开通会员的订单,请进行处理!]", id, clientIP);
|
||||
log.error("[会员开通支付,退款的回调][id({}) payRefundId({}) 不存在开通会员的订单,请进行处理!]", id, payRefundId);
|
||||
}
|
||||
PayRefundRespDTO payRefund = validateOpenTypeCanRefunded(openTypeUserDO, payRefundId);
|
||||
|
||||
OpenTypeUserDO updateObj = new OpenTypeUserDO().setId(id);
|
||||
// 退款成功
|
||||
if (PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
|
||||
updateObj.setRefundStatus(SUCCESS.getStatus())
|
||||
.setRefundTime(payRefund.getSuccessTime())
|
||||
.setRefundPayPrice(openTypeUserDO.getPayPrice());
|
||||
}
|
||||
// 退款失败
|
||||
if (PayRefundStatusEnum.isFailure(payRefund.getStatus())) {
|
||||
updateObj.setRefundStatus(FAILURE.getStatus());
|
||||
}
|
||||
// 更新会员开通的退款状态
|
||||
openTypeUserMapper.update(updateObj, new LambdaQueryWrapperX<OpenTypeUserDO>()
|
||||
.eq(OpenTypeUserDO::getId, openTypeUserDO.getOpenTypeId())
|
||||
.eq(OpenTypeUserDO::getRefundStatus, WAITING.getStatus())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证会员支付订单是否成功
|
||||
* 验证开通会员支付订单是否成功
|
||||
*/
|
||||
private PayOrderRespDTO validatePayOrderPaid(OpenTypeUserDO recharge, Long payOrderId) {
|
||||
// 1. 校验支付单是否存在
|
||||
@@ -351,21 +401,63 @@ public class OpenTypeServiceImpl implements OpenTypeService {
|
||||
// 2.1 校验支付单已支付
|
||||
if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
|
||||
log.error("[validatePayOrderPaid][验证会员支付订单是否成功({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]", recharge.getId(), payOrderId, toJsonString(payOrder));
|
||||
throw exception(MemberErrorCode.EMPTY, "会员充值更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员更新支付状态失败,支付单状态不是【支付成功】状态");
|
||||
}
|
||||
// 2.2 校验支付金额一致
|
||||
if (notEqual(payOrder.getPrice(), recharge.getPayPrice())) {
|
||||
log.error("[validatePayOrderPaid][验证会员支付订单是否成功({}) payOrder({}) 支付金额不匹配,请进行处理!钱包 数据是:{},payOrder 数据是:{}]", recharge.getId(), payOrderId, toJsonString(recharge), toJsonString(payOrder));
|
||||
throw exception(MemberErrorCode.EMPTY, "钱包充值更新支付状态失败,支付单金额不匹配");
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员更新支付状态失败,支付单金额不匹配");
|
||||
}
|
||||
// 2.3 校验支付订单的商户订单匹配
|
||||
if (notEqual(payOrder.getMerchantOrderId(), recharge.getId().toString())) {
|
||||
log.error("[validatePayOrderPaid][验证会员支付订单是否成功({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]", recharge.getId(), payOrderId, toJsonString(payOrder));
|
||||
throw exception(MemberErrorCode.EMPTY, "钱包充值更新支付状态失败,支付单编号不匹配");
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员更新支付状态失败,支付单编号不匹配");
|
||||
}
|
||||
return payOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验开通会员是否已退款
|
||||
*/
|
||||
private PayRefundRespDTO validateOpenTypeCanRefunded(OpenTypeUserDO openTypeUserDO, Long payRefundId) {
|
||||
// 校验退款订单匹配
|
||||
if (notEqual(openTypeUserDO.getPayRefundId(), payRefundId)) {
|
||||
log.error("[校验开通会员是否已退款][钱包充值({}) 退款单不匹配({}),请进行处理!钱包充值的数据是:{}]", openTypeUserDO.getId(), payRefundId, toJsonString(openTypeUserDO));
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员退款更新失败,钱包退款单编号不匹配");
|
||||
}
|
||||
// 校验退款订单
|
||||
PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId);
|
||||
if (payRefund == null) {
|
||||
log.error("[校验开通会员是否已退款][payRefund({})不存在]", payRefundId);
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员退款更新失败,退款订单不存在");
|
||||
}
|
||||
// 校验退款金额一致
|
||||
if (notEqual(payRefund.getRefundPrice(), openTypeUserDO.getPayPrice())) {
|
||||
log.error("[校验开通会员是否已退款][开通会员({}) payRefund({}) 退款金额不匹配,请进行处理!钱包数据是:{},payRefund数据是:{}]", openTypeUserDO.getId(), payRefundId, toJsonString(openTypeUserDO), toJsonString(payRefund));
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员退款更新失败,退款单金额不匹配");
|
||||
}
|
||||
// 校验退款订单商户订单是否匹配
|
||||
if (notEqual(payRefund.getMerchantOrderId(), openTypeUserDO.getId().toString())) {
|
||||
log.error("[校验开通会员是否已退款][开通会员({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]", openTypeUserDO.getId(), payRefundId, toJsonString(payRefund));
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员退款更新失败,钱包退款单编号不匹配");
|
||||
}
|
||||
return payRefund;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验开通会员是否可以发起退款
|
||||
*/
|
||||
private void validateOpenTypeCanRefund(OpenTypeUserDO walletRecharge) {
|
||||
// 校验充值订单是否支付
|
||||
if (!walletRecharge.getPayStatus()) {
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员发起退款失败,钱包充值订单未支付");
|
||||
}
|
||||
// 校验充值订单是否已退款
|
||||
if (walletRecharge.getPayRefundId() != null) {
|
||||
throw exception(MemberErrorCode.EMPTY, "开通会员发起退款失败,钱包充值订单已退款");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOpenTypeExists(Long id) {
|
||||
if (openTypeMapper.selectById(id) == null) {
|
||||
throw exception(MemberErrorCode.OPEN_TYPE_NOT_EXISTS);
|
||||
|
||||
Reference in new issue
Block a user