package com.crm.ucard.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.crm.rely.backend.configuration.LocaleMessage;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.wasabi.*;
import com.crm.rely.backend.core.entity.wasabi.*;
import com.crm.rely.backend.core.pojo.table.ucard.SysUcardConfigTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.util.FileProcessUtil;
import com.crm.ucard.config.WasabiConfig;
import com.crm.ucard.model.ResultData;
import com.crm.ucard.model.TwoTuple;
import com.crm.ucard.service.SysUcardConfigService;
import com.crm.ucard.service.WasabiDocumentApiService;
import com.crm.ucard.util.ObjectIdUtil;
import com.crm.ucard.util.RsaUtils;
import com.crm.ucard.util.WasabiCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class WasabiDocumentApiServiceImpl implements WasabiDocumentApiService {

    public static final String MERCHANT_API_KEY = "f9ddaac1-bec6-42d8-8cc9-876d41b4ca1f-089a2225-d5e2-4733-af8c" +
            "-d8f45536a26f";
    public static final String MERCHANT_PRIVATE_KEY =
            "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=";
    public static final String MERCHANT_PUBLIC_KEY =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIsnp775RQSgoFahLdNQ9wPvGhGBObQpuDvqVT9hZXIuRJ6f61ol6U3hH" +
                    "+58ClW1A8HNA1" +
                    "/X51fNYVmrOqeJgBr5uUFEwaGbBdcKl6f83OGXdLIowlBMCRFgSfW06At9Cga2lBgTmrIHzl5hFpNwWf4xiu6tCR4WD4LmR" +
                    "/Zmb9pQIDAQAB";
    public static final String WSB_PUBLIC_KEY =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyyPUFA1Zu2GFS2DdPL6xP5bGmPG9dFMSXpDy3GykW" +
                    "/lL4VR24UsjKs5h6g8OfSOuOze3yC4jWE/IBW5/L9xM9kGvFQK/S1zr44hMnDn+7S5MSi" +
                    "+jnZDRIrCRQJTqkwfpy39h2cQ4xlHKfbEjkkeo5ZQ0VFgRHYPr7b10l+3j8gwIDAQAB";
    public static String ENDPOINT = "https://sandbox-api-merchant.wasabicard.com";
    /**
     * 商户的标识，可自定义
     */
    public static String MERCHANT_TAG = "CWG";
    @Autowired
    private SysUcardConfigService sysUcardConfigService;
    @Autowired
    private LocaleMessage localeMessage;

    @Value("${web.upload-path:./upload}")
    private String UPLOAD;


    public static void main(String[] args) {
    }

    public static WasabiConfig getConfig() throws ServiceException {
        WasabiConfig config = new WasabiConfig();
        config.setApiUrl(ENDPOINT);
        config.setApiKey(MERCHANT_API_KEY);
        config.setPrivateKey(MERCHANT_PRIVATE_KEY);
        config.setPublicKey(MERCHANT_PUBLIC_KEY);
        config.setWsbPublicKey(WSB_PUBLIC_KEY);
        config.setMerchantTag(MERCHANT_TAG);
        config.setRegionUrl("/merchant/core/mcb/common/region");
        config.setCityUrl("/merchant/core/mcb/common/city");
        config.setCityV2Url("/merchant/core/mcb/common/v2/city");
        config.setMobileAreaUrl("/merchant/core/mcb/common/mobileAreaCode");
        config.setFileUploadUrl("/merchant/core/mcb/common/file/upload");
        config.setWorkSubmitUrl("/merchant/core/mcb/work/submit");
        config.setWorkListUrl("/merchant/core/mcb/work/list");
        config.setAccountInfoUrl("/merchant/core/mcb/account/info");
        config.setWalletDepositUrl("/merchant/core/mcb/account/walletDeposit");
        config.setWalletDepositTransactionUrl("/merchant/core/mcb/account/walletDepositTransaction");
        config.setCardTypesUrl("/merchant/core/mcb/card/v2/cardTypes");
        config.setOpenCardUrl("/merchant/core/mcb/card/openCard");
        config.setActiveCardUrl("/merchant/core/mcb/card/physicalCard/activeCard");
        config.setCardInfoUrl("/merchant/core/mcb/card/info");
        config.setCardBalanceInfoUrl("/merchant/core/mcb/card/balanceInfo");
        config.setCardFreezeV2Url("/merchant/core/mcb/card/v2/freeze");
        config.setCardUnfreezeV2Url("/merchant/core/mcb/card/v2/unfreeze");
        config.setCardDepositUrl("/merchant/core/mcb/card/deposit");
        config.setUpdatePinUrl("/merchant/core/mcb/card/physicalCard/updatePin");
        config.setCardTransactionUrl("/merchant/core/mcb/card/transaction");
        config.setCardAuthTransactionUrl("/merchant/core/mcb/card/authTransaction");
        config.setThird3dsTransactionUrl("/merchant/core/mcb/card/third3dsTransaction");
        config.setHolderOccupationsUrl("/merchant/core/mcb/card/holder/occupations");
        config.setHolderCreateV2Url("/merchant/core/mcb/card/holder/v2/create");
        config.setHolderUpdateV2Url("/merchant/core/mcb/card/holder/v2/update");
        config.setHolderQueryUrl("/merchant/core/mcb/card/holder/query");
        config.setCardSensitiveUrl("/merchant/core/mcb/card/sensitive");
        config.setCardWithdrawUrl("/merchant/core/mcb/card/withdraw");
        config.setCardCancelUrl("/merchant/core/mcb/card/cancel");
        config.setAvailableCurrenciesUrl("/merchant/core/mcb/gt/template/availableCurrencies");
        config.setAvailableFieldParamsUrl("/merchant/core/mcb/gt/template/availableFieldParams");
        config.setStatesUrl("/merchant/core/mcb/gt/template/states");
        config.setAvailableBankCitiesUrl("/merchant/core/mcb/gt/template/availableBankCities");
        config.setExchangeRateUrl("/merchant/core/mcb/gt/transaction/exchangeRate");
        config.setTransactionTransferUrl("/merchant/core/mcb/gt/transaction/transfer");
        config.setTransactionListUrl("/merchant/core/mcb/gt/transaction/list");
        config.setTransactionDetailUrl("/merchant/core/mcb/gt/transaction/detail");
        config.setSubmitRfiUrl("/merchant/core/mcb/gt/transaction/submitRfi");
        return config;
    }

    @Override
    public void verifySignature(TwoTuple<String, String> result, String publicKey) throws Exception {
        ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);
        if (resultData.isSuccess()) {
            boolean verify = RsaUtils.verify(result.getSecond(), publicKey, result.getFirst());
            log.info("验证签名:{}", verify);
        }
    }

    @Override
    public WasabiConfig getWasabiConfig() throws Exception {
        SysUcardConfigTable sysUcardConfigTable = sysUcardConfigService.getByCode(Constants.WASABI_CARD);
        if (sysUcardConfigTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        WasabiConfig wasabiConfig = JSON.parseObject(sysUcardConfigTable.getValue(), WasabiConfig.class);
        return wasabiConfig;
    }

    /**
     * 获取国家/地区列表
     */
    @Override
    public BaseResultDto<List<WasabiRegionDto>> getRegionList() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getRegionUrl(), config);
            log.info("result:{}", result);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiRegionDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiRegionDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            List<WasabiRegionDto> list = resultData.getData();
            return BaseResultDto.success(list);
        } catch (Exception e) {
            log.error("获取国家/地区列表失败", e);
            throw new ServiceException("获取国家/地区列表失败");
        }
    }

    /**
     * 获取城市列表
     */
    @Override
    public BaseResultDto<List<WasabiCityDto>> getCityList(WasabiCityEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCityUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiCityDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiCityDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            List<WasabiCityDto> list = resultData.getData();
            return BaseResultDto.success(list);
        } catch (Exception e) {
            log.error("获取城市列表失败", e);
            throw new ServiceException("获取城市列表失败");
        }
    }

    /**
     * 获取城市列表v2
     */
    @Override
    public BaseResultDto<List<WasabiCityV2Dto>> getCityV2List(WasabiCityEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCityV2Url(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiCityV2Dto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiCityV2Dto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            List<WasabiCityV2Dto> list = resultData.getData();
            return BaseResultDto.success(list);
        } catch (Exception e) {
            log.error("获取城市列表v2失败", e);
            throw new ServiceException("获取城市列表v2失败");
        }
    }

    /**
     * 获取手机区号列表
     */
    @Override
    public BaseResultDto<List<WasabiMobileAreaCodeDto>> getMobileAreaCode() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getMobileAreaUrl(),
                    config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiMobileAreaCodeDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiMobileAreaCodeDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            List<WasabiMobileAreaCodeDto> list = resultData.getData();
            return BaseResultDto.success(list);
        } catch (Exception e) {
            log.error("获取手机区号列表失败", e);
            throw new ServiceException("获取手机区号列表失败");
        }
    }

    /**
     * 文件上传
     */
    @Override
    public String uploadFile(String path, String category) throws Exception {
        WasabiConfig config = getWasabiConfig();
        File file = FileProcessUtil.getFile(UPLOAD + path);
        Map<String, String> paramMap = new HashMap<>();
        //使用默认值：card
        paramMap.put("category", category);

        TwoTuple<String, String> result = WasabiCommonUtil.postFile(config.getApiUrl() + config.getFileUploadUrl(),
                file, paramMap, config);
        verifySignature(result, config.getWsbPublicKey());
        ResultData<WasabiFileUploadDto> resultData = JSON.parseObject(result.getSecond(),
                new TypeReference<ResultData<WasabiFileUploadDto>>() {
                }
        );
        if (!resultData.isSuccess()) {
            throw new ServiceException(resultData.getMsg());
        }

        WasabiFileUploadDto dto = resultData.getData();
        return dto.getFileId();
    }

    /**
     * 文件校验
     */
    @Override
    public void validatedFile(MultipartFile file) throws ServiceException {
        int size = 20;
        String regex = "jpg|png|pdf";
        //验证文件大小
        if (file.getSize() > size * 1000 * 1024) {
            throw new ServiceException(localeMessage.getMessage(Constants.UPLOAD_FILE_SIZE_MAX) + size + "MB");
        }
        //文件格式
        String fileName = file.getOriginalFilename().toLowerCase();
        if (!fileName
                .substring(fileName.lastIndexOf(".") + 1)
                .matches(regex)) {
            throw ServiceException.exception(localeMessage.getMessage(Constants.UPLOAD_FILE_REGEX,
                    Constants.UPLOAD_FILE_REGEX) + " " + regex);

        }
    }

    /**
     * 提交工单
     */
    @Override
    public BaseResultDto<WasabiWorkSubmitAndListDto> workSubmit(WasabiWorkSubmitEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getWorkSubmitUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiWorkSubmitAndListDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiWorkSubmitAndListDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            WasabiWorkSubmitAndListDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("提交工单失败", e);
            throw new ServiceException("提交工单失败");
        }
    }

    /**
     * 获取工单列表
     */
    @Override
    public BaseResultDto<List<WasabiWorkSubmitAndListDto>> workList(WasabiWorkListEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getWorkListUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);
            JSONObject data = JSON.parseObject(resultData.getData().toString());
            JSONArray records = data.getJSONArray("records");
            List<WasabiWorkSubmitAndListDto> dtos = records.toJavaList(WasabiWorkSubmitAndListDto.class);
            return BaseResultDto.success(dtos);
        } catch (Exception e) {
            log.error("获取工单列表失败", e);
            throw new ServiceException("获取工单列表失败");
        }
    }

    /**
     * 获取账户资产信息列表
     */
    @Override
    public BaseResultDto<List<WasabiAccountInfoDto>> queryMerchantAccount() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getAccountInfoUrl(),
                    config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiAccountInfoDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiAccountInfoDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            List<WasabiAccountInfoDto> list = resultData.getData();
            return BaseResultDto.success(list);
        } catch (Exception e) {
            log.error("获取账户资产信息列表失败", e);
            throw new ServiceException("获取账户资产信息列表失败");
        }
    }

    /**
     * 钱包充值
     */
    @Override
    public BaseResultDto<WasabiWalletDepositDto> walletDeposit(WasabiWalletDepositEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getWalletDepositUrl()
                    , JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiWalletDepositDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiWalletDepositDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            WasabiWalletDepositDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("钱包充值失败", e);
            throw new ServiceException("钱包充值失败");
        }
    }

    /**
     * 获取钱包充值记录列表
     */
    @Override
    public ResultWithPagerDto<WasabiWalletDepositTransactionDto> getWalletDepositTransactionList(WasabiWalletDepositTransactionEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();

        try {
            entity.setPageNum((long) entity.getPage().getCurrent());
            entity.setPageSize((long) entity.getPage().getRow());
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getWalletDepositTransactionUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);

            JSONObject data = JSON.parseObject(resultData.getData().toString());
            Integer total = data.getInteger("total");
            PageDto pageDto = PageDto.format(entity, total);
            if (total == null || total <= 0) {
                return ResultWithPagerDto.success(pageDto);
            }
            JSONArray records = data.getJSONArray("records");
            List<WasabiWalletDepositTransactionDto> dtos = records.toJavaList(WasabiWalletDepositTransactionDto.class);
            return ResultWithPagerDto.success(pageDto, dtos);
        } catch (Exception e) {
            log.error("获取钱包充值记录列表失败", e);
            throw new ServiceException("获取钱包充值记录列表失败");
        }
    }

    /**
     * 获取支持的卡BIN列表
     */
    @Override
    public List<WasabiCardTypesDto> getCardTypeList() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardTypesUrl(),
                    config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiCardTypesDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiCardTypesDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());
            }
            return resultData.getData();
        } catch (Exception e) {
            log.error("获取支持的卡BIN列表失败", e);
            throw new ServiceException("获取支持的卡BIN列表失败");
        }
    }

    /**
     * 开卡
     */
    @Override
    public ResultData<List<WasabiOpenCardDto>> openCard(WasabiOpenCardEntity entity, WasabiConfig config) throws ServiceException {
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getOpenCardUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiOpenCardDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiOpenCardDto>>>() {
                    }
            );
            return resultData;
        } catch (Exception e) {
            log.error("开卡失败", e);
            throw new ServiceException("开卡失败");
        }
    }

    /**
     * 获取持卡人信息
     */
    @Override
    public List<WasabiHolderQueryDto> getHolderInfo(WasabiHolderQueryEntity entity, WasabiConfig config) throws ServiceException {
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getHolderQueryUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);
            JSONObject data = JSON.parseObject(resultData.getData().toString());
            JSONArray records = data.getJSONArray("records");
            List<WasabiHolderQueryDto> dtos = records.toJavaList(WasabiHolderQueryDto.class);
            return dtos;
        } catch (Exception e) {
            log.error("获取持卡人列表失败", e);
            throw new ServiceException("获取持卡人列表失败");
        }
    }

    /**
     * 激活卡
     */
    @Override
    public WasabiActiveCardDto activeCard(WasabiActiveCardEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        entity.setMerchantOrderNo(ObjectIdUtil.genSnowFlakeIdStr(config.getMerchantTag()));
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getActiveCardUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiActiveCardDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiActiveCardDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());

            }
            return resultData.getData();
        } catch (Exception e) {
            log.error("激活卡失败", e);
            throw new ServiceException("激活卡失败");
        }
    }

    /**
     * 获取卡信息
     */
    @Override
    public WasabiCardInfoDto getCardInfo(WasabiCardInfoEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardInfoUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiCardInfoDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiCardInfoDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                log.error("获取卡信息失败,cardNo{},message{}", entity.getCardNo(), resultData.getMsg());
                return null;
            }
            WasabiCardInfoDto dto = resultData.getData();
            return dto;
        } catch (Exception e) {
            log.error("获取卡信息失败", e);
            throw new ServiceException("获取卡信息失败");
        }
    }

    /**
     * 查询卡敏感信息
     */
    @Override
    public WasabiCardSensitiveDto getCardSensitive(WasabiBalanceInfoEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardSensitiveUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiCardSensitiveDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiCardSensitiveDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                log.error("获取卡敏感信息失败,cardNo{},message{}", entity.getCardNo(), resultData.getMsg());
                return null;
            }
            WasabiCardSensitiveDto dto = resultData.getData();
            // 解密字段
            dto.setCvv(RsaUtils.decryptPrivateKey(dto.getCvv(), config.getPrivateKey()));
            dto.setExpireDate(RsaUtils.decryptPrivateKey(dto.getExpireDate(), config.getPrivateKey()));
            dto.setCardNumber(RsaUtils.decryptPrivateKey(dto.getCardNumber(), config.getPrivateKey()));
            dto.setActivateUrl(RsaUtils.decryptPrivateKey(dto.getActivateUrl(), config.getPrivateKey()));
            return dto;
        } catch (Exception e) {
            log.error("获取卡敏感信息失败", e);
            throw new ServiceException("获取卡敏感信息失败");
        }
    }

    /**
     * 获取卡余额
     */
    @Override
    public BaseResultDto<WasabiBalanceInfoDto> getBalanceInfo(WasabiBalanceInfoEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getCardBalanceInfoUrl(),
                            JSON.toJSONString(entity),
                            config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiBalanceInfoDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiBalanceInfoDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }

            WasabiBalanceInfoDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("获取卡余额失败", e);
            throw new ServiceException("获取卡余额失败");
        }
    }

    /**
     * 冻结卡-v2
     */
    @Override
    public WasabiFreezeAndUnfreezeV2Dto freezeV2(WasabiFreezeAndUnfreezeEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();

        TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardFreezeV2Url(),
                JSON.toJSONString(entity), config);
        verifySignature(result, config.getWsbPublicKey());
        ResultData<WasabiFreezeAndUnfreezeV2Dto> resultData = JSON.parseObject(result.getSecond(),
                new TypeReference<ResultData<WasabiFreezeAndUnfreezeV2Dto>>() {
                }
        );
        if (!resultData.isSuccess()) {
            throw new ServiceException(resultData.getMsg());
        }

        WasabiFreezeAndUnfreezeV2Dto dto = resultData.getData();
        return dto;

    }

    /**
     * 解冻卡-v2
     */
    @Override
    public WasabiFreezeAndUnfreezeV2Dto unfreezeV2(WasabiFreezeAndUnfreezeEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardUnfreezeV2Url(),
                JSON.toJSONString(entity), config);
        verifySignature(result, config.getWsbPublicKey());
        ResultData<WasabiFreezeAndUnfreezeV2Dto> resultData = JSON.parseObject(result.getSecond(),
                new TypeReference<ResultData<WasabiFreezeAndUnfreezeV2Dto>>() {
                }
        );
        if (!resultData.isSuccess()) {
            throw new ServiceException(resultData.getMsg());
        }

        WasabiFreezeAndUnfreezeV2Dto dto = resultData.getData();
        return dto;
    }

    /**
     * 充值
     */
    @Override
    public ResultData<WasabiDepositDto> cardDeposit(WasabiBalanceEntity entity, WasabiConfig config) throws ServiceException {
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getCardDepositUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiDepositDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiDepositDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());
            }
            return resultData;
        } catch (Exception e) {
            log.error("充值失败", e);
            throw new ServiceException("充值失败");
        }

    }


    /**
     * 销卡
     */
    @Override
    public WasabiDepositDto cardCancel(WasabiCancelEntity entity) throws Exception {
        try {
            WasabiConfig config = getWasabiConfig();
            entity.setMerchantOrderNo(ObjectIdUtil.genSnowFlakeIdStr(config.getMerchantTag()));
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getCardCancelUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiDepositDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiDepositDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());
            }
            WasabiDepositDto dto = resultData.getData();
            return dto;
        } catch (Exception e) {
            log.error("销卡失败", e);
            throw new ServiceException("销卡失败");
        }
    }

    /**
     * 扣款
     */
    @Override
    public ResultData<WasabiDepositDto> withdraw(WasabiBalanceEntity entity, WasabiConfig config) throws Exception {
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getCardWithdrawUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiDepositDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiDepositDto>>() {
                    }
            );
            return resultData;
        } catch (Exception e) {
            log.error("卡扣款失败", e);
            throw new ServiceException("卡扣款失败");
        }
    }


    /**
     * 更新实体卡PIN
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public WasabiUpdatePinDto updatePin(WasabiUpdatePinEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        entity.setMerchantOrderNo(ObjectIdUtil.genSnowFlakeIdStr(config.getMerchantTag()));
        try {
            TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getUpdatePinUrl(),
                    JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiUpdatePinDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiUpdatePinDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());
            }

            WasabiUpdatePinDto dto = resultData.getData();
            return dto;
        } catch (Exception e) {
            log.error("更新实体卡PIN失败", e);
            throw new ServiceException("更新实体卡PIN失败");
        }
    }

    /**
     * 获取卡交易记录
     */
    @Override
    public List<WasabiTransactionDto> getCardTransactionList(WasabiTransactionEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        entity.setPageNum(1L);
        entity.setPageSize(10L);
        TwoTuple<String, String> result = WasabiCommonUtil.post(config.getApiUrl() + config.getCardTransactionUrl(),
                JSON.toJSONString(entity), config);
        verifySignature(result, config.getWsbPublicKey());

        ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);
        if (!resultData.isSuccess()) {
            throw new ServiceException(resultData.getMsg());
        }
        JSONObject data = JSON.parseObject(resultData.getData().toString());
        Integer total = data.getInteger("total");
        if (total == null || total <= 0) {
            return Collections.emptyList();
        }
        JSONArray records = data.getJSONArray("records");
        List<WasabiTransactionDto> dtos = records.toJavaList(WasabiTransactionDto.class);

        return dtos;
    }

    /**
     * 获取卡授权交易记录列表
     */
    @Override
    public BaseResultDto<WasabiAuthTransactionDto> getAuthTransactionList(WasabiAuthTransactionEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getCardAuthTransactionUrl(),
                            JSON.toJSONString(entity)
                            , config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);

            JSONObject data = JSON.parseObject(resultData.getData().toString());
            Integer total = data.getInteger("total");

            if (total == null || total <= 0) {
                throw new ServiceException("数据不存在");
            }
            JSONArray records = data.getJSONArray("records");
            List<WasabiAuthTransactionDto> dtos = records.toJavaList(WasabiAuthTransactionDto.class);
            return BaseResultDto.success(dtos);

        } catch (Exception e) {
            log.error("获取卡授权交易记录列表失败", e);
            throw new ServiceException("获取卡授权交易记录列表失败");
        }
    }

    /**
     * 获取卡3ds交易记录
     */
    @Override
    public List<WasabiThird3dsTransactionDto> getThird3dsTransactionList(WasabiThird3dsTransactionEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            entity.setPageNum(1L);
            entity.setPageSize(10L);
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getThird3dsTransactionUrl(),
                            JSON.toJSONString(entity)
                            , config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);

            JSONObject data = JSON.parseObject(resultData.getData().toString());
            Integer total = data.getInteger("total");
            if (total == null || total <= 0) {
                return Collections.emptyList();
            }
            JSONArray records = data.getJSONArray("records");
            List<WasabiThird3dsTransactionDto> dtos = records.toJavaList(WasabiThird3dsTransactionDto.class);
            if (CollectionUtils.isNotEmpty(dtos)) {
                for (WasabiThird3dsTransactionDto dto : dtos) {
                    if (StringUtils.isNotEmpty(dto.getValues())) {
                        dto.setValues(RsaUtils.decryptPrivateKey(dto.getValues(), config.getPrivateKey()));
                    }
                }
            }
            return dtos;
        } catch (Exception e) {
            log.error("获取卡3ds交易记录失败", e);
            throw new ServiceException("获取卡3ds交易记录失败");
        }
    }


    /**
     * 查询职业信息列表
     */
    @Override
    public List<WasabiOccupationsDto> getHolderOccupations() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getHolderOccupationsUrl(), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiOccupationsDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiOccupationsDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw ServiceException.exception(resultData.getMsg());
            }
            return resultData.getData();
        } catch (Exception e) {
            log.error("更新职业信息列表失败", e);
            throw new ServiceException("更新职业信息列表失败");
        }
    }

    /**
     * 创建持卡人
     */
    @Override
    public ResultData<WasabiUserDto> createHolderV2(WasabiUserEntity entity, WasabiConfig config) throws Exception {
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getHolderCreateV2Url(), JSON.toJSONString(entity),
                            config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiUserDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiUserDto>>() {
                    }
            );
            return resultData;
        } catch (Exception e) {
            log.error("创建持卡人V2失败", e);
            throw new ServiceException("创建持卡人V2失败");
        }
    }

    /**
     * 修改持卡人
     */
    @Override
    public ResultData<WasabiUserDto> updateHolderV2(WasabiUserEntity entity, WasabiConfig config) throws ServiceException {
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getHolderUpdateV2Url(), JSON.toJSONString(entity),
                            config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiUserDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiUserDto>>() {
                    }
            );

            return resultData;
        } catch (Exception e) {
            log.error("修改持卡人 V2失败", e);
            throw new ServiceException("修改持卡人 V2失败");
        }
    }

    /**
     * 查询激活码
     */
    @Override
    public WasabiThird3dsTransactionDto getActivationCode(WasabiThird3dsTransactionEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            entity.setPageNum(1L);
            entity.setPageSize(10L);
            entity.setType("activation_code");
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getThird3dsTransactionUrl(),
                            JSON.toJSONString(entity)
                            , config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(), ResultData.class);

            JSONObject data = JSON.parseObject(resultData.getData().toString());
            Integer total = data.getInteger("total");
            if (total == null || total <= 0) {
                throw ServiceException.exception("未查询到激活码");
            }
            JSONArray records = data.getJSONArray("records");
            List<WasabiThird3dsTransactionDto> dtos = records.toJavaList(WasabiThird3dsTransactionDto.class);
            WasabiThird3dsTransactionDto dto = null;
            if (CollectionUtils.isNotEmpty(dtos)) {
                dto = dtos.get(0);
                if (StringUtils.isNotEmpty(dto.getValues())) {
                    dto.setValues(RsaUtils.decryptPrivateKey(dto.getValues(), config.getPrivateKey()));
                }
            }
            return dto;
        } catch (Exception e) {
            log.error("查询激活码失败", e);
            throw new ServiceException("查询激活码失败");
        }
    }

    /**
     * 全球速汇-查询支持的币种
     */
    @Override
    public BaseResultDto<List<WasabiAvailableCurrenciesDto>> getAvailableCurrencies() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getAvailableCurrenciesUrl(), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiAvailableCurrenciesDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiAvailableCurrenciesDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            List<WasabiAvailableCurrenciesDto> dtos = resultData.getData();
            return BaseResultDto.success(dtos);
        } catch (Exception e) {
            log.error("全球速汇-查询支持的币种失败", e);
            throw new ServiceException("全球速汇-查询支持的币种失败");
        }
    }

    /**
     * 全球速汇-币种发送交易需要的字段
     */
    @Override
    public BaseResultDto<WasabiAvailableFieldParamsDto> getAvailableFieldParams(WasabiAvailableFieldParamsEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getAvailableFieldParamsUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiAvailableFieldParamsDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiAvailableFieldParamsDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            WasabiAvailableFieldParamsDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-查询币种发送交易需要的字段失败", e);
            throw new ServiceException("全球速汇-查询币种发送交易需要的字段失败");
        }
    }

    /**
     * 全球速汇-查询省份/州列表
     */
    @Override
    public BaseResultDto<List<WasabiStatesDto>> getStates() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getStatesUrl(), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiStatesDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiStatesDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            List<WasabiStatesDto> dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-查询省份/州列表失败", e);
            throw new ServiceException("全球速汇-查询省份/州列表失败");
        }
    }

    /**
     * 全球速汇-银行城市名单
     */
    @Override
    public BaseResultDto<List<WasabiMethodDto>> getAvailableBankCities(WasabiAvailableBankCitiesEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getAvailableBankCitiesUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiMethodDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiMethodDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            List<WasabiMethodDto> dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-查询银行城市名单失败", e);
            throw new ServiceException("全球速汇-查询银行城市名单失败");
        }
    }

    /**
     * 全球速汇-法币汇率
     */
    @Override
    public BaseResultDto<List<WasabiExchangeRateDto>> getExchangeRate() throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getExchangeRateUrl(), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<List<WasabiExchangeRateDto>> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<List<WasabiExchangeRateDto>>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            List<WasabiExchangeRateDto> dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-查询法币汇率失败", e);
            throw new ServiceException("全球速汇-查询法币汇率失败");
        }
    }

    /**
     * 全球速汇-发送交易
     */
    @Override
    public WasabiTransactionTransferDto transactionTransfer(WasabiTransactionTransferEntity entity,
                                                            WasabiConfig config) throws Exception {
        TwoTuple<String, String> result =
                WasabiCommonUtil.post(config.getApiUrl() + config.getTransactionTransferUrl(),
                        JSON.toJSONString(entity), config);
        verifySignature(result, config.getWsbPublicKey());
        ResultData<WasabiTransactionTransferDto> resultData = JSON.parseObject(result.getSecond(),
                new TypeReference<ResultData<WasabiTransactionTransferDto>>() {
                }
        );
        if (!resultData.isSuccess()) {
            throw new ServiceException(resultData.getMsg());
        }
        WasabiTransactionTransferDto dto = resultData.getData();
        return dto;
    }

    /**
     * 全球速汇-交易记录查询
     */
    @Override
    public BaseResultDto<WasabiTransactionTransferDto> getTransactionList(WasabiTransactionListEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getTransactionListUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiTransactionTransferDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiTransactionTransferDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            WasabiTransactionTransferDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-交易记录查询失败", e);
            throw new ServiceException("全球速汇-交易记录查询失败");
        }
    }

    /**
     * 全球速汇-交易详情查询
     */
    @Override
    public BaseResultDto<WasabiTransactionDetailDto> getTransactionDetail(WasabiTransactionDetailEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getTransactionDetailUrl(),
                            JSON.toJSONString(entity), config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData<WasabiTransactionDetailDto> resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData<WasabiTransactionDetailDto>>() {
                    }
            );
            if (!resultData.isSuccess()) {
                return BaseResultDto.error(resultData.getMsg());
            }
            WasabiTransactionDetailDto dto = resultData.getData();
            return BaseResultDto.success(dto);
        } catch (Exception e) {
            log.error("全球速汇-交易详情查询失败", e);
            throw new ServiceException("全球速汇-交易详情查询失败");
        }
    }

    /**
     * 全球速汇-提交合规性检查资料
     */
    @Override
    public BaseResultDto transactionSubmitRfi(WasabiTransactionSubmitRfiEntity entity) throws Exception {
        WasabiConfig config = getWasabiConfig();
        try {
            TwoTuple<String, String> result =
                    WasabiCommonUtil.post(config.getApiUrl() + config.getSubmitRfiUrl(), JSON.toJSONString(entity),
                            config);
            verifySignature(result, config.getWsbPublicKey());
            ResultData resultData = JSON.parseObject(result.getSecond(),
                    new TypeReference<ResultData>() {
                    }
            );
            if (!resultData.isSuccess()) {
                throw new ServiceException(resultData.getMsg());
            }
            return BaseResultDto.success();
        } catch (Exception e) {
            log.error("全球速汇-提交合规性检查资料失败", e);
            throw new ServiceException("全球速汇-提交合规性检查资料失败");
        }
    }

}
