TRX преди 1 година
родител
ревизия
270d8d10f1

+ 8 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/dataConfig/OrderConfig.java

@@ -9,4 +9,12 @@ public class OrderConfig {
     // 订单最大有效时间 (默认设置)
     public static final Long orderExpirationTime = 5 * 60 * 1000L;
 
+    // 订单微信支付 回调的数据key
+    public static final String wxSurePaymentTypeOrderPay = "initWxSurePaymentTypeOrderPay";
+
+    // 退款的返回数据 meat key
+    public static final String refundKey = "refundKey";
+
+    // 退款后调用账单的说明
+    public static final String refundTransactionMsg = "refundTransactionMsg";
 }

+ 4 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/domain/payment/ExpenseFlow.java

@@ -229,6 +229,9 @@ public class ExpenseFlow extends SuperMain {
     @Schema(description = "退款订单号")
     private String refundNo;
 
+    @Schema(description = "退款后调用账单是否成功")
+    private Boolean refundTransactionIsSuccess = Boolean.FALSE;
+
     @Schema(description = "退款账单流量")
     private List<TransactionLogModel> refundTransactionIds = new ArrayList<TransactionLogModel>();
 
@@ -236,6 +239,7 @@ public class ExpenseFlow extends SuperMain {
     @DBRef(lazy = true)
     private RefundRecord refundRecord;
 
+
     //-------------------------结算信息 start ----------------
 
     @Schema(description = "结算状态")

+ 12 - 11
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/ExpenseFlowServiceImpl.java

@@ -448,6 +448,7 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
         String msg = "";
         ExpenseFlow expenseFlow = expenseFlowDao.findTopByPaymentNo(orderNo);
         if (ObjectUtils.isNotEmpty(expenseFlow)) {
+            expenseFlow.addMetaInfo(OrderConfig.wxSurePaymentTypeOrderPay, ret);
             // 支付结果状态
             switch (ret.getTradeState()) {
                 case "SUCCESS" -> {
@@ -489,20 +490,20 @@ public class ExpenseFlowServiceImpl extends SuperService implements ExpenseFlowS
                     msg = expenseFlow.getPayRemark();
                 }
             }
+
+            // 发送消息
+            SendMessageModel sendMessageModel = new SendMessageModel();
+            sendMessageModel.setMessage(JsonUtil.toJson(Map.of("status", status,
+                    "orderNo", expenseFlow.getPaymentNo(), "msg", msg, "type", "pay")));
+            String userId = expenseFlow.getUserId();
+            String topic = String.format("/wechat/pay/%s", userId);
+            sendMessageModel.setTopic(topic);
+            sendMessageModel.setUserId(userId);
+            log.info("mq topic : {}", topic);
+            mqttService.sendMessage(sendMessageModel);
         } else {
             log.error("wxSurePaymentTypeOrderPayCallSuccess 订单为空: {}", orderNo);
         }
-
-        // 发送消息
-        SendMessageModel sendMessageModel = new SendMessageModel();
-        sendMessageModel.setMessage(JsonUtil.toJson(Map.of("status", status,
-                "orderNo", expenseFlow.getPaymentNo(), "msg", msg)));
-        String userId = expenseFlow.getUserId();
-        String topic = String.format("/wechat/pay/%s", userId);
-        sendMessageModel.setTopic(topic);
-        sendMessageModel.setUserId(userId);
-        log.info("mq topic : {}", topic);
-        mqttService.sendMessage(sendMessageModel);
     }
 
     /**

+ 191 - 3
FullCardServer/src/main/java/com/zhongshu/card/server/core/service/payment/PayCallService.java

@@ -1,23 +1,29 @@
 package com.zhongshu.card.server.core.service.payment;
 
 import cn.hutool.json.JSONObject;
+import com.github.microservice.core.util.JsonUtil;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.pay.client.model.ledger.TransactionLogModel;
+import com.github.microservice.pay.client.model.weChatMiniApp.WeChatMiniAppRefundRet;
 import com.github.microservice.pay.client.ret.ResultState;
 import com.github.microservice.types.OrderState;
 import com.github.microservice.types.payment.PaymentType;
+import com.zhongshu.card.client.model.mqtt.SendMessageModel;
 import com.zhongshu.card.client.model.operLogs.OperationLogsAddParam;
 import com.zhongshu.card.client.model.pay.SatInfoModel;
+import com.zhongshu.card.client.model.pay.WeChatRefundParam;
 import com.zhongshu.card.client.model.payment.ExpenseRefundParam;
 import com.zhongshu.card.client.type.LogsLevel;
 import com.zhongshu.card.client.type.MessageType;
 import com.zhongshu.card.client.type.RefundState;
+import com.zhongshu.card.client.type.payAccount.RechargeOrderStatus;
 import com.zhongshu.card.client.type.payment.OrderNoType;
 import com.zhongshu.card.client.type.payment.SettlementState;
 import com.zhongshu.card.client.utils.DateUtils;
 import com.zhongshu.card.client.utils.PayExceptionToShowUtil;
 import com.zhongshu.card.server.core.dao.payment.ExpenseFlowDao;
 import com.zhongshu.card.server.core.dao.payment.PaymentProcessDao;
+import com.zhongshu.card.server.core.dataConfig.OrderConfig;
 import com.zhongshu.card.server.core.domain.org.Organization;
 import com.zhongshu.card.server.core.domain.paySetting.ProjectMainPaySetting;
 import com.zhongshu.card.server.core.domain.paySetting.ProjectOrgPaySettingInfo;
@@ -28,10 +34,12 @@ import com.zhongshu.card.server.core.domain.schedule.ScheduleTaskConfig;
 import com.zhongshu.card.server.core.model.pay.UnionFrictionlessPayFinishModel;
 import com.zhongshu.card.server.core.service.base.CommonService;
 import com.zhongshu.card.server.core.service.base.SuperService;
+import com.zhongshu.card.server.core.service.mqtt.MqttServiceImpl;
 import com.zhongshu.card.server.core.service.orgManager.ProjectBindOrgServiceImpl;
 import com.zhongshu.card.server.core.service.pay.BalancePayService;
 import com.zhongshu.card.server.core.service.pay.ChinaumsSenselessPayService;
 import com.zhongshu.card.server.core.service.pay.SettleService;
+import com.zhongshu.card.server.core.service.pay.WechatPayService;
 import com.zhongshu.card.server.core.service.paySetting.PayOrderSettingService;
 import com.zhongshu.card.server.core.service.paySetting.ProjectMainPaySettingService;
 import com.zhongshu.card.server.core.service.user.OperationLogsService;
@@ -92,6 +100,12 @@ public class PayCallService extends SuperService {
     @Autowired
     private ProjectMainPaySettingService projectMainPaySettingService;
 
+    @Autowired
+    private WechatPayService wechatPayService;
+
+    @Autowired
+    private MqttServiceImpl mqttService;
+
     /**
      * 统一调用支付服务 (无感方式,直接后台 扣款)
      *
@@ -325,9 +339,7 @@ public class PayCallService extends SuperService {
         List<SatInfoModel> satInfoModel = buildShare(entity, paymentProcess.getPaymentType());
 
         // 调用支付
-        com.github.microservice.net.ResultContent resultContent = chinaumsSenselessPayService.senselessPay(
-                entity.getProjectOid(), entity.getShopOid(), entity.getUserId(),
-                payAmount, entity.getPaymentNo(), entity.getRemark(), satInfoModel);
+        com.github.microservice.net.ResultContent resultContent = chinaumsSenselessPayService.senselessPay(entity.getProjectOid(), entity.getShopOid(), entity.getUserId(), payAmount, entity.getPaymentNo(), entity.getRemark(), satInfoModel);
         if (resultContent.getState() == com.github.microservice.net.ResultState.Success) {
             // 关联参数
             String msg = "支付中";
@@ -491,6 +503,9 @@ public class PayCallService extends SuperService {
         } else if (entity.getPaymentType() == PaymentType.UnionFrictionlessPay) {
             // 云闪付退款
             return unionFrictionlessPayRefund(entity, param);
+        } else if (entity.getPaymentType() == PaymentType.WeChatPay) {
+            // 微信支付退款
+            return wxChatPayRefund(entity, param);
         }
         return ResultContent.buildFail("不支持退款");
     }
@@ -560,6 +575,179 @@ public class PayCallService extends SuperService {
         }
     }
 
+    /**
+     * 微信支付退款
+     *
+     * @param entity
+     * @param param
+     * @return
+     */
+    public ResultContent wxChatPayRefund(ExpenseFlow entity, ExpenseRefundParam param) {
+        String refundNo = NextNoUtil.getNextPaymentNo("RE");
+        entity.setRefundNo(refundNo);
+        entity.setRefundRemark(param.getRemark());
+        entity.setRefundTime(System.currentTimeMillis());
+        // 申请人
+        entity.setApplicant(getCurrentUserId());
+        // 退款人
+        entity.setRefundUserId(getCurrentUserId());
+        // 退款金额
+        entity.setRefundAMount(entity.getPayAmount());
+
+        orderNoInfoService.saveInfo(refundNo, OrderNoType.Refund, entity.getPaymentType());
+
+        // 退款记录
+        RefundRecord refundRecord = new RefundRecord();
+        refundRecord.setPaymentNo(entity.getPaymentNo());
+        // 申请人
+        refundRecord.setApplicant(getCurrentUserId());
+        BigDecimal payAmount = entity.getPayAmount();
+        refundRecord.setRefundAMount(payAmount);
+        refundRecord.setRefundTime(System.currentTimeMillis());
+        refundRecord.setRefundRemark(param.getRemark());
+        refundRecord.setRefundNo(refundNo);
+        refundRecord.setProjectOid(entity.getProjectOid());
+        refundRecord.setPaymentType(entity.getPaymentType());
+
+        // 退款记录
+        WeChatRefundParam refundParam = new WeChatRefundParam();
+        refundParam.setOid(entity.getShopOid());
+        refundParam.setOrderNo(entity.getPaymentNo());
+        // 退款订单号
+        refundParam.setRefundOrderNo(refundNo);
+        refundParam.setReason(param.getRemark());
+        refundParam.setTotal(entity.getPayAmount());
+        refundParam.setRefundTotal(entity.getPayAmount());
+
+        try {
+            ResultContent<WeChatMiniAppRefundRet> resultContent = wechatPayService.refund(refundParam);
+            if (resultContent.isSuccess()) {
+                entity.setRefundState(RefundState.Refunding);
+
+
+                refundRecord.setRefundState(RefundState.Refunding);
+                refundRecordService.saveEntity(refundRecord);
+
+                entity.setRefundRecord(refundRecord);
+                expenseFlowDao.save(entity);
+
+                return ResultContent.buildSuccess();
+            } else {
+                refundRecord.setRefundUserId(getCurrentUserId());
+                refundRecord.setExamineTime(System.currentTimeMillis());
+                refundRecord.setRefuseRemark(resultContent.getMsg());
+                refundRecord.setRefundState(RefundState.Fail);
+                refundRecordService.saveEntity(refundRecord);
+                return ResultContent.buildFail(String.format("发起退款失败:%s", resultContent.getMsg()));
+            }
+        } catch (Exception e) {
+            refundRecord.setRefundUserId(getCurrentUserId());
+            refundRecord.setExamineTime(System.currentTimeMillis());
+            refundRecord.setRefuseRemark(e.getMessage());
+            refundRecord.setRefundState(RefundState.Fail);
+            refundRecordService.saveEntity(refundRecord);
+            log.error(String.format("wxChatPayRefund: {}", e.getMessage()));
+            return ResultContent.buildFail(String.format("发起退款出错:%s", e.getMessage()));
+        }
+    }
+
+    /**
+     * 退款结果处理
+     */
+    public void handleWxChatPayRefund(WeChatMiniAppRefundRet ret) {
+        String paymentNo = ret.getOutTradeNo();
+        ExpenseFlow entity = expenseFlowDao.findTopByPaymentNo(paymentNo);
+        if (ObjectUtils.isNotEmpty(entity)) {
+            entity.addMetaInfo(OrderConfig.refundKey, ret);
+
+            String status = "";
+            String msg = "";
+            String refundNo = entity.getRefundNo();
+            RefundState refundState = null;
+            List<TransactionLogModel> transactionLogModelList = null;
+
+            // 支付结果状态
+            switch (ret.getStatus()) {
+                case "SUCCESS" -> {
+                    status = RechargeOrderStatus.Success.name();
+                    msg = "退款成功";
+                    entity.setIsRefund(Boolean.TRUE);
+                    entity.setRefundState(RefundState.Refunded);
+                    entity.setOrderState(OrderState.REFUNDED);
+                    entity.setRefundRemark("退款成功");
+                    refundState = RefundState.Refunded;
+
+                    com.github.microservice.pay.client.ret.ResultContent<List<TransactionLogModel>> content = wechatPayService.handleRefundTransactions(entity.getProjectOid(), entity.getShopOid(), entity.getUserId(), entity.getRefundNo(), entity.getRefundAMount());
+                    if (content.getState() == ResultState.Success) {
+                        transactionLogModelList = content.getContent();
+                        entity.setRefundTransactionIsSuccess(Boolean.TRUE);
+                    } else {
+                        entity.setRefundTransactionIsSuccess(Boolean.FALSE);
+                        entity.addMetaInfo(OrderConfig.refundTransactionMsg, content.getMsg());
+                    }
+                }
+                case "PAYERROR", "ABNORMAL" -> {
+                    status = RechargeOrderStatus.Fail.name();
+                    entity.setIsRefund(Boolean.FALSE);
+                    entity.setRefundState(RefundState.Refuse);
+                    entity.setRefundRemark("退款失败");
+                    refundState = RefundState.Refuse;
+                    msg = "退款失败";
+                }
+                case "CLOSED" -> {
+                    status = RechargeOrderStatus.Fail.name();
+                    entity.setIsRefund(Boolean.FALSE);
+                    entity.setRefundState(RefundState.Refuse);
+                    entity.setRefundRemark("退款失败");
+                    refundState = RefundState.Refuse;
+                    msg = "退款失败";
+                }
+            }
+            entity.setRefundTransactionIds(transactionLogModelList);
+            // 订单信息的维护
+            expenseFlowDao.save(entity);
+
+            refundRecordService.markState(refundNo, refundState, transactionLogModelList);
+
+            // 发送消息
+            SendMessageModel sendMessageModel = new SendMessageModel();
+            sendMessageModel.setMessage(JsonUtil.toJson(Map.of("status", status, "orderNo", entity.getRefundNo(), "msg", msg, "type", "refund")));
+            String userId = entity.getUserId();
+            String topic = String.format("/wechat/pay/%s", userId);
+            sendMessageModel.setTopic(topic);
+            sendMessageModel.setUserId(userId);
+            log.info("mq topic : {}", topic);
+            mqttService.sendMessage(sendMessageModel);
+        } else {
+            log.error("handleWxChatPayRefund 微信支付退款回调未找到订单: {}", paymentNo);
+        }
+
+
+//        entity.setIsRefund(Boolean.TRUE);
+//        entity.setRefundRemark(param.getRemark());
+//        entity.setRefundTime(System.currentTimeMillis());
+//
+//        List<TransactionLogModel> list = resultContent.getContent();
+//        if (ObjectUtils.isNotEmpty(list)) {
+//            entity.setRefundTransactionIds(list);
+//        }
+
+//        // 订单状态
+//        entity.setOrderState(OrderState.REFUNDED);
+//        // 退款状态
+//        entity.setRefundState(RefundState.Refunded);
+//        entity.setRefuseRemark("退款成功");
+//        expenseFlowDao.save(entity);
+//
+//        // 保存退款记录
+//        refundRecord.setRefundUserId(getCurrentUserId());
+//        refundRecord.setExamineTime(System.currentTimeMillis());
+//        refundRecord.setRefuseRemark("退款成功");
+//        refundRecord.setRefundState(RefundState.Refunded);
+//        refundRecord.setRefundTransactionIds(list);
+//        refundRecordService.saveEntity(refundRecord);
+    }
+
     /**
      * 云闪付开始退款
      *

+ 5 - 0
FullCardServer/src/main/java/com/zhongshu/card/server/core/stream/WeChatMiniAppReFundStream.java

@@ -4,6 +4,7 @@ import com.github.microservice.app.stream.StreamConsumer;
 import com.github.microservice.pay.client.model.weChatMiniApp.WeChatMiniAppPayRet;
 import com.github.microservice.pay.client.model.weChatMiniApp.WeChatMiniAppRefundRet;
 import com.zhongshu.card.server.core.service.pay.BalancePayService;
+import com.zhongshu.card.server.core.service.payment.PayCallService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -15,8 +16,12 @@ public class WeChatMiniAppReFundStream extends StreamConsumer<WeChatMiniAppRefun
     @Autowired
     BalancePayService balancePayService;
 
+    @Autowired
+    private PayCallService payCallService;
+
     @Override
     public void accept(WeChatMiniAppRefundRet weChatMiniAppRefundRet) {
         log.info("---------------收到微信退款结果通知广播----------------");
+        payCallService.handleWxChatPayRefund(weChatMiniAppRefundRet);
     }
 }