package com.liquidnet.service.dragon.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.liquidnet.common.exception.LiquidnetServiceException;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.dragon.channel.unionpay.biz.UnionpayBiz;
import com.liquidnet.service.dragon.channel.unionpay.constant.UnionpayConstant;
import com.liquidnet.service.dragon.channel.unionpay.sdk.AcpService;
import com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConfig;
import com.liquidnet.service.dragon.channel.unionpay.sdk.SDKConstants;
import com.liquidnet.service.dragon.channel.wepay.resp.AliPayRefundReturnCallBackDto;
import com.liquidnet.service.dragon.channel.wepay.resp.WePayRefundReturnCallBackDto;
import com.liquidnet.service.dragon.channel.wepay.resp.WePayRefundReturnCallBackInfoDto;
import com.liquidnet.service.dragon.channel.wepay.resp.WePayRefundReturnDto;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.constant.DragonErrorCodeEnum;
import com.liquidnet.service.dragon.dto.DragonRefundAppDto;
import com.liquidnet.service.dragon.dto.DragonRefundChannelDto;
import com.liquidnet.service.dragon.dto.NotifyUrlDto;
import com.liquidnet.service.dragon.dto.RefundContentDto;
import com.liquidnet.service.dragon.service.IDragonOrderRefundsService;
import com.liquidnet.service.dragon.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Slf4j
@Service
public class DragonOrderRefundsServiceImpl implements IDragonOrderRefundsService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    DataUtilsDragon dataUtilsDragon;
    @Autowired
    MqHandleUtil mqHandleUtil;
    @Value("${liquidnet.dragon.url}")
    private String url;
    @Autowired
    private SDKConfig sdkConfig;
    @Autowired
    private AcpService acpService;
    //银联 商户号码
    @Value("${liquidnet.dragon.unionpay.merchantId}")
    private String unionMerchantId;
    @Autowired
    private UnionpayBiz unionpayBiz;

    @Override
    public ResponseDto<DragonRefundAppDto> dragonRefund(String orderCode, String code, String orderRefundCode, String reason, String notifyUrl, BigDecimal price, String paymentType, String paymentId, BigDecimal priceTotal) {
        try {
            LocalDateTime nowTime = LocalDateTime.now();
            String refundCode = IDGenerator.refundCode();
            //创建退款单
            boolean insertResult = mqHandleUtil.sendMySqlRedis(
                    SqlMapping.get("dragon_order_refund.insert"),
                    new Object[]{code, refundCode, orderRefundCode, price, reason, notifyUrl, paymentType, nowTime, nowTime},
                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
            );
            dataUtilsDragon.setRefundNotifyUrl(orderRefundCode, notifyUrl);
            DragonRefundChannelDto dto = null;
            String localWePayCallBackUrl = url + "/refund/callBack/wepay";
            String localDouYinCallBackUrl = url + "/refund/callBack/douyinpay";
            String localUnionPayCallBackUrl = url + "/refund/callBack/union";
            if (insertResult) {
                switch (paymentType) {
                    case DragonConstant.REFUND_TYPE_APP_ALIPAY:
                        dto = aliPayRefund(code, orderRefundCode, code, reason, price, paymentId, paymentType, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_WAP_ALIPAY:
                        dto = aliPayRefund(code, orderRefundCode, code, reason, price, paymentId, paymentType, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_WEB_ALIPAY:
                        dto = aliPayRefund(code, orderRefundCode, code, reason, price, paymentId, paymentType, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_APP_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_MICROPAY_ALIPAY:
                        dto = aliPayRefund(code, orderRefundCode, code, reason, price, paymentId, paymentType, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_WAP_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_WEB_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_JS_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_MICROPAY_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_APPLET_WEPAY:
                        dto = weyPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localWePayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_APPLET_DOUYIN:
                        dataUtilsDragon.setOrderCode(orderRefundCode, orderCode);
                        dto = douYinRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localDouYinCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_WAP_UNION:
                        dataUtilsDragon.setOrderCode(orderRefundCode, orderCode);
                        dto = UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime);
                        break;
                    case DragonConstant.REFUND_TYPE_APP_UNION:
                        dataUtilsDragon.setOrderCode(orderRefundCode, orderCode);
                        dto = UnionWapPayRefund(code, orderRefundCode, code, reason, price, priceTotal, paymentId, paymentType, localUnionPayCallBackUrl, nowTime);
                        break;
                }

                log.info("dto = " + JSON.toJSONString(dto));

                if (dto == null) {
                    return ResponseDto.failure("退款失败:参数异常");
                } else if (dto.getResult().equalsIgnoreCase("refunding")) {
                } else if (dto.getResult().equalsIgnoreCase("refunded")) {
                    //调用回调
                } else if (dto.getResult().equalsIgnoreCase("error")) {
                    //调用回调
                    return ResponseDto.failure("退款失败:" + dto.getMessage());
                } else if (dto.getResult().equalsIgnoreCase("exception")) {
                }
                DragonRefundAppDto refundAppDto = new DragonRefundAppDto();
                refundAppDto.setOrderCode(orderCode);
                refundAppDto.setCode(code);
                refundAppDto.setOrderRefundCode(orderRefundCode);
                refundAppDto.setRefundCode(refundCode);

                log.info("refundAppDto = " + JSON.toJSONString(refundAppDto));
                return ResponseDto.success(refundAppDto);
            } else {
                return ResponseDto.failure("退款失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("orderCode = " + orderCode + "", e);
            return ResponseDto.failure("退款失败:" + e.getMessage());
        }
    }

    /**
     * @author zhangfuxin
     * @Description: 抖音退款接口
     * @date 2021/11/10 下午3:22
     */
    public DragonRefundChannelDto douYinRefund(String orderRefundId, String refundCode, String code, String reason, BigDecimal price, BigDecimal priceTotal, String paymentId, String paymentType, String notifyUrl, LocalDateTime nowTime) {
        try {
            String refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
            DragonRefundChannelDto channelDto = new DragonRefundChannelDto();
            RefundContentDto contentDto = new RefundContentDto();
            SortedMap<String, Object> parameters = new TreeMap<>();
            parameters.put("app_id", PayDouYinpayUtils.getInstance().getAPP_ID());
            parameters.put("out_order_no", code);
            parameters.put("out_refund_no", refundCode);
            parameters.put("refund_amount", price.multiply(new BigDecimal(100)).intValue()+"");
            parameters.put("reason", reason);
            parameters.put("notify_url", notifyUrl);
            String sign = PayDouYinpayUtils.getInstance().createSign(parameters);
            parameters.put("sign", sign);
            String data = JSON.toJSONString(parameters);
            String refundError = "";
            try {
                log.info("调用抖音退款:{}", data);
                HttpPost httpost = new HttpPost("https://developer.toutiao.com/api/apps/ecpay/v1/create_refund");
                httpost.setEntity(new StringEntity(data, "UTF-8"));
                CloseableHttpResponse response = PayDouYinpayUtils.getInstance().getHttpClient().execute(httpost);
                try {
                    HttpEntity entity = response.getEntity();
                    entity.getContent();
                    String jsonStr = EntityUtils.toString(entity, "UTF-8");
                    log.info("douYinRefund 返参{}", jsonStr);
                    Map result = JSON.parseObject(jsonStr, HashMap.class);
                    //
                    if (!result.get("err_no").toString().equals("0")) {
                        try {
                            refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
                            refundError = result.get("err_tips").toString();
                            // 修改退款订单
                            mqHandleUtil.sendMySqlRedis(
                                    SqlMapping.get("dragon_order_refund_error.update"),
                                    new Object[]{nowTime, refundError, refundStatus, code},
                                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                            );
                        } catch (Exception e) {
                            e.printStackTrace();
                            //保存错误信息
                            log.error("");
                            channelDto.setResult("exception");
                            channelDto.setMessage("update order refund with db error: " + e.getMessage());
                            contentDto.setRequest(data);
                            contentDto.setResponse(jsonStr);
                            channelDto.setContent(contentDto);
                            return channelDto;
                        }
                        channelDto.setResult("error");
                        channelDto.setMessage(refundError);
                        contentDto.setRequest(data);
                        contentDto.setResponse(jsonStr);
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }
                    // 创建退款日志
                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_log.insert"),
                            new Object[]{orderRefundId, paymentType, data, nowTime, nowTime},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    try {
                        if (result.get("err_no").toString().equals("0")) {
                            refundStatus = DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode();
                        }
                        mqHandleUtil.sendMySqlRedis(
                                SqlMapping.get("dragon_order_refund_success.update"),
                                new Object[]{nowTime, null, refundStatus, code},
                                DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                        );
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("");
                        channelDto.setResult("exception");
                        channelDto.setMessage("update order refund with db error: " + e.getMessage());
                        contentDto.setRequest(data);
                        contentDto.setResponse(jsonStr);
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }
                    channelDto.setResult("refunded");
                    channelDto.setMessage(paymentType + " refund info: ");
                    contentDto.setRequest(data);
                    contentDto.setResponse(jsonStr);
                    channelDto.setContent(contentDto);
                    EntityUtils.consume(entity);
                    return channelDto;
                } finally {
                    response.close();
                }
            } finally {
//                PayWepayUtils.getInstance().getHttpClient().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("退款发生错误", e);
            return null;
        }
    }

    //银联退款
    public DragonRefundChannelDto UnionWapPayRefund(String orderRefundId, String refundCode, String code, String reason, BigDecimal price, BigDecimal priceTotal, String paymentId, String paymentType, String notifyUrl, LocalDateTime nowTime) {
        try {
            RefundContentDto contentDto = new RefundContentDto();
            DragonRefundChannelDto channelDto = new DragonRefundChannelDto();
            String txnTime = DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmssTrim);
            Map<String, String> data = ObjectUtilDragon.cloneHashMapStringAndString();
            /***银联全渠道系统，产品参数，除了encoding自行选择外其他不需修改***/
            data.put("version", sdkConfig.getVersion());               //版本号
            data.put("encoding", UnionpayConstant.encoding);             //字符集编码 可以使用UTF-8,GBK两种方式
            data.put("signMethod", sdkConfig.getSignMethod()); //签名方法
            data.put("txnType", "04");                           //交易类型 04-退货
            data.put("txnSubType", "00");                        //交易子类型  默认00
            data.put("bizType", "000201");                       //业务类型
            data.put("channelType", "08");                       //渠道类型，07-PC，08-手机
            /***商户接入参数***/
            data.put("merId", unionMerchantId);                //商户号码，请改成自己申请的商户号或者open上注册得来的777商户号测试
            data.put("accessType", "0");                         //接入类型，商户接入固定填0，不需修改
            data.put("orderId", refundCode);          //商户订单号，8-40位数字字母，不能含“-”或“_”，可以自行定制规则，重新产生，不同于原消费
            data.put("txnTime", txnTime);      //订单发送时间，格式为yyyyMMddHHmmss，必须取当前时间，否则会报txnTime无效
            data.put("currencyCode", "156");                     //交易币种（境内商户一般是156 人民币）
            data.put("txnAmt", price.multiply(BigDecimal.valueOf(100L)).intValue() + "");                          //交易金额  单位为分
            data.put("backUrl", notifyUrl);               //后台通知地址，后台通知参数详见open.unionpay.com帮助中心 下载  产品接口规范  网关支付产品接口规范 退货交易 商户通知,其他说明同消费交易的后台通知
            /***要调通交易以下字段必须修改***/
            data.put("origQryId", paymentId);      //****原消费交易返回的的queryId，可以从消费交易后台通知接口中或者交易状态查询接口中获取
            // 请求方保留域，
            // 透传字段，查询、通知、对账文件中均会原样出现，如有需要请启用并修改自己希望透传的数据。
            // 出现部分特殊字符时可能影响解析，请按下面建议的方式填写：
            // 1. 如果能确定内容不会出现&={}[]"'等符号时，可以直接填写数据，建议的方法如下。
//		data.put("reqReserved", "透传信息1|透传信息2|透传信息3");
            // 2. 内容可能出现&={}[]"'符号时：
            // 1) 如果需要对账文件里能显示，可将字符替换成全角＆＝｛｝【】“‘字符（自己写代码，此处不演示）；
            // 2) 如果对账文件没有显示要求，可做一下base64（如下）。
            //    注意控制数据长度，实际传输的数据长度不能超过1024位。
            //    查询、通知等接口解析时使用new String(Base64.decodeBase64(reqReserved), UnionpayConstant.encoding);解base64后再对数据做后续解析。
//		data.put("reqReserved", Base64.encodeBase64String("任意格式的信息都可以".toString().getBytes(UnionpayConstant.encoding)));
            /**请求参数设置完毕，以下对请求参数进行签名并发送http post请求，接收同步应答报文------------->**/
            Map<String, String> reqData = acpService.sign(data, UnionpayConstant.encoding);        //报文中certId,signature的值是在signData方法中获取并自动赋值的，只要证书配置正确即可。
            Map<String, String> rspData = acpService.post(reqData, sdkConfig.getBackTransUrl(), UnionpayConstant.encoding);//这里调用signData之后，调用submitUrl之前不能对submitFromData中的键值对做任何修改，如果修改会导致验签不通过
            String refundError = "";
            /**对应答码的处理，请根据您的业务逻辑来编写程序,以下应答码处理逻辑仅供参考------------->**/
            //应答码规范参考open.unionpay.com帮助中心 下载  产品接口规范  《平台接入接口规范-第5部分-附录》
            if (!rspData.isEmpty()) {
                if (acpService.validate(rspData, UnionpayConstant.encoding)) {
                    log.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //交易已受理(不代表交易已成功），等待接收后台通知更新订单状态,也可以主动发起 查询交易确定交易状态。
                        // 创建退款日志
                        mqHandleUtil.sendMySqlRedis(
                                SqlMapping.get("dragon_order_refund_log.insert"),
                                new Object[]{orderRefundId, paymentType, JSON.toJSONString(data), nowTime, nowTime},
                                DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                        );
                        try {
                            mqHandleUtil.sendMySqlRedis(
                                    SqlMapping.get("dragon_order_refund_success.update"),
                                    new Object[]{nowTime, nowTime, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), code},
                                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                            );
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("异常信息", e);
                            channelDto.setResult("exception");
                            channelDto.setMessage("update order refund with db error: " + e.getMessage());
                            contentDto.setRequest(JSON.toJSONString(reqData));
                            contentDto.setResponse(JSON.toJSONString(rspData));
                            channelDto.setContent(contentDto);
                            return channelDto;
                        }
                    } else {
                        //其他应答码为失败请排查原因
                        try {
                            String refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
                            if (("03").equals(respCode) || ("04").equals(respCode) || ("05").equals(respCode)) {
                                refundError = "银联返回状态" + respCode + "请稍后确认。";
                            } else {
                                refundError = rspData.get("respMsg") == null ? "退款失败，原因未知" : rspData.get("respMsg").toString();
                            }
                            // 修改退款订单
                            mqHandleUtil.sendMySqlRedis(
                                    SqlMapping.get("dragon_order_refund_error.update"),
                                    new Object[]{nowTime, refundError, refundStatus, code},
                                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                            );
                        } catch (Exception e) {
                            e.printStackTrace();
                            //保存错误信息
                            log.error("");
                            channelDto.setResult("exception");
                            channelDto.setMessage("update order refund with db error: " + e.getMessage());
                            contentDto.setRequest(JSON.toJSONString(reqData));
                            contentDto.setResponse(JSON.toJSONString(rspData));
                            channelDto.setContent(contentDto);
                            return channelDto;
                        }
                        channelDto.setResult("error");
                        channelDto.setMessage(refundError);
                        contentDto.setRequest(JSON.toJSONString(reqData));
                        contentDto.setResponse(JSON.toJSONString(rspData));
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }
                } else {
                    log.error("银联退款,验证签名失败");
                    return null;
                }
            } else {
                //未返回正确的http状态
                log.error("银联退款,未获取到返回报文或返回http状态码非200");
                return null;
            }
            channelDto.setResult("refunded");
            channelDto.setMessage(paymentType + " refund info: ");
            contentDto.setRequest(JSON.toJSONString(reqData));
            contentDto.setResponse(JSON.toJSONString(rspData));
            channelDto.setContent(contentDto);
            return channelDto;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("异常信息", e);
            return null;
        }
    }

    //微信退款接口
    public DragonRefundChannelDto weyPayRefund(String orderRefundId, String refundCode, String code, String reason, BigDecimal price, BigDecimal priceTotal, String paymentId, String paymentType, String notifyUrl, LocalDateTime nowTime) {
        try {
            String refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
            DragonRefundChannelDto channelDto = new DragonRefundChannelDto();
            RefundContentDto contentDto = new RefundContentDto();
            String nonceStr = PayWepayUtils.getInstance().getNonceStr();
            SortedMap<String, Object> parameters = new TreeMap<>();
            parameters.put("mch_id", PayWepayUtils.getInstance().getMerchantId());
            if (paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_JS_WEPAY.getCode())) {
                parameters.put("appid", PayWepayUtils.getInstance().getJS_APP_ID());
            } else if (paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_WEB_WEPAY.getCode())) {
                parameters.put("appid", PayWepayUtils.getInstance().getWEB_APP_ID());
            } else if (paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_APP_WEPAY.getCode())) {
                parameters.put("appid", PayWepayUtils.getInstance().getAPP_ID());
            } else if (paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_APPLET_WEPAY.getCode())) {
                parameters.put("appid", PayWepayUtils.getInstance().getAPPLET_APP_ID());
            } else if (paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_WAP_WEPAY.getCode())) {
                parameters.put("appid", PayWepayUtils.getInstance().getWAP_APP_ID());
            }else if(paymentType.equalsIgnoreCase(DragonConstant.PayTypeEnum.PAYMENT_TYPE_MICROPAY_WEPAY.getCode())){
                parameters.put("appid", PayWepayUtils.getInstance().getAPP_ID());
            }
            parameters.put("nonce_str", nonceStr);
            parameters.put("out_refund_no", refundCode);
            parameters.put("out_trade_no", code);
            parameters.put("refund_fee", (price.multiply(new BigDecimal(100)).intValue())+"");
            parameters.put("total_fee", (priceTotal.multiply(new BigDecimal(100)).intValue())+"");
            parameters.put("notify_url", notifyUrl);
            parameters.put("refund_desc", reason);
            parameters.put("refund_account", "REFUND_SOURCE_RECHARGE_FUNDS");
            String sign = PayWepayUtils.getInstance().createSign(parameters);
            parameters.put("sign", sign);
            String data = PayWepayUtils.getInstance().getRequestXml(parameters);
            String refundError = "";
            try {
                HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
                httpost.setEntity(new StringEntity(data, "UTF-8"));
                CloseableHttpResponse response = PayWepayUtils.getInstance().getHttpClient().execute(httpost);
                try {
                    HttpEntity entity = response.getEntity();
                    entity.getContent();
                    String jsonStr = EntityUtils.toString(entity, "UTF-8");
                    log.info("JSONSTR = " + jsonStr);
                    WePayRefundReturnDto wePayRefundReturnDto = XmlUtil.toBean(jsonStr, WePayRefundReturnDto.class);
                    if (wePayRefundReturnDto.getErrCodeDes() != null) {
                        channelDto.setResult("error");
                        channelDto.setMessage(wePayRefundReturnDto.getErrCodeDes());
                        contentDto.setRequest(data);
                        contentDto.setResponse(jsonStr);
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }
                    if (!wePayRefundReturnDto.getReturnCode().equalsIgnoreCase("SUCCESS") || wePayRefundReturnDto.getReturnCode() == null) {
                        try {
                            refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
                            if (null == wePayRefundReturnDto.getReturnMsg()) {
                                refundError = "退款失败，原因未知";
                            } else {
                                refundError = wePayRefundReturnDto.getReturnMsg();
                            }
                            // 修改退款订单
                            mqHandleUtil.sendMySqlRedis(
                                    SqlMapping.get("dragon_order_refund_error.update"),
                                    new Object[]{nowTime, refundError, refundStatus, code},
                                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                            );
                        } catch (Exception e) {
                            e.printStackTrace();
                            //保存错误信息
                            log.error("");
                            channelDto.setResult("exception");
                            channelDto.setMessage("update order refund with db error: " + e.getMessage());
                            contentDto.setRequest(data);
                            contentDto.setResponse(jsonStr);
                            channelDto.setContent(contentDto);
                            return channelDto;
                        }
                        channelDto.setResult("error");
                        channelDto.setMessage(refundError);
                        contentDto.setRequest(data);
                        contentDto.setResponse(jsonStr);
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }

                    // 创建退款日志
                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_log.insert"),
                            new Object[]{orderRefundId, paymentType, data, nowTime, nowTime},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    try {
                        if (wePayRefundReturnDto.getReturnCode().equalsIgnoreCase("SUCCESS")) {
                            refundStatus = DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode();
                        }
                        mqHandleUtil.sendMySqlRedis(
                                SqlMapping.get("dragon_order_refund_success.update"),
                                new Object[]{nowTime, null, refundStatus, code},
                                DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                        );
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.error("");
                        channelDto.setResult("exception");
                        channelDto.setMessage("update order refund with db error: " + e.getMessage());
                        contentDto.setRequest(data);
                        contentDto.setResponse(jsonStr);
                        channelDto.setContent(contentDto);
                        return channelDto;
                    }
                    channelDto.setResult("refunded");
                    channelDto.setMessage(paymentType + " refund info: ");
                    contentDto.setRequest(data);
                    contentDto.setResponse(jsonStr);
                    channelDto.setContent(contentDto);
                    EntityUtils.consume(entity);
                    return channelDto;
                } finally {
                    response.close();
                }
            } finally {
//                PayWepayUtils.getInstance().getHttpClient().close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("");
            return null;
        }
    }

    //支付宝退款接口
    public DragonRefundChannelDto aliPayRefund(String orderRefundId, String refundCode, String code, String reason, BigDecimal price, String paymentId, String paymentType, LocalDateTime nowTime) {
        String refundStatus;
        DragonRefundChannelDto channelDto = new DragonRefundChannelDto();
        RefundContentDto contentDto = new RefundContentDto();
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();//创建API对应的request类
        try {
            String refundError = "";
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + code + "\"," +
                    "\"trade_no\":\"" + paymentId + "\"," +
                    "\"out_request_no\":\"" + refundCode + "\"," +
                    "\"refund_reason\":\"" + reason + "\"," +
                    "\"refund_amount\":\"" + price.doubleValue() + "\"}"); //设置业务参数
            AlipayTradeRefundResponse response = PayAlipayUtils.getInstance().getHttpClient().execute(request);
            if (response.getFundChange() == null || response.getFundChange().equals("N")) {
                try {
                    refundStatus = DragonConstant.RefundStatusEnum.STATUS_ERROR.getCode();
                    if (null == response.getSubMsg()) {
                        refundError = "退款失败，原因未知";
                    } else {
                        refundError = response.getSubMsg();
                    }
                    // 修改退款订单
                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_error.update"),
                            new Object[]{nowTime, refundError, refundStatus, code},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                    //保存错误信息
                    log.error("");
                    channelDto.setResult("exception");
                    channelDto.setMessage("update order refund with db error: " + e.getMessage());
                    contentDto.setRequest(JSON.toJSONString(response.getParams()));
                    contentDto.setResponse(response.getBody());
                    channelDto.setContent(contentDto);
                    return channelDto;
                }
                channelDto.setResult("error");
                channelDto.setMessage(refundError);
                contentDto.setRequest(JSON.toJSONString(response.getParams()));
                contentDto.setResponse(response.getBody());
                channelDto.setContent(contentDto);
                return channelDto;
            }

            // 创建退款日志
            mqHandleUtil.sendMySqlRedis(
                    SqlMapping.get("dragon_order_refund_log.insert"),
                    new Object[]{orderRefundId, paymentType, response.getBody(), nowTime, nowTime},
                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
            );
            try {
                String refundAt = "";
                if (response.getFundChange().equals("Y")) {
                    refundStatus = DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode();
                    refundAt = DateUtil.format(response.getGmtRefundPay(), DateUtil.Formatter.yyyyMMddHHmmss);
                } else {
                    refundStatus = DragonConstant.RefundStatusEnum.STATUS_REFUNDING.getCode();
                }
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_success.update"),
                        new Object[]{nowTime, refundAt, refundStatus, code},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
            } catch (Exception e) {
                e.printStackTrace();
                channelDto.setResult("exception");
                channelDto.setMessage("update order refund with db error: " + e.getMessage());
                contentDto.setRequest(JSON.toJSONString(response.getParams()));
                contentDto.setResponse(response.getBody());
                channelDto.setContent(contentDto);
                return channelDto;
            }
            channelDto.setResult("refunded");
            channelDto.setMessage(paymentType + " refund info: ");
            contentDto.setRequest(JSON.toJSONString(response.getParams()));
            contentDto.setResponse(response.getBody());
            channelDto.setContent(contentDto);
            return channelDto;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("");
            return null;
        }
    }

    /**
     * @author zhangfuxin
     * @Description: 抖音退款回调
     * @date 2021/11/11 上午10:55
     */
    public String douYinPayRefundCallBack(HttpServletRequest request, HttpServletResponse response) {
        try {
            LocalDateTime nowTime = LocalDateTime.now();
            JSONObject jsonObject = PayDouYinpayUtils.getJsonObject(request);
            log.info("接收到的抖音退款回调请求参数{}", JSON.toJSONString(jsonObject));
            //再次验证是退款的回调
            if (!jsonObject.getString("type").equals("refund")) {
                throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_PARAM_ERROR.getCode(), DragonErrorCodeEnum.TRADE_PARAM_ERROR.getMessage());
            }
            JSONObject msg = jsonObject.getJSONObject("msg");
            NotifyUrlDto dto = new NotifyUrlDto();
            // 验签
            if (PayDouYinpayUtils.getInstance().notifySign(jsonObject.get("msg_signature").toString(), jsonObject)) {// 根据配置信息验证签名
                //查看退款状态 (退款状态 PROCESSING-处理中|SUCCESS-成功|FAIL-失败)
                if (msg.getString("status").equals("SUCCESS")) {
                    dto.setStatus(1);
                } else {
                    dto.setStatus(0);
                }
                //开发者自定义的退款单号
                dto.setOrderRefundCode(msg.getString("cp_refundno"));
                //  没有订单号 从redids里面查
                dto.setRefundCode(dataUtilsDragon.getOrderCode(msg.getString("cp_refundno")));
                dto.setRefundPrice(msg.getBigDecimal("refund_amount").divide(BigDecimal.valueOf(100)).toString());
                // SimpleDateFormat sdf =   new SimpleDateFormat( " yyyy年MM月dd日 " );
                // 抖音没有传回时间
                dto.setRefundAt(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now()));
                //抖音回调没有写错误原因
                dto.setRefundError("");
                log.info("SEND DOUYINPAY NOTIFTURL = " + JSON.toJSONString(dto));
                sendNotifyUrl(dto, null);
                //创建退款订单日志
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_log.insert"),
                        new Object[]{msg.getString("cp_refundno"), "APPLETDOUYIN", JSON.toJSONString(jsonObject), nowTime, nowTime},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
                //修改订单 状态
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_success.update"),
                        new Object[]{nowTime, nowTime, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), msg.getString("cp_refundno")},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
                return "{\"err_no\": 0, \"err_tips\": \"success\"}";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("退款回调失败", e);
        }

        return "";
    }

    /**
     * @author zhangfuxin
     * @Description: 查询退款
     * @date 2021/11/11 下午3:21
     */
    @Override
    public String douYinPayRefundCodeStatus(String outRefundNo) {
        try {
            //1、组织数据
            Map<String, Object> map = CollectionUtil.mapStringObject();
            map.put("app_id", PayDouYinpayUtils.getInstance().getAPP_ID());
            map.put("out_refund_no", outRefundNo);
            //2、加密
            map.put("sign", PayDouYinpayUtils.getInstance().createSign(map));
            //3、请求
            String data = JSON.toJSONString(map);
            log.info("查询退款请求抖音参数:{}", data);
            HttpPost httpost = new HttpPost("https://developer.toutiao.com/api/apps/ecpay/v1/query_refund");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpClient httpClient = PayDouYinpayUtils.getInstance().getHttpClient();
            CloseableHttpResponse response = httpClient.execute(httpost);
            HttpEntity entity = response.getEntity();
            //接受到返回信息
            String json = EntityUtils.toString(response.getEntity(), "UTF-8");
            EntityUtils.consume(entity);
            log.info("查询抖音退款查询返回值：{}", json);
            //解析、如果成功，则更新
            LocalDateTime nowTime = LocalDateTime.now();
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (jsonObject.getInteger("err_no") == 0) {
                JSONObject refundInfo = jsonObject.getJSONObject("refundInfo");
                NotifyUrlDto dto = new NotifyUrlDto();
                if (refundInfo.getString("refund_status").equals("SUCCESS")) {
                    dto.setStatus(1);
                } else {
                    dto.setStatus(0);
                }
                //开发者自定义的退款单号
                dto.setOrderRefundCode(refundInfo.getString("refund_no"));
                //  没有订单号
                dto.setRefundCode(dataUtilsDragon.getOrderCode(refundInfo.getString("cp_refundno")));
                dto.setRefundPrice(refundInfo.getBigDecimal("refund_amount").divide(BigDecimal.valueOf(100)).toString());
                // 抖音没有传回时间
                dto.setRefundAt(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now()));
                //抖音回调没有写错误原因
                dto.setRefundError("");
                log.info("SEND DOUYINPAY NOTIFTURL = " + JSON.toJSONString(dto));
                sendNotifyUrl(dto, null);
                //创建退款订单日志
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_log.insert"),
                        new Object[]{refundInfo.getString("refund_no"), "", JSON.toJSONString(jsonObject), nowTime, nowTime},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
                //修改订单 状态
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_success.update"),
                        new Object[]{nowTime, dto.getRefundAt(), DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), refundInfo.getString("refund_no")},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
            } else {
                throw new LiquidnetServiceException(DragonErrorCodeEnum.TRADE_DOUYINPAY_QUERY_ERROR.getCode(), DragonErrorCodeEnum.TRADE_DOUYINPAY_QUERY_ERROR.getMessage());
            }
            return json;
        } catch (Exception e) {
            log.info("查询退款报错：{}", e);
        }

        return "";
    }

    /**
     * @author zhangfuxin
     * @Description: 银联退款回调
     * @date 2021/11/18 下午1:32
     */
    public String unionRefundCallBack(HttpServletRequest request, HttpServletResponse response) {
        try {
            LocalDateTime nowTime = LocalDateTime.now();
            String encoding = request.getParameter(SDKConstants.param_encoding);
            Map<String, String> notifyMap = unionpayBiz.parseNotifyMsg(request);
            log.info("银联退款回调{}", JSON.toJSONString(notifyMap));
            if (!acpService.validate(notifyMap, encoding)) {
                //验签失败，需解决验签问题
                log.error("银联回调，验签失败。{}", JSON.toJSONString(notifyMap));
            } else {
                String orderId = notifyMap.get("orderId"); //获取后台通知的数据，其他字段也可用类似方式获取
                String respCode = notifyMap.get("respCode");
                NotifyUrlDto dto = new NotifyUrlDto();
                //成功
                if (respCode.equals("00") || respCode.equals("A6")) {
                    dto.setStatus(1);
                } else {
                    dto.setStatus(0);
                }
                //商户订单号 商户退款单号
                dto.setOrderRefundCode(orderId);
                //从redis里面
                dto.setRefundCode(dataUtilsDragon.getOrderCode(orderId));
                dto.setRefundPrice(new BigDecimal(notifyMap.get("settleAmt")).divide(BigDecimal.valueOf(100)).toString());
                dto.setRefundAt(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now()));
                // 应答信息
                dto.setRefundError(notifyMap.get("respMsg"));
                log.info("SEND union NOTIFTURL = " + JSON.toJSONString(dto));
                sendNotifyUrl(dto, null);
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_log.insert"),
                        new Object[]{orderId, "", JSON.toJSONString(notifyMap), nowTime, nowTime},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
                mqHandleUtil.sendMySqlRedis(
                        SqlMapping.get("dragon_order_refund_success.update"),
                        new Object[]{nowTime, nowTime, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), orderId},
                        DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                );
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "ok";
    }

    @Override
    public String wePayRefundCallBack(HttpServletRequest request, HttpServletResponse response) {
        InputStream inStream;
        ByteArrayOutputStream outSteam;
        LocalDateTime nowTime = LocalDateTime.now();
        try {
            inStream = request.getInputStream();
            outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            // 获取微信调用我们notify_url的返回信息
            String jsonStr = new String(outSteam.toByteArray(), "utf-8");
            outSteam.close();
            inStream.close();
            WePayRefundReturnCallBackDto callBackDto = XmlUtil.toBean(jsonStr, WePayRefundReturnCallBackDto.class);
            log.info("callBackDto = " + callBackDto);
            if (callBackDto.getReturnCode().equalsIgnoreCase("SUCCESS")) {
                String reqInfo = PayWepayUtils.getInstance().unCodeReqInfo(callBackDto.getReqInfo());
                WePayRefundReturnCallBackInfoDto info = XmlUtil.toBean(reqInfo, WePayRefundReturnCallBackInfoDto.class);
                String outRefundNo = info.getOutRefundNo();
                String refundAt = info.getSuccessTime();
                try {
                    NotifyUrlDto dto = new NotifyUrlDto();
                    if (info.getRefundStatus().equalsIgnoreCase("SUCCESS")) {
                        dto.setStatus(1);
                    } else {
                        dto.setStatus(0);
                    }
                    dto.setOrderRefundCode(info.getOutRefundNo());
                    dto.setRefundCode(info.getOutTradeNo());
                    dto.setRefundPrice(new BigDecimal(info.getRefundFee()).divide(BigDecimal.valueOf(100)).toString());
                    dto.setRefundAt(refundAt);
                    dto.setRefundError(callBackDto.getReturnMsg());
                    log.info("SEND WEPAY NOTIFTURL = " + JSON.toJSONString(dto));
                    sendNotifyUrl(dto, null);

                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_log.insert"),
                            new Object[]{outRefundNo, info.getRefundRequestSource(), JSON.toJSONString(info), nowTime, nowTime},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_success.update"),
                            new Object[]{nowTime, refundAt, DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), outRefundNo},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("");
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";
                }
            } else {
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("");
            return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>";
        }
    }

    @Override
    public String aliPayRefundCodeStatus(String outTradeNo, String tradeNo, String outBizNo, String callBackUrl) {
        try {
            LocalDateTime nowTime = LocalDateTime.now();
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();//创建API对应的request类
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + outTradeNo + "\"," +
                    "\"trade_no\":\"" + tradeNo + "\"," +
                    "\"out_request_no\":\"" + outBizNo + "\"}"); //设置业务参数
            AlipayTradeFastpayRefundQueryResponse response = PayAlipayUtils.getInstance().getHttpClient().execute(request);
            log.info("AlipayTradeFastpayRefundQueryRequest -> data = " + JSON.toJSONString(response));

            if (response.isSuccess()) {
                try {
                    NotifyUrlDto dto = new NotifyUrlDto();
                    if (response.getMsg().equalsIgnoreCase("SUCCESS")) {
                        dto.setStatus(1);
                    } else {
                        dto.setStatus(0);
                    }
                    dto.setOrderRefundCode(response.getOutRequestNo());
                    dto.setRefundCode(response.getOutTradeNo());
                    dto.setRefundPrice(response.getRefundAmount());
                    dto.setRefundAt(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now()));
                    dto.setRefundPrice(response.getRefundAmount());
                    dto.setRefundError("");
                    sendNotifyUrl(dto, callBackUrl);

                    log.debug("SEND ALIPAY NOTIFTURL2 = " + JSON.toJSONString(dto));

                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_log.insert"),
                            new Object[]{outBizNo, "ALIPAY", JSON.toJSONString(response), nowTime, nowTime},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );

                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_success.update"),
                            new Object[]{nowTime, DateUtil.format(response.getGmtRefundPay(), DateUtil.Formatter.yyyyMMddHHmmss), DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), response.getOutRequestNo()},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );

                    return "success";
                } catch (Exception e) {
                    log.error("EXCEPTION", e);
                    return "fail";
                }
            } else {
                log.error("response.isSuccess() -> fail ");
                return "fail";
            }

        } catch (Exception e) {

        }
        return null;
    }

    public String aliPayRefundCallBack(String jsonStr) {
        LocalDateTime nowTime = LocalDateTime.now();
        try {
            AliPayRefundReturnCallBackDto callBackDto = JsonUtils.fromJson(jsonStr, AliPayRefundReturnCallBackDto.class);
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();//创建API对应的request类
            request.setBizContent("{" +
                    "\"out_trade_no\":\"" + callBackDto.getOutTradeNo() + "\"," +
                    "\"trade_no\":\"" + callBackDto.getTradeNo() + "\"," +
                    "\"out_request_no\":\"" + callBackDto.getOutBizNo() + "\"}"); //设置业务参数
            AlipayTradeFastpayRefundQueryResponse response = PayAlipayUtils.getInstance().getHttpClient().execute(request);
            log.info("AlipayTradeFastpayRefundQueryRequest -> data = " + JSON.toJSONString(response));

            if (response.isSuccess()) {
                try {
                    NotifyUrlDto dto = new NotifyUrlDto();
                    if (response.getMsg().equalsIgnoreCase("SUCCESS")) {
                        dto.setStatus(1);
                    } else {
                        dto.setStatus(0);
                    }
                    dto.setOrderRefundCode(response.getOutRequestNo());
                    dto.setRefundCode(response.getOutTradeNo());
                    dto.setRefundPrice(response.getRefundAmount());
                    dto.setRefundAt(callBackDto.getGmtRefund());
                    dto.setRefundPrice(response.getRefundAmount());
                    dto.setRefundError("");
                    sendNotifyUrl(dto, null);

                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_log.insert"),
                            new Object[]{callBackDto.getOutBizNo(), "ALIPAY", jsonStr, nowTime, nowTime},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    log.debug("SEND MQ INSERT");
                    mqHandleUtil.sendMySqlRedis(
                            SqlMapping.get("dragon_order_refund_success.update"),
                            new Object[]{nowTime, callBackDto.getGmtRefund(), DragonConstant.RefundStatusEnum.STATUS_REFUNDED.getCode(), response.getOutRequestNo()},
                            DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
                    );
                    log.debug("SEND MQ UPDATE");
                    return "success";
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("");
                    return "fail";
                }
            } else {
                log.error("response.isSuccess() -> fail ");
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("");
            return "fail";
        }
    }

    private void sendNotifyUrl(NotifyUrlDto notifyUrlDto, String url) {
        LocalDateTime nowTime = LocalDateTime.now();
        MultiValueMap<String, String> params = new LinkedMultiValueMap();
        params.add("orderRefundCode", notifyUrlDto.getOrderRefundCode());
        params.add("refundAt", notifyUrlDto.getRefundAt());
        params.add("refundCode", notifyUrlDto.getRefundCode());
        params.add("refundError", notifyUrlDto.getRefundError());
        params.add("refundPrice", notifyUrlDto.getRefundPrice());
        params.add("status", notifyUrlDto.getStatus().toString());
        String response = HttpUtil.post(url == null ? dataUtilsDragon.getRefundNotifyUrl(notifyUrlDto.getOrderRefundCode()) : url, params);
        log.info("RETURN RESPONSE=" + response);
        if (response.equals("success")) {
            mqHandleUtil.sendMySqlRedis(
                    SqlMapping.get("dragon_order_refund_call_back.update"),
                    new Object[]{nowTime, DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime), DragonConstant.RefundStatusEnum.STATUS_SUCCESS.getCode(), notifyUrlDto.getRefundCode()},
                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
            );
        } else {
            mqHandleUtil.sendMySqlRedis(
                    SqlMapping.get("dragon_order_refund_call_back.update"),
                    new Object[]{nowTime, DateUtil.Formatter.yyyyMMddHHmmss.format(nowTime), DragonConstant.RefundStatusEnum.STATUS_FAIL.getCode(), notifyUrlDto.getRefundCode()},
                    DragonConstant.MysqlRedisQueueEnum.DRAGON_REFUND_KEY.getCode()
            );
        }
    }

}
