wlzboy
2025-12-03 656d6f8029f8bf9b2daa9dcc89101a879a70b860
dryad-payment/src/main/java/com/ruoyi/payment/application/service/PaymentService.java
@@ -12,6 +12,7 @@
import com.ruoyi.payment.infrastructure.channel.wechat.WxPayV2Client;
import com.ruoyi.payment.infrastructure.config.AlipayConfig;
import com.ruoyi.payment.infrastructure.config.QrCodeConfig;
import com.ruoyi.payment.infrastructure.config.WechatPayConfig;
import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentOrderMapper;
import com.ruoyi.payment.infrastructure.persistence.mapper.PaymentTransactionMapper;
import com.ruoyi.payment.infrastructure.util.QrCodeUtil;
@@ -60,6 +61,9 @@
    @Autowired
    private AlipayConfig alipayConfig;
    @Autowired
    private WechatPayConfig wechatPayConfig;
    /**
     * 发起微信Native支付
     */
@@ -99,6 +103,7 @@
        requestParams.put("bizOrderId", request.getBizOrderId());
        requestParams.put("amount", request.getAmount());
        requestParams.put("subject", request.getSubject());
        requestParams.put("notifyUrl",wechatPayConfig.getNotifyUrl());
        transaction.setRequestParams(JSON.toJSONString(requestParams));
        paymentTransactionMapper.insert(transaction);
@@ -150,6 +155,7 @@
        requestParams.put("bizOrderId", request.getBizOrderId());
        requestParams.put("amount", request.getAmount());
        requestParams.put("subject", request.getSubject());
        requestParams.put("notifyUrl",alipayConfig.getNotifyUrl());
        transaction.setRequestParams(JSON.toJSONString(requestParams));
        paymentTransactionMapper.insert(transaction);
@@ -202,6 +208,7 @@
        requestParams.put("amount", request.getAmount());
        requestParams.put("subject", request.getSubject());
        requestParams.put("thirdParty", true);
        requestParams.put("notifyUrl",alipayConfig.getThirdParty().getDefaultNotifyUrl());
        transaction.setRequestParams(JSON.toJSONString(requestParams));
        paymentTransactionMapper.insert(transaction);
@@ -283,11 +290,11 @@
    private String callAlipayThirdPartyPrecreate(PaymentOrder order, PaymentRequest request) {
        try {
            // 使用AlipayConfig中配置的回调地址
            String notifyUrl = alipayConfig.getNotifyUrl();
            String notifyUrl = alipayConfig.getThirdParty().getDefaultNotifyUrl();
            String outTradeNo = String.valueOf(order.getId());
            Integer totalFee = order.getAmount(); // 单位:分
            String serviceOrdId = request.getBizOrderId(); // 业务订单ID
            return alipayThirdPartyClient.createQrCodeUrl(notifyUrl, outTradeNo, totalFee, serviceOrdId);
        } catch (Exception e) {
            log.error("调用第三方支付宝接口失败", e);
@@ -335,4 +342,298 @@
            throw new RuntimeException("查询交易状态失败: " + e.getMessage(), e);
        }
    }
}
    /**
     * 轮询查询支付状态(用于回调失败的补偿机制)
     * 支持微信和支付宝
     *
     * @param orderId 订单ID
     * @return 轮询结果(包含订单状态和交易状态)
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> pollPaymentStatus(Long orderId) {
        log.info("开始轮询查询支付状态,订单ID: {}", orderId);
        Map<String, Object> result = new HashMap<>();
        // 1. 查询订单信息
        PaymentOrder order = paymentOrderMapper.selectById(orderId);
        if (order == null) {
            log.error("订单不存在,订单ID: {}", orderId);
            throw new RuntimeException("订单不存在");
        }
        // 如果订单已经是成功状态,直接返回
        if (OrderStatus.SUCCEEDED.getCode().equals(order.getStatus())) {
            log.info("订单已成功,无需轮询,订单ID: {}", orderId);
            result.put("orderStatus", order.getStatus());
            result.put("needPoll", false);
            result.put("message", "订单已成功");
            return result;
        }
        // 2. 查询最新交易记录
        PaymentTransaction transaction = paymentTransactionMapper.selectLatestByOrderId(orderId);
        if (transaction == null) {
            log.error("未找到交易记录,订单ID: {}", orderId);
            throw new RuntimeException("未找到交易记录");
        }
        // 如果交易已成功,但订单状态未更新,更新订单状态
        if (TransactionStatus.SUCCEEDED.getCode().equals(transaction.getStatus())) {
            log.info("交易已成功,同步订单状态,订单ID: {}", orderId);
            order.setStatus(OrderStatus.SUCCEEDED.getCode());
            order.setUpdatedAt(LocalDateTime.now());
            paymentOrderMapper.update(order);
            result.put("orderStatus", OrderStatus.SUCCEEDED.getCode());
            result.put("transactionStatus", transaction.getStatus());
            result.put("needPoll", false);
            result.put("message", "支付成功");
            return result;
        }
        // 3. 根据支付渠道调用相应的查询接口
        String channel = order.getChannel();
        boolean paymentSuccess = false;
        String tradeStatus = null;
        try {
            if (PayChannel.WECHAT.getCode().equals(channel)) {
                // 查询微信支付状态
                paymentSuccess = queryWechatPaymentStatus(order, transaction);
                tradeStatus = paymentSuccess ? "SUCCESS" : "NOTPAY";
                result.put("paymethod","WECHAT");
            } else if (PayChannel.ALIPAY.getCode().equals(channel)) {
                // 判断是否为第三方支付宝
                boolean isThirdParty = isThirdPartyAlipay(transaction);
                result.put("paymethod","ALIPAY");
                if (isThirdParty) {
                    // 查询第三方支付宝状态
                    tradeStatus = queryAlipayThirdPartyTradeStatus(orderId);
                    paymentSuccess = "SUCCESS".equals(tradeStatus);
                } else {
                    // 查询官方支付宝状态
                    paymentSuccess = queryAlipayPaymentStatus(order, transaction);
                    tradeStatus = paymentSuccess ? "TRADE_SUCCESS" : "WAIT_BUYER_PAY";
                }
            } else {
                log.error("不支持的支付渠道: {}", channel);
                throw new RuntimeException("不支持的支付渠道");
            }
        } catch (Exception e) {
            log.error("查询支付状态异常,订单ID: {}", orderId, e);
            result.put("orderStatus", order.getStatus());
            result.put("transactionStatus", transaction.getStatus());
            result.put("needPoll", true);
            result.put("error", e.getMessage());
            result.put("message", "查询异常,请稍后重试");
            return result;
        }
        // 4. 如果支付成功,更新订单和交易状态
        if (paymentSuccess) {
            log.info("轮询查询发现支付成功,订单ID: {}, 交易状态: {}", orderId, tradeStatus);
            // 更新交易状态
            transaction.setStatus(TransactionStatus.SUCCEEDED.getCode());
            transaction.setPaidAt(LocalDateTime.now());
            paymentTransactionMapper.update(transaction);
            // 更新订单状态
            order.setStatus(OrderStatus.SUCCEEDED.getCode());
            order.setUpdatedAt(LocalDateTime.now());
            paymentOrderMapper.update(order);
            result.put("orderStatus", OrderStatus.SUCCEEDED.getCode());
            result.put("transactionStatus", TransactionStatus.SUCCEEDED.getCode());
            result.put("tradeStatus", tradeStatus);
            result.put("needPoll", false);
            result.put("message", "支付成功");
            log.info("轮询查询处理完成,订单和交易状态已更新,订单ID: {}", orderId);
        } else {
            log.info("轮询查询,支付尚未完成,订单ID: {}, 交易状态: {}", orderId, tradeStatus);
            result.put("orderStatus", order.getStatus());
            result.put("transactionStatus", transaction.getStatus());
            result.put("tradeStatus", tradeStatus);
            result.put("needPoll", true);
            result.put("message", "支付尚未完成,请继续轮询");
        }
        return result;
    }
    /**
     * 查询微信支付状态
     */
    private boolean queryWechatPaymentStatus(PaymentOrder order, PaymentTransaction transaction) throws Exception {
        log.info("查询微信支付状态,订单ID: {}", order.getId());
        String outTradeNo = String.valueOf(order.getId());
        Map<String, String> queryResult = wxPayV2Client.queryOrder(outTradeNo);
        // 检查业务结果
        if (!"SUCCESS".equals(queryResult.get("result_code"))) {
            log.warn("微信订单查询业务失败: {}", queryResult.get("err_code_des"));
            return false;
        }
        // 检查交易状态
        String tradeState = queryResult.get("trade_state");
        log.info("微信订单状态: {}", tradeState);
        return "SUCCESS".equals(tradeState);
    }
    /**
     * 查询支付宝支付状态(官方接口)
     */
    private boolean queryAlipayPaymentStatus(PaymentOrder order, PaymentTransaction transaction) throws Exception {
        log.info("查询支付宝支付状态,订单ID: {}", order.getId());
        String outTradeNo = String.valueOf(order.getId());
        com.alipay.api.response.AlipayTradeQueryResponse queryResult = alipayF2FClient.queryOrder(outTradeNo);
        // 检查交易状态
        String tradeStatus = queryResult.getTradeStatus();
        log.info("支付宝订单状态: {}", tradeStatus);
        log.info("支付宝订单查询结果: {}", queryResult.getBody());
        // TRADE_SUCCESS 或 TRADE_FINISHED 表示支付成功
        return "TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus);
    }
    /**
     * 判断是否为第三方支付宝
     */
    private boolean isThirdPartyAlipay(PaymentTransaction transaction) {
        if (transaction.getRequestParams() == null) {
            return false;
        }
        try {
            Map<String, Object> params = JSON.parseObject(transaction.getRequestParams(), Map.class);
            return params.containsKey("thirdParty") && Boolean.TRUE.equals(params.get("thirdParty"));
        } catch (Exception e) {
            log.warn("解析交易请求参数失败", e);
            return false;
        }
    }
    /**
     * 根据交易单号查询微信支付状态
     *
     * @param outTradeNo 商户订单号(交易单号)
     * @return 交易状态信息
     */
    public Map<String, Object> queryWechatTradeByOutTradeNo(String outTradeNo) {
        log.info("根据交易单号查询微信支付状态,商户订单号: {}", outTradeNo);
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, String> queryResult = wxPayV2Client.queryOrder(outTradeNo);
            // 检查调用是否成功
            if (!"SUCCESS".equals(queryResult.get("return_code"))) {
                result.put("success", false);
                result.put("message", "微信查询接口调用失败: " + queryResult.get("return_msg"));
                return result;
            }
            // 检查业务结果
            if (!"SUCCESS".equals(queryResult.get("result_code"))) {
                result.put("success", false);
                result.put("message", "微信订单查询业务失败: " + queryResult.get("err_code_des"));
                result.put("errorCode", queryResult.get("err_code"));
                return result;
            }
            // 返回交易信息
            result.put("success", true);
            result.put("tradeState", queryResult.get("trade_state")); // 交易状态
            result.put("tradeStateDesc", queryResult.get("trade_state_desc")); // 交易状态描述
            result.put("outTradeNo", queryResult.get("out_trade_no")); // 商户订单号
            result.put("transactionId", queryResult.get("transaction_id")); // 微信支付订单号
            result.put("totalFee", queryResult.get("total_fee")); // 订单金额(分)
            result.put("timeEnd", queryResult.get("time_end")); // 支付完成时间
            result.put("openid", queryResult.get("openid")); // 用户标识
            // 判断是否支付成功
            boolean isPaid = "SUCCESS".equals(queryResult.get("trade_state"));
            result.put("isPaid", isPaid);
            result.put("message", isPaid ? "支付成功" : "支付未完成");
            log.info("微信交易查询成功,交易状态: {}", queryResult.get("trade_state"));
        } catch (Exception e) {
            log.error("查询微信交易状态异常,商户订单号: {}", outTradeNo, e);
            result.put("success", false);
            result.put("message", "查询异常: " + e.getMessage());
        }
        return result;
    }
    /**
     * 根据交易单号查询支付宝支付状态
     *
     * @param outTradeNo 商户订单号(交易单号)
     * @return 交易状态信息
     */
    public Map<String, Object> queryAlipayTradeByOutTradeNo(String outTradeNo) {
        log.info("根据交易单号查询支付宝支付状态,商户订单号: {}", outTradeNo);
        Map<String, Object> result = new HashMap<>();
        try {
            com.alipay.api.response.AlipayTradeQueryResponse queryResult = alipayF2FClient.queryOrder(outTradeNo);
            // 检查调用是否成功
            if (!queryResult.isSuccess()) {
                result.put("success", false);
                result.put("message", "支付宝查询失败: " + queryResult.getSubMsg());
                result.put("errorCode", queryResult.getSubCode());
                return result;
            }
            // 返回交易信息
            result.put("success", true);
            result.put("tradeStatus", queryResult.getTradeStatus()); // 交易状态
            result.put("outTradeNo", queryResult.getOutTradeNo()); // 商户订单号
            result.put("tradeNo", queryResult.getTradeNo()); // 支付宝交易号
            result.put("totalAmount", queryResult.getTotalAmount()); // 订单金额(元)
            result.put("buyerPayAmount", queryResult.getBuyerPayAmount()); // 买家实际支付金额
            result.put("sendPayDate", queryResult.getSendPayDate()); // 交易支付时间
            result.put("buyerLogonId", queryResult.getBuyerLogonId()); // 买家支付宝账号
            // 判断是否支付成功
            String tradeStatus = queryResult.getTradeStatus();
            boolean isPaid = "TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus);
            result.put("isPaid", isPaid);
            // 状态说明
            String message;
            if ("TRADE_SUCCESS".equals(tradeStatus)) {
                message = "交易支付成功";
            } else if ("TRADE_FINISHED".equals(tradeStatus)) {
                message = "交易结束,不可退款";
            } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                message = "交易创建,等待买家付款";
            } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                message = "未付款交易超时关闭,或支付完成后全额退款";
            } else {
                message = "未知状态: " + tradeStatus;
            }
            result.put("message", message);
            log.info("支付宝交易查询成功,交易状态: {}", tradeStatus);
        } catch (Exception e) {
            log.error("查询支付宝交易状态异常,商户订单号: {}", outTradeNo, e);
            result.put("success", false);
            result.put("message", "查询异常: " + e.getMessage());
        }
        return result;
    }
}