取消订单后退款
parent
e3967d44c3
commit
bdcbebaf8a
|
|
@ -1,18 +0,0 @@
|
|||
package com.njzscloud.supervisory.money.pojo.param;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RebuildBillParam {
|
||||
|
||||
/**
|
||||
* 公司id
|
||||
*/
|
||||
private Long companyId;
|
||||
|
||||
/**
|
||||
* 产品Id
|
||||
*/
|
||||
private Long goodsId;
|
||||
|
||||
}
|
||||
|
|
@ -57,6 +57,8 @@ import com.njzscloud.supervisory.station.service.StationManageService;
|
|||
import com.njzscloud.supervisory.sys.auth.pojo.result.MyResult;
|
||||
import com.njzscloud.supervisory.sys.stationletter.constant.WarnCategory;
|
||||
import com.njzscloud.supervisory.voicebox.service.CloudVoiceboxService;
|
||||
import com.njzscloud.supervisory.wxPay.dto.RefundRequestDto;
|
||||
import com.njzscloud.supervisory.wxPay.service.PaymentService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
|
@ -95,6 +97,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
|
|||
private final CloudVoiceboxService cloudVoiceboxService;
|
||||
private final MoneyAccountService moneyAccountService;
|
||||
private final MoneyChangeDetailService moneyChangeDetailService;
|
||||
private final PaymentService paymentService;
|
||||
private final AtomicBoolean test_thread_running = new AtomicBoolean(false);
|
||||
Thread test_thread = null;
|
||||
@Value("${app.check-gps:false}")
|
||||
|
|
@ -889,6 +892,18 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
|
|||
AuditStatus auditStatus = orderInfo.getAuditStatus();
|
||||
Assert.isFalse(auditStatus == AuditStatus.TongGuo, () -> Exceptions.clierr("当前订单状态,无法取消"));
|
||||
}
|
||||
// 退款
|
||||
// 验证订单状态
|
||||
if (PaymentStatus.YiZhiFu.getVal().equals(orderInfo.getPaymentStatus().getVal())) {
|
||||
RefundRequestDto dto = new RefundRequestDto();
|
||||
dto.setOrderId(orderId);
|
||||
dto.setRefundAmount(orderInfo.getSettleMoney());
|
||||
dto.setOutTradeNo(orderInfo.getOutTradeNo());
|
||||
dto.setReason("订单取消");
|
||||
// 获取支付上下文
|
||||
PaymentContextResult ctx = this.paymentContext(orderId);
|
||||
paymentService.refund(dto, ctx);
|
||||
}
|
||||
this.updateById(new OrderInfoEntity()
|
||||
.setId(orderInfo.getId())
|
||||
.setCancelReason(reason)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.njzscloud.supervisory.wxPay.controller;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
|
||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||
|
|
@ -17,11 +16,6 @@ import com.njzscloud.common.wechat.WechatUtil;
|
|||
import com.njzscloud.common.wechat.param.Code2SessionParam;
|
||||
import com.njzscloud.common.wechat.result.Code2SessionResult;
|
||||
import com.njzscloud.supervisory.device.service.DeviceInfoService;
|
||||
import com.njzscloud.supervisory.money.contant.MoneyChangeCategory;
|
||||
import com.njzscloud.supervisory.money.pojo.entity.MoneyAccountEntity;
|
||||
import com.njzscloud.supervisory.money.pojo.entity.MoneyChangeDetailEntity;
|
||||
import com.njzscloud.supervisory.money.service.MoneyAccountService;
|
||||
import com.njzscloud.supervisory.money.service.MoneyChangeDetailService;
|
||||
import com.njzscloud.supervisory.order.contant.MoneyWay;
|
||||
import com.njzscloud.supervisory.order.contant.OrderStatus;
|
||||
import com.njzscloud.supervisory.order.contant.PaymentStatus;
|
||||
|
|
@ -37,6 +31,7 @@ import com.njzscloud.supervisory.order.pojo.result.PaymentContextResult;
|
|||
import com.njzscloud.supervisory.order.service.OrderExpenseItemsService;
|
||||
import com.njzscloud.supervisory.order.service.OrderInfoService;
|
||||
import com.njzscloud.supervisory.wxPay.config.WxPayProperties;
|
||||
import com.njzscloud.supervisory.wxPay.service.PaymentService;
|
||||
import com.njzscloud.supervisory.wxPay.service.WeChatPayService;
|
||||
import com.njzscloud.supervisory.wxPay.utils.RequestHolder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
@ -62,12 +57,11 @@ public class PaymentController {
|
|||
|
||||
private final OrderExpenseItemsService orderExpenseItemsService;
|
||||
private final OrderInfoService orderInfoService;
|
||||
private final MoneyAccountService moneyAccountService;
|
||||
private final MoneyChangeDetailService moneyChangeDetailService;
|
||||
private final WeChatPayService wechatPayService;
|
||||
private final WxPayService wxPayService;
|
||||
private final WxPayProperties properties;
|
||||
private final OrderGoodsService orderGoodsService;
|
||||
private final PaymentService paymentService;
|
||||
|
||||
/**
|
||||
* 发起支付(使用生产级微信支付SDK)
|
||||
|
|
@ -243,50 +237,16 @@ public class PaymentController {
|
|||
*/
|
||||
@PostMapping("/refund")
|
||||
public R<?> refund(@RequestBody RefundRequestDto refundRequest) {
|
||||
try {
|
||||
// 验证订单存在性
|
||||
OrderInfoEntity orderInfo = orderInfoService.getById(refundRequest.getOrderId());
|
||||
if (orderInfo == null) {
|
||||
throw Exceptions.clierr("订单不存在");
|
||||
}
|
||||
|
||||
// 验证订单状态
|
||||
if (!PaymentStatus.YiZhiFu.getVal().equals(orderInfo.getPaymentStatus().getVal())) {
|
||||
throw Exceptions.clierr("订单未支付,无法退款");
|
||||
}
|
||||
|
||||
// 获取支付上下文
|
||||
PaymentContextResult ctx = orderInfoService.paymentContext(refundRequest.getOrderId());
|
||||
if (ctx == null) {
|
||||
throw Exceptions.clierr("获取支付上下文失败");
|
||||
}
|
||||
|
||||
// 根据支付方式处理退款
|
||||
if (SettlementWay.CASH.getVal().equals(ctx.getOiPayWay())) {
|
||||
// 微信退款
|
||||
//生成退款单号
|
||||
String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
|
||||
int money = ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue();
|
||||
// 微信退全款
|
||||
String notifyUrl = properties.getRefundNotifyUrl();
|
||||
wechatPayService.refund(orderInfo.getOutTradeNo(), orderSn, money, money, notifyUrl);
|
||||
return R.success("退款成功");
|
||||
} else if (SettlementWay.MONTH.getVal().equals(ctx.getOiPayWay()) || SettlementWay.BALANCE.getVal().equals(ctx.getOiPayWay())) {
|
||||
// 公司退款
|
||||
return processCompanyRefund(refundRequest, ctx);
|
||||
} else {
|
||||
throw Exceptions.clierr("不支持的支付方式");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("退款处理异常,订单ID:{}", refundRequest.getOrderId(), e);
|
||||
return R.failed(ExceptionMsg.CLI_ERR_MSG, "退款处理失败:" + e.getMessage());
|
||||
// 验证订单存在性
|
||||
OrderInfoEntity orderInfo = orderInfoService.getById(refundRequest.getOrderId());
|
||||
if (null == orderInfo) {
|
||||
throw Exceptions.clierr("订单不存在");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理公司退款
|
||||
*/
|
||||
private R<?> processCompanyRefund(RefundRequestDto refundRequest, PaymentContextResult ctx) {
|
||||
// 验证订单状态
|
||||
if (!PaymentStatus.YiZhiFu.getVal().equals(orderInfo.getPaymentStatus().getVal())) {
|
||||
throw Exceptions.clierr("订单未支付,无法退款");
|
||||
}
|
||||
if (refundRequest.getRefundAmount() == null) {
|
||||
throw Exceptions.clierr("公司退款金额不能为空");
|
||||
}
|
||||
|
|
@ -294,6 +254,11 @@ public class PaymentController {
|
|||
if (refundRequest.getRefundAmount().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw Exceptions.clierr("退款金额必须大于0");
|
||||
}
|
||||
// 获取支付上下文
|
||||
PaymentContextResult ctx = orderInfoService.paymentContext(refundRequest.getOrderId());
|
||||
if (null == ctx) {
|
||||
throw Exceptions.clierr("获取支付上下文失败");
|
||||
}
|
||||
|
||||
if (refundRequest.getRefundAmount().compareTo(ctx.getSettleMoney()) > 0) {
|
||||
throw Exceptions.clierr("退款金额不能超过订单已结算金额");
|
||||
|
|
@ -303,50 +268,18 @@ public class PaymentController {
|
|||
if (refundRequest.getRefundAmount().add(ctx.getRefundMoney()).compareTo(ctx.getSettleMoney()) > 0) {
|
||||
throw Exceptions.clierr("退款金额总和不能超过订单已结算金额");
|
||||
}
|
||||
|
||||
// 恢复公司账户余额
|
||||
restoreCompanyBalance(ctx, refundRequest.getRefundAmount(), refundRequest.getOrderId(), refundRequest.getReason());
|
||||
|
||||
// 更新订单状态为已退款
|
||||
orderInfoService.lambdaUpdate()
|
||||
.eq(OrderInfoEntity::getId, refundRequest.getOrderId())
|
||||
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.YiTuiKuan)
|
||||
.set(OrderInfoEntity::getRefundTime, LocalDateTime.now())
|
||||
.update();
|
||||
|
||||
log.info("公司退款成功,订单ID:{},退款金额:{}", refundRequest.getOrderId(), refundRequest.getRefundAmount());
|
||||
return R.success("退款成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复公司账户余额
|
||||
*/
|
||||
private void restoreCompanyBalance(PaymentContextResult ctx, BigDecimal refundAmount, Long orderId, String reason) {
|
||||
if (ctx.getCompanyUserId() == null || ctx.getCompanyAccountId() == null) {
|
||||
throw Exceptions.clierr("公司账户信息不完整,无法退款");
|
||||
refundRequest.setOutTradeNo(orderInfo.getOutTradeNo());
|
||||
paymentService.refund(refundRequest, ctx);
|
||||
if (SettlementWay.MONTH.getVal().equals(ctx.getOiPayWay()) || SettlementWay.BALANCE.getVal().equals(ctx.getOiPayWay())) {
|
||||
// 更新订单状态为已退款
|
||||
orderInfoService.lambdaUpdate()
|
||||
.eq(OrderInfoEntity::getId, refundRequest.getOrderId())
|
||||
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.YiTuiKuan)
|
||||
.set(OrderInfoEntity::getRefundTime, LocalDateTime.now())
|
||||
.update();
|
||||
}
|
||||
|
||||
// 恢复公司账户余额
|
||||
BigDecimal oldBalance = ctx.getCompanyBalance();
|
||||
BigDecimal newBalance = oldBalance.add(refundAmount);
|
||||
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
|
||||
.setId(ctx.getCompanyAccountId())
|
||||
.setMoney(newBalance);
|
||||
moneyAccountService.updateById(companyAccount);
|
||||
|
||||
// 记录资金明细(这里需要实现资金明细记录功能)
|
||||
MoneyChangeDetailEntity changeDetail = new MoneyChangeDetailEntity()
|
||||
.setCompanyId(ctx.getTransCompanyId())
|
||||
.setOrderId(orderId)
|
||||
.setMoneyAccountId(companyAccount.getId())
|
||||
.setOldMoney(oldBalance)
|
||||
.setDelta(refundAmount) // 扣减为负数
|
||||
.setNewMoney(newBalance)
|
||||
.setMoneyChangeCategory(MoneyChangeCategory.DingDanTuiKuan)
|
||||
.setMemo(reason);
|
||||
|
||||
moneyChangeDetailService.save(changeDetail);
|
||||
log.info("公司账户余额恢复成功,账户ID:{},恢复金额:{}", ctx.getCompanyAccountId(), refundAmount);
|
||||
return R.success();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -28,5 +28,7 @@ public class RefundRequestDto {
|
|||
*/
|
||||
@Size(max = 200, message = "退款原因不能超过200个字符")
|
||||
private String reason;
|
||||
|
||||
private String outTradeNo;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.njzscloud.supervisory.wxPay.service;
|
||||
|
||||
import com.njzscloud.supervisory.order.pojo.result.PaymentContextResult;
|
||||
import com.njzscloud.supervisory.wxPay.dto.RefundRequestDto;
|
||||
|
||||
/**
|
||||
* 退款服务接口
|
||||
*/
|
||||
public interface PaymentService {
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
void refund(RefundRequestDto refundRequest, PaymentContextResult ctx);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
package com.njzscloud.supervisory.wxPay.service.impl;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.njzscloud.common.core.ex.Exceptions;
|
||||
import com.njzscloud.supervisory.money.contant.MoneyChangeCategory;
|
||||
import com.njzscloud.supervisory.money.pojo.entity.MoneyAccountEntity;
|
||||
import com.njzscloud.supervisory.money.pojo.entity.MoneyChangeDetailEntity;
|
||||
import com.njzscloud.supervisory.money.service.MoneyAccountService;
|
||||
import com.njzscloud.supervisory.money.service.MoneyChangeDetailService;
|
||||
import com.njzscloud.supervisory.order.contant.SettlementWay;
|
||||
import com.njzscloud.supervisory.order.pojo.result.PaymentContextResult;
|
||||
import com.njzscloud.supervisory.wxPay.config.WxPayProperties;
|
||||
import com.njzscloud.supervisory.wxPay.dto.RefundRequestDto;
|
||||
import com.njzscloud.supervisory.wxPay.service.PaymentService;
|
||||
import com.njzscloud.supervisory.wxPay.service.WeChatPayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* 退款服务实现类
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PaymentServiceImpl implements PaymentService {
|
||||
|
||||
private final WxPayProperties properties;
|
||||
private final WeChatPayService wechatPayService;
|
||||
private final MoneyAccountService moneyAccountService;
|
||||
private final MoneyChangeDetailService moneyChangeDetailService;
|
||||
|
||||
/**
|
||||
* 申请退款
|
||||
*/
|
||||
public void refund(RefundRequestDto refundRequest, PaymentContextResult ctx) {
|
||||
try {
|
||||
// 根据支付方式处理退款
|
||||
if (SettlementWay.CASH.getVal().equals(ctx.getOiPayWay())) {
|
||||
//微信退款 生成退款单号
|
||||
String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
|
||||
int money = ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue();
|
||||
// 微信退全款
|
||||
String notifyUrl = properties.getRefundNotifyUrl();
|
||||
wechatPayService.refund(refundRequest.getOutTradeNo(), orderSn, money, money, notifyUrl);
|
||||
} else if (SettlementWay.MONTH.getVal().equals(ctx.getOiPayWay()) || SettlementWay.BALANCE.getVal().equals(ctx.getOiPayWay())) {
|
||||
// 公司退款
|
||||
processCompanyRefund(refundRequest, ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("退款处理异常,订单ID:{}", refundRequest.getOrderId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理公司退款
|
||||
*/
|
||||
private void processCompanyRefund(RefundRequestDto refundRequest, PaymentContextResult ctx) {
|
||||
|
||||
// 恢复公司账户余额
|
||||
restoreCompanyBalance(ctx, refundRequest.getRefundAmount(), refundRequest.getOrderId(), refundRequest.getReason());
|
||||
|
||||
log.info("公司退款成功,订单ID:{},退款金额:{}", refundRequest.getOrderId(), refundRequest.getRefundAmount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复公司账户余额
|
||||
*/
|
||||
private void restoreCompanyBalance(PaymentContextResult ctx, BigDecimal refundAmount, Long orderId, String reason) {
|
||||
if (ctx.getCompanyUserId() == null || ctx.getCompanyAccountId() == null) {
|
||||
throw Exceptions.clierr("公司账户信息不完整,无法退款");
|
||||
}
|
||||
|
||||
// 恢复公司账户余额
|
||||
BigDecimal oldBalance = ctx.getCompanyBalance();
|
||||
BigDecimal newBalance = oldBalance.add(refundAmount);
|
||||
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
|
||||
.setId(ctx.getCompanyAccountId())
|
||||
.setMoney(newBalance);
|
||||
moneyAccountService.updateById(companyAccount);
|
||||
|
||||
// 记录资金明细(这里需要实现资金明细记录功能)
|
||||
MoneyChangeDetailEntity changeDetail = new MoneyChangeDetailEntity()
|
||||
.setCompanyId(ctx.getTransCompanyId())
|
||||
.setOrderId(orderId)
|
||||
.setMoneyAccountId(companyAccount.getId())
|
||||
.setOldMoney(oldBalance)
|
||||
.setDelta(refundAmount) // 扣减为负数
|
||||
.setNewMoney(newBalance)
|
||||
.setMoneyChangeCategory(MoneyChangeCategory.DingDanTuiKuan)
|
||||
.setMemo(reason);
|
||||
|
||||
moneyChangeDetailService.save(changeDetail);
|
||||
log.info("公司账户余额恢复成功,账户ID:{},恢复金额:{}", ctx.getCompanyAccountId(), refundAmount);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue