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

import cn.com.sand.hmpay.HmpayClient;
import cn.com.sand.hmpay.contants.TradeContants;
import cn.com.sand.hmpay.enums.TradeApiMethodEnums;
import cn.com.sand.hmpay.enums.TradeBizPayTypeEnums;
import cn.com.sand.hmpay.util.JacksonUtil;
import cn.com.sand.hmpay.util.RsaUtil;
import cn.com.sand.hmpay.vo.request.TradeRequest;
import cn.com.sand.hmpay.vo.request.biz.*;
import cn.com.sand.hmpay.vo.response.TradeResponse;
import cn.com.sand.hmpay.vo.response.biz.TradeBizCreateResponse;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.tzy.common.dto.OutDTO;
import com.tzy.common.utils.*;
import com.tzy.framework.pay.config.HmPayConfig;
import com.tzy.framework.pay.config.PayConfig;
import com.tzy.framework.pay.dto.PaymentInfoResponseDto;
import com.tzy.framework.pay.dto.PaymentRequestDto;
import com.tzy.framework.pay.dto.RefundRequestDto;
import com.tzy.framework.pay.dto.ResultMap;
import com.tzy.framework.pay.service.HmPayService;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 河马付
 */
@Slf4j
@Service
public class HmPayServiceImpl implements HmPayService {
    @Autowired
    private HmPayConfig hmPayConfig ;
    @Value("${pay.hm.app.payNotifyUrl:1}")
    private String notifyUrl;
    @Value("${pay.hm.app.refundNotifyUrl:1}")
    private String refundNotifyUrl;
    private String host = "https://hmpay.sandpay.com.cn/gateway";
//    private String host = "http://star.sandgate.cn/gateway";
    HmpayClient hmpayClient = new HmpayClient(host+"/api");
    @Autowired
    private PayConfig payConfig;

    /**
     * 统一下单
     */
    @Override
    public String hmTradeCreate(String payWay ,String buyerId, String orderNo, BigDecimal totalAmount, String body) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ipAddr = IpUtils.getIpAddr(request);
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH,mm,ss"));
        String merAppId = null;
        String merBuyerId = null;
        long startTime = System.currentTimeMillis();
        String payType = TradeBizPayTypeEnums.MWEB.name();
        String method = TradeApiMethodEnums.TRADE_CREATE.getMethod();
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String expireTime = LocalDateTime.now().plusMinutes(5).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));//设置5分钟失效
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
//                .subAppId(hmPayConfig.getWxMchID())
                .format(hmPayConfig.getFormat())
                .charset("UTF-8")
                .method(method)
                .signType("RSA")
                .timestamp(timestamp)
                .nonce(RandomUtil.random(8))
                .bizContent(
                        TradeCreateRequest
                                .builder()
                                .payType(payType)
                                .buyerId(buyerId)
                                .merAppId(merAppId)
                                .merBuyerId(merBuyerId)
                                .body(body)
                                .createIp(ipAddr)
                                .createTime(createTime)
                                .expireTime(expireTime)
                                .notifyUrl(notifyUrl)
//                                .operatorId(operatorId)
                                .outOrderNo(orderNo)
                                .payWay( (StringUtils.isNotEmpty(payWay) && payWay.equals("wxpay") ? "WECHAT" : payWay).toUpperCase() )
                                .storeId(hmPayConfig.getStoreId())
//                                .terminalId(terminalId)
                                .totalAmount(totalAmount.doubleValue())
//                                .extendParams(ExtendParams.builder().accessPartyCode("SDK_TEST").build())
//                                .discountInfo(DisCountInfo.builder()
//                                        .goodsTag(goodsTag)
//                                        .discountableAmount(discountableAmount)
//                                        .productCode(productCode)
//                                        .build())
//                                .goodsDetails(goodsDetail)
//                                .limitPay(limitPay)
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());

        System.out.println(tradeRequest);
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        System.out.println(tradeResponse);

        long endTime = System.currentTimeMillis();

        System.out.println("花费时间, " + (endTime - startTime) + "ms");
        boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getPublicKey(), TradeContants.CHARSET);
        System.out.println("验签结果：" + b);

        String callbackUrl = "";
        String cancelUrl = "";

        String payUrl = host + "/trade/jsApiPay?";

        String param = "pay_way=%s&pay_data=%s&callback_url=%s&cancel_url=%s";
        String data = tradeResponse.getData();
        TradeBizCreateResponse tradeBizCreateResponse = JacksonUtil.jsonToBean(data, TradeBizCreateResponse.class);
        String payData = tradeBizCreateResponse.getPayData();

        try {
            payWay = URLEncoder.encode(payWay, "UTF-8");
            payData = URLEncoder.encode(payData, "UTF-8");
            callbackUrl = URLEncoder.encode(callbackUrl, "UTF-8");
            cancelUrl = URLEncoder.encode(cancelUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        param = String.format(param, payWay, payData, callbackUrl, cancelUrl);
        String payCodeUrl = payUrl + param;
        System.out.println("支付地址：" + payCodeUrl);
        return payCodeUrl;
    }
    /**
     * 统一下单
     */
    @Override
    public String tradeCreate(Map<String,Object> param){
        try {
            String body = String.valueOf(param.get("body"));
            if(StringUtils.isNotEmpty(body)){
                body = Base64Util.subStringByBytes(body,120)+"...";
            }
            body = URLEncoder.encode(body, "UTF-8");
            BigDecimal totalAmount = (BigDecimal) param.get("totalAmount");

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ipAddr = IpUtils.getIpAddr(request);
            ipAddr = (StringUtils.isEmpty(ipAddr) ? "116.233.194.22" : ipAddr).replaceAll("\\.", "_");
            if(ipAddr.indexOf(",") != -1){
                ipAddr = ipAddr.split(",")[0];
            }
            String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String expireTime = LocalDateTime.now().plusMinutes(5).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));//设置5分钟失效
            Map<String ,String > map = new TreeMap<>();
            map.put("create_ip",ipAddr);
            map.put("version", hmPayConfig.getVersion());
            map.put("mer_no", hmPayConfig.getAppId());
            map.put("mer_order_no", String.valueOf(param.get("orderNo")));
            map.put("create_time", createTime);
            map.put("order_amt", String.valueOf(totalAmount.setScale(2,BigDecimal.ROUND_DOWN).doubleValue()));
            map.put("notify_url", hmPayConfig.getPayNotifyUrl());
            map.put("return_url", hmPayConfig.getReturnUrl());
            map.put("store_id", hmPayConfig.getStoreId());
            map.put("sign_type", "RSA");
            //map.put("accsplit_flag", "NO");
            String appid=param.get("appid")==null?"":param.get("appid").toString();
            String openid=param.get("openid")==null?"":param.get("openid").toString();
            String path_url=param.get("path_url")==null?"":param.get("path_url").toString();
            String pay_extra = "{\"mer_app_id\":\"\",\"openid\":\"" +
                    "\"wx_app_id\":\""+appid+"\",\"gh_ori_id\":" +openid+"\",\"path_url\":\"" +path_url+"\",\"miniProgramType\":\"2\"" +"\"}";

            map.put("gh_static_url",hmPayConfig.getGhStaticUrl());
            String content = BeanUtil.param2str(map) ;
            String rsa = AlipaySignature.rsaSign(content, hmPayConfig.getPrivateKey(), "UTF-8", "RSA");
            //--------------不参与签名
            log.info("sign参数》》{}",content);
            log.info("签名》》{}",rsa);
            map.put("notify_url", URLEncoder.encode(hmPayConfig.getPayNotifyUrl() ,"UTF-8"));
            map.put("return_url", URLEncoder.encode(hmPayConfig.getReturnUrl() ,"UTF-8"));
//            String pay_extra = "{\"mer_app_id\":\""+param.get("appid")+"\",\"openid\":\""+param.get("openid")
            map.put("pay_extra", "");
            //map.put("pay_extra", URLEncoder.encode( pay_extra,"UTF-8"));
            map.put("expire_time", expireTime);
            map.put("goods_name",  body);
            map.put("clear_cycle", "0");
            map.put("jump_scheme", "hemacash://hmpay");
            map.put("sign",  URLEncoder.encode(rsa,"UTF-8"));
            map.put("meta_option", URLEncoder.encode( "[{\"s\":\"Android\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"},{\"s\":\"IOS\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"}]","UTF-8"));
            if(String.valueOf(param.get("payWay")).equals("alipay")){
                map.put("product_code", "01020002");//支付宝H5
                // 支付宝app 01020004
                String retStr = BeanUtil.param2str(map) ;
                return "https://cash.sandgate.cn/h5/?"+retStr+"#/hippoh5";
            }else{
//                map.put("product_code", "01010005"); //微信app
                //map.put("product_code", "01010002,01010005,02010006");//微信H5
                map.put("product_code", "01010006");//云函数
                String retStr = BeanUtil.param2str(map) ;
                return "https://cash.sandgate.cn/h5/?"+retStr+"#/applet";
            }
            //return "https://cash.sandgate.cn/h5/?"+retStr+"#/applet";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/sandcashier1";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/hippoPublic";
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 统一下单
     * @param paymentRequestDto
     * @return
     */
    @Override
    public ResultMap tradeCreate(PaymentRequestDto paymentRequestDto){
        ResultMap resultMap = new ResultMap();
        try {
            HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(paymentRequestDto.getAppid());
            if(null == hmPayConfig){
                hmPayConfig = this.hmPayConfig;
            }
            String body = String.valueOf(paymentRequestDto.getBody());
            if(StringUtils.isNotEmpty(body) ){
                body = Base64Util.subStringByBytes(body,80)+"...";
            }
            body = URLEncoder.encode(body, "UTF-8");
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ipAddr = IpUtils.getIpAddr(request);
            ipAddr = (StringUtils.isEmpty(ipAddr) ? "116.233.194.22" : ipAddr).replaceAll("\\.", "_");
            if(ipAddr.indexOf(",") != -1){
                ipAddr = ipAddr.split(",")[0];
            }
            String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String expireTime = DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS,new Date(paymentRequestDto.getCreateOrderTime().getTime()+2800*60));//设置3分钟失效
            Map<String ,String > map = new TreeMap<>();
            map.put("create_ip",ipAddr);
            map.put("version", hmPayConfig.getVersion());
            map.put("mer_no", hmPayConfig.getAppId());
            map.put("mer_order_no", paymentRequestDto.getOrderNo());
            map.put("create_time", createTime);
            map.put("order_amt", String.valueOf(paymentRequestDto.getTotalAmount().setScale(2,BigDecimal.ROUND_DOWN).doubleValue()));
            map.put("notify_url", hmPayConfig.getPayNotifyUrl());
            map.put("return_url", hmPayConfig.getReturnUrl());
            map.put("store_id", hmPayConfig.getStoreId());
            map.put("sign_type", "RSA");
            //map.put("accsplit_flag", "NO");
            String pay_extra = "{\"mer_app_id\":\"\",\"openid\":\"" +
                    "\"wx_app_id\":\""+ paymentRequestDto.getWxAppid()+"\",\"gh_ori_id\":" + paymentRequestDto.getWxOpenid()+"\",\"path_url\":\"" + paymentRequestDto.getPath_url()+"\",\"miniProgramType\":\"2\"" +"\"}";

            map.put("gh_static_url",hmPayConfig.getGhStaticUrl());
            String content = BeanUtil.param2str(map) ;
            String rsa = AlipaySignature.rsaSign(content, hmPayConfig.getPrivateKey(), "UTF-8", "RSA");
            //--------------不参与签名
            log.info("sign参数》》{}",content);
            log.info("签名》》{}",rsa);
            map.put("notify_url", URLEncoder.encode(hmPayConfig.getPayNotifyUrl() ,"UTF-8"));
            map.put("return_url", URLEncoder.encode(hmPayConfig.getReturnUrl() ,"UTF-8"));
//            String pay_extra = "{\"mer_app_id\":\""+param.get("appid")+"\",\"openid\":\""+param.get("openid")
            map.put("pay_extra", "");
            //map.put("pay_extra", URLEncoder.encode( pay_extra,"UTF-8"));
            map.put("expire_time", expireTime);
            map.put("goods_name",  body);
            map.put("clear_cycle", "0");
            map.put("jump_scheme", "hemacash://hmpay");
            map.put("sign",  URLEncoder.encode(rsa,"UTF-8"));
            map.put("meta_option", URLEncoder.encode( "[{\"s\":\"Android\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"},{\"s\":\"IOS\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"}]","UTF-8"));
            String paymentUrl = "";
            if(paymentRequestDto.getPayWay().contains("alipay")){
                map.put("product_code", "01020002");//支付宝H5
                // 支付宝app 01020004
                paymentUrl = "https://cash.sandgate.cn/h5/?"+BeanUtil.param2str(map)+"#/hippoh5";
            }else{
                map.put("product_code", "01010006");//云函数
                paymentUrl = "https://cash.sandgate.cn/h5/?"+BeanUtil.param2str(map)+"#/applet";
            }
            //return "https://cash.sandgate.cn/h5/?"+retStr+"#/applet";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/sandcashier1";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/hippoPublic";
            Map dataMap = new HashMap();
            dataMap.put("hmUrl", paymentUrl);
            resultMap.put("data", dataMap);
            return resultMap;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ResultMap.error("下单失败！");
    }

    /**
     * {
     * 	map.put("create_ip", "127_0_0_1");
     * 	map.put("store_id", "100001");
     * 	map.put("goods_name", "测试商品");
     * 	map.put("pay_extra", "{\"mer_app_id\",\"wxdc71tul975fd3drr\",\"openid\",\"oUnDDFGererfZPzspzi_bEhMM\"}");
     * 	map.put("mer_no", "123456");
     * 	map.put("create_time", "20200831160114");
     * 	map.put("mer_key", "123");
     * 	map.put("expire_time", "20200831160118");
     * 	map.put("notify_url", "https,//baidu.com.cn/notify_test/sand");
     * 	map.put("product_code", "01010001,01010002");
     * 	map.put("version", "10");
     * 	map.put("accsplit_info", "NO");
     * 	map.put("return_url", "https,//baidu.com.cn/notify_test/returnUrl");
     * 	map.put("clear_cycle", "0");
     * 	map.put("order_amt", "0.01");
     * 	map.put("mer_order_no", "1598860874173");
     * 	map.put("sign", "820AB93E4A3CB968BF78F4ADD75E9C4D");
     * }
     */
//    String AlipaySignature.rsaSign(String content, String privateKey, String charset,String signType)

    /**
     * 退款
     * @param param
     * @return
     */
    @Override
    public ResultMap refundOrder(Map<String,Object> param) {
        String appid = (String) param.getOrDefault("appid",null);
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        BigDecimal totalAmount = (BigDecimal) param.get("totalAmount");
        String outOrderNo = (String) param.get("orderNo");
        String refund_request_no = (String) param.get("refund_request_no");
        String method = TradeApiMethodEnums.TRADE_REFUND.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeRefundRequest
                                .builder()
                                .outOrderNo(outOrderNo)
                                .refundAmount(Double.valueOf(String.valueOf(totalAmount.setScale(2, BigDecimal.ROUND_DOWN).doubleValue())))
                                .refundRequestNo(refund_request_no)
                                .refundReason((String) param.get("refundMsg"))
                                .storeId(hmPayConfig.getStoreId())
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b) {
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if (null != stringStringMap && !stringStringMap.isEmpty()) {
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if ("REFUND_SUCCESS".equals(code)) {
                        stringStringMap.put("out_refund_no", String.valueOf(jsonObject.get("refund_request_no")));
                        stringStringMap.put("refund_id", String.valueOf(jsonObject.get("refund_plat_trx_no")));
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(jsonObject.get("refund_settle_amount"))) * 100));
                        stringStringMap.put("fund_change", "Y");
                        //退款成功
                        return ResultMap.ok()
                                .put("data", stringStringMap)
                                ;
                    } else {
                        errMsg = stringStringMap.get("sub_msg");
                    }
                } else if (null == stringStringMap) {
                    errMsg = "退款请求失败！";
                } else {
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return ResultMap.error(errMsg)
                ;
    }

    /**
     * 查询订单信息
     */
    @Override
    public PaymentInfoResponseDto queryOrder(String appid,String orderNo){
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        String platTrxNo = "";
        String bankOrderNo = "";
        String method = TradeApiMethodEnums.TRADE_QUERY.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeQueryRequest
                        .builder()
                        .outOrderNo(orderNo)
                        .platTrxNo(platTrxNo)
                        .bankOrderNo(bankOrderNo)
                        .build()
                        .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b){
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if(null != stringStringMap && !stringStringMap.isEmpty()){
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if("SUCCESS".equals(code)){
                        //查询
                        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
                        paymentInfoResponseDto.setSuccess(true);
                        paymentInfoResponseDto.setOrderNo(orderNo);
                        paymentInfoResponseDto.setPayWay(jsonObject.getString("pay_way_code"));
                        paymentInfoResponseDto.setAppid(hmPayConfig.getApp_id());
                        paymentInfoResponseDto.setPaymentNo(jsonObject.getString("plat_trx_no"));
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(jsonObject.getDouble("total_amount")));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(jsonObject.getDouble("total_amount")));
                        paymentInfoResponseDto.setTradeState(code);
                        paymentInfoResponseDto.setTradeStateDesc(code);
    //                        paymentInfoResponseDto.setPaymentTime();
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        try {
                            paymentInfoResponseDto.setPaymentSuccessTime(sdf.parse(jsonObject.getString("success_time")));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return paymentInfoResponseDto;
                    }else{
                        errMsg = stringStringMap.get("sub_msg");
                    }
                }else if(null == stringStringMap){
                    errMsg = "查询请求失败！";
                }else{
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return PaymentInfoResponseDto.error(-2,errMsg);
    }
    /**
     * 查询订单信息
     */
    @Override
    public OutDTO queryOrder(Map<String,Object> param){
        String appid = (String) param.getOrDefault("appid",null);
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        String platTrxNo = "";
        String bankOrderNo = "";
        String outOrderNo = (String) param.get("orderNo");
        String method = TradeApiMethodEnums.TRADE_QUERY.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeQueryRequest
                                .builder()
                                .outOrderNo(outOrderNo)
                                .platTrxNo(platTrxNo)
                                .bankOrderNo(bankOrderNo)
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b){
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if(null != stringStringMap && !stringStringMap.isEmpty()){
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if("SUCCESS".equals(code)){
                        //退款成功
                        return OutDTO.ok(jsonObject.getString("sub_msg"))
                                .put("data",stringStringMap)
                                ;
                    }else{
                        errMsg = stringStringMap.get("sub_msg");
                    }
                }else if(null == stringStringMap){
                    errMsg = "退款请求失败！";
                }else{
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return OutDTO.error(-2,errMsg)
                ;
    }
    /**
     * 查询退款订单信息
     */
    @Override
    public OutDTO queryRefundOrder(Map<String,Object> param){
        String appid = (String) param.getOrDefault("appid",null);
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        String outOrderNo = (String) param.get("orderNo");
        String platTrxNo = "";
        String bankOrderNo = "";
        String refundRequestNo = (String) param.get("refund_request_no");
        String method = TradeApiMethodEnums.TRADE_REFUND_QUERY.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeRefundQueryRequest
                                .builder()
                                .outOrderNo(outOrderNo)
                                .platTrxNo(platTrxNo)
                                .bankOrderNo(bankOrderNo)
                                .refundRequestNo(refundRequestNo)
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b) {
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if (null != stringStringMap && !stringStringMap.isEmpty()) {
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if ("REFUND_SUCCESS".equals(code)) {
                        stringStringMap.put("out_refund_no", String.valueOf(jsonObject.get("refund_request_no")));
                        stringStringMap.put("refund_id", String.valueOf(jsonObject.get("refund_plat_trx_no")));
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(jsonObject.get("refund_success_amount"))) * 100));
                        stringStringMap.put("fund_change", "Y");
                        //退款成功
                        return OutDTO.ok(jsonObject.getString("sub_msg"))
                                .put("data", stringStringMap)
                                ;
                    } else {
                        errMsg = stringStringMap.get("sub_msg");
                    }
                } else if (null == stringStringMap) {
                    errMsg = "退款请求失败！";
                } else {
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return OutDTO.error(-2,errMsg)
                ;
    }
    /**
     * 取消订单
     */
    @Override
    public OutDTO cancelOrder(Map<String,Object> param){
        String appid = (String) param.getOrDefault("appid",null);
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        String outOrderNo = (String) param.get("orderNo");
        String platTrxNo = "";
        String bankOrderNo = "";
        String method = TradeApiMethodEnums.TRADE_CANCEL.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeCancelRequest
                                .builder()
                                .outOrderNo(outOrderNo)
                                .platTrxNo(platTrxNo)
                                .bankOrderNo(bankOrderNo)
                                .storeId(hmPayConfig.getStoreId())
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        System.out.println(tradeRequest);
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            System.out.println(tradeResponse);
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b){
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if(null != stringStringMap && !stringStringMap.isEmpty()){
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if("REFUND_SUCCESS".equals(code)){
                        stringStringMap.put("out_refund_no", String.valueOf(jsonObject.get("refund_request_no")));
                        stringStringMap.put("refund_id", String.valueOf(jsonObject.get("refund_plat_trx_no")));
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(jsonObject.get("refund_success_amount")))*100));
                        stringStringMap.put("fund_change", "Y");
                        //退款成功
                        return OutDTO.ok(jsonObject.getString("sub_msg"))
                                .put("data",stringStringMap)
                                ;
                    }else{
                        errMsg = stringStringMap.get("sub_msg");
                    }
                }else if(null == stringStringMap){
                    errMsg = "退款请求失败！";
                }else{
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return OutDTO.error(-2,errMsg)
                ;
    }


    /************新逻辑***************/
    /**
     * 统一下单
     * @param paymentRequestDto
     * @return
     */
    @Override
    public ResultMap tradeCreateNew(PaymentRequestDto paymentRequestDto){
        ResultMap resultMap = new ResultMap();
        try {
            HmPayConfig hmPayConfig = (HmPayConfig) paymentRequestDto.getPayConfigByClass(HmPayConfig.class);
//            HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(paymentRequestDto.getAppid());
//            if(null == hmPayConfig){
//                hmPayConfig = this.hmPayConfig;
//            }
            String body = String.valueOf(paymentRequestDto.getBody());
            if(StringUtils.isNotEmpty(body) ){
                body = Base64Util.subStringByBytes(body,80)+"...";
            }
            body = URLEncoder.encode(body, "UTF-8");
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String ipAddr = IpUtils.getIpAddr(request);
            ipAddr = (StringUtils.isEmpty(ipAddr) ? "116.233.194.22" : ipAddr).replaceAll("\\.", "_");
            if(ipAddr.indexOf(",") != -1){
                ipAddr = ipAddr.split(",")[0];
            }
            String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

            //String expireTime = LocalDateTime.now().plusMinutes(5).format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String expireTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,paymentRequestDto.getExpireTime());
            Map<String ,String > map = new TreeMap<>();
            map.put("create_ip",ipAddr);
            map.put("version", hmPayConfig.getVersion());
            map.put("mer_no", hmPayConfig.getAppId());
            map.put("mer_order_no", paymentRequestDto.getOrderNo());
            map.put("create_time", createTime);
            map.put("order_amt", String.valueOf(paymentRequestDto.getTotalAmount().setScale(2,BigDecimal.ROUND_DOWN).doubleValue()));
            map.put("notify_url", hmPayConfig.getPayNotifyUrl());
            map.put("return_url", hmPayConfig.getReturnUrl());
            map.put("store_id", hmPayConfig.getStoreId());
            map.put("sign_type", "RSA");
            //map.put("accsplit_flag", "NO");
            String pay_extra = "{\"mer_app_id\":\"\",\"openid\":\"" +
                    "\"wx_app_id\":\""+ paymentRequestDto.getWxAppid()+"\",\"gh_ori_id\":" + paymentRequestDto.getWxOpenid()+"\",\"path_url\":\"" + paymentRequestDto.getPath_url()+"\",\"miniProgramType\":\"2\"" +"\"}";

            map.put("gh_static_url",hmPayConfig.getGhStaticUrl());
            String content = BeanUtil.param2str(map) ;
            String rsa = AlipaySignature.rsaSign(content, hmPayConfig.getPrivateKey(), "UTF-8", "RSA");
            //--------------不参与签名
            log.info("sign参数》》{}",content);
            log.info("签名》》{}",rsa);
            map.put("notify_url", URLEncoder.encode(hmPayConfig.getPayNotifyUrl() ,"UTF-8"));
            map.put("return_url", URLEncoder.encode(hmPayConfig.getReturnUrl() ,"UTF-8"));
//            String pay_extra = "{\"mer_app_id\":\""+param.get("appid")+"\",\"openid\":\""+param.get("openid")
            map.put("pay_extra", "");
            //map.put("pay_extra", URLEncoder.encode( pay_extra,"UTF-8"));
            map.put("expire_time", expireTime);
            map.put("goods_name",  body);
            map.put("clear_cycle", "0");
            map.put("jump_scheme", "hemacash://hmpay");
            map.put("sign",  URLEncoder.encode(rsa,"UTF-8"));
            map.put("meta_option", URLEncoder.encode( "[{\"s\":\"Android\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"},{\"s\":\"IOS\",\"n\":\"HOBBYSTOCKS\",\"id\":\"com.hobbystocks\",\"sc\":\"\"}]","UTF-8"));
            String paymentUrl = "";
            if(paymentRequestDto.getPayWay().contains("alipay")){
                map.put("product_code", "01020002");//支付宝H5
                // 支付宝app 01020004
                paymentUrl = "https://cash.sandgate.cn/h5/?"+BeanUtil.param2str(map)+"#/hippoh5";
            }else{
                map.put("product_code", "01010006");//云函数
                paymentUrl = "https://cash.sandgate.cn/h5/?"+BeanUtil.param2str(map)+"#/applet";
            }
            //return "https://cash.sandgate.cn/h5/?"+retStr+"#/applet";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/sandcashier1";
//            return "https://cash.sandgate.cn/h5/?"+retStr+"#/hippoPublic";
            Map dataMap = new HashMap();
            dataMap.put("hmUrl", paymentUrl);
            resultMap.put("data", dataMap);
            return resultMap;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ResultMap.error("下单失败！");
    }
    /**
     * 退款
     * @param refundRequestDto
     * @return
     */
    @Override
    public ResultMap refundOrder(RefundRequestDto refundRequestDto) {
        HmPayConfig hmPayConfig = (HmPayConfig) refundRequestDto.getPayConfigByClass(HmPayConfig.class);
        /*String appid = (String) param.getOrDefault("appid",null);
        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(appid);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }*/
        BigDecimal totalAmount = refundRequestDto.getRefundAmount();
        String outOrderNo = refundRequestDto.getOrderNo();
        String refund_request_no = refundRequestDto.getRefundNo();
        String method = TradeApiMethodEnums.TRADE_REFUND.getMethod();
        String refundMsg = refundRequestDto.getRefundMsg();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeRefundRequest
                                .builder()
                                .outOrderNo(outOrderNo)
                                .refundAmount(Double.valueOf(String.valueOf(totalAmount.setScale(2, BigDecimal.ROUND_UP).doubleValue())))
                                .refundRequestNo(refund_request_no)
                                .refundReason(refundMsg)
                                .storeId(hmPayConfig.getStoreId())
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b) {
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if (null != stringStringMap && !stringStringMap.isEmpty()) {
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if ("REFUND_SUCCESS".equals(code)) {
                        stringStringMap.put("out_refund_no", String.valueOf(jsonObject.get("refund_request_no")));
                        stringStringMap.put("refund_id", String.valueOf(jsonObject.get("refund_plat_trx_no")));
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(jsonObject.get("refund_settle_amount"))) * 100));
                        stringStringMap.put("fund_change", "Y");
                        //退款成功
                        return ResultMap.ok()
                                .put("data", stringStringMap)
                                ;
                    } else {
                        errMsg = stringStringMap.get("sub_msg");
                    }
                } else if (null == stringStringMap) {
                    errMsg = "退款请求失败！";
                } else {
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return ResultMap.error(errMsg)
                ;
    }

    /**
     * 查询订单信息
     */
    @Override
    public PaymentInfoResponseDto queryOrder(PaymentRequestDto paymentRequestDto){
//        HmPayConfig hmPayConfig = (HmPayConfig) payConfig.get(paymentRequestDto.getAppid());
        HmPayConfig hmPayConfig = (HmPayConfig) paymentRequestDto.getPayConfigByClass(HmPayConfig.class);
        if(null == hmPayConfig){
            hmPayConfig = this.hmPayConfig;
        }
        String platTrxNo = "";
        String bankOrderNo = "";
        String method = TradeApiMethodEnums.TRADE_QUERY.getMethod();
        TradeRequest tradeRequest = TradeRequest
                .builder()
                .appId(hmPayConfig.getApp_id())
                .format(hmPayConfig.getFormat())
                .charset("utf-8")
                .method(method)
                .signType("RSA")
                .timestamp(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .nonce(String.valueOf(System.currentTimeMillis()))
                .bizContent(
                        TradeQueryRequest
                                .builder()
                                .outOrderNo(paymentRequestDto.getOrderNo())
                                .platTrxNo(platTrxNo)
                                .bankOrderNo(bankOrderNo)
                                .build()
                                .toJsonString()
                )
                .version(hmPayConfig.getVersion())
                .build()
                .buildSign(hmPayConfig.getPrivateKey());
        TradeResponse tradeResponse = hmpayClient.execute(tradeRequest);
        String errMsg = "";
        if(StringUtils.isNotEmpty(tradeResponse.getCode()) && "200".equals(tradeResponse.getCode()) ){
            boolean b = RsaUtil.rsaCheckV2(tradeResponse.toMap(), hmPayConfig.getHmPublicKey(), TradeContants.CHARSET);
            log.info("验签结果：" + b);
            if(b){
                //请求成功：
                Map<String, String> stringStringMap = tradeResponse.toMap();
                if(null != stringStringMap && !stringStringMap.isEmpty()){
                    String data = stringStringMap.get("data");
                    JSONObject jsonObject = JSONObject.parseObject(data);
                    String code = jsonObject.getString("sub_code");
                    if("SUCCESS".equals(code)){
                        //查询
                        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
                        paymentInfoResponseDto.setSuccess(true);
                        paymentInfoResponseDto.setOrderNo(paymentRequestDto.getOrderNo());
                        paymentInfoResponseDto.setPayWay(jsonObject.getString("pay_way_code"));
                        paymentInfoResponseDto.setAppid(hmPayConfig.getApp_id());
                        paymentInfoResponseDto.setPaymentNo(jsonObject.getString("plat_trx_no"));
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(jsonObject.getDouble("total_amount")));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(jsonObject.getDouble("total_amount")));
                        //                        paymentInfoResponseDto.setPaymentTime();
                        SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmss");
                        try {
                            paymentInfoResponseDto.setPaymentSuccessTime(sdf.parse(jsonObject.getString("success_time")));
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                        return paymentInfoResponseDto;
                    }else{
                        errMsg = stringStringMap.get("sub_msg");
                    }
                }else if(null == stringStringMap){
                    errMsg = "查询请求失败！";
                }else{
                    errMsg = stringStringMap.get("sub_msg");
                }
            }else {
                errMsg = "退款错误[SIGN ERROR]，请联系开发人员！";
            }
        }else{
            errMsg = tradeResponse.getMsg();
        }
        return PaymentInfoResponseDto.error(-2,errMsg);
    }


}
