package com.slodon.b2b2c.controller.business.front;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.XmlUtil;
import com.alipay.api.internal.util.AlipaySignature;
import com.gexin.fastjson.JSON;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.paypal.api.payments.*;
import com.paypal.base.rest.APIContext;
import com.slodon.b2b2c.business.example.OrderExample;
import com.slodon.b2b2c.business.pojo.Order;
import com.slodon.b2b2c.business.pojo.OrderPay;
import com.slodon.b2b2c.core.constant.OrderConst;
import com.slodon.b2b2c.core.constant.PayConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.response.WxPayCallbackVO;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.core.util.XmlUtils;
import com.slodon.b2b2c.model.business.OrderModel;
import com.slodon.b2b2c.model.business.OrderPayModel;
import com.slodon.b2b2c.starter.entity.*;
import com.slodon.b2b2c.starter.pay.SlodonPay;
import com.slodon.b2b2c.util.PayPropertiesUtil;
import cpcn.institution.tools.util.Base64;
import cpcn.institution.tools.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import payment.api.notice.Notice5018Request;
import payment.api.notice.NoticeRequest;
import payment.api.notice.NoticeResponse;

import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单支付回调controller
 */
@Slf4j
@RestController
@RequestMapping("v3/business/front/orderPayCallback")
public class FrontOrderPayCallbackController extends BaseController {

    @Resource
    private PayPropertiesUtil payPropertiesUtil;
    @Resource
    private SlodonPay slodonPay;
    @Resource
    private OrderPayModel orderPayModel;
    @Resource
    private OrderModel orderModel;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 微信返回  fail 失败，success 成功
     */
    private static final String RETURN_CODE_SUCCESS = "SUCCESS";
    private static final String RETURN_MSG_OK = "OK";
    private static final String RETURN_CODE_FAIL = "FAIL";

    /**
     * 订单支付支付宝回调
     *
     * @param request  request
     * @param response response
     */
    @PostMapping("ali")
    public void aliPayCallback(HttpServletRequest request, HttpServletResponse response) {
        log.debug("-----------------------------------------------------------------------------");
        log.debug("支付宝通知开始");
        log.debug("-----------------------------------------------------------------------------");
        try {
            //获取支付宝post过来的反馈信息 map
            HashMap<String, String> params = new HashMap<>();
            //getParameterMap()一般多用于接收前台表单多参数传输的数据
            //支付宝的回调都是把信息放到request里面
            Map<String, String[]> parameterMap = request.getParameterMap();
            //迭代遍历,keySet()是获取所有的key值
            for (String name : parameterMap.keySet()) {
                String[] values = parameterMap.get(name);
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i]
                            : valueStr + values[i] + ",";
                }
                //赋值
                params.put(name, valueStr);
            }

            //调用SDK,验证签名
            AliPayProperties aliPayProperties = payPropertiesUtil.getAliPayProperties();
            //证书验签
            boolean signVerified = AlipaySignature.rsaCertCheckV1(params, aliPayProperties.aliPayPublicCertPath, aliPayProperties.inputCharset, aliPayProperties.signType);
            if (signVerified) {
                // TODO 验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商户自身业务处理，校验失败返回failure
                //获取支付宝的通知返回参数，可参考技术文档中页面跳转异步通知参数列表(以下仅供参考)//补:参考跳转checkPayState-->AlipayTradeQueryResponse
                //商户订单号
                String paySn = params.get("out_trade_no");
                //支付宝交易号
                String trade_no = params.get("trade_no");
                //交易金额
                String total_amount = params.get("total_amount");
                //交易状态
                String trade_status = params.get("trade_status");
                //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
                if ("TRADE_FINISHED".equals(trade_status)) {
                    //checkPayState 交易完成

//                    判断该笔订单是否在商户网站中已经做过处理
//                    如果没有做过处理，根据订单号（out_trade_no）在商户网站
//                    的订单系统中查到该笔订单的详细，并执行商户的业务程序
//                    请务必判断请求时的total_amount、seller_id与通知时获取的total_amount、seller_id为一致的
//                    如果有做过处理，不执行商户的业务程序
//
//                    注意：
//                    退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                } else if ("TRADE_SUCCESS".equals(trade_status)) {
                    //已支付
                    //判断该笔订单是否在商户网站中已经做过处理
                    OrderPay orderpay = orderPayModel.getOrderPayByPaySn(paySn);
                    if (OrderConst.API_PAY_STATE_1.equals(orderpay.getApiPayState())) {
                        //订单已支付，执行退款操作
                        if (orderpay.getPaymentCode().contains(PayConst.METHOD_ALIPAY.toUpperCase())) {
                            //重复回调，不处理，直接返回成功
                            response.getWriter().println(RETURN_CODE_SUCCESS);
                            return;
                        }
                        //其他方式已支付，如余额、微信，执行退款
                        this.aliRefund(paySn, orderpay.getTradeSn(), new BigDecimal(total_amount));
                        response.getWriter().println(RETURN_CODE_SUCCESS);
                        return;
                    }

                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_amount、seller_id与通知时获取的total_amount、seller_id 为一致的
                    // 1-开启测试, 0-关闭测试
                    if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                        //不校验支付额
                    } else {
                        if (!total_amount.equals(this.getPayAmountDb(paySn).toString())) {
                            log.error("订单支付金额不一致paySn:" + paySn);
                            response.getWriter().println("fail");
                            //订单金额不一致不往下执行
                            return;
                        }
                    }

                    //如果有做过处理，不执行商户的业务程序
                    //更改订单状态
                    OrderExample example = new OrderExample();
                    example.setPaySn(paySn);
                    List<Order> list = orderModel.getOrderList(example, null);
                    for (Order order : list) {
                        if (order.getOrderState() == OrderConst.ORDER_STATE_0) {
                            BigDecimal payAmount;
                            if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                                payAmount = new BigDecimal("0.01");
                            } else {
                                payAmount = order.getPayAmount();
                            }
                            //订单已取消，执行退款
                            this.aliRefund(order.getOrderSn(), trade_no, payAmount);
                        } else {
                            if (order.getOrderState() == OrderConst.ORDER_STATE_10) {
                                //支付成功
                                orderPayModel.orderPaySuccess(order.getOrderSn(), paySn, trade_no, order.getBalanceAmount(),
                                        order.getOrderAmount().subtract(order.getBalanceAmount()).subtract(order.getPayAmount()),
                                        order.getPaymentCode(), order.getPaymentName(),
                                        order.getOrderType(), order.getMemberId(), order.getMemberName());
                            }
                        }
                    }
                    //请不要修改或删除
                    response.getWriter().println(RETURN_CODE_SUCCESS);
                }
            } else {
                // TODO 验签失败则记录异常日志，并在response中返回failure.
                log.error("验签失败");
                response.getWriter().println("fail");
            }
        } catch (Exception e) {
            log.error("支付宝通知失败", e);
        }
    }

    /**
     * 订单支付微信回调
     *
     * @param request  request
     * @param response response
     */
    @PostMapping("wx")
    public void wxPayCallback(HttpServletRequest request, HttpServletResponse response) {
        log.debug("-----------------------------------------------------------------------------");
        log.debug("微信通知开始");
        log.debug("-----------------------------------------------------------------------------");
        ServletInputStream in;

        try {
            // post 过来的xml
            in = request.getInputStream();
            //转换微信post过来的xml内容
            String notifyData = IoUtil.read(in, StandardCharsets.UTF_8);

            WxPayCallbackVO vo = XmlUtils.convertToObject(notifyData, WxPayCallbackVO.class);

            String outTradeNo = vo.getOut_trade_no();
            //格式为paySn_payType，截取paySn
            String paySn = outTradeNo.split("_")[0];
            String payType = outTradeNo.split("_")[1];
            log.error("通知开始...." + paySn);

            //微信支付配置
            WxPayProperties wxPayProperties = payPropertiesUtil.getWxPayProperties(payType);
            WxPayServiceImpl wxPayService = new WxPayServiceImpl();
            WxPayConfig wxPayConfig = new WxPayConfig();
            wxPayConfig.setAppId(StringUtils.trimToNull(wxPayProperties.getAppId()));
            wxPayConfig.setMchId(StringUtils.trimToNull(wxPayProperties.getMchId()));
            wxPayConfig.setMchKey(StringUtils.trimToNull(wxPayProperties.getMchKey()));
            wxPayService.setConfig(wxPayConfig);

            //处理xml
            WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(notifyData);

            //调用SDK,验证签名
            notifyResult.checkResult(wxPayService, notifyResult.getSignType(), true);

            // 签名正确
            // 进行处理。
            // 注意特殊情况：订单已经退款，但收到了支付结果成功的通知，不应把商户侧订单状态从退款改成支付成功
            //安全校验(比较订单金额)二次校验
            OrderPay orderpay = orderPayModel.getOrderPayByPaySn(paySn);
            if (OrderConst.API_PAY_STATE_1.equals(orderpay.getApiPayState())) {
                //订单已支付
                if (orderpay.getPaymentCode().contains(PayConst.METHOD_WX.toUpperCase()) &&
                        orderpay.getPaymentCode().contains(payType)) {
                    //同一客户端重复回调，不做处理
                    sendMsg(response);
                    return;
                }
                //不同客户端重复支付，执行退款
                this.wxRefund(orderpay.getPaySn(), orderpay.getTradeSn(), payType, notifyResult.getTotalFee());
                sendMsg(response);
                return;
            }
            // 1-开启测试, 0-关闭测试
            if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                //不校验支付额
            } else {
                int totalFeeDb = this.getPayAmountDb(paySn).multiply(new BigDecimal(100)).intValue();
                if (totalFeeDb != notifyResult.getTotalFee()) {
                    log.error("订单支付金额不一致paySn:" + paySn);
                    response.getWriter().println("fail");
                    //订单金额不一致不往下执行
                    return;
                }
            }
            //如果有做过处理，不执行商户的业务程序
            //更改订单状态
            OrderExample example = new OrderExample();
            example.setPaySn(paySn);
            List<Order> list = orderModel.getOrderList(example, null);
            for (Order order : list) {
                if (order.getOrderState() == OrderConst.ORDER_STATE_0) {
                    BigDecimal payAmount;
                    if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                        payAmount = new BigDecimal("0.01");
                    } else {
                        payAmount = order.getPayAmount();
                    }
                    //订单已取消，执行退款
                    this.wxRefund(order.getOrderSn(), notifyResult.getTransactionId(), payType, payAmount.multiply(new BigDecimal("100")).intValue());
                } else {
                    if (order.getOrderState() == OrderConst.ORDER_STATE_10) {
                        //支付成功
                        orderPayModel.orderPaySuccess(order.getOrderSn(), paySn, notifyResult.getTransactionId(), order.getBalanceAmount(),
                                order.getOrderAmount().subtract(order.getBalanceAmount()).subtract(order.getPayAmount()),
                                order.getPaymentCode(), order.getPaymentName(),
                                order.getOrderType(), order.getMemberId(), order.getMemberName());
                    }
                }
            }

            //返回微信应答报文,防止重复回调
            sendMsg(response);
        } catch (Exception e) {
            log.error("微信通知失败", e);
        }
    }

    /**
     * 订单支付payPal回调
     *
     * @param request  request
     * @param response response
     */
    @PostMapping("payPal")
    public void payPalPayCallback(HttpServletRequest request, HttpServletResponse response) {
        log.debug("-----------------------------------------------------------------------------");
        log.debug("payPal通知开始");
        log.debug("-----------------------------------------------------------------------------");
        try {
            String paymentId = request.getParameter("paymentId");
            String payerId = request.getParameter("PayerID");

            PayPalProperties payPalProperties = payPropertiesUtil.getPayPalProperties();
            APIContext apiContext = new APIContext(payPalProperties.getClientId(), payPalProperties.getSecret(), payPalProperties.getMode());

            Payment payment = new Payment();
            payment.setId(paymentId);
            PaymentExecution paymentExecute = new PaymentExecution();
            paymentExecute.setPayerId(payerId);
            Payment paymentResponse = payment.execute(apiContext, paymentExecute);
            log.info("回调信息：" + paymentResponse);
            if ("approved".equals(paymentResponse.getState())) {
                Transaction transaction = paymentResponse.getTransactions().get(0);
                RelatedResources resources = transaction.getRelatedResources().get(0);
                Amount amount = transaction.getAmount();
                String saleId = resources.getSale().getId();
                String totalAmount = amount.getTotal();
                String paySn = transaction.getCustom();

                //安全校验(比较订单金额)
                OrderPay orderPay = orderPayModel.getOrderPayByPaySn(paySn);
                if (orderPay == null) {
                    log.error("[FrontOrderPayCallbackController][getOrderPayByPaySn]订单支付信息获取失败paySn:" + paySn);
                    response.getWriter().println(RETURN_CODE_FAIL);
                    return;
                }

                if (OrderConst.API_PAY_STATE_1.equals(orderPay.getApiPayState())) {
                    //订单已支付，执行退款操作
                    if (orderPay.getPaymentCode().contains(PayConst.METHOD_PAYPAL.toUpperCase())) {
                        //重复回调，不处理，直接返回成功
                        response.getWriter().println(RETURN_CODE_SUCCESS);
                        return;
                    }
                    //其他方式已支付，如余额、微信、payPal，执行退款
                    this.payPalRefund(paySn, orderPay.getTradeSn(), new BigDecimal(totalAmount));
                    response.getWriter().println(RETURN_CODE_SUCCESS);
                    return;
                }

                // 1-开启测试, 0-关闭测试
                if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                    //不校验支付额
                } else {
                    if (!totalAmount.equals(this.getPayAmountDb(paySn).toString())) {
                        log.error("订单支付金额不一致paySn:" + paySn);
                        response.getWriter().println(RETURN_CODE_FAIL);
                        //订单金额不一致不往下执行
                        return;
                    }
                }

                //更改订单状态
                OrderExample example = new OrderExample();
                example.setPaySn(paySn);
                List<Order> list = orderModel.getOrderList(example, null);
                AssertUtil.notEmpty(list, "订单不存在");
                for (Order order : list) {
                    if (order.getOrderState() == OrderConst.ORDER_STATE_0) {
                        BigDecimal payAmount;
                        if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                            payAmount = new BigDecimal("0.01");
                        } else {
                            payAmount = order.getPayAmount();
                        }
                        //订单已取消，执行退款
                        this.payPalRefund(order.getOrderSn(), saleId, payAmount);
                    } else {
                        if (order.getOrderState() == OrderConst.ORDER_STATE_10) {
                            //支付成功
                            orderPayModel.orderPaySuccess(order.getOrderSn(), paySn, saleId, order.getBalanceAmount(),
                                    order.getOrderAmount().subtract(order.getBalanceAmount()).subtract(order.getPayAmount()),
                                    order.getPaymentCode(), order.getPaymentName(),
                                    order.getOrderType(), order.getMemberId(), order.getMemberName());
                        }
                    }
                }
            } else {
                log.error("回调状态state：{}", paymentResponse.getState());
                log.error("回调失败原因failed_transactions：{}", paymentResponse.getFailureReason());
                response.getWriter().println(RETURN_CODE_FAIL);
            }
        } catch (Exception e) {
            log.error("未知异常", e);
        }
    }

    /**
     * 订单支付中金回调
     */
    @PostMapping("zj")
    public void txPayCallback(HttpServletRequest request, HttpServletResponse response) {
        log.debug("=========================================");
        log.debug("中金支付回调开始");
        log.debug(JSON.toJSONString(request.getParameterMap()));
        log.debug("=========================================");

        try {
            // 1 获得参数message和signature
            String message = request.getParameter("message");
            String signature = request.getParameter("signature");
            String isDgEnv = request.getParameter("isDgEnv");
            String digitalEnvelope = request.getParameter("digitalEnvelope");
            String signAlgorithm = request.getParameter("signAlgorithm");
            String signSN = request.getParameter("signSN");
            String encryptSN = request.getParameter("encryptSN");

            // 2 生成交易结果对象
            NoticeRequest noticeRequest;
            if ("YES".equals(isDgEnv)) {
                //数字信封解密验签
                noticeRequest = new NoticeRequest(message, signature, digitalEnvelope, signSN, encryptSN, signAlgorithm);
            } else {
                //非数字信封解密验签
                if (StringUtil.isNotEmpty(signSN)) {
                    message = message + "," + signSN + "," + signAlgorithm;
                }
                noticeRequest = new NoticeRequest(message, signature);
            }

            Notice5018Request nr = new Notice5018Request(noticeRequest.getDocument());
            log.debug("=========================================");
            log.debug(JSON.toJSONString(nr));
            log.debug("=========================================");

            /*
            支付状态:
            10=未支付
            20=支付处理中
            30=支付成功
            40=支付失败
            50=订单关闭
             */
            String status = nr.getStatus();
            if ("30".equals(status)) {
                //只处理支付成功的情况
                String paySn = nr.getOrderNo();
                paySn = paySn.substring(0, paySn.length() - 6);

                BigDecimal payAmount = new BigDecimal(nr.getAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);//支付金额
                OrderPay orderpay = orderPayModel.getOrderPayByPaySn(paySn);
                if (OrderConst.API_PAY_STATE_1.equals(orderpay.getApiPayState())) {
                    //订单已支付，执行退款操作
                    SlodonRefundResponse refundResponse = orderPayModel.zjRefund(payAmount, paySn, nr.getTxSN(), nr.getInstitutionID());
                    AssertUtil.isTrue(!refundResponse.getSuccess(), "订单已支付，回调退款异常");
                    PrintWriter out = response.getWriter();
                    this.response(out);
                    out.flush();
                    out.close();
                    return;
                }

                // 1-开启测试, 0-关闭测试
                if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
                    //不校验支付额
                } else {
                    BigDecimal needPay = this.getPayAmountDb(paySn);//应付金额
                    if (payAmount.compareTo(needPay) != 0) {
                        log.error("订单支付金额不一致paySn:{}，回调金额：{},应付金额{}", paySn, payAmount, needPay);
                        throw new MallException("订单支付金额不一致");
                    }
                }

                //如果有做过处理，不执行商户的业务程序
                //更改订单状态
                OrderExample example = new OrderExample();
                example.setPaySn(paySn);
                example.setOrderState(OrderConst.ORDER_STATE_10);
                List<Order> list = orderModel.getOrderList(example, null);
                for (Order order : list) {
                    //支付成功
                    orderPayModel.orderPaySuccess(order.getOrderSn(), paySn, nr.getTxSN(), order.getBalanceAmount(),
                            order.getOrderAmount().subtract(order.getBalanceAmount()).subtract(order.getPayAmount()),
                            order.getPaymentCode(), order.getPaymentName(),
                            order.getOrderType(), order.getMemberId(), order.getMemberName());
                }
            }
            PrintWriter out = response.getWriter();
            this.response(out);
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error("中金支付回调异常：", e);

        }
    }

    /**
     * 给支付平台发送回调成功信息，发送后支付平台不再进行回调
     *
     * @param out 响应
     */
    private void response(PrintWriter out) {
        String xmlString = new NoticeResponse().getMessage();
        String base64String = new String(Base64.encode(xmlString.getBytes(StandardCharsets.UTF_8)));
        out.print(base64String);
    }

    /**
     * 获取三方支付实际应支付金额
     *
     * @param paySn paySn
     * @return 返回值
     */
    private BigDecimal getPayAmountDb(String paySn) {
        //查询订单
        OrderExample orderExample = new OrderExample();
        orderExample.setPaySn(paySn);
        orderExample.setOrderState(OrderConst.ORDER_STATE_10);
        List<Order> list = orderModel.getOrderList(orderExample, null);
        //三方支付实际应支付金额
        BigDecimal payAmount = BigDecimal.ZERO;
        for (Order order : list) {
            payAmount = payAmount.add(order.getOrderAmount().subtract(order.getBalanceAmount()).subtract(order.getPayAmount()));
        }
        return payAmount;
    }

    /**
     * 给微信反回应答报文，防止重复回调
     *
     * @param response response
     */
    private void sendMsg(HttpServletResponse response) {
        LinkedHashMap<String, String> responseMap = new LinkedHashMap<>();
        responseMap.put("return_code", RETURN_CODE_SUCCESS);
        responseMap.put("return_msg", RETURN_MSG_OK);
        String mapToXml = XmlUtil.mapToXmlStr(responseMap);
        response.setContentType("text/html;charset=utf-8");
        try (PrintWriter out = response.getWriter()) {
            out.print(mapToXml);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行微信退款
     *
     * @param refundSn 退款单号
     * @param tradeSn  交易流水号
     * @param payType  支付类型
     * @param totalFee 支付金额，单位分
     */
    private void wxRefund(String refundSn, String tradeSn, String payType, Integer totalFee) {
        SlodonRefundRequest refundRequest = new SlodonRefundRequest();

        //微信退款
        refundRequest.setWxPayProperties(payPropertiesUtil.getWxPayProperties(payType));
        //微信需要设置原支付金额
        BigDecimal payAmount = new BigDecimal(totalFee).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
        refundRequest.setTotalAmount(payAmount);
        refundRequest.setRefundAmount(payAmount);
        refundRequest.setTradeSn(tradeSn);
        refundRequest.setRefundSn(refundSn);
        try {
            SlodonRefundResponse refundResponse = slodonPay.refund(refundRequest, PayConst.METHOD_WX.toUpperCase());
            if (!refundResponse.getSuccess()) {
                log.error("微信重复支付退款失败，交易流水号：{}，失败原因：{}", tradeSn, refundResponse.getMsg());
            }
        } catch (Exception e) {
            log.error("微信重复支付退款失败，交易流水号：{}", tradeSn, e);
        }
    }

    /**
     * 支付宝退款
     *
     * @param refundSn     退款单号
     * @param tradeSn      交易流水号
     * @param refundAmount 退款金额
     */
    private void aliRefund(String refundSn, String tradeSn, BigDecimal refundAmount) {
        SlodonRefundRequest refundRequest = new SlodonRefundRequest();
        refundRequest.setAlipayProperties(payPropertiesUtil.getAliPayProperties());
        refundRequest.setTradeSn(tradeSn);
        refundRequest.setRefundSn(refundSn);
        refundRequest.setRefundAmount(refundAmount);
        try {
            SlodonRefundResponse refundResponse = slodonPay.refund(refundRequest, PayConst.METHOD_ALIPAY.toUpperCase());
            if (!refundResponse.getSuccess()) {
                log.error("支付宝重复支付退款失败，交易流水号：{}，失败原因：{}", tradeSn, refundResponse.getMsg());
            }
        } catch (Exception e) {
            log.error("支付宝重复支付退款失败，交易流水号：{}", tradeSn, e);
        }
    }

    /**
     * payPal退款
     *
     * @param refundSn     退款单号
     * @param tradeSn      交易流水号
     * @param refundAmount 退款金额
     */
    private void payPalRefund(String refundSn, String tradeSn, BigDecimal refundAmount) {
        SlodonRefundRequest refundRequest = new SlodonRefundRequest();
        refundRequest.setPayPalProperties(payPropertiesUtil.getPayPalProperties());
        refundRequest.setTradeSn(tradeSn);
        refundRequest.setRefundSn(refundSn);
        refundRequest.setRefundAmount(refundAmount);
        try {
            SlodonRefundResponse refundResponse = slodonPay.refund(refundRequest, PayConst.METHOD_ALIPAY.toUpperCase());
            if (!refundResponse.getSuccess()) {
                log.error("payPal重复支付退款失败，交易流水号：{}，失败原因：{}", tradeSn, refundResponse.getMsg());
            }
        } catch (Exception e) {
            log.error("payPal重复支付退款失败，交易流水号：{}", tradeSn, e);
        }
    }
}
