package com.crm.pay.service.impl.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.crm.pay.dto.finance.withdraw.automatic.FinanceWithdrawFlashDto;
import com.crm.pay.entity.callback.FlashPayCallbackEntity;
import com.crm.pay.entity.property.FlashPayPropertyEntity;
import com.crm.pay.entity.property.FlashWithdrawPropertyEntity;
import com.crm.pay.service.FinanceDepositService;
import com.crm.pay.service.FinanceWithdrawService;
import com.crm.pay.service.FlashPayService;
import com.crm.pay.service.impl.base.BasePayServiceImpl;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.model.constant.PayConstants;
import com.crm.rely.backend.model.dto.finance.withdraw.FinanceWithdrawDto;
import com.crm.rely.backend.model.entity.finance.deposit.FinanceDepositAddEntity;
import com.crm.pay.entity.FinanceDepositCallbackUpdateEntity;
import com.crm.rely.backend.model.entity.finance.deposit.FinanceMerchantDepositAddEntity;
import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelEntity;
import com.crm.pay.entity.finance.withdraw.FinanceWithdrawApproveChannelSubmitEntity;
import com.crm.pay.entity.finance.withdraw.automatic.FinanceWithdrawFlashEntity;
import com.crm.pay.entity.finance.withdraw.automatic.FinanceWithdrawInfoEntity;
import com.crm.rely.backend.model.pojo.table.FinanceDepositTable;
import com.crm.rely.backend.model.pojo.table.SysRemitChannelTable;
import com.crm.rely.backend.model.pojo.table.SysRemittanceChannelTable;
import com.crm.rely.backend.core.exception.PayValidatedException;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.util.*;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FlashPayServiceImpl extends BasePayServiceImpl implements FlashPayService {

    @Autowired
    private FinanceDepositService financeDepositService;

    @Autowired
    private FinanceWithdrawService financeWithdrawService;

    public static void main(String[] args) throws Exception {
        String con = "{\n" +
                "\"privateKey\":\"123\",\n" +
                "\"publicKey\":\"456\",\n" +
                "\"baseUrl\":\"https://gateway.flashpay.tv\",\n" +
                "\"withdrawUrl\":\"/api/remitOrder/create\",\n" +
                "\"withdrawQueryUrl\":\"/api/remitOrder/query\",\n" +
                "\"notifyUrl\":\"https://ad.44a5c8109e4.com/flash/withdraw/callback\",\n" +
                "\"agentNotifyUrl\":\"https://ad.44a5c8109e4.com/flash/agent/withdraw/callback\",\n" +
                "\"merchantId\":\"10008\",\n" +
                "\"version\":\"1.0.1\",\n" +
                "\"model\":\"821\"\n" +
                "}";
        System.out.println(AESUtil.encrypt(con, "bfa5559109f94c78af615bcf00d52060"));

        /*System.out.println(AESUtil.encrypt("123123", "bfa5559109f94c78af615bcf00d52060"));
        System.out.println(AESUtil.decrypt("eWNjOnzrfFrP33giazVchQ==",
                "bfa5559109f94c78af615bcf00d52060"));*/

        //String orderNo = balanceTable.getSerial() + "_" + balanceTable.getLogin();
        String orderNo = "20250324234323424";
        Map<String, String> map = new LinkedHashMap<>();
        /*map.put("merchantId","10008");
        map.put("version","1.0.1");
        map.put("merchantOrderNo","20230630167005");
        map.put("amount", "100");
        map.put("model", "821");
        map.put("memberNo", "fa521b19e002095b");
        map.put("notifyUrl", "http://www.baidu.com");*/


        map.put("amount", "100");
        map.put("merchantId", "10008");
        map.put("merchantOrderNo", "2023062120200808");
        map.put("orderNo", "CZ2023062198923721");
        map.put("remark", "交易成功");
        map.put("status", "1");

        String signString = MapUtil.getStringSortByKey(map);
        System.out.println(signString);
        String sign = RSAUtil.signSHA1(signString,
                "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIiyenvvlFBKCgVqEt01D3A+8aEYE5tCm4O+pVP2Flci5Enp" +
                        "/rWiXpTeEf7nwKVbUDwc0DX9fnV81hWas6p4mAGvm5QUTBoZsF1wqXp" +
                        "/zc4Zd0sijCUEwJEWBJ9bToC30KBraUGBOasgfOXmEWk3BZ/jGK7q0JHhYPguZH9mZv2lAgMBAAECgYBxqm885R" +
                        "+fj6E7lVNwSzG2NTC4souDG+SyrPFOmp9C/4lyiLc6k3QwN2QhYNYI6aATDCZ57nqb" +
                        "+R0PQ99HzhUef4fLyCYLAhybmeMD7Y7EN3o+2cRNLFsKz4hw9GtqmDnT4ra8dcLk6oqjSabDPPPENw9E72cDEzqddAc" +
                        "/JQj6NQJBANeZa6Rx5LGYtVLhf7i8c7La4kbtuU3uQ" +
                        "/nbq0YaIxl421MUMGnUZU46dn9PjiDTSy7s8AKq4jZB23NlqeqjmT8CQQCiUAVAZuYOsVQZyQX6l+aA1MyK5d0Drd" +
                        "/nsfMWa2Ts0zI5akVx1p16W9AVPPpQQohKMZSMpWUiSfwXuDoccSwbAkEAya1ZVQ25SSw5Sdto921JqWA5VPIhajXc3ohPMhdXCAfW2mNDWmv1i/UCTdskb65XYQEBDu29B9YZK1xJUxVQTwJAZtuk6FIM+kSf0hNVCZ/XP88aq+7M53b5TD+1l4CJHZcc3cudpG1nsFGchMj2q4PuEG5o/9QUSe1upq1ljf6d/wJBAK2RodHBq+IrsUHDZzE1jFFn+jKWQZGz/WEKpeFnWFcaCNjtBR/SK3vZ7U1fyoUSIWK7LEdey8qVlheG78/OhtY=");
        System.out.println(sign);

        String signData = new TreeMap<>(map).entrySet().stream()
                .filter(e -> StringUtils.isNotEmpty(e.getValue()))
                .map(e -> e.getKey().concat("=").concat(e.getValue()))
                .collect(Collectors.joining("&"));

        boolean v = RSAUtil.verify(signData, sign,
                "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIsnp775RQSgoFahLdNQ9wPvGhGBObQpuDvqVT9hZXIuRJ6f61ol6U3hH" +
                        "+58ClW1A8HNA1" +
                        "/X51fNYVmrOqeJgBr5uUFEwaGbBdcKl6f83OGXdLIowlBMCRFgSfW06At9Cga2lBgTmrIHzl5hFpNwWf4xiu6tCR4WD4LmR/Zmb9pQIDAQAB");
        System.out.println(v);

         /*Connection.Response response = HttpUtil.post("https://gateway.flashpay.tv/api/payOrder/create", data);
        System.out.println("result:" + JSON.parseObject(response.body()).toJSONString());*/

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pay(FinanceDepositAddEntity balanceSaveEntity) throws Exception {
        //通道配置
        SysRemittanceChannelTable channel = getPayChannel(balanceSaveEntity.getPayType());
        //通道配置实体
        FlashPayPropertyEntity propertyEntity = getPayProperty(channel, FlashPayPropertyEntity.class);

        balanceSaveEntity.setCurrency(channel.getCurrency());
        balanceSaveEntity.setTransformCurrency(channel.getTransformCurrency());

        FinanceDepositTable balanceTable = financeDepositService.save(balanceSaveEntity, channel);

        String orderNo = balanceTable.getSerial() + "_" + balanceTable.getLogin();

        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantId", propertyEntity.getMerchantId());
        map.put("version", propertyEntity.getVersion());
        map.put("merchantOrderNo", orderNo);
        map.put("amount", String.format("%.2f", balanceTable.getTransformAmount().doubleValue()));
        map.put("model", propertyEntity.getModel());
        map.put("memberNo", balanceTable.getName());
        map.put("notifyUrl", propertyEntity.getNotifyUrl());
        String url = getUrl(propertyEntity, map, balanceSaveEntity);
        balanceTable.setFormUrl(url);
        
        return url;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String pay(FinanceMerchantDepositAddEntity balanceSaveEntity) throws Exception {
        //通道配置
        SysRemittanceChannelTable channel = getPayChannel(balanceSaveEntity.getPayType());
        //通道配置实体
        FlashPayPropertyEntity propertyEntity = getPayProperty(channel, FlashPayPropertyEntity.class);

        balanceSaveEntity.setCurrency(channel.getCurrency());
        balanceSaveEntity.setTransformCurrency(channel.getTransformCurrency());

        FinanceDepositTable balanceTable = financeDepositService.save(balanceSaveEntity, channel);


        String orderNo = balanceTable.getSerial() + "_" + balanceTable.getLogin();

        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantId", propertyEntity.getMerchantId());
        map.put("version", propertyEntity.getVersion());
        map.put("merchantOrderNo", orderNo);
        map.put("amount", String.format("%.2f", balanceTable.getTransformAmount().doubleValue()));
        map.put("model", propertyEntity.getModel());
        map.put("memberNo", balanceSaveEntity.getName());
        map.put("notifyUrl", propertyEntity.getNotifyUrl());
        String url = getUrl(propertyEntity, map, balanceSaveEntity);
        balanceTable.setFormUrl(url);
        
        return url;
    }

    /**
     * 回调处理数据
     *
     * @param callbackEntity
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String callback(FlashPayCallbackEntity callbackEntity, String payType) throws Exception {
        log.info(String.format("callback data:%s", JSON.toJSONString(callbackEntity)));

        if (Strings.isNullOrEmpty(callbackEntity.getSign())) {
            return Constants.FAIL;
        }
        //获取配置
        FlashPayPropertyEntity payProperty = getPayProperty(payType, FlashPayPropertyEntity.class);

        boolean validate = validate(callbackEntity, payProperty);
        if (!validate) {
            return Constants.FAIL;
        }

        //验证传输数据
        int status = PayConstants.CALLBACE_PROCESSING_STATUS;
        if ("1".equals(callbackEntity.getStatus())) {
            status = PayConstants.CALLBACE_SUCCESS_STATUS;
        } else if ("2".equals(callbackEntity.getStatus())) {
            status = PayConstants.CALLBACE_FAIL_STATUS;
        }

        FinanceDepositTable table =
                financeDepositService.getBySerial(callbackEntity.getMerchantOrderNo().split("_")[0]);
        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantId", payProperty.getMerchantId());
        map.put("version", payProperty.getVersion());
        map.put("merchantOrderNo", callbackEntity.getMerchantOrderNo());
        map.put("submitTime", DateUtil.format("yyyyMMddHHmmss", table.getAddTime()));

        String signString = MapUtil.getStringSortByKey(map);
        String sign = RSAUtil.signSHA1(signString, payProperty.getPrivateKey());
        map.put("sign", sign);

        Map<String, String> heardMap = new LinkedHashMap<>();
        heardMap.put("Content-type", "application/json");

        Connection.Response response = HttpUtil.post(payProperty.getBaseUrl() + payProperty.getDeposiQueryUrl(),
                heardMap, map);
        log.info(String.format("url:%s,request:%s,body:%s", payProperty.getDeposiQueryUrl(), JSON.toJSONString(map),
                response.body()));

        JSONObject requestEntity = JSON.parseObject(response.body());
        if (requestEntity == null || Strings.isNullOrEmpty(requestEntity.getString("code")) || !requestEntity.getString("code").equals("0")) {
            log.error("Payment platform is abnormal, please try again later or contact customer service.");
            return Constants.FAIL;
        }
        if (!callbackEntity.getMerchantOrderNo().equals(requestEntity.getString("merchantOrderNo")) || !callbackEntity.getStatus().equals(requestEntity.getString("status"))
                || !callbackEntity.getOrderNo().equals(requestEntity.getString("orderNo")) || new BigDecimal(callbackEntity.getPayAmount()).compareTo(new BigDecimal(requestEntity.getString("payAmount"))) != 0) {
            return Constants.FAIL;
        }

        FinanceDepositCallbackUpdateEntity balanceCallbackUpdateEntity =
                getFinanceDepositCallbackUpdateEntity(callbackEntity.getMerchantOrderNo(), callbackEntity.getOrderNo(),
                        status, callbackEntity);
        balanceCallbackUpdateEntity.setTransformAmount(new BigDecimal(callbackEntity.getPayAmount()));

        /**
         * 更新数据
         */
        financeDepositService.updateCallback(balanceCallbackUpdateEntity);
        return Constants.SUCCESS;
    }

    /**
     * 获取支付url
     *
     * @param map
     * @return
     * @throws ServiceException
     */
    private String getUrl(FlashPayPropertyEntity propertyEntity, Map<String, String> map,
                          FinanceDepositAddEntity balanceSaveEntity) throws Exception {


        String signString = MapUtil.getStringSortByKey(map);
        String sign = RSAUtil.signSHA1(signString, propertyEntity.getPrivateKey());
        map.put("sign", sign);

        Map<String, String> heardMap = new LinkedHashMap<>();
        heardMap.put("Content-type", "application/json");

        Connection.Response response = HttpUtil.post(propertyEntity.getBaseUrl() + propertyEntity.getDepositUrl(),
                heardMap, JSON.toJSONString(map));
        log.info(String.format("url:%s,json:%s,body:%s", propertyEntity.getBaseUrl() + propertyEntity.getDepositUrl()
                , JSON.toJSONString(map), response.body()));

        JSONObject requestEntity = JSON.parseObject(response.body());
        if (requestEntity == null || Strings.isNullOrEmpty(requestEntity.getString("code")) || !requestEntity.getString("code").equals("0")) {
            throw new PayValidatedException("Payment platform is abnormal, please try again later or contact customer" +
                    " service.");
        }

        String url = requestEntity.getString("url");
        log.info(String.format("支付请求,请求orderNo:%s,请求url:%s", map.get("merchantOrderNo"), url));

        return url;
    }

    @Override
    public FinanceWithdrawFlashDto withdrawInfo(FinanceWithdrawInfoEntity entity) throws Exception {
        FinanceWithdrawDto withdrawDto = null;
        if (entity.getWithdrawInfoType() == null || entity.getWithdrawInfoType().equals(1)) {
            withdrawDto = financeWithdrawService.searchSingle(entity.getId());

        } else {
            //withdrawDto = financeAgentWithdrawService.searchSingle(entity.getId());
        }
        entity.setPayType(PayConstants.FLASH_PAY_TYPE_REMIT);

        SysRemitChannelTable withdrawChannel = getWithdrawChannel(entity.getPayType());

        FinanceWithdrawFlashDto dto = new FinanceWithdrawFlashDto();
        dto.setAmount(withdrawDto.getTransformAmount() == null ? null :
                withdrawDto.getTransformAmount().setScale(2, BigDecimal.ROUND_DOWN));
        dto.setBankcardAccountName(withdrawDto.getBankUname());
        dto.setBankcardAccountNo(withdrawDto.getBankName());
        dto.setBankCode(withdrawDto.getCustomBankCode());

        dto.setId(withdrawDto.getId());
        dto.setWithdrawUrl(withdrawChannel.getWithdrawUrl());
        dto.setSerial(withdrawDto.getSerial());
        dto.setPayType(entity.getPayType());
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String withdraw(FinanceWithdrawFlashEntity entity) throws Exception {
        FinanceWithdrawDto withdrawDto = null;
        if (entity.getWithdrawInfoType() == null || entity.getWithdrawInfoType().equals(1)) {
            withdrawDto = financeWithdrawService.searchSingle(entity.getId());
        } else {
            //withdrawDto = financeAgentWithdrawService.searchSingle(entity.getId());
        }
        entity.setCId(withdrawDto.getCId());
        entity.setSerial(withdrawDto.getSerial());
        entity.setLogin(withdrawDto.getLogin());

        FlashWithdrawPropertyEntity proxpayWithdrawProperty = getWithdrawProperty(PayConstants.FLASH_PAY_TYPE_REMIT,
                FlashWithdrawPropertyEntity.class);

        payout(entity, proxpayWithdrawProperty);

        FinanceWithdrawApproveChannelSubmitEntity financeWithdrawApproveChannelSubmitEntity =
                new FinanceWithdrawApproveChannelSubmitEntity();
        financeWithdrawApproveChannelSubmitEntity.setSubmitStatus(PayConstants.PASSED_STATUS);
        financeWithdrawApproveChannelSubmitEntity.setId(entity.getId());
        financeWithdrawApproveChannelSubmitEntity.setActualPayType(entity.getPayType());
        if (entity.getWithdrawInfoType() == null || entity.getWithdrawInfoType().equals(1)) {
            financeWithdrawService.approve(financeWithdrawApproveChannelSubmitEntity);

        } else {
            //financeAgentWithdrawService.approve(financeWithdrawApproveChannelSubmitEntity);
        }

        return null;
    }

    private void payout(FinanceWithdrawFlashEntity entity, FlashWithdrawPropertyEntity propertyEntity) throws Exception {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantId", propertyEntity.getMerchantId());
        map.put("version", propertyEntity.getVersion());
        map.put("merchantOrderNo", entity.getSerial());
        map.put("amount", String.format("%.2f", entity.getAmount().doubleValue()));
        map.put("bankCode", entity.getBankCode());
        map.put("bankcardAccountNo", entity.getBankcardAccountNo());
        map.put("bankcardAccountName", entity.getBankcardAccountName());
        //map.put("model", propertyEntity.getModel());
        if (entity.getWithdrawInfoType() == null || entity.getWithdrawInfoType().equals(1)) {
            map.put("notifyUrl", propertyEntity.getNotifyUrl());
        } else {
            map.put("notifyUrl", propertyEntity.getAgentNotifyUrl());
        }

        String signString = MapUtil.getStringSortByKey(map);
        String sign = RSAUtil.signSHA1(signString, propertyEntity.getPrivateKey());
        map.put("sign", sign);

        Map<String, String> heardMap = new LinkedHashMap<>();
        heardMap.put("Content-type", "application/json");

        Connection.Response response = HttpUtil.post(propertyEntity.getBaseUrl() + propertyEntity.getWithdrawUrl(),
                heardMap, map);
        log.info(String.format("url:%s,json:%s,body:%s",
                propertyEntity.getBaseUrl() + propertyEntity.getWithdrawUrl(), JSON.toJSONString(map),
                response.body()));

        JSONObject requestEntity = JSON.parseObject(response.body());
        if (requestEntity == null || Strings.isNullOrEmpty(requestEntity.getString("code")) || !requestEntity.getString("code").equals("0")) {
            throw new PayValidatedException("Payment platform is abnormal, please try again later or contact customer" +
                    " service.");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String withdrawCallback(Integer withdrawType, FlashPayCallbackEntity callbackEntity) throws Exception {
        log.info(String.format("callback data:%s", JSON.toJSONString(callbackEntity)));
        if (Strings.isNullOrEmpty(callbackEntity.getSign())) {
            return Constants.FAIL;
        }
        //获取配置
        FlashWithdrawPropertyEntity payProperty = getWithdrawProperty(PayConstants.FLASH_PAY_TYPE_REMIT,
                FlashWithdrawPropertyEntity.class);

        boolean validateWith = validateWith(callbackEntity, payProperty);
        if (!validateWith) {
            return Constants.FAIL;
        }

        FinanceDepositTable table =
                financeDepositService.getBySerial(callbackEntity.getMerchantOrderNo().split("_")[0]);
        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantId", payProperty.getMerchantId());
        map.put("version", payProperty.getVersion());
        map.put("merchantOrderNo", callbackEntity.getMerchantOrderNo());
        map.put("submitTime", DateUtil.format("yyyyMMddHHmmss", table.getModifyTime()));

        String signString = MapUtil.getStringSortByKey(map);
        String sign = RSAUtil.signSHA1(signString, payProperty.getPrivateKey());
        map.put("sign", sign);

        Map<String, String> heardMap = new LinkedHashMap<>();
        heardMap.put("Content-type", "application/json");

        Connection.Response response = HttpUtil.post(payProperty.getBaseUrl() + payProperty.getWithdrawQueryUrl(),
                heardMap, map);
        log.info(String.format("url:%s,request:%s,body:%s", payProperty.getWithdrawQueryUrl(), JSON.toJSONString(map)
                , response.body()));

        JSONObject requestEntity = JSON.parseObject(response.body());
        if (requestEntity == null || Strings.isNullOrEmpty(requestEntity.getString("code")) || !requestEntity.getString("code").equals("0")) {
            log.error("Payment platform is abnormal, please try again later or contact customer service.");
            return Constants.FAIL;
        }
        if (!callbackEntity.getMerchantOrderNo().equals(requestEntity.getString("merchantOrderNo")) || !callbackEntity.getStatus().equals(requestEntity.getString("status"))
                || !callbackEntity.getOrderNo().equals(requestEntity.getString("orderNo")) || new BigDecimal(callbackEntity.getAmount()).compareTo(new BigDecimal(requestEntity.getString("amount"))) != 0) {
            return Constants.FAIL;
        }

        FinanceWithdrawApproveChannelEntity financeWithdrawApproveChannelEntity =
                new FinanceWithdrawApproveChannelEntity();
        financeWithdrawApproveChannelEntity.setChannelSerial(callbackEntity.getOrderNo());

        if ("1".equals(callbackEntity.getStatus())) {
            financeWithdrawApproveChannelEntity.setCallbackStatus(PayConstants.CALLBACE_SUCCESS_STATUS);
        } else if ("2".equals(callbackEntity.getStatus())) {
            financeWithdrawApproveChannelEntity.setCallbackStatus(PayConstants.CALLBACE_FAIL_STATUS);
        }
        financeWithdrawApproveChannelEntity.setSerial(callbackEntity.getMerchantOrderNo());

        /**
         * 更新数据
         */

        if (withdrawType == null || withdrawType.equals(1)) {
            financeWithdrawService.approve(financeWithdrawApproveChannelEntity);

        } else {
            //financeAgentWithdrawService.channel(financeWithdrawApproveChannelEntity);
        }

        return Constants.SUCCESS;
    }

    /**
     * 验证回调参数是否被篡改
     *
     * @param callbackEntity
     * @return
     * @throws ServiceException
     */
    private boolean validate(FlashPayCallbackEntity callbackEntity, FlashPayPropertyEntity payProperty) throws Exception {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantOrderNo", callbackEntity.getMerchantOrderNo());
        map.put("merchantId", payProperty.getMerchantId());
        map.put("amount", callbackEntity.getAmount());
        map.put("status", callbackEntity.getStatus());
        map.put("orderNo", callbackEntity.getOrderNo());
        map.put("payAmount", callbackEntity.getPayAmount());

        String data = new TreeMap<>(map).entrySet().stream()
                .filter(e -> StringUtils.isNotEmpty(e.getValue()))
                .map(e -> e.getKey().concat("=").concat(e.getValue()))
                .collect(Collectors.joining("&"));

        Boolean validate = RSAUtil.verify(data, callbackEntity.getSign(), payProperty.getPublicKey());
        log.info(String.format("order no:%scallback result sign compare--callback sign:%s, encryption data:%s , " +
                        "result:%s"
                , callbackEntity.getMerchantOrderNo(), callbackEntity.getSign(), JSON.toJSONString(map), validate));

        return validate;
    }

    private boolean validateWith(FlashPayCallbackEntity callbackEntity, FlashWithdrawPropertyEntity payProperty) throws Exception {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("merchantOrderNo", callbackEntity.getMerchantOrderNo());
        map.put("merchantId", payProperty.getMerchantId());
        map.put("amount", callbackEntity.getAmount());
        map.put("status", callbackEntity.getStatus());
        map.put("orderNo", callbackEntity.getOrderNo());
        map.put("remark", callbackEntity.getRemark());

        String data = new TreeMap<>(map).entrySet().stream()
                .filter(e -> StringUtils.isNotEmpty(e.getValue()))
                .map(e -> e.getKey().concat("=").concat(e.getValue()))
                .collect(Collectors.joining("&"));

        Boolean validate = RSAUtil.verify(data, callbackEntity.getSign(), payProperty.getPublicKey());
        log.info(String.format("order no:%s withdraw callback result sign compare--callback sign:%s, encryption " +
                        "data:%s , result:%s"
                , callbackEntity.getMerchantOrderNo(), callbackEntity.getSign(), JSON.toJSONString(map), validate));

        return validate;
    }

}



