package com.tzy.framework.pay.service.impl;

import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.tzy.common.dto.InDto;
import com.tzy.common.dto.OutDTO;
import com.tzy.common.utils.*;
import com.tzy.framework.pay.config.PayConfig;
import com.tzy.framework.pay.config.WxPayAppConfig;
import com.tzy.framework.pay.dto.*;
import com.tzy.framework.pay.service.WxPayService;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 微信支付
 */
@Slf4j
@Service
public class WxPayServiceImpl implements WxPayService {

    @Autowired
    private WxPayAppConfig wxPayAppConfig;
    @Autowired
    private PayConfig payConfig;
//    @Autowired
//    private GroupApiService groupApiService;
    /**
     * 查询订单
     * @param orderNo
     * @return
     */
    @Override
    public OutDTO searchOrder(String orderNo){
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(wxPayAppConfig);
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-",""));
            returnMap.put("sign", WXPayUtil.generateSignature(requestMap, wxPayAppConfig.getKey()));//微信支付签名// 商户订单号
            responseMap = wxpay.orderQuery(requestMap);
            String return_code = responseMap.get("return_code");
            String return_msg = responseMap.get("return_msg");
            if("SUCCESS".equals(return_code)){
                String result_code = responseMap.get("result_code");
                if("SUCCESS".equals(result_code)){
                    String trade_state = responseMap.get("trade_state");
                    if("SUCCESS".equals(trade_state)){
                        ResourceData resourceData = new ResourceData();
                        resourceData.setOut_trade_no(orderNo);
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
                        Date time_end = sdf.parse(responseMap.get("time_end"));
                        resourceData.setSuccess_time(sdf2.format(time_end));
                        resourceData.setTransaction_id(responseMap.get("transaction_id"));
                        resourceData.setTrade_type(responseMap.get("trade_type"));
                        resourceData.setTrade_state(responseMap.get("result_code"));
                        resourceData.setTrade_state_desc(responseMap.get("result_code"));
                        resourceData.setBank_type(responseMap.get("bank_type"));
                        resourceData.setAmount(new ResourceData.PayAmount(Integer.parseInt(responseMap.get("total_fee")),Integer.parseInt(responseMap.get("cash_fee")),responseMap.get("fee_type"),responseMap.get("fee_type")));
//                        groupApiService.paymentResult(resourceData);
                        return OutDTO.ok(responseMap.get("trade_state_desc"));
                    }else{
                        return OutDTO.error(-2,responseMap.get("trade_state_desc"));
                    }
                }else{
                    return OutDTO.error(-1,responseMap.get("err_code_des"));
                }
            }else{
                return OutDTO.error(-1,return_msg);
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        return OutDTO.error(-1,"查询微信支付订单失败");
    }
    /**
     * 查询订单
     * @param orderNo
     * @return
     */
    @Override
    public PaymentInfoResponseDto queryOrder(String appid,String orderNo){
        WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) payConfig.get(appid);
        if(null == wxPayAppConfig){
            wxPayAppConfig = this.wxPayAppConfig;
        }
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(wxPayAppConfig);
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-",""));
            returnMap.put("sign", WXPayUtil.generateSignature(requestMap, wxPayAppConfig.getKey()));//微信支付签名// 商户订单号
            responseMap = wxpay.orderQuery(requestMap);
            String return_code = responseMap.get("return_code");
            String return_msg = responseMap.get("return_msg");
            if("SUCCESS".equals(return_code)){
                String result_code = responseMap.get("result_code");
                if("SUCCESS".equals(result_code)){
                    String trade_state = responseMap.get("trade_state");
                    if("SUCCESS".equals(trade_state)){
                        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
                        paymentInfoResponseDto.setOrderNo(orderNo);
                        paymentInfoResponseDto.setPayWay("wxpay");
                        paymentInfoResponseDto.setAppid(wxPayAppConfig.getAppID());
                        paymentInfoResponseDto.setPaymentNo(responseMap.get("transaction_id"));
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(responseMap.get("total_fee")).divide(new BigDecimal(100)));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(responseMap.get("cash_fee")).divide(new BigDecimal(100)));
//                        paymentInfoResponseDto.setPaymentTime();
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        paymentInfoResponseDto.setPaymentSuccessTime(sdf.parse(responseMap.get("time_end")));
                        paymentInfoResponseDto.setTradeState(trade_state);
                        paymentInfoResponseDto.setTradeStateDesc(trade_state);
                        paymentInfoResponseDto.setSuccess(true);
                        return paymentInfoResponseDto;
                    }else{
                        return PaymentInfoResponseDto.error(-2,responseMap.get("trade_state_desc"));
                    }
                }else{
                    return PaymentInfoResponseDto.error(-1,responseMap.get("err_code_des"));
                }
            }else{
                return PaymentInfoResponseDto.error(-1,return_msg);
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        return PaymentInfoResponseDto.error(-1,"查询微信支付订单失败");
    }

    /**
     * 关闭订单
     * @param orderNo
     * @return
     */
    @Override
    public OutDTO closeOrder(String orderNo){
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(wxPayAppConfig);
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-",""));
            returnMap.put("sign", WXPayUtil.generateSignature(requestMap, wxPayAppConfig.getKey()));//微信支付签名// 商户订单号
            responseMap = wxpay.closeOrder(requestMap);
            String return_code = responseMap.get("return_code");
            String return_msg = responseMap.get("return_msg");
            if("SUCCESS".equals(return_code)){
                String result_code = responseMap.get("result_code");
                if("FAIL".equals(result_code)){//如果失败
                    String err_code = responseMap.get("err_code");
                    if("ORDERPAID".equals(err_code)){//已经支付成功
                        ResourceData resourceData = new ResourceData();
                        resourceData.setOut_trade_no(orderNo);
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
                        resourceData.setSuccess_time(sdf2.format(new Date()));
                        resourceData.setTransaction_id("因异常等未查到[微信支付订单号]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setTrade_type("因异常等未查到[交易类型]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setTrade_state("SUCCESS");
                        resourceData.setTrade_state_desc("因异常等未查到[交易结果]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setBank_type("因异常等未查到[付款银行]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setAmount(new ResourceData.PayAmount(Integer.parseInt(responseMap.get("total_fee")),Integer.parseInt(responseMap.get("cash_fee")),responseMap.get("fee_type"),responseMap.get("fee_type")));
//                        groupApiService.paymentResult(resourceData);
                        return OutDTO.error(-1,responseMap.get("trade_state_desc"));
                    }else if("ORDERCLOSED".equals(err_code)){ //订单已经关闭
                        return OutDTO.ok();
                    }
                }else{
                    return OutDTO.ok();
                }
            }else{
                return OutDTO.error(-1,return_msg);
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        return OutDTO.error(-1,"关闭微信支付订单失败");
    }
    /**
     * 关闭订单-新
     * @param orderNo
     * @return
     */
    @Override
    public ResultMap closeOrderNew(String appid,String orderNo){
        WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) payConfig.get(appid);
        if(null == wxPayAppConfig){
            wxPayAppConfig = this.wxPayAppConfig;
        }
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(wxPayAppConfig);
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-",""));
            returnMap.put("sign", WXPayUtil.generateSignature(requestMap, wxPayAppConfig.getKey()));//微信支付签名// 商户订单号
            responseMap = wxpay.closeOrder(requestMap);
            String return_code = responseMap.get("return_code");
            String return_msg = responseMap.get("return_msg");
            if("SUCCESS".equals(return_code)){
                String result_code = responseMap.get("result_code");
                if("FAIL".equals(result_code)){//如果失败
                    String err_code = responseMap.get("err_code");
                    if("ORDERPAID".equals(err_code)){//已经支付成功
                        ResourceData resourceData = new ResourceData();
                        resourceData.setOut_trade_no(orderNo);
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        SimpleDateFormat sdf2 = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
                        resourceData.setSuccess_time(sdf2.format(new Date()));
                        resourceData.setTransaction_id("因异常等未查到[微信支付订单号]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setTrade_type("因异常等未查到[交易类型]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setTrade_state("SUCCESS");
                        resourceData.setTrade_state_desc("因异常等未查到[交易结果]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setBank_type("因异常等未查到[付款银行]，但微信返回订单已支付，可使用[订单编码]查询交易记录");
                        resourceData.setAmount(new ResourceData.PayAmount(Integer.parseInt(responseMap.get("total_fee")),Integer.parseInt(responseMap.get("cash_fee")),responseMap.get("fee_type"),responseMap.get("fee_type")));
//                        groupApiService.paymentResult(resourceData);
                        return ResultMap.error(-1,responseMap.get("trade_state_desc"));
                    }else if("ORDERCLOSED".equals(err_code)){ //订单已经关闭
                        return ResultMap.ok();
                    }
                }else{
                    return ResultMap.ok();
                }
            }else{
                return ResultMap.error(-1,return_msg);
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        return ResultMap.error(-1,"关闭微信支付订单失败");
    }
    /**
     * 统一下单
     * @param inDto
     * @param orderNo: 订单编号
     * @param amount: 实际支付金额
     * @param body: 订单描述
     * @return
     */
    @Override
    public ResultMap unifiedOrder(InDto inDto, String orderNo, BigDecimal amount, String body) {
        if(StringUtils.isNotEmpty(body) ){
            body = Base64Util.subStringByBytes(body,50)+"...";
        }
        String userType = inDto .getUserType();
        String appid = inDto.getAppid();
        String openId = inDto.getOpenid();
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            String trade_type = "";
            if(userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH)) trade_type = "APP";
            else trade_type = "JSAPI";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            long times = new Date().getTime()+3*60*1000;
            WxPayAppConfig wxPayConfig = wxPayAppConfig;
            log.info("微信支付配置：{}"+wxPayConfig);
            if(userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH)) wxPayConfig.setAppID(wxPayAppConfig.getThirdAndriID());
            else wxPayConfig.setAppID(wxPayAppConfig.getAppletID());
            WXPay wxpay = new WXPay(wxPayConfig);
            if(!userType.startsWith(UserType.THIRD) && !userType.equals(UserType.WX_AUTH) ) requestMap.put("openid",openId);
            requestMap.put("body", body);                                       // 商品描述
            requestMap.put("out_trade_no", orderNo);                            // 商户订单号
            requestMap.put("total_fee", String.valueOf((amount.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));     // 支付总金额
//            requestMap.put("total_fee", String.valueOf(1));                     // 支付总金额
            requestMap.put("spbill_create_ip", IpUtils.getHostIp());            // 终端IP
            requestMap.put("trade_type", trade_type);                              // App支付类型
            requestMap.put("notify_url", wxPayConfig.getPayNotifyUrl());   // 接收微信支付异步通知回调地址
            requestMap.put("time_expire", sdf.format(new Date(times)));   // 交易结束时间
            log.info("统一下单参数》》》"+requestMap);
            Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);
            log.info("---111>>>"+resultMap);
            //获取返回码
            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            //若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = resultMap.get("result_code");
                String errCodeDes = resultMap.get("err_code_des");
                if ("SUCCESS".equals(resultCode)) {
                    responseMap = resultMap;
                }
            }

            if (responseMap == null || responseMap.isEmpty()) {
                return ResultMap.error("获取预支付交易会话标识失败");
            }
            // 3、签名生成算法

            returnMap.put("appId", wxPayConfig.getAppID());
            if(StringUtils.isNotEmpty(userType) && (userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH) )) {
                returnMap.put("partnerid", wxPayConfig.getMchID());
                returnMap.put("prepayid", responseMap.get("prepay_id"));
            }
            returnMap.put("nonceStr", responseMap.get("nonce_str"));
            returnMap.put("timeStamp", JsThirdSignUtil.create_timestamp());
            if(StringUtils.isNotEmpty(userType) && !(userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH) ))returnMap.put( "signType", "MD5");
            if(StringUtils.isNotEmpty(userType) && (userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH) )){
                returnMap.put("package", "Sign=WXPay");
            }else{
                returnMap.put("package", "prepay_id="+responseMap.get("prepay_id"));
            }
            log.info("---222>>>"+requestMap);
            String sign = WXPayUtil.generateSignature(returnMap, wxPayConfig.getKey());
            if(StringUtils.isNotEmpty(userType)
                    && (userType.startsWith(UserType.THIRD) || userType.equals(UserType.WX_AUTH) ))
                sign = sign.substring(0,30);
            returnMap.put("sign", sign);//微信支付签名
            log.info("---333>>>"+returnMap);
            return ResultMap.ok().put("data", returnMap);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("订单号：{}，错误信息：{}", orderNo, e.getMessage());
            return ResultMap.error("微信支付统一下单失败");
        }
    }
    /**
     * 统一下单/新
     * @param paymentRequestDto
     * @return
     */
    @Override
    public ResultMap unifiedOrder(PaymentRequestDto paymentRequestDto) {
        if(StringUtils.isNotEmpty(paymentRequestDto.getBody()) ){
            paymentRequestDto.setBody( Base64Util.subStringByBytes(paymentRequestDto.getBody(),50)+"...");
        }
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            String trade_type = "";
            if(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH)) trade_type = "APP";
            else trade_type = "JSAPI";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            long times = paymentRequestDto.getCreateOrderTime().getTime()+3*60*1000;
            WxPayAppConfig wxPayConfig = (WxPayAppConfig) payConfig.get(paymentRequestDto.getAppid());
            if(null == wxPayConfig){
                wxPayConfig = this.wxPayAppConfig;
            }
            log.info("微信支付配置：{}"+wxPayConfig);
            if(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH)) wxPayConfig.setAppID(wxPayAppConfig.getThirdAndriID());
            else wxPayConfig.setAppID(wxPayAppConfig.getAppletID());
            WXPay wxpay = new WXPay(wxPayConfig);
            if(!paymentRequestDto.getUserType().startsWith(UserType.THIRD) && !paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ) requestMap.put("openid", paymentRequestDto.getWxOpenid());
            requestMap.put("body", paymentRequestDto.getBody());                                       // 商品描述
            requestMap.put("out_trade_no", paymentRequestDto.getOrderNo());                            // 商户订单号
            requestMap.put("total_fee", String.valueOf((paymentRequestDto.getTotalAmount().multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));     // 支付总金额
//            requestMap.put("total_fee", String.valueOf(1));                     // 支付总金额
            requestMap.put("spbill_create_ip", IpUtils.getHostIp());            // 终端IP
            requestMap.put("trade_type", trade_type);                              // App支付类型
            requestMap.put("notify_url", wxPayConfig.getPayNotifyUrl());   // 接收微信支付异步通知回调地址
            requestMap.put("time_expire", sdf.format(new Date(times)));   // 交易结束时间
            log.info("统一下单参数》》》"+requestMap);
            Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);
            log.info("---111>>>"+resultMap);
            //获取返回码
            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            //若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = resultMap.get("result_code");
                String errCodeDes = resultMap.get("err_code_des");
                if ("SUCCESS".equals(resultCode)) {
                    responseMap = resultMap;
                }
            }
            if (responseMap == null || responseMap.isEmpty()) {
                return ResultMap.error("获取预支付交易会话标识失败");
            }
            // 3、签名生成算法
            returnMap.put("appId", wxPayConfig.getAppID());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) )) {
                returnMap.put("partnerid", wxPayConfig.getMchID());
                returnMap.put("prepayid", responseMap.get("prepay_id"));
            }
            returnMap.put("nonceStr", responseMap.get("nonce_str"));
            returnMap.put("timeStamp", JsThirdSignUtil.create_timestamp());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && !(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ))returnMap.put( "signType", "MD5");
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) )){
                returnMap.put("package", "Sign=WXPay");
            }else{
                returnMap.put("package", "prepay_id="+responseMap.get("prepay_id"));
            }
            log.info("---222>>>"+requestMap);
            String sign = WXPayUtil.generateSignature(returnMap, wxPayConfig.getKey());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType())
                    && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ))
                sign = sign.substring(0,30);
            returnMap.put("sign", sign);//微信支付签名
            requestMap.put("paySubType",wxPayConfig.getName());
            log.info("---333>>>"+returnMap);
            return ResultMap.ok().put("data", returnMap);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("订单号：{}，错误信息：{}", paymentRequestDto.getOrderNo(), e.getMessage());
            return ResultMap.error("微信支付统一下单失败");
        }
    }
    /**
     * 退款
     */
    @Override
    public ResultMap wxRefund(String appid,String orderNo, BigDecimal amount, String refundReason){
        try{
            WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) payConfig.get(appid);
            if(null == wxPayAppConfig){
                wxPayAppConfig = this.wxPayAppConfig;
            }
            log.info("退款金额:{}",amount);
            WXPay wxpay = new WXPay(wxPayAppConfig);
            Map<String, String> responseMap = new HashMap<>();
            Map<String, String> requestMap = new HashMap<>();
            //判断返回状态 修改 订单的退款状态
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("out_refund_no", RandomUtil.getRandom(RandomUtil.REFUND_NO));
            requestMap.put("total_fee", String.valueOf((amount.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));//订单金额
            requestMap.put("refund_fee", String.valueOf((amount.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));//所需退款金额
            requestMap.put("refund_desc", refundReason);
            requestMap.put("notify_url", wxPayAppConfig.getRefundNotifyUrl());
            log.info("退款请求信息:{}",requestMap);
            try {
                responseMap = wxpay.refund(requestMap);
                log.info("退款返回信息:{}"+responseMap);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String return_code = responseMap.get("return_code");   //返回状态码
            String return_msg = responseMap.get("return_msg");     //返回信息
            if ("SUCCESS".equals(return_code)) {
                String result_code = responseMap.get("result_code");       //业务结果
                String err_code_des = responseMap.get("err_code_des");     //错误代码描述
                if ("SUCCESS".equals(result_code)) {
                    return ResultMap.ok("退款申请成功").put("data",responseMap);
                } else {
                    log.info("订单号:{}错误信息:{}", orderNo, err_code_des);
                    return ResultMap.error(err_code_des);
                }
            } else {
                log.info("订单号:{}错误信息:{}", orderNo, return_msg);
                return ResultMap.error(return_msg);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("订单号：{}，错误信息：{}", orderNo, e.getMessage());
            return ResultMap.error("微信退款失败");
        }
    }

    /**********************新支付逻辑*********************/
    /**
     * 查询订单
     * @param paymentRequestDto
     * @return
     */
    @Override
    public PaymentInfoResponseDto queryOrder(PaymentRequestDto paymentRequestDto){
//        WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) payConfig.get(appid);
        WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) paymentRequestDto.getPayConfigByClass(WxPayAppConfig.class);
//        if(null == wxPayAppConfig){
//            wxPayAppConfig = this.wxPayAppConfig;
//        }
        String orderNo = paymentRequestDto.getOrderNo();

        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(wxPayAppConfig);
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-",""));
            returnMap.put("sign", WXPayUtil.generateSignature(requestMap, wxPayAppConfig.getKey()));//微信支付签名// 商户订单号
            responseMap = wxpay.orderQuery(requestMap);
            String return_code = responseMap.get("return_code");
            String return_msg = responseMap.get("return_msg");
            if("SUCCESS".equals(return_code)){
                String result_code = responseMap.get("result_code");
                if("SUCCESS".equals(result_code)){
                    String trade_state = responseMap.get("trade_state");
                    if("SUCCESS".equals(trade_state)){
                        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
                        paymentInfoResponseDto.setOrderNo(orderNo);
                        paymentInfoResponseDto.setPayWay("wxpay");
                        paymentInfoResponseDto.setAppid(wxPayAppConfig.getAppID());
                        paymentInfoResponseDto.setPaymentNo(responseMap.get("transaction_id"));
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(responseMap.get("total_fee")).divide(new BigDecimal(100)));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(responseMap.get("cash_fee")).divide(new BigDecimal(100)));
//                        paymentInfoResponseDto.setPaymentTime();
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        paymentInfoResponseDto.setPaymentSuccessTime(sdf.parse(responseMap.get("time_end")));
                        paymentInfoResponseDto.setSuccess(true);
                        return paymentInfoResponseDto;
                    }else{
                        return PaymentInfoResponseDto.error(-2,responseMap.get("trade_state_desc"));
                    }
                }else{
                    return PaymentInfoResponseDto.error(-1,responseMap.get("err_code_des"));
                }
            }else{
                return PaymentInfoResponseDto.error(-1,return_msg);
            }
        }catch (Exception e ){
            e.printStackTrace();
        }
        return PaymentInfoResponseDto.error(-1,"查询微信支付订单失败");
    }
    /**
     * 统一下单/新
     * @param paymentRequestDto
     * @return
     */
    @Override
    public ResultMap unifiedOrderNew(PaymentRequestDto paymentRequestDto) {
        if(StringUtils.isNotEmpty(paymentRequestDto.getBody()) ){
            paymentRequestDto.setBody( Base64Util.subStringByBytes(paymentRequestDto.getBody(),50)+"...");
        }
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            String trade_type = "";
            if(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH)) trade_type = "APP";
            else trade_type = "JSAPI";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            //long times = new Date().getTime()+3*60*1000;
            WxPayAppConfig wxPayConfig = (WxPayAppConfig) paymentRequestDto.getPayConfigByClass(WxPayAppConfig.class);
            /*WxPayAppConfig wxPayConfig = (WxPayAppConfig) payConfig.get(paymentRequestDto.getAppid());
            if(null == wxPayConfig){
                wxPayConfig = this.wxPayAppConfig;
            }*/
            log.info("微信支付配置：{}"+wxPayConfig);
            if(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH)) wxPayConfig.setAppID(wxPayConfig.getThirdAndriID());
            else wxPayConfig.setAppID(wxPayConfig.getAppletID());
            WXPay wxpay = new WXPay(wxPayConfig);
            if(!paymentRequestDto.getUserType().startsWith(UserType.THIRD) && !paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ) requestMap.put("openid", paymentRequestDto.getWxOpenid());
            requestMap.put("body", paymentRequestDto.getBody());                                       // 商品描述
            requestMap.put("out_trade_no", paymentRequestDto.getOrderNo());                            // 商户订单号
            requestMap.put("total_fee", String.valueOf((paymentRequestDto.getTotalAmount().multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_UP))));     // 支付总金额
//            requestMap.put("total_fee", String.valueOf(1));                     // 支付总金额
            requestMap.put("spbill_create_ip", IpUtils.getHostIp());            // 终端IP
            requestMap.put("trade_type", trade_type);                              // App支付类型
            requestMap.put("notify_url", wxPayConfig.getPayNotifyUrl());   // 接收微信支付异步通知回调地址
            requestMap.put("attach", paymentRequestDto.getPayWay());   // 自定义参数
            String expireTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,paymentRequestDto.getExpireTime());
            requestMap.put("time_expire", expireTime);   // 交易结束时间
            log.info("统一下单参数》》》"+requestMap);
            Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);
            log.info("---111>>>"+resultMap);
            //获取返回码
            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            //若返回码为SUCCESS，则会返回一个result_code,再对该result_code进行判断
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = resultMap.get("result_code");
                String errCodeDes = resultMap.get("err_code_des");
                if ("SUCCESS".equals(resultCode)) {
                    responseMap = resultMap;
                }
            }
            if (responseMap == null || responseMap.isEmpty()) {
                return ResultMap.error("获取预支付交易会话标识失败");
            }
            // 3、签名生成算法
            returnMap.put("appId", wxPayConfig.getAppID());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) )) {
                returnMap.put("partnerid", wxPayConfig.getMchID());
                returnMap.put("prepayid", responseMap.get("prepay_id"));
            }
            returnMap.put("nonceStr", responseMap.get("nonce_str"));
            returnMap.put("timeStamp", JsThirdSignUtil.create_timestamp());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && !(paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ))returnMap.put( "signType", "MD5");
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType()) && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) )){
                returnMap.put("package", "Sign=WXPay");
            }else{
                returnMap.put("package", "prepay_id="+responseMap.get("prepay_id"));
            }
            log.info("---222>>>"+requestMap);
            String sign = WXPayUtil.generateSignature(returnMap, wxPayConfig.getKey());
            if(StringUtils.isNotEmpty(paymentRequestDto.getUserType())
                    && (paymentRequestDto.getUserType().startsWith(UserType.THIRD) || paymentRequestDto.getUserType().equals(UserType.WX_AUTH) ))
                sign = sign.substring(0,30);
            returnMap.put("sign", sign);//微信支付签名
            requestMap.put("paySubType",wxPayConfig.getName());
            log.info("---333>>>"+returnMap);
            return ResultMap.ok().put("data", returnMap);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("订单号：{}，错误信息：{}", paymentRequestDto.getOrderNo(), e.getMessage());
            return ResultMap.error("微信支付统一下单失败");
        }
    }
    /**
     * 退款
     */
    @Override
    public ResultMap wxRefund(RefundRequestDto refundRequestDto){
        try{
            WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) refundRequestDto.getPayConfigByClass(WxPayAppConfig.class);
            BigDecimal amount = refundRequestDto.getRefundAmount();
            String orderNo = refundRequestDto.getOrderNo();
            String refundReason = refundRequestDto.getRefundMsg();
//            WxPayAppConfig wxPayAppConfig = (WxPayAppConfig) payConfig.get(appid);
//            if(null == wxPayAppConfig){
//                wxPayAppConfig = this.wxPayAppConfig;
//            }
            log.info("退款金额:{}",amount);
            WXPay wxpay = new WXPay(wxPayAppConfig);
            Map<String, String> responseMap = new HashMap<>();
            Map<String, String> requestMap = new HashMap<>();
            //判断返回状态 修改 订单的退款状态
            requestMap.put("out_trade_no", orderNo);
            requestMap.put("out_refund_no", RandomUtil.getRandom(RandomUtil.REFUND_NO));
            requestMap.put("total_fee", String.valueOf((amount.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));//订单金额
            requestMap.put("refund_fee", String.valueOf((amount.multiply(new BigDecimal(100)).setScale(0,BigDecimal.ROUND_DOWN))));//所需退款金额
            requestMap.put("refund_desc", refundReason);
            requestMap.put("notify_url", wxPayAppConfig.getRefundNotifyUrl());
            log.info("退款请求信息:{}",requestMap);
            try {
                responseMap = wxpay.refund(requestMap);
                log.info("退款返回信息:{}"+responseMap);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String return_code = responseMap.get("return_code");   //返回状态码
            String return_msg = responseMap.get("return_msg");     //返回信息
            if ("SUCCESS".equals(return_code)) {
                String result_code = responseMap.get("result_code");       //业务结果
                String err_code_des = responseMap.get("err_code_des");     //错误代码描述
                if ("SUCCESS".equals(result_code)) {
                    return ResultMap.ok("退款申请成功").put("data",responseMap);
                } else {
                    log.info("订单号:{}错误信息:{}", orderNo, err_code_des);
                    return ResultMap.error(err_code_des);
                }
            } else {
                log.info("订单号:{}错误信息:{}", orderNo, return_msg);
                return ResultMap.error(return_msg);
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("订单号：{}，错误信息：{}", refundRequestDto.getOrderNo(), e.getMessage());
            return ResultMap.error("微信退款失败");
        }
    }
}
