import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.primitives.Bytes;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.Payment;
import com.huifu.adapay.model.PaymentReverse;
import com.huifu.adapay.model.Refund;
import com.jsowell.JsowellApplication;
import com.jsowell.adapay.common.AdaPayment;
import com.jsowell.adapay.config.AbstractAdapayConfig;
import com.jsowell.adapay.dto.QueryAcctFlowDTO;
import com.jsowell.adapay.dto.QueryPaymentConfirmDTO;
import com.jsowell.adapay.dto.SettleAccountDTO;
import com.jsowell.adapay.factory.AdapayConfigFactory;
import com.jsowell.adapay.operation.PaymentReverseOperation;
import com.jsowell.adapay.response.PaymentConfirmResponse;
import com.jsowell.adapay.response.PaymentReverseResponse;
import com.jsowell.adapay.response.QueryPaymentConfirmDetailResponse;
import com.jsowell.adapay.response.RefundResponse;
import com.jsowell.adapay.service.AdapayService;
import com.jsowell.adapay.vo.DrawCashDetailVO;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.entity.SysDictData;
import com.jsowell.common.core.domain.ykc.LoginRequestData;
import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.AcquirerEnum;
import com.jsowell.common.enums.DelFlagEnum;
import com.jsowell.common.enums.ykc.*;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.*;
import com.jsowell.common.util.Cp56Time2a.Cp56Time2aUtil;
import com.jsowell.common.util.http.HttpUtils;
import com.jsowell.common.util.id.IdUtils;
import com.jsowell.common.util.id.SnowflakeIdWorker;
import com.jsowell.common.util.ip.AddressUtils;
import com.jsowell.netty.handler.HeartbeatRequestHandler;
import com.jsowell.netty.handler.TransactionRecordsRequestHandler;
import com.jsowell.netty.service.yunkuaichong.YKCBusinessService;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.domain.ykcCommond.IssueQRCodeCommand;
import com.jsowell.pile.domain.ykcCommond.ProofreadTimeCommand;
import com.jsowell.pile.dto.*;
import com.jsowell.pile.dto.amap.GetStationInfoDTO;
import com.jsowell.pile.dto.lutongyunting.BindCouponDTO;
import com.jsowell.pile.mapper.MemberBasicInfoMapper;
import com.jsowell.pile.mapper.PileBillingTemplateMapper;
import com.jsowell.pile.service.*;
import com.jsowell.pile.service.orderlogic.AbstractOrderLogic;
import com.jsowell.pile.service.orderlogic.OrderLogicFactory;
import com.jsowell.pile.transaction.dto.OrderTransactionDTO;
import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.util.SnUtils;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.uniapp.MemberVO;
import com.jsowell.pile.vo.uniapp.PileConnectorDetailVO;
import com.jsowell.pile.vo.web.BalanceDeductionAmountVO;
import com.jsowell.pile.vo.web.BillingTemplateVO;
import com.jsowell.pile.vo.web.OrderListVO;
import com.jsowell.pile.vo.web.PileDetailVO;
import com.jsowell.service.MemberService;
import com.jsowell.service.OrderService;
import com.jsowell.service.PileService;
import com.jsowell.service.TempService;
import com.jsowell.thirdparty.amap.service.AMapService;
import com.jsowell.thirdparty.lianlian.dto.CommonParamsDTO;
import com.jsowell.thirdparty.lianlian.service.LianLianService;
import com.jsowell.thirdparty.lianlian.util.Cryptos;
import com.jsowell.thirdparty.lianlian.util.Encodes;
import com.jsowell.thirdparty.lianlian.util.GBSignUtils;
import com.jsowell.thirdparty.lutongyunting.service.LTYTService;
import com.jsowell.wxpay.common.WeChatPayParameter;
import com.jsowell.wxpay.dto.AppletTemplateMessageSendDTO;
import com.jsowell.wxpay.response.WechatPayRefundRequest;
import com.jsowell.wxpay.service.WxAppletRemoteService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StopWatch;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@ActiveProfiles("dev")
@SpringBootTest(classes = JsowellApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class SpringBootTestController {

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    String wechatAppId1 = "wxbb3e0d474569481d"; // 万车充

    String wechatAppId2 = "wx20abc5210391649c"; // 嘉佳充电

    @Autowired
    private SnUtils snUtils;

    @Autowired
    private PileService pileService;

    @Autowired
    private YKCPushCommandService ykcPushCommandService;

    @Autowired
    private IAdapayMemberAccountService adapayMemberAccountService;

    @Autowired
    private IPileMsgRecordService pileMsgRecordService;

    @Autowired
    private IPileStationInfoService pileStationInfoService;

    @Autowired
    private YKCPushCommandService ykcPushBusinessService;

    @Autowired
    private HeartbeatRequestHandler heartbeatRequestHandler;

    @Autowired
    private YKCBusinessService ykcBusinessService;

    @Autowired
    private PileBillingTemplateMapper pileBillingTemplateMapper;

    @Autowired
    private PileRemoteService pileRemoteService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private IPileBillingTemplateService pileBillingTemplateService;

    @Autowired
    private MemberBasicInfoMapper memberBasicInfoMapper;

    @Autowired
    private SimCardService simCardService;

    @Autowired
    private IPileBasicInfoService pileBasicInfoService;

    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private IOrderBasicInfoService orderBasicInfoService;

    @Autowired
    private WxpayCallbackRecordService wxpayCallbackRecordService;

    @Autowired
    private WxAppletRemoteService wxAppletRemoteService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IPileAuthCardService pileAuthCardService;

    @Autowired
    private LianLianService lianLianService;

    @Autowired
    private IMemberTransactionRecordService memberTransactionRecordService;

    @Autowired
    private IMemberPlateNumberRelationService memberPlateNumberRelationService;

    static final String MAC_KEY = "53TtFpc4gdVZbF3x";

    static final String ALGORITHM_MAC = "HmacMD5";

    @Autowired
    private AdapayCallbackRecordService adapayCallbackRecordService;

    @Autowired
    private IAdapayRefundRecordService adapayRefundRecordService;

    @Autowired
    private AdapayService adapayService;

    @Autowired
    private AMapService aMapService;

    @Autowired
    private IPileConnectorInfoService pileConnectorInfoService;

    @Autowired
    private TransactionRecordsRequestHandler transactionRecordsRequestHandler;

    @Autowired
    private IMemberBasicInfoService memberBasicInfoService;

    @Autowired
    private ClearingWithdrawInfoService clearingWithdrawInfoService;

    @Autowired
    private OrderPileOccupyService orderPileOccupyService;

    @Autowired
    private LTYTService ltytService;

    @Autowired
    private IPileMerchantInfoService pileMerchantInfoService;

    @Autowired
    private MemberAdapayRecordService memberAdapayRecordService;

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private OrderPayRecordService orderPayRecordService;

    @Autowired
    private TempService tempService;

    @Test
    public void queryPaymentByOrderNoTest() {
        String orderNo = "C44903356969";
        String wechatAppId = "wxbb3e0d474569481d";
        try {
            List<AdaPayment> adaPayments = adapayService.queryPaymentByOrderNo(orderNo, wechatAppId);
            System.out.println(JSON.toJSONString(adaPayments));
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void checkPaymentTest() {
        QueryOrderDTO dto = new QueryOrderDTO();
        String startTime = "2023-09-01 00:00:00";
        String endTime = "2023-09-30 23:59:59";
        dto.setStartTime(startTime);
        dto.setEndTime(endTime);

        try {
            tempService.checkPayment(dto);
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void toStringTest() {
        String jsonString = "{\"business\":\"00\",\"communicationVersion\":\"v1.5\",\"connectorNum\":\"01\",\"iccid\":\"89860620180085681816\",\"internetConnection\":\"00\",\"pileSn\":\"88230000000259\",\"pileType\":\"01\",\"programVersion\":\"gyk-V29\\u0000\"}";
        LoginRequestData loginRequestData = JSONObject.parseObject(jsonString, LoginRequestData.class);
        System.out.println(loginRequestData.toString());
    }

    /**
     * 单元测试，测试订单流程
     */
    @Test
    public void testTheOrderProcess() throws Exception {
        // 生成订单
        // OrderBasicInfo orderBasicInfo = generateAnOrder();
        // System.out.println(orderBasicInfo);
        // // 支付订单
        // int a = payOrder(orderBasicInfo);
        // System.out.println(a);
        // 结算订单
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode("C46006767636");
        settleOrder(orderBasicInfo);
        // 订单退款
		BigDecimal payAmount = orderBasicInfo.getPayAmount();
		BigDecimal settleAmount = orderBasicInfo.getSettleAmount();

		BigDecimal refundAmt = payAmount.subtract(settleAmount);
		// 延时分账的，可以部分解冻
		memberAdapayRecordService.updateRefundAmountFromFreezeAmount("1234", refundAmt);

		// 实时分账，全部解冻
		// memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount("test01", payAmount, refundAmt);
    }

	// 生成订单
    private OrderBasicInfo generateAnOrder() throws ParseException {
        GenerateOrderDTO dto = new GenerateOrderDTO();
        PileConnectorDetailVO vo = new PileConnectorDetailVO();
        vo.setStationId("2");
        dto.setPileConnector(vo);

        dto.setMemberId("1");
        dto.setStartMode("1");
        dto.setPayMode("4");
        dto.setPileSn("88000000000001");
        dto.setConnectorCode("01");
        dto.setChargeAmount(new BigDecimal("10"));
        // 查询充电桩的计费模板
        BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(dto.getPileSn());
        dto.setBillingTemplate(billingTemplateVO);
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.saveOrder2Database(dto);

        return orderBasicInfo;
    }

    // 支付订单
    private int payOrder(OrderBasicInfo orderBasicInfo) throws Exception {
        // PayOrderDTO dto = new PayOrderDTO();
        // dto.setMemberId(orderBasicInfo.getMemberId());
        // dto.setOrderCode(orderBasicInfo.getOrderCode());
        // dto.setStartMode(orderBasicInfo.getStartMode());
        // dto.setPayMode(orderBasicInfo.getPayMode());
        // dto.setPayAmount(orderBasicInfo.getPayAmount());
        //
        // Map<String, Object> map = orderBasicInfoService.payOrder(dto);
        // return map;
        String paymentId = "1234";
        BigDecimal amount = orderBasicInfo.getPayAmount();
        String orderCode = orderBasicInfo.getOrderCode();

        JSONObject json = new JSONObject();
        json.put("paymentId", paymentId);
        json.put("amount", amount);

        // 记录订单支付流水
        OrderPayRecord orderPayRecord = OrderPayRecord.builder()
                .orderCode(orderCode)
                .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue())
                .payAmount(amount)
                .acquirer(AcquirerEnum.ADAPAY.getValue())
                .deductionRecord(json.toJSONString())
                .createBy(null)
                .delFlag(DelFlagEnum.NORMAL.getValue())
                .build();
        orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord));

        // 更新冻结金额 支付成功后全部冻结
        memberAdapayRecordService.updateFreezeAmount(paymentId, amount);

        // 支付订单成功
        PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
                .orderCode(orderCode)
                .payAmount(amount)
                .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
                .acquirer(AcquirerEnum.ADAPAY.getValue())
                .build();
        // 订单支付成功 支付回调
        // orderBasicInfoService.payOrderSuccessCallback(callbackDTO);
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(callbackDTO.getOrderCode());

        // 修改订单
        orderInfo.setPayMode(callbackDTO.getPayMode());
        orderInfo.setPayStatus(Constants.ONE);
        orderInfo.setPayAmount(callbackDTO.getPayAmount());
        orderInfo.setPayTime(new Date());
        orderInfo.setChargeStartTime(new Date());
        orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue());
        return orderBasicInfoService.updateOrderBasicInfo(orderInfo);

    }

	// 结算订单
    private void settleOrder(OrderBasicInfo orderBasicInfo) {
        TransactionRecordsData data = TransactionRecordsData.builder()
                .transactionCode(orderBasicInfo.getTransactionCode())
                .pileSn(orderBasicInfo.getPileSn())
                .connectorCode(orderBasicInfo.getConnectorCode())
                .startTime("2023-03-10 17:10:24")
                .endTime("2023-03-10 17:10:46")
                .sharpPrice("1.10000")
                .sharpUsedElectricity("2.0000")
                .sharpAmount("2.2000")
                .peakPrice("1.20000")
                .peakUsedElectricity("0")
                .peakAmount("0")
                .flatPrice("1.30000")
                .flatUsedElectricity("0")
                .flatAmount("0")
                .valleyPrice("1.40000")
                .valleyUsedElectricity("0")
                .valleyAmount("0")
                .totalElectricity("2")
                .consumptionAmount("5.3000")
                .vinCode("\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000")
                .transactionIdentifier("01")
                .transactionTime("2023-03-10 17:10:46")
                .stopReasonMsg("结束充电，APP远程停止")
                .logicCard("0")
                .createTime(new Date())

                .build();

        // orderBasicInfoService.settleOrder(data, orderBasicInfo);
		// 获取更新数据后的orderBasicInfo对象
		orderBasicInfoService.returnUpdateOrderBasicInfo(orderBasicInfo, data);
		// 获取更新数据后的orderDetail对象/更新订单详情 查询订单详情 修改订单数据
		OrderDetail orderDetail = orderBasicInfoService.returnUpdateOrderDetail(orderBasicInfo, data);
		// 更新数据库
		OrderTransactionDTO dto = new OrderTransactionDTO();
		dto.setOrderBasicInfo(orderBasicInfo);
		dto.setOrderDetail(orderDetail);
		transactionService.doUpdateOrder(dto);
    }

    public static List<BigDecimal> calculateRefund(BigDecimal totalAmount, List<BigDecimal> payments) {
        List<BigDecimal> refundList = new ArrayList<>();
        BigDecimal remainingAmount = totalAmount;

        for (BigDecimal payment : payments) {
            if (remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
                // refundList.add(BigDecimal.ZERO);
                refundList.add(payment);
            } else {
                BigDecimal refundPerPayment = remainingAmount.min(payment);
                // refundList.add(refundPerPayment);
                refundList.add(payment.subtract(refundPerPayment));
                remainingAmount = remainingAmount.subtract(refundPerPayment);
            }
        }

        return refundList;
    }

    public static void main(String[] args) {
        BigDecimal totalAmount = new BigDecimal("0.1");
        List<BigDecimal> payments = Lists.newArrayList(new BigDecimal("0.97"), new BigDecimal("1.00"));

        List<BigDecimal> refunds = calculateRefund(totalAmount, payments);
        System.out.println("每笔单需要退还的金额: " + refunds);
    }

/**
 * 测试多笔支付情况，解冻部分金额
 */
    @Test
    public void calculateUnfreezeAmountTest() {
        BigDecimal orderAmount = new BigDecimal("0.06");
        List<OrderPayRecord> payRecordList = Lists.newArrayList();
        // 第一笔支付记录
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("paymentId", "002212023083114213410543206907226374144");
        jsonObject.put("amount", "0.97");

        JSONObject jsonObject2 = new JSONObject();
        jsonObject2.put("paymentId", "002212023083114213410543206907226374144");
        jsonObject2.put("amount", "1");

        JSONArray jsonArray = new JSONArray();
        jsonArray.add(jsonObject);
        jsonArray.add(jsonObject2);

        OrderPayRecord build = OrderPayRecord.builder()
                .payAmount(new BigDecimal("1.97"))
                .deductionRecord(jsonArray.toJSONString())
                .build();
        payRecordList.add(build);

        AbstractOrderLogic orderLogic = OrderLogicFactory.getOrderLogic("1");
        List<Map<String, Object>> maps = orderLogic.calculateUnfreezeAmount(orderAmount, payRecordList);
        System.out.println(maps);
    }

    @Test
    public void unfreezeAmountAndUpdateSpendAmountTest() {
        String paymentId = "123";
        memberAdapayRecordService.updateRefundAmount(paymentId, new BigDecimal("5"));
        // memberAdapayRecordService.updateRefundAmountFromFreezeAmount(paymentId, new BigDecimal("20"));
        // BigDecimal unfreezeAmount = new BigDecimal("32");
        // BigDecimal spendAmount = new BigDecimal("10");
        // memberAdapayRecordService.unfreezeAmountAndUpdateSpendAmount(paymentId, unfreezeAmount, spendAmount);
        // memberAdapayRecordService.updateRefundAmountFromFreezeAmount(paymentId, new BigDecimal("2"));
    }

    @Test
    public void getFirstLevelMerchantByMerchantIdTest() {
        String merchantId = "13";
        PileMerchantInfo merchantInfo = pileMerchantInfoService.getFirstLevelMerchantByMerchantId(merchantId);
        System.out.println(JSON.toJSONString(merchantInfo));
    }

    @Test
    public void queryPaymentInfoTest() throws BaseAdaPayException {
        String paymentId = "002212023082514501110541039779091623936";
        // 在完成初始化设置情况下，调用查询方法，获取 Payment 查询结果
        Map<String, Object> response = Payment.query(paymentId, wechatAppId1);
        System.out.println(response);
    }

    /**
     * 手动变更银行卡信息
     */
    @Test
    public void createSettleAccountRequestTest() throws BaseAdaPayException {
        SettleAccountDTO dto = new SettleAccountDTO();
        dto.setCardId("31050180460000002469");
        dto.setCardName("上海擎昆物业管理有限公司");
        dto.setTelNo("18021373333");
        dto.setBankCode("01050000");
        dto.setBankAcctType("1");
        dto.setProvCode("0031");
        dto.setAreaCode("3100");
        String adapayMemberId = "ACM80899105";
        adapayService.createSettleAccountRequest(dto, adapayMemberId, wechatAppId1);
    }

    @Test
    public void createDeleteSettleAccountRequestTest() throws BaseAdaPayException {
        String adapayMemberId = "ACM69424215";
        String settleAccountId = "0498291998695360";
        adapayService.createDeleteSettleAccountRequest(adapayMemberId, settleAccountId, wechatAppId1);
    }

    @Test
    public void queryDrawcashDetailTest() throws BaseAdaPayException {
        String orderNo = "drawcash_1692339516947";
        DrawCashDetailVO drawCashDetailVO = adapayService.queryDrawCashDetail(orderNo, wechatAppId1);
        System.out.println(drawCashDetailVO);
    }

    @Test
    public void queryPaymentConfirmListTest() {
        QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO();
        dto.setWechatAppId(wechatAppId1);
        // dto.setPaymentId("0022120230910032226990546664907296944128");
        dto.setPaymentConfirmId("0022120231009032351990557174514064834560");
        QueryPaymentConfirmDetailResponse.PaymentConfirmInfo paymentConfirmInfo = adapayService.queryPaymentConfirmDetail(dto);
        System.out.println(JSON.toJSONString(paymentConfirmInfo));
    }

    @Test
    public void queryAcctFlowListTest() {
        QueryAcctFlowDTO dto = new QueryAcctFlowDTO();
        try {
            dto.setPageNo(1);
            dto.setPageSize(100);
            dto.setAcctType("01");
            dto.setWechatAppId(wechatAppId1);
            dto.setAdapayMemberId("ACM69424215");
            dto.setBeginDate("20230823");
            dto.setEndDate("20230823");
            adapayService.queryAcctFlowList(dto);
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void testCalculateTheBalanceDeductionAmount() {
        String memberId = "123456";
        BigDecimal amount = new BigDecimal("20");

        List<BalanceDeductionAmountVO> resultList = Lists.newArrayList();
        // 查询会员的余额充值记录 按照充值时间正序
        List<MemberAdapayRecord> memberAdapayRecords = Lists.newArrayList();
        memberAdapayRecords.add(MemberAdapayRecord.builder().paymentId("1").balanceAmt(new BigDecimal("50")).build());
        memberAdapayRecords.add(MemberAdapayRecord.builder().paymentId("2").balanceAmt(new BigDecimal("60")).build());
        memberAdapayRecords.add(MemberAdapayRecord.builder().paymentId("3").balanceAmt(new BigDecimal("10")).build());

        // 定义一个临时金额等于消费金额
        BigDecimal tempAmount = new BigDecimal(amount.toString());
        for (MemberAdapayRecord memberAdapayRecord : memberAdapayRecords) {
            // 该笔支付剩余金额 取出一笔判断是否剩余金额够支付订单消费吗
            BigDecimal balanceAmt = memberAdapayRecord.getBalanceAmt();
            // 该笔支付扣除金额
            BigDecimal deductionAmount;
            // 获取延时分账模式  延时分账的使用撤销方法退款，实时分账的使用退款方法
            // AdapayCallbackRecord callbackRecord = adapayCallbackRecordService.selectByPaymentId(memberAdapayRecord.getPaymentId());
            // String payMode = null;
            // if (callbackRecord != null) {
            //     JSONObject expendJsonObject = JSON.parseObject(callbackRecord.getExpend());
            //     payMode = expendJsonObject.getString("payMode");
            // }
            // 消费金额 - 剩余金额
            tempAmount = tempAmount.subtract(balanceAmt);
            if (tempAmount.compareTo(BigDecimal.ZERO) >= 0) {
                // 计算以后，大于等于0，说明这笔支付剩余金额需要扣完
                deductionAmount = balanceAmt;
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
            } else {
                // 如果小于0，则说明剩余的钱用不完，扣除金额等于消费金额，并结束循环
                deductionAmount = balanceAmt.add(tempAmount);
                BalanceDeductionAmountVO build = BalanceDeductionAmountVO.builder()
                        .memberId(memberId)
                        .paymentId(memberAdapayRecord.getPaymentId())
                        .deductionAmount(deductionAmount)
                        .build();
                resultList.add(build);
                break;
            }
        }

        System.out.println(JSON.toJSONString(resultList));
    }

    @Test
    public void testGenerateOccupyPileOrder() {
        String memberId = "67569684";
        String pileSn = "88230000000135";
        String connectorCode = "01";
        GenerateOccupyOrderDTO dto = new GenerateOccupyOrderDTO();
        dto.setMemberId(memberId);
        dto.setPileSn(pileSn);
        dto.setConnectorCode(connectorCode);

        orderPileOccupyService.generateOccupyPileOrder(dto);
    }

    @Test
    public void testStopOccupyPileOrder() {
        String wechatAppId = "54135135";
        AbstractAdapayConfig config = AdapayConfigFactory.getConfig(wechatAppId);
        System.out.println(JSON.toJSONString(config));

        AbstractAdapayConfig config2 = AdapayConfigFactory.getConfig(wechatAppId1);
        System.out.println(JSON.toJSONString(config2));
    }

    /**
     * 查询分账信息
     * @throws BaseAdaPayException
     */
    @Test
    public void queryCreateConfirmReverse() throws BaseAdaPayException {
        // 用于verify的汇付会员id
        String verifyAdapayMemberId = "ACM46086128";

        List<String> list = getList();
        List<String> resultList = Lists.newArrayList();
        List<QueryPaymentConfirmDetailResponse.PaymentConfirmInfo> successList= Lists.newArrayList();

        for (String s : list) {
            // 查询支付确认id
            QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO();
            dto.setPaymentId(s);
            dto.setWechatAppId(wechatAppId1);
            QueryPaymentConfirmDetailResponse response = adapayService.queryPaymentConfirmList(dto);
            System.out.println("response==" + JSON.toJSONString(response));
            if (response != null) {
                List<QueryPaymentConfirmDetailResponse.PaymentConfirmInfo> confirms = response.getPaymentConfirms();
                if (CollectionUtils.isEmpty(confirms)) {
                    resultList.add(s);
                } else {
                    for (QueryPaymentConfirmDetailResponse.PaymentConfirmInfo confirm : confirms) {
                        JSONObject jsonObject = JSON.parseObject(confirm.getDescription());
                        // 校验是不是分给正确的商户
                        String adapayMemberId = jsonObject.getString("adapayMemberId");
                        System.out.println("分账账号：" + adapayMemberId);
                        if (StringUtils.equals(adapayMemberId, verifyAdapayMemberId)) {
                            successList.addAll(confirms);
                        } else {
                            resultList.add(s);
                        }
                    }
                }
            }
        }
        System.out.println("=================未分账:" + JSON.toJSONString(resultList));
        System.out.println("=================已分账:" + JSON.toJSONString(successList));
    }

    /**
     * 测试分账
     */
    @Test
    public void test() {
        String paymentId = "002212023102616240210563531446717337600";
        AdapayMemberAccount adapayMemberAccount = new AdapayMemberAccount();
        adapayMemberAccount.setAdapayMemberId("ACM25158725");
        BigDecimal deductionAmount = new BigDecimal("12.14");
        String orderCode = "C63381533584";
        // 延时分账，使用确认交易API
        PaymentConfirmResponse paymentConfirmResponse = adapayService.createPaymentConfirmRequest(paymentId,
                adapayMemberAccount, deductionAmount, orderCode, wechatAppId1);
        System.out.println(JSON.toJSONString(paymentConfirmResponse));
    }

    /**
     * 延迟分账未确认调撤销调撤销接口退款
     */
    @Test
    public void createPaymentReverseRequestTest() {
        String paymentId = "002212023082409392010540599165461884928";
        BigDecimal refundAmount = new BigDecimal("0.09");
        String memberId = null;

        // 延迟分账未确认调撤销调撤销接口退款
        PaymentReverseOperation operation = new PaymentReverseOperation();
        operation.setPaymentId(paymentId);
        operation.setReverseAmt(refundAmount);
        operation.setMerchantKey(wechatAppId2);
        operation.setMemberId(memberId);
        operation.setScenarioType(ScenarioEnum.ORDER.getValue());
        operation.setOrderCode(null);
        PaymentReverseResponse response = adapayService.createPaymentReverseRequest(operation);
        System.out.println(JSON.toJSONString(response));
    }

    /**
     * 测试创建退款请求
     */
    @Test
    public void createRefundRequestTest() {
        String paymentId = "0022120231026150915990563512626531311616";
        BigDecimal refundAmount = new BigDecimal("30.53");
        String memberId = "65879222";
        String orderCode = "C61028961274";
        // 调汇付的交易退款接口
        RefundResponse response = adapayService.createRefundRequest(paymentId, refundAmount,
                wechatAppId1, memberId, ScenarioEnum.ORDER.getValue(), orderCode);
        System.out.println(JSON.toJSONString(response));
    }

    /**
     * 批量支付确认撤销
     * @throws BaseAdaPayException
     */
    @Test
    public void testCreateConfirmReverse() throws BaseAdaPayException {
        List<String> list = getList();
        for (String paymentId : list) {
            // 查询支付确认id
            QueryPaymentConfirmDTO dto = new QueryPaymentConfirmDTO();
            dto.setPaymentId(paymentId);
            dto.setWechatAppId(wechatAppId1);
            QueryPaymentConfirmDetailResponse response = adapayService.queryPaymentConfirmList(dto);
            if (response != null) {
                List<QueryPaymentConfirmDetailResponse.PaymentConfirmInfo> confirms = response.getPaymentConfirms();
                System.out.println("支付id:" + paymentId + ", 确认信息:" + JSON.toJSONString(confirms));
                if (CollectionUtils.isNotEmpty(confirms)) {
                    for (QueryPaymentConfirmDetailResponse.PaymentConfirmInfo confirm : confirms) {
                        adapayService.createConfirmReverse(confirm.getId(), wechatAppId1);
                    }
                }
            }
        }
    }

    /**
     * 查询撤销列表
     * @throws BaseAdaPayException
     */
    @Test
    public void queryPaymentReverseListTest() throws BaseAdaPayException {
        JSONArray jsonList = getJsonList();
        List<String> list = getList();

        List<String> idList = Lists.newArrayList();
        for (int i = 0; i < jsonList.size(); i++) {
            JSONObject jsonObject = (JSONObject) jsonList.get(i);
            // System.out.println(jsonObject.toJSONString());
            BigDecimal refundAmount = jsonObject.getBigDecimal("refundAmount");
            String paymentId = jsonObject.getString("paymentId");

            if (list.contains(paymentId)) {
                // 创建撤销请求
                adapayService.createPaymentReverseRequest(paymentId, refundAmount, wechatAppId1, "", ScenarioEnum.ORDER.getValue(), "");
            }

        }
        System.out.println("需要撤销idList:" + idList);
    }

    public JSONArray getJsonList() {
        String jsonArrayString = "[{\"refundAmount\":\"30.53\", \"paymentId\":\"002212023102509494810563069847078420480\"},\n" +
                "{\"refundAmount\":\"15.37\", \"paymentId\":\"002212023102510460310563084002302054400\"},\n" +
                "{\"refundAmount\":\"6.99\", \"paymentId\":\"002212023102511124110563090701846355968\"},\n" +
                "{\"refundAmount\":\"2.15\", \"paymentId\":\"002212023102515344310563156645282902016\"},\n" +
                "{\"refundAmount\":\"4.77\", \"paymentId\":\"002212023102517555310563192171581886465\"},\n" +
                "{\"refundAmount\":\"47.11\", \"paymentId\":\"002212023102518195010563198200956100608\"},\n" +
                "{\"refundAmount\":\"16.31\", \"paymentId\":\"002212023102518554510563207239038910464\"},\n" +
                "{\"refundAmount\":\"0.11\", \"paymentId\":\"002212023102520555510563237478250602496\"},\n" +
                "{\"refundAmount\":\"0.16\", \"paymentId\":\"002212023102521045110563239728223133696\"},\n" +
                "{\"refundAmount\":\"8.45\", \"paymentId\":\"002212023102521143910563242193132945408\"},\n" +
                "{\"refundAmount\":\"0.11\", \"paymentId\":\"002212023102521192910563243409580007424\"},\n" +
                "{\"refundAmount\":\"14.83\", \"paymentId\":\"002212023102521223710563244199296192512\"},\n" +
                "{\"refundAmount\":\"0.16\", \"paymentId\":\"002212023102521234310563244474368217088\"},\n" +
                "{\"refundAmount\":\"13.43\", \"paymentId\":\"002212023102521570210563252859192963072\"},\n" +
                "{\"refundAmount\":\"4.21\", \"paymentId\":\"002212023102522155910563257627847467008\"},\n" +
                "{\"refundAmount\":\"14.22\", \"paymentId\":\"002212023102522193410563258528941170688\"},\n" +
                "{\"refundAmount\":\"50.56\", \"paymentId\":\"002212023102522274710563260600221925376\"},\n" +
                "{\"refundAmount\":\"0.20\", \"paymentId\":\"002212023102522342910563262284556705792\"},\n" +
                "{\"refundAmount\":\"100.00\", \"paymentId\":\"002212023102523022210563269303469297664\"},\n" +
                "{\"refundAmount\":\"70.95\", \"paymentId\":\"002212023102523071910563270545934163968\"},\n" +
                "{\"refundAmount\":\"60.97\", \"paymentId\":\"002212023102523094710563271166910484480\"},\n" +
                "{\"refundAmount\":\"13.18\", \"paymentId\":\"002212023102523130010563271978154807296\"},\n" +
                "{\"refundAmount\":\"0.14\", \"paymentId\":\"002212023102523235110563274707384705024\"},\n" +
                "{\"refundAmount\":\"0.17\", \"paymentId\":\"002212023102523430110563279531766407168\"},\n" +
                "{\"refundAmount\":\"34.60\", \"paymentId\":\"002212023102600075510563285799532720128\"},\n" +
                "{\"refundAmount\":\"10.76\", \"paymentId\":\"002212023102600101210563286372754374656\"},\n" +
                "{\"refundAmount\":\"0.15\", \"paymentId\":\"002212023102600233610563289745851981824\"},\n" +
                "{\"refundAmount\":\"3.72\", \"paymentId\":\"002212023102600391810563293694689501184\"},\n" +
                "{\"refundAmount\":\"4.27\", \"paymentId\":\"002212023102600492010563296219237933056\"},\n" +
                "{\"refundAmount\":\"0.17\", \"paymentId\":\"002212023102605345910563368108020506624\"},\n" +
                "{\"refundAmount\":\"0.14\", \"paymentId\":\"002212023102606164510563378616393760768\"},\n" +
                "{\"refundAmount\":\"12.47\", \"paymentId\":\"002212023102607391110563399361643106304\"},\n" +
                "{\"refundAmount\":\"10.20\", \"paymentId\":\"002212023102608340210563413167228276736\"},\n" +
                "{\"refundAmount\":\"2.08\", \"paymentId\":\"002212023102608405910563414915526729728\"},\n" +
                "{\"refundAmount\":\"39.30\", \"paymentId\":\"002212023102608471510563416492917350400\"},\n" +
                "{\"refundAmount\":\"100.00\", \"paymentId\":\"002212023102609350010563428508330663936\"},\n" +
                "{\"refundAmount\":\"54.49\", \"paymentId\":\"002212023102609402210563429858239901696\"},\n" +
                "{\"refundAmount\":\"52.48\", \"paymentId\":\"002212023102610400610563444892424953856\"},\n" +
                "{\"refundAmount\":\"0.47\", \"paymentId\":\"002212023102611395410563459942744924160\"},\n" +
                "{\"refundAmount\":\"5.59\", \"paymentId\":\"002212023102611415010563460428726755328\"},\n" +
                "{\"refundAmount\":\"0.21\", \"paymentId\":\"002212023102611430810563460756207607808\"},\n" +
                "{\"refundAmount\":\"1.72\", \"paymentId\":\"002212023102611502810563462601938264064\"},\n" +
                "{\"refundAmount\":\"0.12\", \"paymentId\":\"002212023102611562710563464107365986304\"},\n" +
                "{\"refundAmount\":\"0.75\", \"paymentId\":\"002212023102612163810563469186573033472\"},\n" +
                "{\"refundAmount\":\"4.19\", \"paymentId\":\"002212023102612245810563471282161143808\"},\n" +
                "{\"refundAmount\":\"37.38\", \"paymentId\":\"002212023102612284210563472220675592192\"},\n" +
                "{\"refundAmount\":\"0.44\", \"paymentId\":\"002212023102612312310563472896678674432\"},\n" +
                "{\"refundAmount\":\"18.32\", \"paymentId\":\"002212023102612352510563473913451704320\"},\n" +
                "{\"refundAmount\":\"0.16\", \"paymentId\":\"002212023102612512410563477934609485824\"},\n" +
                "{\"refundAmount\":\"3.20\", \"paymentId\":\"002212023102612514510563478021491613696\"},\n" +
                "{\"refundAmount\":\"0.50\", \"paymentId\":\"002212023102613045810563481350137245696\"},\n" +
                "{\"refundAmount\":\"44.12\", \"paymentId\":\"002212023102613251410563486448079036417\"},\n" +
                "{\"refundAmount\":\"3.52\", \"paymentId\":\"002212023102613425710563490909512749056\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102614083410563497354011049984\"},\n" +
                "{\"refundAmount\":\"8.33\", \"paymentId\":\"002212023102614290310563502509800251392\"},\n" +
                "{\"refundAmount\":\"0.06\", \"paymentId\":\"002212023102614424710563505964930363392\"},\n" +
                "{\"refundAmount\":\"25.24\", \"paymentId\":\"002212023102614435010563506231223803904\"},\n" +
                "{\"refundAmount\":\"20.00\", \"paymentId\":\"002212023102614463110563506905694818304\"},\n" +
                "{\"refundAmount\":\"72.28\", \"paymentId\":\"002212023102615062710563511919125426176\"},\n" +
                "{\"refundAmount\":\"0.08\", \"paymentId\":\"002212023102615063310563511947233878016\"},\n" +
                "{\"refundAmount\":\"28.96\", \"paymentId\":\"002212023102615153910563514235439505408\"},\n" +
                "{\"refundAmount\":\"26.27\", \"paymentId\":\"002212023102615184210563515004194213888\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102615293310563517734596337664\"},\n" +
                "{\"refundAmount\":\"11.19\", \"paymentId\":\"002212023102615363410563519498664767488\"},\n" +
                "{\"refundAmount\":\"0.08\", \"paymentId\":\"002212023102615423010563520991255289856\"},\n" +
                "{\"refundAmount\":\"50.00\", \"paymentId\":\"002212023102615493810563522790390521856\"},\n" +
                "{\"refundAmount\":\"6.11\", \"paymentId\":\"002212023102615501910563522959780311040\"},\n" +
                "{\"refundAmount\":\"0.42\", \"paymentId\":\"002212023102616035010563526363172274176\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102616045510563526635063300096\"},\n" +
                "{\"refundAmount\":\"0.06\", \"paymentId\":\"002212023102616111810563528239177777152\"},\n" +
                "{\"refundAmount\":\"0.44\", \"paymentId\":\"002212023102616191610563530246626197504\"},\n" +
                "{\"refundAmount\":\"36.66\", \"paymentId\":\"002212023102616253410563531830216851456\"},\n" +
                "{\"refundAmount\":\"4.49\", \"paymentId\":\"002212023102616333110563533831168913408\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102616530910563538774125670400\"},\n" +
                "{\"refundAmount\":\"40.62\", \"paymentId\":\"002212023102617014310563540927198552064\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102617081710563542583271456768\"},\n" +
                "{\"refundAmount\":\"20.38\", \"paymentId\":\"002212023102617161110563544570726408192\"},\n" +
                "{\"refundAmount\":\"43.62\", \"paymentId\":\"002212023102617170810563544806559129600\"},\n" +
                "{\"refundAmount\":\"105.60\", \"paymentId\":\"002212023102617174910563544982164119552\"},\n" +
                "{\"refundAmount\":\"64.13\", \"paymentId\":\"002212023102617304610563548238191493120\"},\n" +
                "{\"refundAmount\":\"1.53\", \"paymentId\":\"002212023102617340310563549064220680192\"},\n" +
                "{\"refundAmount\":\"20.74\", \"paymentId\":\"002212023102618190210563560385759633408\"},\n" +
                "{\"refundAmount\":\"44.80\", \"paymentId\":\"002212023102618220610563561159283728384\"},\n" +
                "{\"refundAmount\":\"100.00\", \"paymentId\":\"002212023102618324910563563854380384256\"},\n" +
                "{\"refundAmount\":\"18.21\", \"paymentId\":\"002212023102618352510563564510333071360\"},\n" +
                "{\"refundAmount\":\"1.65\", \"paymentId\":\"002212023102618405910563565908406550528\"},\n" +
                "{\"refundAmount\":\"20.00\", \"paymentId\":\"002212023102619043210563571836180193280\"},\n" +
                "{\"refundAmount\":\"9.24\", \"paymentId\":\"002212023102619095210563573178559590400\"},\n" +
                "{\"refundAmount\":\"7.86\", \"paymentId\":\"002212023102619152510563574577509920768\"},\n" +
                "{\"refundAmount\":\"2.86\", \"paymentId\":\"002212023102619173110563575104886235136\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102619174410563575160413847552\"},\n" +
                "{\"refundAmount\":\"12.44\", \"paymentId\":\"002212023102619190310563575491855867904\"},\n" +
                "{\"refundAmount\":\"10.95\", \"paymentId\":\"002212023102619203510563575875551846400\"},\n" +
                "{\"refundAmount\":\"8.75\", \"paymentId\":\"002212023102619222110563576320179027968\"},\n" +
                "{\"refundAmount\":\"8.80\", \"paymentId\":\"002212023102619265310563577459178020864\"},\n" +
                "{\"refundAmount\":\"10.85\", \"paymentId\":\"002212023102619274810563577691998736384\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102619303110563578375249092608\"},\n" +
                "{\"refundAmount\":\"9.83\", \"paymentId\":\"002212023102619541010563584325530124288\"},\n" +
                "{\"refundAmount\":\"15.05\", \"paymentId\":\"002212023102620060710563587335757459456\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102620071510563587618242785280\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102620103810563588471011188736\"},\n" +
                "{\"refundAmount\":\"33.89\", \"paymentId\":\"002212023102620423610563596514914508800\"},\n" +
                "{\"refundAmount\":\"5.20\", \"paymentId\":\"002212023102620535910563599380128423936\"},\n" +
                "{\"refundAmount\":\"33.20\", \"paymentId\":\"002212023102621002510563601001478578176\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102621022210563601491448524800\"},\n" +
                "{\"refundAmount\":\"50.00\", \"paymentId\":\"002212023102621112510563603768625553408\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102621143810563604576338403328\"},\n" +
                "{\"refundAmount\":\"16.26\", \"paymentId\":\"002212023102621310510563608717454168064\"},\n" +
                "{\"refundAmount\":\"11.97\", \"paymentId\":\"002212023102621432010563611801107623936\"},\n" +
                "{\"refundAmount\":\"37.71\", \"paymentId\":\"002212023102621433210563611849459560448\"},\n" +
                "{\"refundAmount\":\"0.09\", \"paymentId\":\"002212023102621450610563612245166358528\"},\n" +
                "{\"refundAmount\":\"15.00\", \"paymentId\":\"002212023102621474410563612905889157120\"}]";
        JSONArray jsonArray = JSONArray.parseArray(jsonArrayString);
        return jsonArray;
    }

    public List<String> getList() {
        List<String> list = Lists.newArrayList();
        list.add("002212023102509494810563069847078420480");
        list.add("002212023102510460310563084002302054400");
        list.add("002212023102511124110563090701846355968");
        list.add("002212023102515344310563156645282902016");
        list.add("002212023102517555310563192171581886465");
        list.add("002212023102518195010563198200956100608");
        list.add("002212023102518554510563207239038910464");
        list.add("002212023102520555510563237478250602496");
        list.add("002212023102521045110563239728223133696");
        list.add("002212023102521143910563242193132945408");
        list.add("002212023102521192910563243409580007424");
        list.add("002212023102521223710563244199296192512");
        list.add("002212023102521234310563244474368217088");
        list.add("002212023102521570210563252859192963072");
        list.add("002212023102522155910563257627847467008");
        list.add("002212023102522193410563258528941170688");
        list.add("002212023102522274710563260600221925376");
        list.add("002212023102522342910563262284556705792");
        list.add("002212023102523022210563269303469297664");
        list.add("002212023102523071910563270545934163968");
        list.add("002212023102523094710563271166910484480");
        list.add("002212023102523130010563271978154807296");
        list.add("002212023102523235110563274707384705024");
        list.add("002212023102523430110563279531766407168");
        return list;
    }

    @Test
    public void testClearingWithdraw() {
        // 保存提现记录
        ClearingWithdrawInfo record = new ClearingWithdrawInfo();
        record.setWithdrawCode("132321354");
        record.setWithdrawStatus(Constants.ZERO);
        Date now = new Date();
        record.setApplicationTime(now);
        record.setCreateTime(now);
        record.setDelFlag(DelFlagEnum.NORMAL.getValue());
        clearingWithdrawInfoService.insertOrUpdate(record);
    }

    @Test
    public void testGetPileTypeNum() {
        Long stationId = 1L;
        pileConnectorInfoService.getPileTypeNum(stationId);
    }

    @Test
    public void testUpdateStatus() {
        String pileConnectorCode = "8800000000012601";
        String status = "0";
        pileConnectorInfoService.updateConnectorStatus(pileConnectorCode, status);
    }

    @Test
    public void testRedisSet() {
        String redisKey = "push_station_connector";
        redisCache.setCacheSet(redisKey, Sets.newHashSet("1"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("3"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("5"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("1"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("1"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("7"));

        redisCache.setCacheSet(redisKey, Sets.newHashSet("3"));


        Set<Object> cacheSet = redisCache.getCacheSet(redisKey);
        System.out.println(cacheSet);
    }

    @Test
    public void testSettleOrder() {
        Map<String, BigDecimal> returnAmountMap = Maps.newHashMap();
        returnAmountMap.put("returnPrincipal", new BigDecimal("16.8700"));
        // 更新会员钱包
        BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal");
        // if (returnPrincipal != null && principalPayRecord != null) {
        // 	principalPayRecord.setRefundAmount(returnPrincipal);
        // 	updatePayRecordList.add(principalPayRecord);
        // }
        BigDecimal returnGift = returnAmountMap.get("returnGift");

        System.out.println(returnPrincipal);
        // if (returnGift != null && giftPayRecord != null) {
        // 	giftPayRecord.setRefundAmount(returnGift);
        // 	updatePayRecordList.add(giftPayRecord);
        // 	// 支付的赠送金额-退回的赠送金额 = 实际使用赠送金额消费的部分
        // 	virtualAmount = giftPay.subtract(returnGift);
        // }
        // UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder()
        // 		.memberId(orderBasicInfo.getMemberId())
        // 		.type(MemberWalletEnum.TYPE_IN.getValue()) // 进账
        // 		.subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款
        // 		.updatePrincipalBalance(returnPrincipal)
        // 		.updateGiftBalance(returnGift)
        // 		.relatedOrderCode(orderBasicInfo.getOrderCode())
        // 		.build();
        // memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO);
    }


    @Test
    public void testVin() {
        String vinCode = "tango";
        MemberPlateNumberRelation memberPlateInfoByVinCode = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
        System.out.println(memberPlateInfoByVinCode);
    }

    @Test
    public void testParking() throws UnsupportedEncodingException {
        // GetTokenDTO dto = new GetTokenDTO();
        // dto.setAppId("I2qa3hdr116100dc");
        // dto.setSecretKey("2qa3hdr13754a8e");
        // String token = ltytService.getToken(dto);
        // System.out.println(token);

        BindCouponDTO dto = new BindCouponDTO();
        dto.setAppId("I2qa3hdr116100dc");
        dto.setSecretKey("2qa3hdr13754a8e");
        dto.setMerchantId("3prv98bm8db70a9");
        dto.setCouponId("3prvd0q7a4817bf");
        dto.setPlateNumber("贵A12345");
        dto.setPlateColor(1);
        String s = ltytService.bindCoupon(dto);
        System.out.println(s);
    }

    @Test
    public void testUpdateConnectorStatus() {
        String pileConnectorCode = "8800000000000101";
        String status = PileConnectorStatusEnum.FREE.getValue();
        pileConnectorInfoService.updateConnectorStatus(pileConnectorCode, status);
    }

    @Test
    public void testOrder() throws Exception {
        // 通过vin码查询数据库绑定用户信息
        MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode("LNBSCC4H1LT107646");
        GenerateOrderDTO dto = new GenerateOrderDTO();
        dto.setMemberPlateNumberRelation(plateInfo);
        dto.setPileSn("88000000000126");
        dto.setConnectorCode("01");
        dto.setStartMode(StartModeEnum.VIN_CODE.getValue());
        dto.setMemberId(plateInfo.getMemberId());
        // 通过memberId获取账户余额
        MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId());
        if (memberVO == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_GET_MEMBER_ACCOUNT_AMOUNT_ERROR);
        }
        BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount();
        if (totalAccountAmount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT);
        }

        dto.setChargeAmount(totalAccountAmount); // 充电金额
        dto.setPayMode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue()); // 1-余额支付

        OrderBasicInfo basicInfo = orderBasicInfoService.generateOrder(dto);

        // 支付订单
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setOrderCode(basicInfo.getOrderCode());
        payOrderDTO.setPayAmount(totalAccountAmount);
        payOrderDTO.setPayMode(dto.getPayMode());
        payOrderDTO.setMemberId(dto.getMemberId());
        // payOrderDTO.setCode();
        // payOrderDTO.setLockValue();
        // payOrderDTO.setOrderBasicInfo(basicInfo);

        Map<String, Object> map = orderBasicInfoService.payOrder(payOrderDTO);

        System.out.println(map);
    }

    @Test
    public void testTransactionRecord() {
        // 获取消息体
        String msg = "8823000000123302230707215317078588230000001233020000341507071763023615070717b02a0200a00f0000000000003016000090dc010000000000000000000000000020c50100000000000000000000000000888a0100000000000000000000000000b0220749005032074900a00f000000000000e01500004c4e425343433448314c543130373634360563023615070717450000000000000000";
        byte[] msgBody = BytesUtil.str2Bcd(msg);

        int startIndex = 0;
        int length = 16;

        // 交易流水号
        byte[] orderCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String transactionCode = BytesUtil.bcd2Str(orderCodeByteArr);

        // 桩编码
        startIndex += length;
        length = 7;
        byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileSn = BytesUtil.bcd2Str(pileSnByteArr);

        // 枪号
        startIndex += length;
        length = 1;
        byte[] connectorCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String connectorCode = BytesUtil.bcd2Str(connectorCodeByteArr);


        // 开始时间  CP56Time2a 格式
        startIndex += length;
        length = 7;
        byte[] startTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        // String binary = BytesUtil.binary(startTimeByteArr, 16);
        Date startDate = Cp56Time2aUtil.byte2Hdate(startTimeByteArr);
        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, startDate);


        // 结束时间  CP56Time2a 格式
        startIndex += length;
        byte[] endTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        Date endDate = Cp56Time2aUtil.byte2Hdate(endTimeByteArr);
        String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, endDate);

        // 尖单价   精确到小数点后五位（尖电费+尖服务费，见费率帧）
        startIndex += length;
        length = 4;
        byte[] sharpPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String sharpPrice = YKCUtils.convertDecimalPoint(sharpPriceByteArr, 5);

        // 尖电量   精确到小数点后四位
        startIndex += length;
        length = 4;
        byte[] sharpUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String sharpUsedElectricity = YKCUtils.convertDecimalPoint(sharpUsedElectricityByteArr, 4);

        // 计损尖电量
        startIndex += length;
        byte[] sharpPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String sharpPlanLossElectricity = YKCUtils.convertDecimalPoint(sharpPlanLossElectricityByteArr, 4);

        // 尖金额
        startIndex += length;
        byte[] sharpAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String sharpAmount = YKCUtils.convertDecimalPoint(sharpAmountByteArr, 4);

        // 峰单价   精确到小数点后五位（峰电费+峰服务费）
        startIndex += length;
        byte[] peakPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String peakPrice = YKCUtils.convertDecimalPoint(peakPriceByteArr, 5);

        // 峰电量
        startIndex += length;
        byte[] peakUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String peakUsedElectricity = YKCUtils.convertDecimalPoint(peakUsedElectricityByteArr, 4);

        // 计损峰电量
        startIndex += length;
        byte[] peakPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String peakPlanLossElectricity = YKCUtils.convertDecimalPoint(peakPlanLossElectricityByteArr, 4);

        // 峰金额
        startIndex += length;
        byte[] peakAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String peakAmount = YKCUtils.convertDecimalPoint(peakAmountByteArr, 4);

        // 平单价   精确到小数点后五位（平电费+平服务费）
        startIndex += length;
        byte[] flatPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String flatPrice = YKCUtils.convertDecimalPoint(flatPriceByteArr, 5);

        // 平电量
        startIndex += length;
        byte[] flatUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String flatUsedElectricity = YKCUtils.convertDecimalPoint(flatUsedElectricityByteArr, 4);

        // 计损平电量
        startIndex += length;
        byte[] flatPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String flatPlanLossElectricity = YKCUtils.convertDecimalPoint(flatPlanLossElectricityByteArr, 4);

        // 平金额
        startIndex += length;
        byte[] flatAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String flatAmount = YKCUtils.convertDecimalPoint(flatAmountByteArr, 4);

        // 谷单价   精确到小数点后五位（谷电费+谷 服务费）
        startIndex += length;
        byte[] valleyPriceByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String valleyPrice = YKCUtils.convertDecimalPoint(valleyPriceByteArr, 5);

        // 谷电量
        startIndex += length;
        byte[] valleyUsedElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String valleyUsedElectricity = YKCUtils.convertDecimalPoint(valleyUsedElectricityByteArr, 4);

        // 计损谷电量
        startIndex += length;
        byte[] valleyPlanLossElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String valleyPlanLossElectricity = YKCUtils.convertDecimalPoint(valleyPlanLossElectricityByteArr, 4);

        // 谷金额
        startIndex += length;
        byte[] valleyAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String valleyAmount = YKCUtils.convertDecimalPoint(valleyAmountByteArr, 4);

        // 电表总起值
        startIndex += length;
        length = 5;
        byte[] ammeterTotalStartByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String ammeterTotalStart = YKCUtils.convertDecimalPoint(ammeterTotalStartByteArr, 4);

        // 电表总止值
        startIndex += length;
        byte[] ammeterTotalEndByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String ammeterTotalEnd = YKCUtils.convertDecimalPoint(ammeterTotalEndByteArr, 4);

        // 总电量
        startIndex += length;
        length = 4;
        byte[] totalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String totalElectricity = YKCUtils.convertDecimalPoint(totalElectricityByteArr, 4);

        // 计损总电量
        startIndex += length;
        byte[] planLossTotalElectricityByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String planLossTotalElectricity = YKCUtils.convertDecimalPoint(planLossTotalElectricityByteArr, 4);

        // 消费金额   精确到小数点后四位，包含电费、 服务费
        startIndex += length;
        byte[] consumptionAmountByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String consumptionAmount = YKCUtils.convertDecimalPoint(consumptionAmountByteArr, 4);

        // VIN 码   VIN 码，此处 VIN 码和充电时 VIN 码不同， 正序直接上传， 无需补 0 和反序
        startIndex += length;
        length = 17;
        byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String vinCode = BytesUtil.ascii2Str(vinCodeByteArr);

        /**
         * 交易标识
         * 0x01： app 启动
         * 0x02：卡启动
         * 0x04：离线卡启动
         * 0x05: vin 码启动充电
         */
        startIndex += length;
        length = 1;
        byte[] transactionIdentifierByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String transactionIdentifier = BytesUtil.bcd2Str(transactionIdentifierByteArr);

        // 交易时间  CP56Time2a 格式
        startIndex += length;
        length = 7;
        byte[] transactionTimeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        Date transactionDate = Cp56Time2aUtil.byte2Hdate(transactionTimeByteArr);
        String transactionTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, transactionDate);

        // 停止原因
        startIndex += length;
        length = 1;
        byte[] stopReasonByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String stopReason = BytesUtil.bin2HexStr(stopReasonByteArr);
        String stopReasonMsg = YKCChargingStopReasonEnum.getMsgByCode(Integer.parseInt(stopReason, 16));

        // 物理卡号  不足 8 位补 0
        startIndex += length;
        length = 8;
        byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        // byte[] logicCardNum = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16);
        String logicCard = BytesUtil.binary(cardNumByteArr, 16);
        // log.info("桩号:{}发送交易记录物理卡号:{}", pileSn, logicCard);
        //
        // log.info("[===交易记录===]交易流水号:{}, 桩编号:{}, 枪号:{}, 开始时间:{}, 结束时间:{}, 尖单价:{}, 尖电量:{}, 计损尖电量:{}, 尖金额:{}, " +
        // 				"峰单价:{}, 峰电量:{}, 计损峰电量:{}, 峰金额:{}, 平单价:{}, 平电量:{}, 计损平电量:{}, 平金额:{}, " +
        // 				"谷单价:{}, 谷电量:{}, 计损谷电量:{}, 谷金额:{}, 电表总起值:{}, 电表总止值:{}, 总电量:{}, 计损总电量:{}, 消费金额:{}, " +
        // 				"电动汽车唯一标识:{}, 交易标识:{}, 交易日期、时间:{}, 停止原因码:{}, 停止原因描述:{}, 物理卡号:{}",
        // 		transactionCode, pileSn, connectorCode, startTime, endTime, sharpPrice, sharpUsedElectricity, sharpPlanLossElectricity, sharpAmount,
        // 		peakPrice, peakUsedElectricity, peakPlanLossElectricity, peakAmount, flatPrice, flatUsedElectricity, flatPlanLossElectricity, flatAmount,
        // 		valleyPrice, valleyUsedElectricity, valleyPlanLossElectricity, valleyAmount, ammeterTotalStart, ammeterTotalEnd, totalElectricity, planLossTotalElectricity,
        // 		consumptionAmount, vinCode, transactionIdentifier, transactionTime, stopReason, stopReasonMsg, logicCard);

        // 交易记录封装到对象里
        TransactionRecordsData data = TransactionRecordsData.builder()
                // .orderCode(transactionCode)
                .transactionCode(transactionCode)
                .pileSn(pileSn)
                .connectorCode(connectorCode)
                .startTime(startTime)
                .endTime(endTime)
                .sharpPrice(sharpPrice)
                .sharpUsedElectricity(sharpUsedElectricity)
                .sharpPlanLossElectricity(sharpPlanLossElectricity)
                .sharpAmount(sharpAmount)
                .peakPrice(peakPrice)
                .peakUsedElectricity(peakUsedElectricity)
                .peakPlanLossElectricity(peakPlanLossElectricity)
                .peakAmount(peakAmount)
                .flatPrice(flatPrice)
                .flatUsedElectricity(flatUsedElectricity)
                .flatPlanLossElectricity(flatPlanLossElectricity)
                .flatAmount(flatAmount)
                .valleyPrice(valleyPrice)
                .valleyUsedElectricity(valleyUsedElectricity)
                .valleyPlanLossElectricity(valleyPlanLossElectricity)
                .valleyAmount(valleyAmount)
                .ammeterTotalStart(ammeterTotalStart)
                .ammeterTotalEnd(ammeterTotalEnd)
                .totalElectricity(totalElectricity)
                .planLossTotalElectricity(planLossTotalElectricity)
                .consumptionAmount(consumptionAmount)
                .vinCode(vinCode)
                .transactionIdentifier(transactionIdentifier)
                .transactionTime(transactionTime)
                .stopReasonMsg(stopReasonMsg)
                .logicCard(logicCard)
                .build();

        // boolean flag = !StringUtils.equals("0000000000000000", "a511101970000000");
        // System.out.println(flag);

        // 处理订单加锁
        String lockKey = "settle_order_" + transactionCode;
        String uuid = IdUtils.fastUUID();
        try {
            // redis锁
            Boolean isLock = redisCache.lock(lockKey, uuid, 1500);
            if (isLock) {
                // transactionRecordsRequestHandler.processOrder(data);
            }
        } catch (Exception e) {
            System.out.println("处理订单发生异常: " + e);
        } finally {
            if (uuid.equals(redisCache.getCacheObject(lockKey).toString())) {
                redisCache.unLock(lockKey);
            }
        }
    }

    @Test
    public void testFault() {
        StringBuffer sb = new StringBuffer("0100");
        String lowOrder = sb.substring(0, 2);
        String highOrder = sb.substring(2, 4);

        // String hardwareFault = highOrder + lowOrder;
        byte[] hardwareFaultByteArr = BytesUtil.str2Bcd(highOrder + lowOrder);
        String binStr = BytesUtil.bytes2BinStr(hardwareFaultByteArr);
        // log.info("binStr:{}", binStr); // 0000 0000 0000 0001
        int faultCode = 0;
        for (int i = 0; i < binStr.length(); i++) {
            if (binStr.charAt(i) == '1') {
                faultCode = 15 - i;
                break;
            }
        }
        String faultReason = YKCPileFaultReasonEnum.getValueByCode(faultCode);
        System.out.println(faultReason);
    }


    @Test
    public void testQueryCorpMember() {
        List<AdapayMemberAccount> accountList = adapayMemberAccountService.selectAdapayMemberAccountList(new AdapayMemberAccount());
        if (CollectionUtils.isNotEmpty(accountList)) {
            Long[] ids = accountList.stream().map(AdapayMemberAccount::getId).toArray(Long[]::new);
            adapayMemberAccountService.deleteAdapayMemberAccountByIds(ids);
        }

        // try {
        // 	Map<String, Object> map = adapayMemberService.selectAdapayMember("5");
        //
        // 	String adapayMemberId = "ACM29562569";
        // 	AdapayCorpMemberVO adapayCorpMemberVO = adapayMemberService.queryCorpAdapayMemberInfo(adapayMemberId);
        // 	System.out.println(adapayCorpMemberVO);
        //
        //
        // } catch (BaseAdaPayException e) {
        // 	throw new RuntimeException(e);
        // }
    }

    @Test
    public void testGetPileListByStationIdList() {

        // List<String> stationIdList = Lists.newArrayList("2");
        // Map<String, List<AMapEquipmentInfo>> pileListByStationIdList = aMapService.getPileListByStationIdList(stationIdList);
        // System.out.println(pileListByStationIdList);

        GetStationInfoDTO dto = new GetStationInfoDTO();
        dto.setType("page");
        aMapService.getStationInfosV2(dto);
    }

    @Test
    public void testMultiSave() {
        String prefix = "test_multi_save:";

        Map<String, Object> redisMap = Maps.newHashMap();

        for (int i = 0; i < 1000; i++) {
            redisMap.put(prefix + i, PileInfoVO.builder().pileSn(i + "").build());
        }
        redisCache.multiSave(redisMap, 60);
    }


    @Test
    public void testBillingTemplate() {
        pileBillingTemplateService.queryStationBillingTemplateListForUniApp("2");
    }


    @Test
    public void testQueryAdapayMemberInfo() {
        String adapayMemberId = "AM25703321";
        String settleAccountId = "0489089447022976";
        try {
            // adapayMemberService.queryAdapayMemberInfo(adapayMemberId);

            adapayService.queryAdapaySettleAccount(adapayMemberId, settleAccountId, "");
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void testSaveAdapayCallbackRecord() throws JsonProcessingException {
        String data = "{\n" +
                "    \"object\": \"refund\",\n" +
                "    \"status\": \"succeeded\",\n" +
                "    \"prod_mode\": \"true\",\n" +
                "    \"id\": \"0022120230531111946980509821471137853440\",\n" +
                "    \"refund_order_no\": \"823725974557265920\",\n" +
                "    \"payment_id\": \"002212023053110524210509814658135928832\",\n" +
                "    \"payment_order_no\": \"C27262970851\",\n" +
                "    \"refund_amt\": \"7.82\",\n" +
                "    \"fee_amt\": \"0.04\",\n" +
                "    \"channel_no\": \"2023053121R064uj\",\n" +
                "    \"created_time\": \"1685503187000\",\n" +
                "    \"succeed_time\": \"1685503199000\",\n" +
                "    \"app_id\": \"app_d0c80cb1-ffc8-48cb-a030-fe9bec823aaa\",\n" +
                "    \"reason\": \"\",\n" +
                "    \"notify_url\": \"https://api.jsowellcloud.com/uniapp/pay/adapayRefundCallback\"\n" +
                "}";

        JSONObject jsonObject = JSON.parseObject(data);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        AdapayRefundRecord adapayRefundRecord = mapper.readValue(jsonObject.toJSONString(), AdapayRefundRecord.class);
        adapayRefundRecord.setRefundId(jsonObject.getString("id"));
        // 保存到数据库
        adapayRefundRecordService.insertAdapayRefundRecord(adapayRefundRecord);
    }

    @Test
    public void testQueryCallback() {
        AdapayCallbackRecord aaaa = adapayCallbackRecordService.selectByOrderCode("aaaa");
        System.out.println(aaaa);
    }

    @Test
    public void testAdapayRefund() {
        // 创建汇付退款对象 在完成初始化设置情况下，调用方法，获取 Refund对象
        try {
            String id = "002212023052710075810508353847861903360";
            String refundAmount = "0.01";
            Map<String, Object> refundParams = Maps.newHashMap();
            refundParams.put("refund_amt", AdapayUtil.formatAmount(refundAmount));
            refundParams.put("refund_order_no", SnowflakeIdWorker.getSnowflakeId());
            refundParams.put("notify_url", "https://api.jsowellcloud.com/uniapp/pay/adapayRefundCallback");
            Map<String, Object> response = Refund.create(id, refundParams);
            System.out.println(JSON.toJSONString(response));
            // if (response != null && !response.isEmpty()) {
            // 	JSONObject jsonObject = JSONObject.parseObject(response.get("expend").toString());
            // 	JSONObject pay_info = jsonObject.getJSONObject("pay_info");
            // 	Map<String, Object> resultMap = JSONObject.parseObject(pay_info.toJSONString(), new TypeReference<Map<String, Object>>() {});
            // }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    @Test
    public void testSaveCallback() throws JsonProcessingException {
        String data = "{\"app_id2\":\"app_d0c80cb1-ffc8-48cb-a030-fe9bec823aaa\",\"created_time\":\"20230530132956\",\"description\":\"{\\\"orderCode\\\":\\\"C29505932783\\\",\\\"type\\\":\\\"order\\\"}\",\"end_time\":\"20230530133027\",\"expend\":{\"bank_type\":\"OTHERS\",\"open_id\":\"o8jhot6PJF93EPhNISsXi28dKdS8\",\"sub_open_id\":\"o4REX5MprZfTaLnVNxfdOY-wnwGI\"},\"fee_amt\":\"0.11\",\"id\":\"002212023053013295610509491838664794112\",\"order_no\":\"C29505932783\",\"out_trans_id\":\"4200001855202305308670391485\",\"party_order_id\":\"02212305304859640306711\",\"pay_amt\":\"20.00\",\"pay_channel\":\"wx_lite\",\"real_amt\":\"20.00\",\"share_eq\":\"Y\",\"status\":\"succeeded\",\"wx_user_id\":\"\"}";
        JSONObject jsonObject = JSON.parseObject(data);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        AdapayCallbackRecord adapayCallbackRecord = mapper.readValue(jsonObject.toJSONString(), AdapayCallbackRecord.class);
        adapayCallbackRecord.setExpend(jsonObject.getString("expend"));
        adapayCallbackRecord.setPaymentId(jsonObject.getString("id"));
        // adapayCallbackRecordService.saveAdapayCallbackRecord(adapayCallbackRecord);

    }

    @Test
    public void testAMap() throws Exception {
        String pileConnectorCode = "8800000000012601";
        // String s = aMapService.pushChargingDeviceDynamics(pileConnectorCode);
        GetStationInfoDTO dto = new GetStationInfoDTO();
        dto.setType("page");
        aMapService.getStationInfos(dto);
    }

    @Test
    public void testVinCode() {
        String msg = "880000000000210203000000000000000000000000000000000000000000000000004C5257594743454B584D43303437313434";
        // 获取消息体
        byte[] msgBody = BytesUtil.str2Bcd(msg);

        int startIndex = 0;
        int length = 7;

        // 桩编码
        byte[] pileSnByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileSn = BytesUtil.binary(pileSnByteArr, 16);

        // 保存时间
        // saveLastTime(pileSn);

        // 枪号
        startIndex += length;
        length = 1;
        byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String connectorCode = BytesUtil.bcd2Str(connectorNumByteArr);

        // 启动方式
        // 0x01 表示通过刷卡启动充电
        // 0x02 表求通过帐号启动充电 （暂不支持）
        // 0x03 表示vin码启动充电
        startIndex += length;
        byte[] startModeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String startMode = BytesUtil.bcd2Str(startModeByteArr);

        // 是否需要密码  0x00 不需要 0x01 需要
        startIndex += length;
        byte[] needPasswordFlagByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String needPasswordFlag = BytesUtil.bcd2Str(needPasswordFlagByteArr);

        // 物理卡号  不足 8 位补 0
        startIndex += length;
        length = 8;
        byte[] cardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String physicsCard = BytesUtil.binary(cardNumByteArr, 16);

        // 输入密码  对用户输入的密码进行16 位MD5 加密，采用小写上传
        startIndex += length;
        length = 16;
        byte[] inputPasswordByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);

        // VIN码
        startIndex += length;
        length = 17;
        byte[] vinCodeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String vinCode = BytesUtil.ascii2Str(vinCodeByteArr);
        System.out.println("桩号:" + pileSn + "申请充电VIN码:" + vinCode);

        /**
         * 刷卡启动充电
         */
        String logicCard = "";
        byte[] authenticationFlagByteArr = Constants.zeroByteArray; // 鉴权成功标识
        byte[] accountBalanceByteArr = Constants.zeroByteArray; // 账户余额
        String transactionCode = "";

        try {
            /**
             * VIN码启动充电
             */
            if (StringUtils.equals("03", startMode)) {
                // 通过vin码查询数据库绑定用户信息
                MemberPlateNumberRelation plateInfo = memberPlateNumberRelationService.getMemberPlateInfoByVinCode(vinCode);
                if (plateInfo == null) {
                    throw new BusinessException("", "未查到绑定用户信息");
                }
                if (!StringUtils.equals("1", plateInfo.getVinStatus())) {
                    // 1- 正常使用
                    throw new BusinessException("", "vin状态不正确");
                }
                // vin码生成订单 vin启动充电
                GenerateOrderDTO dto = new GenerateOrderDTO();
                dto.setMemberPlateNumberRelation(plateInfo);
                dto.setPileSn(pileSn);
                dto.setConnectorCode(connectorCode);
                dto.setStartMode(StartModeEnum.VIN_CODE.getValue());
                Map<String, Object> map = orderBasicInfoService.generateOrderByCard(dto);
                if (map != null) {
                    transactionCode = (String) map.get("transactionCode");
                    accountBalanceByteArr = YKCUtils.getPriceByte(String.valueOf(map.get("accountBalance")), 2);
                    // 鉴权成功标识  0x00 失败 0x01 成功
                    authenticationFlagByteArr = Constants.oneByteArray;
                } else {
                    throw new BusinessException("", "生成vin订单失败");
                }
            }
        } catch (BusinessException e) {
            e.printStackTrace();
            System.out.println("1");
            // log.error("VIN码启动充电鉴权 error:{}, {}", e.getCode(), e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("2");
            transactionCode = "00000000000000000000000000000000";
            accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);
            authenticationFlagByteArr = Constants.zeroByteArray;
            // log.error("VIN码启动充电鉴权 error", e);
        }
        byte[] serialNumByteArr = BytesUtil.str2Bcd(transactionCode);

        byte[] defeatReasonByteArr = Constants.zeroByteArray;

        // 不足位数的值补零
        // cardNumByteArr = BytesUtil.checkLengthAndBehindAppendZero(cardNumByteArr, 16);
        // serialNumByteArr = BytesUtil.checkLengthAndBehindAppendZero(serialNumByteArr, 32);
        // pileSnByteArr = BytesUtil.checkLengthAndBehindAppendZero(pileSnByteArr, 14);
        // accountBalanceByteArr = BytesUtil.checkLengthAndBehindAppendZero(accountBalanceByteArr, 8);

        // 拼装消息体
        byte[] msgBodyByteArr = Bytes.concat(serialNumByteArr, pileSnByteArr, connectorNumByteArr, cardNumByteArr, accountBalanceByteArr,
                authenticationFlagByteArr, defeatReasonByteArr);

        String s = BytesUtil.bin2HexStr(msgBodyByteArr);
        System.out.println(s);
    }

    @Test
    public void testGenerateLianlianToken() throws UnsupportedEncodingException {
        String OperatorID = "425010765";
        String OperatorSecret = "123123123123aaaa"; // 1234567890abcdef

        //请求dataX
        Map<String, String> data = new HashMap<>();
        data.put("OperatorID", OperatorID);
        data.put("OperatorSecret", OperatorSecret);
        String dataJson = JSONUtil.toJsonStr(data);

        //加密
        byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes(StandardCharsets.UTF_8),
                OperatorSecret.getBytes(), OperatorSecret.getBytes());
        String strData = Encodes.encodeBase64(encryptText);

        Map<String, String> request = new LinkedHashMap<>();
        request.put("OperatorID", OperatorID);
        request.put("Data", strData);
        request.put("TimeStamp", System.currentTimeMillis() + "");
        request.put("Seq", "0001");

        //生成签名
        String sig = GBSignUtils.sign(request, OperatorSecret);
        request.put("Sig", sig);
        String tokenRequest = JSONUtil.toJsonStr(request);

        CommonParamsDTO dto = JSONObject.parseObject(tokenRequest, CommonParamsDTO.class);

        lianLianService.generateToken(dto);
    }

    @Test
    public void testupdateElecAmount() {
        // orderBasicInfoService.updateElecAmount();
    }

    @Test
    public void testSelectSomeStatusCardInfo() {
        PileAuthCard pileAuthCard = pileAuthCardService.selectCardInfoByLogicCard("1111111111111111");
        System.out.println(pileAuthCard);
    }

    @Test
    public void testLianLian() throws UnsupportedEncodingException {
        // 获取令牌
        // LianLianGetTokenDTO dto = new LianLianGetTokenDTO();
        // dto.setOperatorId("MA1JLFUU8");
        // dto.setOperatorSecret("Nh62XxlIR5OjAzFj");
        // String token = lianLianService.getToken("", "MA1JLFUU8", "fGwLsxW1HdzLw7jp");
        // System.out.println("token:" + token);

        String operatorId = "425010765";
        String operatorSecret = "3DSBTWHVIC6KVCKI";
        // 请求data
        // Map<String, String> data = new HashMap<>();
        // data.put("OperatorID", operatorId);
        // data.put("OperatorSecret", operatorSecret);
        // String dataJson = JSONUtil.toJsonStr(data);

        JSONObject json = new JSONObject();
        // json.put("StationIDs", com.google.common.collect.Lists.newArrayList("1", "2"));
        json.put("LastQueryTime", "2023-05-29 10:00:00");
        json.put("PageNo", 1);
        json.put("PageSize", 10);

        String dataJson = JSONObject.toJSONString(json);
        // 加密
        byte[] encryptText = Cryptos.aesEncrypt(dataJson.getBytes(StandardCharsets.UTF_8),
                operatorSecret.getBytes(), operatorSecret.getBytes());
        String strData = Encodes.encodeBase64(encryptText);
        String timeStamp = DateUtils.parseDateToStr(DateUtils.YYYYMMDDHHMMSS, new Date());
        Map<String, String> request = new LinkedHashMap<>();
        request.put("OperatorID", operatorId);
        request.put("Data", strData);
        request.put("TimeStamp", timeStamp);
        request.put("Seq", "0001");

        // 生成签名
        String sig = GBSignUtils.sign(request, operatorSecret);
        request.put("Sig", sig);
        JSONObject jsonObject = new JSONObject(request);
        System.out.println(jsonObject);
        // CommonParamsDTO dto = new CommonParamsDTO();
        // dto.setOperatorID(operatorId);
        // dto.setData(strData);
        // dto.setTimeStamp(timeStamp);
        // dto.setSeq("0001");
        // dto.setSig(sig);
        // Map<String, String> map = lianLianService.generateToken(dto);
        QueryStationInfoDTO dto = new QueryStationInfoDTO();
        dto.setOperatorId(operatorId);
        Map<String, String> map = lianLianService.query_stations_info(dto);
        // String data1 = map.get("Data");
        // 解密data
        // String data1 = "JudlP17tnYuQc2zwOzmjJAb9hgghIymefG5v3ZzSOlPDh5+bJHIedsYzKMD56tHlmlg6Cb7vG+o6KjMSSpn1fyqBH3UVaEFF7uEc+lOuEc9c1vUzq20vBQ7N3EpDKqVBKjZbOezMsKYaCX7Br8XTsCYT8VCQui/np3cn+phi3VC+0s1coNxBX7xoEDZ7iuPjPoSWL7g3J0uOw2SoGaIdBQG3eTxaZJ5L+vBmuDF0pEXgazTMnuKml1mx1QHkig2F7h/ILT0VEKVXWMmmogYgiBk5ItO0DyzRl+ASb184gOhYGo82GJmWRiXrAXmceCiSNvTGg6aL26imIGKkJNfOx9/9mTqjGvy6kzxvWJ29PBU=";
        // byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(data1),
        // 		operatorSecret.getBytes(), operatorSecret.getBytes());
        // String dataStr = new String(plainText, "UTF-8");
        // Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
        //
        // String token = resultMap.get("AccessToken");
        //
        // System.out.println("解密后token：" + token);

        // LianLianPushStationInfoDTO dto1 = LianLianPushStationInfoDTO.builder()
        // 		.OperatorID("MA1JLFUU8")
        // 		.DataSecret("HVicnbRZbhPdIdpF")
        // 		.DataSecretIV("JNvcjSOn1vhrE11M")
        // 		.SigSecret("53TtFpc4gdVZbF3x")
        // 		// .token(token)
        // 		.stationId(2L)
        //
        // 		.build();
        // lianLianService.pushStationInfo(dto1);

        // 推送订单状态
        // lianLianService.pushConnectorStatus("8800000000000101", "1");

        // 推送订单信息
        // lianLianService.pushOrderInfo("C27680791529");

        // 推送启动充电结果
        // lianLianService.pushStartChargeResult("C27680791529");

        // 推送充电状态
        // lianLianService.pushChargeStatus("C27680791529");

        // 推送停止充电结果
        // lianLianService.pushStopChargeResult("C27680791529");

        // 推送充电订单信息
        // lianLianService.pushChargeOrderInfo("C27680791529");

        // 推送订单结算信息
        // lianLianService.pushOrderSettlementInfo("C27680791529");

        // 查询订单结算信息
        // lianLianService.queryOrderSettlementInfo("C27680791529");

        // 推送订单对账结果信息
        // lianLianService.pushOrderReconciliationInfo("C27680791529");

        // 测试生成、解密令牌
        // long ttlMillis = 60 * 60 * 24 * 1000;
        // String token = JWTUtils.createToken(operatorId, operatorSecret, ttlMillis);
        // System.out.println(JWTUtils.checkThirdPartyToken(token));

        JSONObject jsonObject1 = new JSONObject(map);
        jsonObject1.put("OperatorID", "425010765");
        jsonObject1.put("Data", "Ntu99RpveEOm2VUNq6RpD7OuOPXRbNxMOPmaBl67nkLk0nD/VmhipdSpq/Qfswhe1o55YMT+3Z7e6xe3fiJA3cZcvetxOEUF6sjvKLRq2rU=");
        jsonObject1.put("TimeStamp", "20230530090132");
        jsonObject1.put("Seq", "0001");
        jsonObject1.put("Sig", "1568D2D35B245A0205B33D0EF92E7981");

        String jsonString = JSONObject.toJSONString(jsonObject1);

        String result = HttpUtils.sendPostContentType("http://localhost:8080/LianLian/v1/query_stations_info", jsonString, "application/json");
        JSONObject object = JSONObject.parseObject(result);
        String data1 = (String) object.get("data");
        // 解密data
        byte[] plainText = Cryptos.aesDecrypt(Encodes.decodeBase64(data1),
                operatorSecret.getBytes(), operatorSecret.getBytes());
        String dataStr = new String(plainText, "UTF-8");
        Map<String, String> resultMap = (Map<String, String>) JSON.parse(dataStr);
    }


    @Test
    public void testRefundForBalance() {
        BigDecimal refundAmount = new BigDecimal("2");
        // 退款金额 元转分 123
        int refundTotalCents = refundAmount.multiply(new BigDecimal(100)).intValue();

        // 查询用户充值余额订单 过滤掉已经退款的充值订单 refundableOrder
        List<RefundableWxPayOrderData> recordList = Lists.newArrayList();
        // recordList.add(RefundableWxPayOrderData.builder().outTradeNo("1").transactionId("1").payerAmount(new BigDecimal("1000")).refundableAmount(new BigDecimal("0")).build());
        // recordList.add(RefundableWxPayOrderData.builder().outTradeNo("2").transactionId("2").payerAmount(new BigDecimal("1000")).refundableAmount(new BigDecimal("0")).build());
        recordList.add(RefundableWxPayOrderData.builder().outTradeNo("3").transactionId("3").payerAmount(new BigDecimal("500")).refundableAmount(new BigDecimal("300")).build());

        // 也许需要多笔支付订单才够退款
        List<WechatPayRefundRequest> requestList = com.google.common.collect.Lists.newArrayList();
        WechatPayRefundRequest request;
        for (RefundableWxPayOrderData record : recordList) {
            int refundableTotal = record.getRefundableAmount().intValue(); // 该笔支付订单的可退金额，单位分
            int payerTotal = record.getPayerAmount().intValue(); // 该笔支付订单的支付金额，单位分
            // 用户申请退款金额-可退金额
            refundTotalCents = refundTotalCents - refundableTotal; // 123 - 100
            request = new WechatPayRefundRequest();
            request.setTransaction_id(record.getTransactionId()); // 微信支付单号
            request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号
            request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
            request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
            request.setReason("用户余额退款");
            request.setFunds_account("AVAILABLE");
            if (refundTotalCents > 0) {
                // 如果大于0说明，这笔单退完也不够
                WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
                amount.setRefund(refundableTotal); // 退款金额
                amount.setTotal(payerTotal); // 原订单金额
                request.setAmount(amount);
                requestList.add(request);
            } else {
                // 如果小于0，这笔单退一部分
                // 生成退款单号
                WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
                // 部分退
                int i = refundableTotal + refundTotalCents;
                amount.setRefund(i); // 退款金额
                amount.setTotal(payerTotal); // 原订单金额
                request.setAmount(amount);
                requestList.add(request);
                break;
            }
        }

        System.out.println(requestList);
    }

    @Test
    public void testCloseStartFailedOrder() {
        String startTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.addDays(new Date(), -2));
        String endTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, new Date());
        orderBasicInfoService.closeStartFailedOrder(startTime, endTime);
    }

    @Test
    public void testRedisSaveRealTimeData() {
        String pileSn = "88000000000001";
        String connectorCode = "01";
        String orderCode = "88000000000001012211161342359448";

        String pileConnectorCode = pileSn + connectorCode;
        String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + orderCode;

        // for (int i = 0; i < 10; i++) {
        // 	try {
        // 		Thread.sleep(10000);
        // 	} catch (InterruptedException e) {
        // 		e.printStackTrace();
        // 	}
        // 	Date now = new Date();
        // 	redisCache.hset(redisKey, DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:00", now), i + ":" + DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", now));
        // }

        orderBasicInfoService.getChargingRealTimeData(orderCode);
    }

    @Test
    public void testuniformMessageSend() {
        AppletTemplateMessageSendDTO appletTemplateMessageSendDTO = new AppletTemplateMessageSendDTO();
        // String openId = wxAppletRemoteService.getOpenIdByCode("0537u2100jTXsP1Y0Y300j426t47u210");
        // System.out.println("openId:" + openId);

        appletTemplateMessageSendDTO.setTouser("o4REX5MprZfTaLnVNxfdOY-wnwGI"); // openid

        String templateId = "UyBPbADlZfsCj89rh_xvfZGlxTW5J5KURpZtt9CNFrY";
        appletTemplateMessageSendDTO.setTemplate_id(templateId);
        // appletTemplateMessageSendDTO.setPage("跳转的页面");
        Map<String, Object> map = new HashMap<>();
        map.put("amount17", ImmutableMap.of("value", "￥100")); // 结束时间
        map.put("time3", ImmutableMap.of("value", "2022-12-30")); // 结束时间
        map.put("thing7", ImmutableMap.of("value", "thing7")); // 结束原因

        // map.put("thing5", ImmutableMap.of("value", "thing5")); // 结束原因
        // map.put("time2", ImmutableMap.of("value", "time2")); // 结束原因
        appletTemplateMessageSendDTO.setData(map);

        wxAppletRemoteService.uniformMessageSend(appletTemplateMessageSendDTO);
    }

    @Test
    public void testWeChatRefund() {
        ApplyRefundDTO dto = new ApplyRefundDTO();
        dto.setRefundType("2");
        dto.setMemberId("82100864");
        dto.setRefundAmount(new BigDecimal("1.23"));
        orderBasicInfoService.weChatRefund(dto);
    }

    @Test
    public void testSelectBalanceRechargeRecord() {
        List<WxpayCallbackRecord> list = wxpayCallbackRecordService.queryBalanceRechargeRecordOfTheLatestYear("82100864");
        System.out.println(list);
    }

    @Test
    public void testSelectOrderBasicInfoList() {
        QueryOrderDTO orderBasicInfo = new QueryOrderDTO();
        orderBasicInfo.setPileSn("88000000000001");
        orderBasicInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue());
        List<OrderListVO> orderListVOS = orderBasicInfoService.selectOrderBasicInfoList(orderBasicInfo);
        System.out.println(orderListVOS);
        for (OrderListVO orderListVO : orderListVOS) {
            if (StringUtils.equals(orderListVO.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) {
                // 修改数据库订单状态
                OrderBasicInfo info = OrderBasicInfo.builder()
                        .id(Long.parseLong(orderListVO.getId()))
                        .orderStatus(OrderStatusEnum.ABNORMAL.getValue())
                        .build();
                orderBasicInfoService.updateOrderBasicInfo(info);
            }
        }
    }

    @Test
    public void testWechatRefund() throws JsonProcessingException {
        WechatPayRefundRequest request = new WechatPayRefundRequest();
        request.setTransaction_id("4200001656202212302746036536"); // 微信支付单号
        request.setOut_trade_no("768677222373363712"); // 商户订单号
        // 生成退款单号
        request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号
        request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口
        WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount();
        amount.setRefund(10 * 100); // 退款金额
        amount.setTotal(10 * 100); // 原订单金额
        request.setAmount(amount);
        request.setReason("结算退款");
        request.setFunds_account("AVAILABLE");

        wechatPayService.ApplyForWechatPayRefundV3(request);

        // 退款方法

    }

    @Test
    public void testUpdatePileSimInfo() {
        String pileSn = "88000000000001";
        String iccid = "89860402102091089943";
        pileBasicInfoService.updatePileSimInfo(pileSn, iccid);
    }

    @Test
    public void testPay() {
        String code = "081zIoGa11GamE0iVVIa1aaJ4G0zIoGE";
        String openId = memberService.getOpenIdByCode(code);
        Map<String, Object> pay = null;
        try {
            WeixinPayDTO dto = new WeixinPayDTO();
            dto.setOpenId(openId);
            dto.setAmount("0.01");
            pay = orderService.weixinPayV3(dto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(JSONObject.toJSONString(pay));
    }

    @Test
    public void testMemberRegisterAndLogin() throws BaseAdaPayException {


    }

    @Test
    public void testMemberBasicInfoMapper() {
        // String memberId = "21772870";
        // BigDecimal principalBalance = new BigDecimal("-10");
        // BigDecimal giftBalance = new BigDecimal("-110");
        // Integer version = 2;
        // int i = memberBasicInfoMapper.updateMemberBalance(memberId, principalBalance, giftBalance, version);
        // if (i == 1) {
        // 	System.out.println("更新余额成功");
        // } else {
        // 	System.out.println("更新余额失败");
        // }

        Map<String, Object> refundParams = new HashMap<>(2);
        refundParams.put("payment_id", "002212023071011321210524320114191904768");
        // refundParams.put("refund_id", refund_id);
        // refundParams.put("refund_order_no", refund_order_no);
        try {
            Map<String, Object> refund = Refund.query(refundParams);
            System.out.println(refund);
        } catch (BaseAdaPayException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询退款信息
     */
    @Test
    public void queryRefundTest() {
        List<String> list = getList();
        for (String paymentId : list) {
            Map<String, Object> refundParams = Maps.newHashMap();
            refundParams.put("payment_id", paymentId);
            try {
                Map<String, Object> refund = Refund.query(refundParams, wechatAppId2);
                System.out.println("支付id:" + paymentId + ", 退款信息:" + JSON.toJSONString(refund));
                System.out.println();
            } catch (BaseAdaPayException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 查询支付撤销信息
     */
    @Test
    public void queryPaymentReverseTest() {
        List<String> list = getList();
        for (String paymentId : list) {
            try {
                Map<String, Object> reverse = Maps.newHashMap();
                reverse.put("payment_id", paymentId);
                reverse.put("app_id", wechatAppId2);
                Map<String, Object> response = PaymentReverse.queryList(reverse, wechatAppId2);
                System.out.printf("支付id: %s, 支付撤销信息: %s%n", paymentId, JSON.toJSONString(response));
                System.out.println();
            } catch (BaseAdaPayException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Test
    public void testGenerateBillingTemplateMsgBody() {
        String pileSn = "88000000000001";
        // 根据桩号查询计费模板
        BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn);

        byte[] messageBody = pileBillingTemplateService.generateBillingTemplateMsgBody(pileSn, billingTemplateVO);
        System.out.println(BytesUtil.binary(messageBody, 16));
    }

    @Test
    public void testAnalysisPileParameter() {
        BasicPileDTO dto = new BasicPileDTO();
        // 3个都不传的情况
        try {
            System.out.println("3个都不传的情况");
            dto.setPileSn("");
            dto.setConnectorCode("");
            dto.setPileConnectorCode("");
            // orderService.analysisPileParameter(dto);
            System.out.println("数据正确");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
        System.out.println();

        // 只传sn的情况
        try {
            System.out.println("只传sn的情况");
            dto.setConnectorCode("");
            dto.setPileConnectorCode("");
            dto.setPileSn("88000000000001");
            // orderService.analysisPileParameter(dto);
            System.out.println("数据正确");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
        System.out.println();

        //
        try {
            System.out.println("只穿枪口号的情况");
            dto.setConnectorCode("01");
            dto.setPileConnectorCode("");
            dto.setPileSn("");
            // orderService.analysisPileParameter(dto);
            System.out.println("数据正确");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
        System.out.println();

        // 只传充电桩枪口编号的情况
        try {
            System.out.println("只传充电桩枪口编号的情况");
            dto.setPileConnectorCode("8800000000000101");
            dto.setConnectorCode("");
            dto.setPileSn("");
            // orderService.analysisPileParameter(dto);
            System.out.println("数据正确");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }

        try {
            System.out.println();
            System.out.println("传充电桩枪sn+枪口号的情况");
            dto.setPileConnectorCode("");
            dto.setConnectorCode("01");
            dto.setPileSn("88000000000001");
            // orderService.analysisPileParameter(dto);
            System.out.println("数据正确");
        } catch (BusinessException e) {
            System.out.println(e.getMessage());
        }
    }

    @Test
    public void testImportBillingTemplate() {
        ImportBillingTemplateDTO dto = new ImportBillingTemplateDTO();
        dto.setBillingTemplateId("1");
        // 查询公共计费模板是否存在
        PileBillingTemplate pileBillingTemplate = pileBillingTemplateMapper.selectPileBillingTemplateById(Long.valueOf(dto.getBillingTemplateId()));
        if (pileBillingTemplate == null) {

        }
        List<PileBillingDetail> billingDetailList = pileBillingTemplate.getPileBillingDetailList();
    }

    @Test
    public void testProcess() {
        // 62   68
        String msgString = "680da300000388000000000001010020d06840a40000130000000000000000000000000000000088000000000001010202000000000000000000000000000000000000000000000000000000000000000000001516";
        byte[] msg = BytesUtil.str2Bcd(msgString);
        boolean b = YKCUtils.checkMsg(msg);
        // ykcBusinessService.process(msg, null);
    }

    @Test
    public void testHeartbeat() {
        // heartbeatRequestHandler.updateStatus("88000000000001", "01", "0");

        // heartbeatRequestHandler.updateStatus("88000000000001", "02", "0");
    }

    @Test
    public void testPush() {
        byte[] msg = new byte[]{};
        String pileSn = "88000000000001";
        // ykcPushBusinessService.push(msg, pileSn, YKCFrameTypeCode.READ_REAL_TIME_MONITOR_DATA_CODE);
    }

    @Test
    public void TestMapUtils() {
        String address = "淀山湖镇黄浦江南路278号";
        String areaCode = "320000,320500,320583";
        Map<String, String> longitudeAndLatitude = AddressUtils.getLongitudeAndLatitude(areaCode, address);
        System.out.println(longitudeAndLatitude);
    }

    @Test
    public void testCreatePile() {
        BatchCreatePileDTO dto = BatchCreatePileDTO.builder()
                .merchantId("1")
                .stationId("1")
                .softwareProtocol("1")
                // .connectorNum(1)
                // .num(10)
                // .productionDate(new Date())
                .build();
        pileService.batchCreatePile(dto);
    }

    @Test
    public void testGetIncre() {
        StopWatch stopWatch = new StopWatch();

        // 生成100个
        stopWatch.start("生成100个sn号");
        List<String> list2 = snUtils.generateSN(1);
        stopWatch.stop();
        System.out.println(list2);

        System.out.println(stopWatch.getLastTaskTimeMillis());
    }

    @Test
    public void testDict() {
        // String dictValue = DictUtils.getDictValue("query_pile_info", "url");
        // String station_type = DictUtils.getDictLabel("station_type", "1");
        // System.out.println(station_type);
        // System.out.println("123");

        List<SysDictData> adapay_station = DictUtils.getDictCache("adapay_station");
        List<String> stationIdList = com.google.common.collect.Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(adapay_station)) {
            for (SysDictData sysDictData : adapay_station) {
                stationIdList.add(sysDictData.getDictValue());
            }
        }
        System.out.println(stationIdList);
    }

    @Test
    public void testSelectByMerchantId() {
        List<PileStationInfo> list = pileStationInfoService.selectStationListByMerchantId(Long.valueOf(Constants.ONE));
        System.out.println(list);
    }

    @Test
    public void testStr2Bcd() {
        String logicCardNum = "00000000";
        byte[] logicCardNumByteArr = BytesUtil.str2Bcd(logicCardNum);
        System.out.println(Arrays.toString(logicCardNumByteArr));
    }

    @Test
    public void testBigDecimalMultiply() {
        BigDecimal a = new BigDecimal("216.5");
        BigDecimal b = new BigDecimal("11.5");

        BigDecimal result = a.multiply(b).setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println(result);
    }

    @Test
    public void testRemoteUpdate() {
        ArrayList<String> list = new ArrayList<>();
        list.add("88000000000001");
        // pileRemoteService.updateFirmware(list);
    }

    @Test
    public void testGetUserPhoneNum() {
        String code = "0e5394cfa4eb41c6181ed257f2368a86dfe4ebdac0a4fac85df63657637e6cc3";
        wxAppletRemoteService.getMobileNumberByCode(code);
    }

    @Test
    public void testDistance() {
        QueryStationDTO dto = new QueryStationDTO();
        dto.setStationLat("123.2222");
        dto.setStationLng("55.6232");

        // pileStationInfoService.uniAppQueryStationInfos(dto);
    }

    /**
     * 生成英文字母随机数  RandomStringUtils.randomAlphabetic(10);
     * 生成数字随机数 RandomStringUtils.randomNumeric(10);
     * 字母+数字结合  RandomStringUtils.randomAlphanumeric(10);
     */
    @Test
    public void Test() throws ParseException {
		/*String s = RandomStringUtils.randomAlphanumeric(32);
		System.out.println(s); // PuLe4Tyyg1jSFNPhF5d2Ts9ejRn6E8KQ
		String str = "JS160829";
		System.out.println(Md5Utils.hash(str).toUpperCase(Locale.ROOT));
*/
        String s = RandomStringUtils.randomAlphanumeric(16).toUpperCase(Locale.ROOT);
        System.out.println(s);

        Date startTimeDate = sdf.parse("2022-11-26 10:44:11");
        Date endTimeDate = sdf.parse("2022-11-27 12:45:11");

        System.out.println(DateUtils.getDatePoor(endTimeDate, startTimeDate)); // 1天2小时1分钟




		/*String stra = "sp_mchid=1632405339&sub_mchid=1632405339&out_trade_no=1217752501201407033233368318&sp_appid=wxbb3e0d474569481d&sub_appid=wxbb3e0d474569481d" +
				"bbac689f4654b209de4d6944808ec80b";
		System.out.println(Md5Utils.hash(stra).toUpperCase(Locale.ROOT));*/
    }

    @Test
    public void testSimCard() throws ParseException {
        ArrayList<String> list = Lists.newArrayList();
        Collections.addAll(list, "898607B9102090253556", "898607B9102090253560");
        // String s = list.toString().replaceAll("(?:\\[|null|\\]| +)", "");
        // System.out.println(s);
        // List<SimCardVO> simCardVOList = simCardService.selectSimCardInfoByIccId(list);
        // System.out.println(simCardVOList.toString());

        // simCardService.XunZhongSimRenewal(list, 12);
        // System.out.println(s);

        // SimCardVO simCardVO = simCardService.searchByLoop("898607B9102090253556");
        //
        // System.out.println(simCardVO.toString());

        simCardService.WuLianSimRenew(list, 1);


    }

    @Test
    public void testRefund() {
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode("88000000000001012212171045412218");
        orderInfo.setReason("充电异常中止，急停开入");

        TransactionRecordsData data = TransactionRecordsData.builder()
                .transactionCode("88000000000001012212171045412218")
                .consumptionAmount(String.valueOf(0.00))
                .stopReasonMsg(orderInfo.getReason())
                .totalElectricity("0")
                .sharpUsedElectricity("0")
                .peakUsedElectricity("0")
                .flatUsedElectricity("0")
                .valleyUsedElectricity("0")
                .build();

        // orderBasicInfoService.settleOrder(data, orderInfo);
    }


    @Test
    public void testLoginHandler() {
        String msg = "8800000000001001010f63362d333000000000898604b319227036282200";
        byte[] msgBody = BytesUtil.str2Bcd(msg);

        int startIndex = 0;
        int length = 7;

        // 桩编码
        byte[] pileSnByte = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileSn = BytesUtil.binary(pileSnByte, 16);
        // log.info("桩号：{}", pileSn);


        // 桩类型  0 表示直流桩， 1 表示交流桩
        startIndex += length;
        length = 1;
        byte[] pileTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String pileType = BytesUtil.bcd2Str(pileTypeByteArr);

        // 充电枪数量
        startIndex += length;
        byte[] connectorNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String connectorNum = BytesUtil.bcd2Str(connectorNumByteArr);

        // 通信协议版本  版本号乘 10，v1.0 表示 0x0A
        startIndex += length;
        byte[] communicationVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        // int i = Integer.parseInt(BytesUtil.bcd2Str(communicationVersionByteArr)); // 0F --> 15
        BigDecimal bigDecimal = new BigDecimal(BytesUtil.bcd2Str(communicationVersionByteArr));
        BigDecimal communicationVersionTemp = bigDecimal.divide(new BigDecimal(10));
        String communicationVersion = "v" + communicationVersionTemp;

        // 程序版本
        startIndex += length;
        length = 8;
        byte[] programVersionByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String programVersion = BytesUtil.bcd2Str(programVersionByteArr);

        // 网络连接类型  0x00 SIM 卡  0x01 LAN   0x02 WAN  0x03 其他
        startIndex += length;
        length = 1;
        byte[] internetConnectionTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String internetConnection = BytesUtil.bcd2Str(internetConnectionTypeByteArr);

        // sim卡
        startIndex += length;
        length = 10;
        byte[] simCardNumByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String iccid = BytesUtil.bin2HexStr(simCardNumByteArr);

        // 运营商  0x00 移动  0x02 电信  0x03 联通  0x04 其他
        startIndex += length;
        length = 1;
        byte[] businessTypeByteArr = BytesUtil.copyBytes(msgBody, startIndex, length);
        String business = BytesUtil.bcd2Str(businessTypeByteArr);

        LoginRequestData loginRequestData = LoginRequestData.builder()
                .pileSn(pileSn)
                .pileType(pileType)
                .connectorNum(connectorNum)
                .communicationVersion(communicationVersion)
                .programVersion(programVersion)
                .internetConnection(internetConnection)
                .iccid(iccid)
                .business(business)
                .build();

        // 结果（默认 0x01:登录失败）
        byte[] flag = Constants.oneByteArray;

        // 通过桩编码SN查询数据库，如果有数据，则登录成功，否则登录失败
        QueryPileDTO dto = new QueryPileDTO();
        dto.setPileSn(pileSn);
        List<PileDetailVO> list = pileBasicInfoService.queryPileInfos(dto);
        if (CollectionUtils.isNotEmpty(list)) {
            flag = Constants.zeroByteArray;
            // 登录成功，保存桩号和channel的关系

            // PileChannelEntity.put(pileSn, channel);
            // 更改桩和该桩下的枪口状态分别为 在线、空闲
            // pileBasicInfoService.updatePileStatus(pileSn, PileStatusEnum.ON_LINE.getValue());
            // pileConnectorInfoService.updateConnectorStatusByPileSn(pileSn, PileConnectorDataBaseStatusEnum.FREE.getValue());

            // 对时
            ProofreadTimeCommand command = ProofreadTimeCommand.builder().pileSn(pileSn).build();
            ykcPushCommandService.pushProofreadTimeCommand(command);

            // 公共方法修改状态
            pileBasicInfoService.updateStatus(BytesUtil.bcd2Str(new byte[]{0x01}), pileSn, null, null, null);


            // 下发二维码
            IssueQRCodeCommand issueQRCodeCommand = IssueQRCodeCommand.builder().pileSn(pileSn).build();
            ykcPushCommandService.pushIssueQRCodeCommand(issueQRCodeCommand);

        }


        // 充电桩使用的sim卡，把信息存库
        if (StringUtils.equals("00", internetConnection)) {
            try {
                pileBasicInfoService.updatePileSimInfo(pileSn, iccid);
            } catch (Exception e) {
                // log.error("更新充电桩sim卡信息失败", e);
                System.out.println(e.getMessage());
            }
        }

        // 保存报文
        String jsonMsg = JSONObject.toJSONString(loginRequestData);
        // pileMsgRecordService.save(pileSn, pileSn, type, jsonMsg, ykcDataProtocol.getHEXString());

        // // 消息体
        // byte[] messageBody = Bytes.concat(pileSnByte, flag);
        // return getResult(ykcDataProtocol, messageBody);
    }

    @Test
    public void testGetMemberToken() {
        String memberId = JWTUtils.getMemberId("eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2NzY1MTY5MzgsImV4cCI6MTY3OTEwODkzOH0.4MwhZIOpnCfQloR7zEm2hwPOh2yyI2qxbBbTcv_SnZ4");
        System.out.println(memberId);
    }

}
