|
|
@@ -0,0 +1,170 @@
|
|
|
+package com.izouma.jiashanxia.service;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
|
|
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
|
|
+import com.github.binarywang.wxpay.exception.WxPayException;
|
|
|
+import com.github.binarywang.wxpay.service.WxPayService;
|
|
|
+import com.izouma.jiashanxia.domain.OrderInfo;
|
|
|
+import com.izouma.jiashanxia.domain.OrderRefund;
|
|
|
+import com.izouma.jiashanxia.domain.WxFee;
|
|
|
+import com.izouma.jiashanxia.dto.PageQuery;
|
|
|
+import com.izouma.jiashanxia.enums.OrderInfoStatus;
|
|
|
+import com.izouma.jiashanxia.enums.RefundStatus;
|
|
|
+import com.izouma.jiashanxia.exception.BusinessException;
|
|
|
+import com.izouma.jiashanxia.repo.OrderInfoRepo;
|
|
|
+import com.izouma.jiashanxia.repo.OrderRefundRepo;
|
|
|
+import com.izouma.jiashanxia.repo.WxFeeRepo;
|
|
|
+import com.izouma.jiashanxia.utils.JpaUtils;
|
|
|
+import com.izouma.jiashanxia.utils.SnowflakeIdWorker;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.core.env.Environment;
|
|
|
+import org.springframework.data.domain.Page;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.transaction.Transactional;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Service
|
|
|
+@AllArgsConstructor
|
|
|
+@Slf4j
|
|
|
+public class OrderRefundService {
|
|
|
+
|
|
|
+ private final OrderRefundRepo orderRefundRepo;
|
|
|
+ private final OrderInfoRepo orderInfoRepo;
|
|
|
+ private final WxFeeRepo wxFeeRepo;
|
|
|
+ private final WxPayService wxPayService;
|
|
|
+ private final Environment env;
|
|
|
+
|
|
|
+ public Page<OrderRefund> all(PageQuery pageQuery) {
|
|
|
+ return orderRefundRepo.findAll(JpaUtils.toSpecification(pageQuery, OrderRefund.class), JpaUtils.toPageRequest(pageQuery));
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ 申请退款
|
|
|
+ */
|
|
|
+ public OrderRefund apply(Long orderId) {
|
|
|
+ OrderInfo orderInfo = orderInfoRepo.findById(orderId).orElseThrow(new BusinessException("无订单"));
|
|
|
+ switch (orderInfo.getStatus()) {
|
|
|
+ case UNPAID:
|
|
|
+ throw new BusinessException("暂未支付");
|
|
|
+ case CANCELLED:
|
|
|
+ throw new BusinessException("已取消");
|
|
|
+ case REFUNDED:
|
|
|
+ throw new BusinessException("已退款");
|
|
|
+ case REQUEST_REFUND:
|
|
|
+ throw new BusinessException("申请中");
|
|
|
+ }
|
|
|
+ orderInfo.setStatus(OrderInfoStatus.REQUEST_REFUND);
|
|
|
+
|
|
|
+ OrderRefund refund = OrderRefund.builder()
|
|
|
+ .orderInfoId(orderId)
|
|
|
+ .applyTime(LocalDateTime.now())
|
|
|
+ .status(RefundStatus.PENDING)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ orderInfoRepo.save(orderInfo);
|
|
|
+ return orderRefundRepo.save(refund);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ 取消退款
|
|
|
+ */
|
|
|
+ public void cancel(Long orderId) {
|
|
|
+ // 恢复订单状态
|
|
|
+ OrderInfo orderInfo = orderInfoRepo.findById(orderId).orElseThrow(new BusinessException("无订单"));
|
|
|
+ orderInfo.setStatus(OrderInfoStatus.PAID);
|
|
|
+ orderInfoRepo.save(orderInfo);
|
|
|
+
|
|
|
+ // 修改退款状态
|
|
|
+ OrderRefund OrderRefund = orderRefundRepo.findByOrderInfoIdAndStatus(orderId, RefundStatus.PENDING)
|
|
|
+ .orElseThrow(new BusinessException("未申请退款"));
|
|
|
+ OrderRefund.setStatus(RefundStatus.CANCEL);
|
|
|
+ orderRefundRepo.save(OrderRefund);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 审核退款
|
|
|
+ *
|
|
|
+ * @param orderRefundId 申请退款ID
|
|
|
+ * @param pass 是否通过
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public void audit(Long orderRefundId, boolean pass) {
|
|
|
+ // 退款记录
|
|
|
+ OrderRefund refund = orderRefundRepo.findById(orderRefundId).orElseThrow(new BusinessException("无记录"));
|
|
|
+ if (refund.getStatus() != RefundStatus.PENDING) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 审核时间
|
|
|
+ refund.setAuditTime(LocalDateTime.now());
|
|
|
+
|
|
|
+ // 订单记录
|
|
|
+ OrderInfo orderInfo = orderInfoRepo.findById(refund.getOrderInfoId()).orElseThrow(new BusinessException("无订单"));
|
|
|
+
|
|
|
+ if (pass) {
|
|
|
+ String refundId = String.valueOf(new SnowflakeIdWorker(1, 1).nextId());
|
|
|
+ refund.setStatus(RefundStatus.REFUNDING);
|
|
|
+// if (StringUtils.isEmpty(refund.getRefundId())) {
|
|
|
+ refund.setRefundId(refundId);
|
|
|
+// }
|
|
|
+ orderRefundRepo.save(refund);
|
|
|
+ // 退款
|
|
|
+ payRefund(orderInfo, refundId);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ refund.setStatus(RefundStatus.DENY);
|
|
|
+ orderInfo.setStatus(OrderInfoStatus.PAID);
|
|
|
+ orderInfoRepo.save(orderInfo);
|
|
|
+ orderRefundRepo.save(refund);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ 微信退款
|
|
|
+ */
|
|
|
+ private void payRefund(OrderInfo orderInfo, String refundId) {
|
|
|
+ try {
|
|
|
+ WxPayRefundRequest req = WxPayRefundRequest.newBuilder()
|
|
|
+ .transactionId(orderInfo.getTransactionId())
|
|
|
+ .outRefundNo(refundId)
|
|
|
+ .totalFee(orderInfo.getPrice().multiply(BigDecimal.valueOf(100)).intValue())
|
|
|
+ .refundFee(orderInfo.getPrice().multiply(BigDecimal.valueOf(100)).intValue())
|
|
|
+ .notifyUrl(env.getProperty("wx.pay.refundNotifyUrl"))
|
|
|
+ .build();
|
|
|
+
|
|
|
+ wxPayService.refund(req);
|
|
|
+ } catch (WxPayException e) {
|
|
|
+ log.error("发起微信退款", e);
|
|
|
+ throw new BusinessException("操作失败,请稍后再试", e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void handleRefundNotify(WxPayRefundNotifyResult notifyResult) {
|
|
|
+ OrderInfo orderInfo = orderInfoRepo.findByTransactionId(notifyResult.getReqInfo().getTransactionId());
|
|
|
+
|
|
|
+ // 微信退款流水
|
|
|
+ WxFee wxFee = WxFee.builder()
|
|
|
+ .amount(BigDecimal.valueOf(notifyResult.getReqInfo().getRefundFee() / 100.0))
|
|
|
+ .isRefund(true)
|
|
|
+ .orderId(orderInfo.getId())
|
|
|
+ .type("refund")
|
|
|
+ .transactionId(notifyResult.getReqInfo().getRefundId())
|
|
|
+ .userId(orderInfo.getUserId())
|
|
|
+ .build();
|
|
|
+ wxFeeRepo.save(wxFee);
|
|
|
+
|
|
|
+ // 订单状态
|
|
|
+ orderInfo.setStatus(OrderInfoStatus.REFUNDED);
|
|
|
+ orderInfoRepo.save(orderInfo);
|
|
|
+
|
|
|
+ // 退款状态
|
|
|
+ OrderRefund refund = orderRefundRepo.findByRefundId(notifyResult.getReqInfo().getRefundId());
|
|
|
+ refund.setStatus(RefundStatus.SUCCESS);
|
|
|
+ refund.setAuditTime(LocalDateTime.now());
|
|
|
+ }
|
|
|
+}
|