package com.liquidnet.service.dragon.channel.alipay.biz;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeCreateModel;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.commons.lang.util.StringUtil;
import com.liquidnet.service.dragon.channel.alipay.req.AlipayTradePayReq;
import com.liquidnet.service.dragon.channel.alipay.sign.MD5;
import com.liquidnet.service.dragon.constant.DragonConstant;
import com.liquidnet.service.dragon.utils.ObjectUtilDragon;
import com.liquidnet.service.dragon.utils.PayAlipayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author AnJiabin <anjiabin@zhengzai.tv>
 * @version V1.0
 * @Description: TODO
 * @class: AlipayBiz
 * @Package com.liquidnet.service.dragon.channel.alipay.biz
 * @Copyright: LightNet @ Copyright (c) 2021
 * @date 2021/7/10 16:21
 */
@Slf4j
@Component
public class AlipayBiz{
    /**
     * tradeMicroPay
     * @param alipayTradePayReq
     * @return
     */
    public static Map<String, Object> tradeMicroPay(AlipayTradePayReq alipayTradePayReq) {
        log.info("AlipayBiz.tradeMicroPay-->> req : {}",alipayTradePayReq.toString());
        AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();
        SortedMap<String, Object> paramMap = new TreeMap<>();
        paramMap.put("out_trade_no", alipayTradePayReq.getOutTradeNo());
        paramMap.put("total_amount", alipayTradePayReq.getTotalAmount().toString());
        paramMap.put("subject", alipayTradePayReq.getSubject());
        paramMap.put("scene", "bar_code");
        paramMap.put("auth_code",alipayTradePayReq.getAuthCode());
        AlipayTradePayRequest request = new AlipayTradePayRequest();
        log.info("bizContent :{}", JsonUtils.toJson(paramMap));
        request.setBizContent(JsonUtils.toJson(paramMap));
        try {
            long startTime = System.currentTimeMillis();
            AlipayTradePayResponse response = alipayClient.execute(request);
            log.info("alipay-alipayClient.sdkExecut->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
            startTime = System.currentTimeMillis();
            Map<String,Object> responseJSON = ObjectUtilDragon.cloneHashMapStringAndObj();
            log.info("AlipayUtil-->tradeMicroPay-->cloneHashMapStringAndObj 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");

            responseJSON.put("code",response.getCode());
            responseJSON.put("msg",response.getMsg());
            responseJSON.put("subCode",response.getSubCode());
            responseJSON.put("subMsg",response.getSubMsg());
            responseJSON.put("body",response.getBody());
            //responseJSON.put("merchantOrderNo",response.getMerchantOrderNo());
            responseJSON.put("outTradeNo",response.getOutTradeNo());
            //responseJSON.put("sellerId",response.getSellerId());
            responseJSON.put("totalAmount",response.getTotalAmount());
            responseJSON.put("tradeNo",response.getTradeNo());
            startTime = System.currentTimeMillis();
            log.info("AlipayUtil-->tradeMicroPay-->支付宝返回结果:{}", JsonUtils.toJson(response));
            log.info("AlipayUtil-->tradeMicroPay-->支付宝返回结果 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
            return responseJSON;
        } catch (Exception e) {
            log.error("支付宝支付异常:{}", e);
            JSONObject resultJSON = ObjectUtilDragon.cloneJsonObjectObj();
            resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
            resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
            resultJSON.put("errorCode", "9999");
            return resultJSON;
        }
    }
    /**
     * tradeWapPay
     * @param alipayTradePayReq
     * @return
     */
    public static Map<String, Object> tradeWapPay(AlipayTradePayReq alipayTradePayReq) {
        log.info("AlipayBiz.tradeWapPaytradeWapPay-->> req : {}",alipayTradePayReq.toString());
        String timeExpress = "5m";// 支付超时，线下扫码交易定义为5分钟

        AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();

        SortedMap<String, Object> paramMap = new TreeMap<>();
        paramMap.put("product_code", alipayTradePayReq.getProductCode());
        paramMap.put("total_amount", alipayTradePayReq.getTotalAmount().toString());
        paramMap.put("subject", alipayTradePayReq.getSubject());
        paramMap.put("body", alipayTradePayReq.getBody());
        paramMap.put("out_trade_no", alipayTradePayReq.getOutTradeNo());
        paramMap.put("timeout_express", timeExpress);


        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        request.setNotifyUrl(alipayTradePayReq.getNotifyUrl());
//        request.setTimestamp(DateUtil.now());
        log.info("bizContent :{}", JsonUtils.toJson(paramMap));
        request.setBizContent(JsonUtils.toJson(paramMap));
        try {
            long startTime = System.currentTimeMillis();
            AlipayTradeWapPayResponse response = alipayClient.sdkExecute(request);
//            AlipayTradeWapPayResponse response = new AlipayTradeWapPayResponse();

            log.info("alipay-alipayClient.sdkExecut->耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");

//            Map<String,Object> responseJSON = JsonUtils.OM().convertValue(response,Map.class);
            startTime = System.currentTimeMillis();
            Map<String,Object> responseJSON = ObjectUtilDragon.cloneHashMapStringAndObj();
            log.info("AlipayUtil-->tradeWapPay-->cloneHashMapStringAndObj 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");

            responseJSON.put("code",response.getCode());
            responseJSON.put("msg",response.getMsg());
            responseJSON.put("subCode",response.getSubCode());
            responseJSON.put("subMsg",response.getSubMsg());
            responseJSON.put("body",response.getBody());
            responseJSON.put("merchantOrderNo",response.getMerchantOrderNo());
            responseJSON.put("outTradeNo",response.getOutTradeNo());
            responseJSON.put("sellerId",response.getSellerId());
            responseJSON.put("totalAmount",response.getTotalAmount());
            responseJSON.put("tradeNo",response.getTradeNo());
            startTime = System.currentTimeMillis();
//            log.info("AlipayUtil-->tradeWapPay-->支付宝返回结果:{}", JsonUtils.toJson(response));
            log.info("AlipayUtil-->tradeWapPay-->支付宝返回结果 耗时:{}",(System.currentTimeMillis() - startTime)+"毫秒");
            return responseJSON;
        } catch (Exception e) {
            log.error("支付宝支付异常:{}", e);
            JSONObject resultJSON = ObjectUtilDragon.cloneJsonObjectObj();
            resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
            resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
            resultJSON.put("errorCode", "9999");
            return resultJSON;
        }
    }

    /**
     * 支付宝支付
     * @param alipayTradePayReq
     * @return
     */
    public static Map<String, Object> tradeAppPay(AlipayTradePayReq alipayTradePayReq) {
        log.info("AlipayUtil.tradeAppPay-->> req : {}",alipayTradePayReq.toString());
        String timeExpress = "5m";// 支付超时，线下扫码交易定义为5分钟

        AlipayClient alipayClient = PayAlipayUtils.getInstance().getHttpClient();

        SortedMap<String, Object> paramMap = new TreeMap<>();
        paramMap.put("product_code", alipayTradePayReq.getProductCode());
        paramMap.put("total_amount", alipayTradePayReq.getTotalAmount().toString());
        paramMap.put("subject", alipayTradePayReq.getSubject());
        paramMap.put("body", alipayTradePayReq.getBody());
        paramMap.put("out_trade_no", alipayTradePayReq.getOutTradeNo());
        paramMap.put("timeout_express", timeExpress);


        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        request.setNotifyUrl(alipayTradePayReq.getNotifyUrl());
//        request.setTimestamp(DateUtil.now());
        log.info("bizContent :{}",JSONObject.toJSONString(paramMap));
        request.setBizContent(JSONObject.toJSONString(paramMap));
        try {
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
//            JSONObject responseJSON = JSONObject.parseObject(JSONObject.toJSONString(response));
            Map<String,Object> responseJSON = JsonUtils.fromJson(JsonUtils.toJson(response), new TypeReference<Map<String,Object>>() {
            });
            log.info("AlipayUtil-->tradeAppPay-->支付宝返回结果:{}", responseJSON);
            return responseJSON;
        } catch (AlipayApiException e) {
            log.error("支付宝支付异常:{}", e);
            JSONObject resultJSON = new JSONObject();
            resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
            resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
            resultJSON.put("errorCode", "9999");
            return resultJSON;
        }
    }
    /**
     * 支付宝小程序支付
     * @author zjp
     * @param alipayTradePayReq 
     * @return: java.util.Map<java.lang.String,java.lang.Object>
     * @date 2024/4/26 13:35
    */
    public static Map<String, Object> tradeAppletPay(AlipayTradePayReq alipayTradePayReq) {
        log.info("AlipayUtil.tradeAppletPay-->> req : {}",alipayTradePayReq.toString());
        String timeExpress = "5m";// 支付超时，线下扫码交易定义为5分钟
        AlipayClient httpClientApplet = PayAlipayUtils.getInstance().getHttpClientApplet();
        // 构造请求参数以调用接口
        AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
        //回调函数
        request.setNotifyUrl(alipayTradePayReq.getNotifyUrl());
        AlipayTradeCreateModel model = new AlipayTradeCreateModel();
        // 设置商户订单号
        model.setOutTradeNo(alipayTradePayReq.getOutTradeNo());
        // 设置订单总金额
        model.setTotalAmount(alipayTradePayReq.getTotalAmount().toString());
        // 设置订单标题
        model.setSubject(alipayTradePayReq.getSubject());
        // 设置订单相对超时时间
        model.setTimeoutExpress(timeExpress);
        // uid参数未来计划废弃，存量商户可继续使用，新商户请使用openid。请根据应用-开发配置-openid配置选择支持的字段。
        model.setBuyerOpenId(alipayTradePayReq.getOpenId());
        // 设置产品码
        model.setProductCode(alipayTradePayReq.getProductCode());

        log.info("BizModel :{}",JSONObject.toJSONString(model));
        request.setBizModel(model);
        try {
            AlipayTradeCreateResponse response = httpClientApplet.execute(request);
            log.info("AlipayUtil-->tradeAppletPay-->支付宝返回结果:{}", response.getBody());
            if(response.isSuccess()){
                Map<String,Object> responseJSON = JsonUtils.fromJson(JsonUtils.toJson(response), new TypeReference<Map<String,Object>>() {
                });
                return responseJSON;
            }else {
                JSONObject resultJSON = new JSONObject();
                resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
                resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
                resultJSON.put("errorCode", "9999");
                return resultJSON;
            }
        } catch (AlipayApiException e) {
            log.error("支付宝小程序支付异常:{}", e);
            JSONObject resultJSON = new JSONObject();
            resultJSON.put("outTradeNo", alipayTradePayReq.getOutTradeNo());
            resultJSON.put("totalAmount", alipayTradePayReq.getTotalAmount().toString());
            resultJSON.put("errorCode", "9999");
            return resultJSON;
        }
    }

    /**
     * 订单查询
     *
     * @return
     */
    public static Map<String, Object> tradeQuery(String outTradeNo,String paymentType) {
        log.info("AlipayBiz.tradeQuery-->> 支付宝交易查询");
        AlipayClient alipayClient;
        if(StringUtil.isNotEmpty(paymentType)&&paymentType.equals(DragonConstant.PayTypeEnum.PAYMENT_TYPE_APPLET_ALIPAY.getCode())){
            //支付宝小程序
            alipayClient = PayAlipayUtils.getInstance().getHttpClientApplet();
        }else {
            alipayClient = PayAlipayUtils.getInstance().getHttpClient();
        }
        SortedMap<String, Object> bizContentMap = new TreeMap<>();
        bizContentMap.put("out_trade_no", outTradeNo);
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent(JSONObject.toJSONString(bizContentMap));
        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            JSONObject responseJSON = JSONObject.parseObject(JSONObject.toJSONString(response));
            log.info("支付宝订单查询返回结果:{}", responseJSON);
            return responseJSON;
        } catch (AlipayApiException e) {
            log.error("支付宝交易查询异常:{}", e);
            return null;
        }
    }

    private static String getSign(SortedMap<String, String> paramMap, String key) {
        StringBuilder signBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            if (!"sign".equals(entry.getKey()) && !"sign_type".equals(entry.getKey()) && !StringUtil.isEmpty(entry.getValue())) {
                signBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        return MD5.sign(signBuilder.substring(0, signBuilder.length() - 1), key, "UTF-8");
    }

    public static Map<String , String> parseNotifyMsg(Map<String, String[]> requestParams){

        Map<String,String> params = new HashMap<String,String>();

        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        return params;
    }
}
