Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
e2fc06d56c
@ -12,17 +12,17 @@ public interface RefundStatus {
|
|||||||
/**
|
/**
|
||||||
* 退款成功
|
* 退款成功
|
||||||
*/
|
*/
|
||||||
int APPLYING = 0;
|
int SUCCESS = 0;
|
||||||
/**
|
/**
|
||||||
* 关闭
|
* 关闭
|
||||||
*/
|
*/
|
||||||
int PROCESSING = 1;
|
int CLOSED = 1;
|
||||||
/**
|
/**
|
||||||
* 退款中
|
* 退款中
|
||||||
*/
|
*/
|
||||||
int PROCESSED = 2;
|
int PROCESSING = 2;
|
||||||
/**
|
/**
|
||||||
* 异常
|
* 异常
|
||||||
*/
|
*/
|
||||||
int CLOSED = 3;
|
int ABNORMAL = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
package com.cdzy.payment.model.vo;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款信息
|
|
||||||
*
|
|
||||||
* @author yanglei
|
|
||||||
* @since 2025-10-21 10:26
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class EbikeRefundInfoVo implements Serializable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 退款金额,单位为元
|
|
||||||
*/
|
|
||||||
private BigDecimal refund;
|
|
||||||
/**
|
|
||||||
* 原订单金额,单位为元
|
|
||||||
*/
|
|
||||||
private BigDecimal total;
|
|
||||||
/**
|
|
||||||
* 退款币种 (默认CNY)
|
|
||||||
*/
|
|
||||||
private String currency = "CNY";
|
|
||||||
}
|
|
||||||
@ -14,21 +14,21 @@ import com.mybatisflex.core.service.IService;
|
|||||||
public interface EbikeOrderService extends IService<EbikeOrder> {
|
public interface EbikeOrderService extends IService<EbikeOrder> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单退款完成
|
* 订单退款完成 由退款中 -> 退款成功
|
||||||
*
|
*
|
||||||
* @param orderId 订单ID
|
* @param orderId 订单ID
|
||||||
*/
|
*/
|
||||||
void doneRefund(Long orderId);
|
void doneRefund(Long orderId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单退款
|
* 订单退款 由退款申请中 -> 退款中
|
||||||
*
|
*
|
||||||
* @param orderId 订单ID
|
* @param orderId 订单ID
|
||||||
*/
|
*/
|
||||||
void refund(Long orderId);
|
void refund(Long orderId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单退款失败
|
* 订单退款失败 由退款中 -> 退款失败
|
||||||
*
|
*
|
||||||
* @param orderId 订单ID
|
* @param orderId 订单ID
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -36,7 +36,7 @@ public class EbikeOrderServiceImpl extends ServiceImpl<EbikeOrderMapper, EbikeOr
|
|||||||
public void doneRefund(Long orderId) {
|
public void doneRefund(Long orderId) {
|
||||||
QueryWrapper queryWrapper = QueryWrapper.create()
|
QueryWrapper queryWrapper = QueryWrapper.create()
|
||||||
.where(EBIKE_ORDER.ORDER_ID.eq(orderId))
|
.where(EBIKE_ORDER.ORDER_ID.eq(orderId))
|
||||||
.where(EBIKE_ORDER.ORDER_STATUS.eq(EbikeOrderStatus.REFUND_APPLYING));
|
.where(EBIKE_ORDER.ORDER_STATUS.eq(EbikeOrderStatus.REFUNDING));
|
||||||
EbikeOrder userOrders = this.mapper.selectOneByQuery(queryWrapper);
|
EbikeOrder userOrders = this.mapper.selectOneByQuery(queryWrapper);
|
||||||
if (userOrders == null) {
|
if (userOrders == null) {
|
||||||
log.warn("退款完成时未找到订单,订单ID: {}, 或订单状态不是退款中", orderId);
|
log.warn("退款完成时未找到订单,订单ID: {}, 或订单状态不是退款中", orderId);
|
||||||
@ -50,7 +50,7 @@ public class EbikeOrderServiceImpl extends ServiceImpl<EbikeOrderMapper, EbikeOr
|
|||||||
public void failRefund(Long orderId) {
|
public void failRefund(Long orderId) {
|
||||||
QueryWrapper queryWrapper = QueryWrapper.create()
|
QueryWrapper queryWrapper = QueryWrapper.create()
|
||||||
.where(EBIKE_ORDER.ORDER_ID.eq(orderId))
|
.where(EBIKE_ORDER.ORDER_ID.eq(orderId))
|
||||||
.where(EBIKE_ORDER.ORDER_STATUS.eq(EbikeOrderStatus.REFUND_APPLYING));
|
.where(EBIKE_ORDER.ORDER_STATUS.eq(EbikeOrderStatus.REFUNDING));
|
||||||
EbikeOrder userOrders = this.mapper.selectOneByQuery(queryWrapper);
|
EbikeOrder userOrders = this.mapper.selectOneByQuery(queryWrapper);
|
||||||
userOrders.setOrderStatus(EbikeOrderStatus.REFUND_FAILED);
|
userOrders.setOrderStatus(EbikeOrderStatus.REFUND_FAILED);
|
||||||
this.mapper.update(userOrders);
|
this.mapper.update(userOrders);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ public class EbikeRefundServiceImpl extends ServiceImpl<EbikeRefundMapper, Ebike
|
|||||||
totalSeconds
|
totalSeconds
|
||||||
);
|
);
|
||||||
QueryWrapper query = QueryWrapper.create()
|
QueryWrapper query = QueryWrapper.create()
|
||||||
.where(EBIKE_REFUND.REFUND_STATUS.eq(RefundStatus.PROCESSED))
|
.where(EBIKE_REFUND.REFUND_STATUS.eq(RefundStatus.PROCESSING))
|
||||||
.and(timeFilter);
|
.and(timeFilter);
|
||||||
return list(query);
|
return list(query);
|
||||||
}
|
}
|
||||||
@ -99,10 +99,15 @@ public class EbikeRefundServiceImpl extends ServiceImpl<EbikeRefundMapper, Ebike
|
|||||||
log.error("未找到对应的退款记录,refundOrderId: {}", refundOrderId);
|
log.error("未找到对应的退款记录,refundOrderId: {}", refundOrderId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ebikeRefund.getRefundStatus() == RefundStatus.APPLYING) {
|
if (ebikeRefund.getRefundStatus() == RefundStatus.SUCCESS) {
|
||||||
log.info("退款已处理成功。refundOrderId: {}", refundOrderId);
|
log.info("退款已处理成功。refundOrderId: {}", refundOrderId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (ebikeRefund.getRefundStatus() == RefundStatus.CLOSED ||
|
||||||
|
ebikeRefund.getRefundStatus() == RefundStatus.ABNORMAL) {
|
||||||
|
log.info("退款单状态异常或关闭。refundOrderId: {}", refundOrderId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
log.info("退款回调订单Id:{}, 退款回调订单状态:{}", refundOrderId, refundNotification.getRefundStatus());
|
log.info("退款回调订单Id:{}, 退款回调订单状态:{}", refundOrderId, refundNotification.getRefundStatus());
|
||||||
ebikeRefund.setRefundStatus(refundNotification.getRefundStatus().ordinal());
|
ebikeRefund.setRefundStatus(refundNotification.getRefundStatus().ordinal());
|
||||||
if (Status.SUCCESS.equals(refundNotification.getRefundStatus())) {
|
if (Status.SUCCESS.equals(refundNotification.getRefundStatus())) {
|
||||||
@ -115,9 +120,13 @@ public class EbikeRefundServiceImpl extends ServiceImpl<EbikeRefundMapper, Ebike
|
|||||||
Long orderId = ebikeRefund.getOrderId();
|
Long orderId = ebikeRefund.getOrderId();
|
||||||
// 更新订单退款状态
|
// 更新订单退款状态
|
||||||
switch (refundNotification.getRefundStatus()) {
|
switch (refundNotification.getRefundStatus()) {
|
||||||
case PROCESSING, CLOSED -> ebikeOrderService.refund(orderId);
|
// 退款中
|
||||||
|
case PROCESSING -> ebikeOrderService.refund(orderId);
|
||||||
|
// 成功退款
|
||||||
case SUCCESS -> ebikeOrderService.doneRefund(orderId);
|
case SUCCESS -> ebikeOrderService.doneRefund(orderId);
|
||||||
|
// 失败/关闭 → 订单“退款失败”
|
||||||
case ABNORMAL -> ebikeOrderService.failRefund(orderId);
|
case ABNORMAL -> ebikeOrderService.failRefund(orderId);
|
||||||
|
default -> log.warn("未知的微信退款状态: {}, orderId: {}", refundNotification.getRefundStatus(), orderId);
|
||||||
}
|
}
|
||||||
return updateById(ebikeRefund);
|
return updateById(ebikeRefund);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
package com.cdzy.payment.service.impl;
|
package com.cdzy.payment.service.impl;
|
||||||
|
|
||||||
import com.cdzy.common.enums.GlobalConstants;
|
import com.cdzy.common.enums.GlobalConstants;
|
||||||
|
import com.cdzy.common.ex.EbikeException;
|
||||||
import com.cdzy.payment.config.WxPayConfig;
|
import com.cdzy.payment.config.WxPayConfig;
|
||||||
import com.cdzy.payment.enums.PaymentMethod;
|
import com.cdzy.payment.enums.PaymentMethod;
|
||||||
|
import com.cdzy.payment.enums.RefundStatus;
|
||||||
import com.cdzy.payment.model.entity.EbikePayment;
|
import com.cdzy.payment.model.entity.EbikePayment;
|
||||||
import com.cdzy.payment.model.entity.EbikeRefund;
|
import com.cdzy.payment.model.entity.EbikeRefund;
|
||||||
import com.cdzy.payment.model.vo.*;
|
import com.cdzy.payment.model.vo.EbikePaymentAmountVo;
|
||||||
|
import com.cdzy.payment.model.vo.EbikePaymentDetailVo;
|
||||||
|
import com.cdzy.payment.model.vo.EbikePaymentVo;
|
||||||
|
import com.cdzy.payment.model.vo.EbikeWxHandleNotifyVo;
|
||||||
|
import com.cdzy.payment.model.vo.EbikeWxJsapiPromptVo;
|
||||||
|
import com.cdzy.payment.service.EbikeOrderService;
|
||||||
import com.cdzy.payment.service.EbikePaymentService;
|
import com.cdzy.payment.service.EbikePaymentService;
|
||||||
import com.cdzy.payment.service.EbikeRefundService;
|
import com.cdzy.payment.service.EbikeRefundService;
|
||||||
import com.cdzy.payment.service.EbikeWxPayService;
|
import com.cdzy.payment.service.EbikeWxPayService;
|
||||||
@ -27,11 +34,22 @@ import com.wechat.pay.java.core.notification.RequestParam;
|
|||||||
import com.wechat.pay.java.core.util.NonceUtil;
|
import com.wechat.pay.java.core.util.NonceUtil;
|
||||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||||
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
|
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.CloseOrderRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.Detail;
|
||||||
import com.wechat.pay.java.service.payments.jsapi.model.GoodsDetail;
|
import com.wechat.pay.java.service.payments.jsapi.model.GoodsDetail;
|
||||||
import com.wechat.pay.java.service.payments.jsapi.model.*;
|
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
|
||||||
|
import com.wechat.pay.java.service.payments.jsapi.model.SettleInfo;
|
||||||
import com.wechat.pay.java.service.payments.model.Transaction;
|
import com.wechat.pay.java.service.payments.model.Transaction;
|
||||||
import com.wechat.pay.java.service.refund.RefundService;
|
import com.wechat.pay.java.service.refund.RefundService;
|
||||||
import com.wechat.pay.java.service.refund.model.*;
|
import com.wechat.pay.java.service.refund.model.AmountReq;
|
||||||
|
import com.wechat.pay.java.service.refund.model.CreateRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.QueryByOutRefundNoRequest;
|
||||||
|
import com.wechat.pay.java.service.refund.model.Refund;
|
||||||
|
import com.wechat.pay.java.service.refund.model.RefundNotification;
|
||||||
|
import com.wechat.pay.java.service.refund.model.Status;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -44,8 +62,13 @@ import java.time.Instant;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import static com.wechat.pay.java.core.http.Constant.*;
|
import static com.wechat.pay.java.core.http.Constant.REQUEST_ID;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_NONCE;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SERIAL;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SIGNATURE;
|
||||||
|
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_TIMESTAMP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付服务类(JSAPI支付),小程序
|
* 微信支付服务类(JSAPI支付),小程序
|
||||||
@ -81,6 +104,9 @@ public class EbikeWxPayServiceImpl implements EbikeWxPayService {
|
|||||||
@Resource
|
@Resource
|
||||||
private ObjectMapper objectMapper;
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private EbikeOrderService orderService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean closeOrder(String outTradeNo) {
|
public boolean closeOrder(String outTradeNo) {
|
||||||
try {
|
try {
|
||||||
@ -385,31 +411,26 @@ public class EbikeWxPayServiceImpl implements EbikeWxPayService {
|
|||||||
notifyVo.setSuccess(false);
|
notifyVo.setSuccess(false);
|
||||||
// 检查退款记录是否存在
|
// 检查退款记录是否存在
|
||||||
EbikeRefund ebikeRefund = ebikeRefundService.getById(refundDto.getRefundId());
|
EbikeRefund ebikeRefund = ebikeRefundService.getById(refundDto.getRefundId());
|
||||||
if (ebikeRefund == null) {
|
if (Objects.isNull(ebikeRefund)) {
|
||||||
log.error("退款refund失败,{} 退款申请不存在", refundDto.getRefundId());
|
throw new EbikeException("退款订单不存在");
|
||||||
notifyVo.setMessage(String.format("{%s}退款申请不存在", refundDto.getRefundId()));
|
|
||||||
return notifyVo;
|
|
||||||
}
|
}
|
||||||
// 检查退款状态
|
// 检查退款状态
|
||||||
if (Status.SUCCESS.ordinal() == ebikeRefund.getRefundStatus()) {
|
if (RefundStatus.SUCCESS == ebikeRefund.getRefundStatus()) {
|
||||||
log.error("退款refund失败,{} 退款已经成功,不能重复退款", refundDto.getRefundId());
|
throw new EbikeException("当前订单已完成退款");
|
||||||
notifyVo.setMessage(String.format("{%s}退款已经成功,不能重复退款", refundDto.getRefundId()));
|
|
||||||
return notifyVo;
|
|
||||||
}
|
}
|
||||||
if (Status.CLOSED.ordinal() == ebikeRefund.getRefundStatus() ||
|
if (RefundStatus.CLOSED == ebikeRefund.getRefundStatus() ||
|
||||||
Status.ABNORMAL.ordinal() == ebikeRefund.getRefundStatus()) {
|
RefundStatus.ABNORMAL == ebikeRefund.getRefundStatus()) {
|
||||||
//重新发起
|
//重新生成退款id并发起退款
|
||||||
String newOrder = StringUtils.generateSnowflakeId("refundId");
|
String newOrder = StringUtils.generateSnowflakeId("refundId");
|
||||||
ebikeRefund.setRefundOrderId(newOrder);
|
ebikeRefund.setRefundOrderId(newOrder);
|
||||||
}
|
}
|
||||||
// 查询支付记录
|
// 查询支付记录
|
||||||
Long orderId = ebikeRefund.getOrderId();
|
Long orderId = ebikeRefund.getOrderId();
|
||||||
EbikePayment ebikePayment = ebikePaymentService.getByOrderId(orderId);
|
EbikePayment ebikePayment = ebikePaymentService.getByOrderId(orderId);
|
||||||
|
if (Objects.isNull(ebikePayment)) {
|
||||||
|
throw new EbikeException("支付记录不存在");
|
||||||
|
}
|
||||||
String transactionId = ebikePayment.getTransactionId();
|
String transactionId = ebikePayment.getTransactionId();
|
||||||
EbikeRefundInfoVo amount = new EbikeRefundInfoVo();
|
|
||||||
amount.setTotal(ebikePayment.getCostPrice());
|
|
||||||
amount.setRefund(ebikePayment.getTotal());
|
|
||||||
amount.setCurrency(ebikeRefund.getCurrency());
|
|
||||||
// 发起退款
|
// 发起退款
|
||||||
CreateRequest request = new CreateRequest();
|
CreateRequest request = new CreateRequest();
|
||||||
request.setTransactionId(transactionId);
|
request.setTransactionId(transactionId);
|
||||||
@ -418,43 +439,36 @@ public class EbikeWxPayServiceImpl implements EbikeWxPayService {
|
|||||||
request.setReason(ebikeRefund.getProblemDescription());
|
request.setReason(ebikeRefund.getProblemDescription());
|
||||||
request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
|
request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
|
||||||
AmountReq amountReq = new AmountReq();
|
AmountReq amountReq = new AmountReq();
|
||||||
amountReq.setRefund(yuanToCent(amount.getRefund()));
|
amountReq.setRefund(yuanToCent(ebikePayment.getTotal()));
|
||||||
amountReq.setTotal(yuanToCent(amount.getTotal()));
|
amountReq.setTotal(yuanToCent(ebikePayment.getTotal()));
|
||||||
amountReq.setCurrency(amount.getCurrency());
|
amountReq.setCurrency(ebikePayment.getCurrency());
|
||||||
request.setAmount(amountReq);
|
request.setAmount(amountReq);
|
||||||
try {
|
try {
|
||||||
Refund result = wxRefundService.create(request);
|
Refund result = wxRefundService.create(request);
|
||||||
// 更新退款信息
|
if (result == null) {
|
||||||
if (result != null) {
|
log.error("调用微信退款接口返回空,订单号: {}", orderId);
|
||||||
ebikeRefund.setOrderId(orderId);
|
notifyVo.setMessage("退款请求失败");
|
||||||
ebikeRefund.setTransactionId(transactionId);
|
|
||||||
ebikeRefund.setTotal(amount.getTotal());
|
|
||||||
ebikeRefund.setRefundStatus(result.getStatus().ordinal());
|
|
||||||
ebikeRefund.setCurrency(amount.getCurrency());
|
|
||||||
ebikeRefund.setRefund(new BigDecimal(result.getAmount().getRefund())
|
|
||||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
|
|
||||||
ebikeRefund.setRefundTime(LocalDateTime.now());
|
|
||||||
ebikeRefund.setRefundTransactionId(result.getRefundId());
|
|
||||||
ebikeRefundService.updateById(ebikeRefund);
|
|
||||||
notifyVo.setSuccess(true);
|
|
||||||
notifyVo.setMessage("退款成功");
|
|
||||||
return notifyVo;
|
return notifyVo;
|
||||||
}
|
}
|
||||||
log.error("退款refund失败,订单号:{}", orderId);
|
orderService.refund(orderId);
|
||||||
notifyVo.setMessage("退款失败");
|
// 更新退款信息
|
||||||
|
ebikeRefund.setOrderId(orderId);
|
||||||
|
ebikeRefund.setTransactionId(transactionId);
|
||||||
|
ebikeRefund.setTotal(ebikePayment.getCostPrice());
|
||||||
|
ebikeRefund.setRefundStatus(result.getStatus().ordinal());
|
||||||
|
ebikeRefund.setCurrency(ebikePayment.getCurrency());
|
||||||
|
ebikeRefund.setRefund(new BigDecimal(result.getAmount().getRefund())
|
||||||
|
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
|
||||||
|
ebikeRefund.setRefundTime(LocalDateTime.now());
|
||||||
|
ebikeRefund.setRefundTransactionId(result.getRefundId());
|
||||||
|
ebikeRefundService.updateById(ebikeRefund);
|
||||||
|
notifyVo.setSuccess(true);
|
||||||
|
notifyVo.setMessage("退款已提交");
|
||||||
return notifyVo;
|
return notifyVo;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String err = logError("退款refund", e);
|
log.error("发起退款异常,refundId: {}, orderId: {}, error: {}",
|
||||||
try {
|
refundDto.getRefundId(), orderId, e.getMessage(), e);
|
||||||
JsonNode jsonNode = objectMapper.readTree(err);
|
notifyVo.setMessage("退款失败: " + e.getMessage());
|
||||||
if (jsonNode.has("message")) {
|
|
||||||
notifyVo.setMessage(jsonNode.get("message").asText());
|
|
||||||
} else {
|
|
||||||
notifyVo.setMessage(err);
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
|
||||||
notifyVo.setMessage(err);
|
|
||||||
}
|
|
||||||
return notifyVo;
|
return notifyVo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user