@Override
 public void syncPayCancelLog(PayCancel payCancel) {
   PayCups payCups = payCupsService.findPayCups(payCancel.getPaycancelNo());
   if (payCups == null) {
     // throw new TransferFailedException(AppExCode.TRANS_NOT_EXIST, "sysncPayLog failed,not find
     // payCups");
     payCancel.setTransStatus(Const.TransStatus.FAILED); // 银联直连表无交易流水记录,未发交易,撤销失败
     return;
   }
   // 如果iso中心已经返回,但app与xposp已经断开
   String isoRespCode = payCups.getRespCode();
   if (StringUtils.isNotBlank(isoRespCode)) {
     // modify zengyj 20140716 服务端到银联已经响应成功,但客户端因超时交易未知
     if (Const.ISO_RESPCODE_OK.equals(isoRespCode)) {
       payCancel.setTransStatus(Const.TransStatus.SUCCESS);
     } else {
       payCancel.setTransStatus(Const.TransStatus.FAILED);
       isoRespCode =
           Const.TP_BEGIN_ISO + StringUtils.leftPad("" + Integer.parseInt(isoRespCode), 3, "0");
       payCancel.setErrCode(isoRespCode);
     }
     return;
   }
   CupsTrmnl cupsTrmnl =
       cupsTrmnlService.findByTrmnlNoAndMrchNo(payCups.getTrmnlNo(), payCups.getTrmnlMrchNo());
   if (cupsTrmnl == null) {
     throw new TransferFailedException(
         AppExCode.TERMINAL_NOT_EXIST, "goodee sysncPayLog failed,not find CupsTrmnl");
   }
   reversalProcess.process(cupsTrmnl, payCups, getAddress(payCancel.getAppAccessId()));
   payCancel.setTransStatus(TransStatus.FAILED);
 }
 @Override
 public BillInfo findBillInfo(String payNo) {
   PayCups payCups = payCupsService.findPayCups(payNo);
   if (payCups == null) {
     throw new AppRTException(AppExCode.TRANS_NOT_EXIST, "payCups[" + payNo + "] not exist");
   }
   BillInfo billInfo = new BillInfo(payCups);
   return billInfo;
 }
  @Override
  public void insertPayCupsFlow(SendFlowCondition condition) {

    logger.info("[开始将t_pay_cups 表中的流水写入到t_history表中!]");
    // 查出paycup表中满足条件的数据
    PayCupsCondition payCupsCondition = new PayCupsCondition();
    payCupsCondition.setBeginDate(condition.getStartDate());
    payCupsCondition.setEndDate(condition.getEndDate());
    payCupsCondition.setTransType(condition.getTransType());
    // 分页的参数
    Page<PayCups> payCupsPage =
        payCupsService.queryPayCupsByCondition(payCupsCondition, 0, EVERY_PAGE_NUMBER);
    int startIndexCups = 0;
    int totalCups = payCupsPage.getTotalCount();
    int countTimeCups =
        totalCups % EVERY_PAGE_NUMBER > 0
            ? (totalCups / EVERY_PAGE_NUMBER) + 1
            : (totalCups / EVERY_PAGE_NUMBER);

    if (totalCups <= 0) {
      logger.error(
          "[将t_pay_cups 表中的流水写入到t_history表失败,指定查询周期("
              + condition.getStartDate()
              + ")到("
              + condition.getEndDate()
              + ") t_pay_cups 中无流水记录!]");
      return;
    }
    // 分页查询
    for (int i = 0; i < countTimeCups; i++) {
      List<PayCups> payCupsList = new ArrayList<PayCups>();
      List<SendFlow> flowList = new LinkedList<SendFlow>();
      payCupsList =
          payCupsService
              .queryPayCupsByCondition(payCupsCondition, startIndexCups, EVERY_PAGE_NUMBER)
              .getItems();
      flowList = insertPayCups(payCupsList);
      startIndexCups = startIndexCups + EVERY_PAGE_NUMBER;
      sendFlowDao.saveAll(flowList);
      logger.info("[payCups分页第" + (i + 1) + "页同步完成...]");
    }
    logger.info("[将t_pay_cups 表中的流水写入到t_history表完成!]");
  }
  private IcScriptUploadTradeRequestEntity packUp(
      CupsTrmnl cupsTrmnl, CupsKeyManage cupsKeyManage, PepsiColaRequestInfo request)
      throws TransferFailedException {
    if (request.getIcScript() == null) {
      throw new TransferFailedException(
          AppExCode.ILLEGAL_PARAMS, "isScript upload failed! IcScript objet is null");
    }
    PayCups originalPayCups = payCupsService.findPayCups(request.getOriginalPayNo());
    // 脚本上送打包
    IcScriptUploadTradeRequestEntity entity = new IcScriptUploadTradeRequestEntity();
    entity.setCardNo(originalPayCups.getCardNo()); // 2 卡号
    entity.setProcessCode(originalPayCups.getProcessCode()); // 3 未选卡种
    String amount = null;
    if (originalPayCups.getTransAmt() != null
        || BigDecimal.ZERO.compareTo(originalPayCups.getTransAmt()) != 0) {
      amount = com.newland.base.util.StringUtils.amtToBCD(originalPayCups.getTransAmt());
    }
    entity.setTransAmt(amount); // 4 交易金额
    entity.setTrmnlFlowNo(cupsTrmnl.getTrmnlFlowNo()); // 11 终端流水号
    entity.setPosEntryMode(originalPayCups.getPosEntryMode()); // 22 卡输入方式
    if (StringUtils.isBlank(originalPayCups.getIcData())) { // 磁条卡
      entity.setSelfDefined60(
          Const.SD60_1_MSGTYPE_CONTROL
              + cupsTrmnl.getTrmnlBatchNo()); // 60 自定义域 22(交易类型码)+000001(批次号)+000(网络管理信息码)
    } else { // IC卡
      entity.setCardSeqNum(originalPayCups.getCardSeqNum()); // IC卡必须上送该域
      byte[] icData = getIcData(originalPayCups.getIcData(), request.getIcScript());
      entity.setIcData(icData); // 55 IC卡数据
      String selfDefined60 =
          Const.SD60_1_MSGTYPE_CONTROL
              + cupsTrmnl.getTrmnlBatchNo()
              + Const.SD60_3_IC_CRIPT_UPLOAD
              + Const.SD60_4_TERMINAL_READING_ABILITY_CONTACT_ICCARD
              + Const.SD60_5_IC_SERVICE_CODE_NORMAL;
      entity.setSelfDefined60(selfDefined60);
    }
    entity.setTrmnlRefferNo(originalPayCups.getTrmnlReferNo()); // 37
    entity.setTrmnlNo(originalPayCups.getTrmnlNo()); // 41 终端号
    entity.setTrmnlMrchNo(originalPayCups.getTrmnlMrchNo()); // 42 终端商户号
    entity.setCurrency(originalPayCups.getCurrency()); // 49 货币代码
    entity.setOriginalMessage(
        originalPayCups.getTrmnlBatchNo()
            + originalPayCups.getTrmnlFlowNo()
            + originalPayCups.getTransDate()); // 61 原批次号+原流水号
    entity.setMacCode(new byte[8]); // 64 mac

    return entity;
  }
 @Override
 public void syncCashLoadLog(PayCashLoad cashLoad, Integer appSyn) {
   PayCups payCups = payCupsService.findPayCups(cashLoad.getCashLoadNo());
   if (payCups == null) {
     // throw new TransferFailedException(AppExCode.TRANS_NOT_EXIST, "sysncPayLog failed,not find
     // payCups");
     cashLoad.setTransStatus(Const.TransStatus.FAILED); // 银联直连表无交易流水记录,未发交易,消费失败
     return;
   }
   if (appSyn == null) {
     // 如果iso中心已经返回,但app与xposp已经断开,写卡失败
     String isoRespCode = payCups.getRespCode();
     if (StringUtils.isNotBlank(isoRespCode)) {
       // 服务端到银联已经响应成功,但客户端因超时交易未知
       if (Const.ISO_RESPCODE_OK.equals(isoRespCode)) {
         cashLoad.setTransStatus(Const.TransStatus.SUCCESS);
       } else {
         cashLoad.setTransStatus(Const.TransStatus.FAILED);
         isoRespCode =
             Const.TP_BEGIN_ISO
                 + StringUtils.leftPad(
                     "" + Integer.parseInt(isoRespCode.replace("A", "10")), 3, "0");
         cashLoad.setErrCode(isoRespCode);
       }
       return;
     }
   }
   CupsTrmnl cupsTrmnl =
       cupsTrmnlService.findByTrmnlNoAndMrchNo(payCups.getTrmnlNo(), payCups.getTrmnlMrchNo());
   if (cupsTrmnl == null) {
     throw new TransferFailedException(
         AppExCode.TERMINAL_NOT_EXIST, "sysncPayLog failed,not find CupsTrmnl");
   }
   reversalProcess.process(cupsTrmnl, payCups);
   cashLoad.setTransStatus(TransStatus.FAILED);
 }
  @Override
  public boolean icScriptUpload(ICScriptUploadRequest request) {
    boolean isIcScriptUloadSuccess = false;
    List<ICScript> lists = request.getIcScripts();
    for (ICScript temp : lists) {
      if (temp == null) {
        continue;
      }
      // 获取原始交易信息
      String originalPayNo = temp.getTransRefNo();
      if (StringUtils.isEmpty(originalPayNo)) {
        throw new TransferFailedException(
            AppExCode.ILLEGAL_PARAMS,
            "goodee isScript upload failed! not find original payNo[" + originalPayNo + "]");
      }
      PayCups originalPayCups = payCupsService.findPayCups(originalPayNo);
      if (originalPayCups == null) {
        throw new TransferFailedException(
            AppExCode.TRANS_NOT_EXIST,
            "goodee isScript upload failed! not find original payNo[" + originalPayNo + "]");
      }
      int transTypeInt = originalPayCups.getTransType();
      if (!(TransType.CONSUME.getOrdinal() == transTypeInt
          || TransType.BALANCE.getOrdinal() == transTypeInt)) {
        throw new TransferFailedException(
            AppExCode.NOT_SUPPORTED_OPERATION,
            getDescription()
                + " channel not support icsSriptUpload["
                + transTypeInt
                + "] operation");
      }
      CupsTrmnl cupsTrmnl =
          cupsTrmnlService.findByTrmnlNoAndMrchNo(
              originalPayCups.getTrmnlNo(), originalPayCups.getTrmnlMrchNo());
      PaySignUp paySignUp =
          paySignUpService.findPaySignUpByMrchNoAndTrmnlNo(
              originalPayCups.getTrmnlMrchNo(), originalPayCups.getTrmnlNo());
      CupsKeyManage cupsKeyManage = new CupsKeyManage();
      cupsKeyManage.setTrmnlMacKey(paySignUp.getTrmnlMacKey());
      // 保存二次授权数据
      JSONObject json = JSONObject.fromObject(temp);
      originalPayCups.setIcScriptRlst(json.toString());
      originalPayCups = payCupsService.updatePayCups(originalPayCups);

      // 如果二次授权失败,则发起冲正交易,成功则保存二次授权数据,并且如果有脚本则上送脚本交易
      if (temp.getSecondAuthRlst() != null && temp.getSecondAuthRlst() == false) {
        // reversalProcess.process(cupsTrmnl, originalPayCups);
      } else {
        if (StringUtils.isNotEmpty(temp.getScriptExecuteRslt())) {
          CupsRequestInfo requestInfo = new CupsRequestInfo();
          requestInfo.setOriginalPayNo(temp.getTransRefNo());
          requestInfo.setIcScript(temp);
          try {
            icScriptUploadProcess.process(cupsTrmnl, cupsKeyManage, requestInfo);
          } catch (TransferFailedException e) {
            throw e;
          }
        }
      }
    }
    isIcScriptUloadSuccess = true;
    return isIcScriptUloadSuccess;
  }
  @Override
  public void refund(Device device, PayRefund refund, RefundRequest request)
      throws TransferFailedException {
    logger.info("entryMode:" + request.getEntryMode());
    logger.info("Pinblock is not null:" + StringUtils.isNotBlank(request.getPinblock()));
    logger.info("EmvTransInfo is not null:" + StringUtils.isNotBlank(request.getEmvTransInfo()));

    // 校验数据
    if (StringUtils.isBlank(request.getTrack2Data())
        && StringUtils.isBlank(request.getTrackData())) {
      throw new TransferFailedException(
          AppExCode.ILLEGAL_PARAMS, "goodee refund failed,track2data or trackData null");
    }
    // 卡输入方式
    if (StringUtils.isNotBlank(request.getEntryMode())) {
      boolean isOk =
          isEntryModeOk(request.getEntryMode(), request.getPinblock(), request.getEmvTransInfo());
      if (!isOk) {
        throw new TransferFailedException(
            AppExCode.ILLEGAL_PARAMS,
            "goodee refund failed,entryMode is "
                + request.getEntryMode()
                + " but pinBlock is not null:"
                + StringUtils.isNotBlank(request.getPinblock())
                + " ,emvTransInfo is not null:"
                + StringUtils.isNotBlank(request.getEmvTransInfo()));
      }
    }
    // modify by zengyj 20140331 cancel by orginal trmnl not by device trmnl;
    // 获取当前设备的终端信息
    PayCups originalPayCups = payCupsService.findPayCups(request.getLastTransRefNo());
    if (originalPayCups == null) {
      throw new TransferFailedException(
          AppExCode.TRANS_NOT_EXIST, "goodee refund failed,not find originalPayCups");
    }
    CupsTrmnl cupsTrmnl =
        cupsTrmnlService.findByTrmnlNoAndMrchNo(
            originalPayCups.getTrmnlNo(), originalPayCups.getTrmnlMrchNo());
    if (cupsTrmnl == null) {
      throw new TransferFailedException(
          AppExCode.TERMINAL_NOT_EXIST, "goodee refund failed,not find CupsTrmnl");
    }
    // 获取密钥信息
    DeviceKeymanage deviceKeymanage =
        deviceKeymanageService.findDeviceKeymanageByDevId(device.getDevId());
    if (deviceKeymanage == null) {
      throw new TransferFailedException(
          AppExCode.DEVICE_KEY_NOT_EXIST, "goodee refund failed,not find deviceKeymanage info");
    }
    PaySignUp paySignUp =
        paySignUpService.findPaySignUpByMrchNoAndTrmnlNo(
            cupsTrmnl.getMrchNo(), cupsTrmnl.getTrmnlNo());
    if (paySignUp == null) {
      throw new TransferFailedException(
          AppExCode.TERMINAL_KEY_NOT_EXIST, "goodee refund failed,not find cups signUp info");
    }
    // 密钥体系转换
    CupsKeyManage cupsKeyManage = new CupsKeyManage();
    cupsKeyManage.setDevPinKey(deviceKeymanage.getPinkey());
    cupsKeyManage.setTrmnlPinKey(paySignUp.getTrmnlPinKey());
    cupsKeyManage.setTrmnlMacKey(paySignUp.getTrmnlMacKey());
    // CUPS请求信息
    CupsRequestInfo requestInfo = new CupsRequestInfo();
    requestInfo.setPayNo(refund.getPayrefundNo());
    requestInfo.setAmount(refund.getPayAmt());
    requestInfo.setOriginalPayNo(request.getLastTransRefNo());
    requestInfo.setPinblock(request.getPinblock());
    requestInfo.setEmvTransInfo(request.getEmvTransInfo());
    requestInfo.setCardSeqNum(request.getCardSeqNum());
    requestInfo.setExtFld01(request.getStoreNo());
    requestInfo.setOrderNo(request.getOrderNo());
    try {
      TrackContext trackContext =
          getTrackData(deviceKeymanage.getDatakey(), request.getTrackData());
      requestInfo.setCardNo(trackContext.getTrack2Data().split("=")[0]);
      requestInfo.setTrack2Data(trackContext.getTrack2Data());
      requestInfo.setTrack3Data(trackContext.getTrack3Data());
    } catch (HSMException e) {
      String hsmRespCode = XPOSPClientUtils.getCode(e);
      if (!AppExCode.UNKNOWN.equals(hsmRespCode)) {
        hsmRespCode = Const.TP_BEGIN_HSM + hsmRespCode;
      }
      throw new TransferFailedException(
          hsmRespCode,
          "goodee refund failed, when descrypt track data form hsm error code["
              + hsmRespCode
              + "]");
    }
    try {
      refundProcess.process(
          cupsTrmnl, cupsKeyManage, requestInfo, getAddress(refund.getAppAccessId()));
    } catch (TransferFailedException e) {
      String errorCode = XPOSPClientUtils.getCode(e);
      processErrorCode(errorCode, cupsTrmnl);
      throw e;
    }
    // 如果没有抛异常,则交易成功
    refund.setTransStatus(Const.TransStatus.SUCCESS);
  }
  public PepsiColaResponseInfo process(
      CupsTrmnl cupsTrmnl, CupsKeyManage cupsKeyManage, PepsiColaRequestInfo request)
      throws TransferFailedException {
    logger.info("[PepsiCola渠道IC卡脚本上送开始...]");
    // 1.组装报文
    IcScriptUploadTradeRequestEntity requestEntity = packUp(cupsTrmnl, cupsKeyManage, request);
    // iso mac计算
    byte[] iso_8583_main = requestEntity.pack();
    byte[] input = ArrayUtils.subarray(iso_8583_main, 6, iso_8583_main.length - 8);
    byte[] macKey = CodecUtils.hex2byte(cupsKeyManage.getTrmnlMacKey());
    byte[] mac;
    try {
      mac = hsmService.calculateMAC_CUPS(macKey, input).getBytes();
      input = ArrayUtils.subarray(iso_8583_main, 0, iso_8583_main.length - 8);
      iso_8583_main = ArrayUtils.addAll(input, mac);
    } catch (HSMException e) {
      String hsmRespCode = XPOSPClientUtils.getCode(e);
      if (!AppExCode.UNKNOWN.equals(hsmRespCode)) {
        hsmRespCode = Const.TP_BEGIN_HSM + hsmRespCode;
      }
      logger.error("[IC卡脚本上送失败,calculate mac form hsm error code:" + hsmRespCode + "]");
      throw new TransferFailedException(
          hsmRespCode, "[IC卡脚本上送失败, 加密机计算MAC失败, errorCode:" + hsmRespCode + "]");
    }

    // 组装报文报文头
    byte[] iso_8583_body =
        ArrayUtils.addAll(
            XPOSPClientUtils.getTpduHeader(XpospSysProperty.getPepsiColaTPDU()).pack(),
            iso_8583_main);
    String iso_8583_body_length =
        StringUtils.leftPad(Integer.toHexString(iso_8583_body.length), 4, "0");
    byte[] iso_8583_length = ISOUtils.hex2byte(iso_8583_body_length);
    byte[] iso_8583 = ArrayUtils.addAll(iso_8583_length, iso_8583_body);

    // 新增银联CUPS流水记录 {2,3,4,11,22,25,26,35,36,41,42,49,52,53,60,64}
    String payNo = transRefNoGenerator.generate();
    PayCups payCups = new PayCups();
    payCups.setPayNo(payNo);
    payCups.setCardNo(requestEntity.getCardNo());
    payCups.setProcessCode(requestEntity.getProcessCode());
    payCups.setTrmnlFlowNo(requestEntity.getTrmnlFlowNo());
    payCups.setTrmnlBatchNo(cupsTrmnl.getTrmnlBatchNo());
    payCups.setPosEntryMode(requestEntity.getPosEntryMode());
    payCups.setCardSeqNum(request.getCardSeqNum());
    payCups.setTrmnlNo(requestEntity.getTrmnlNo());
    payCups.setTrmnlMrchNo(requestEntity.getTrmnlMrchNo());
    payCups.setCurrency(requestEntity.getCurrency());
    payCups.setIcData(request.getEmvTransInfo());
    payCups.setSelfDefined060(requestEntity.getSelfDefined60());
    payCups.setOriginalInfo(requestEntity.getOriginalMessage());
    payCups.setTransType(TransType.ICSCRIPTUPLOAD.getOrdinal());
    payCups.setSubChannel(SubChannelType.PEPSICOLATRANSFERCHANNEL.getChannelName());
    payCupsService.addPayCups(payCups);
    // 打包,新增流水记录后更新终端流水信息
    cupsTrmnlService.updateCupsTrmnlFlowNo(cupsTrmnl);

    // 2.发送报文
    byte[] respData =
        TCPUtils.getInstance().sendReciveMsg(iso_8583, XpospSysProperty.getPepsiColaIP_PORT());

    // 3.解析报文
    PepsiColaResponseInfo pepsiColaResponseInfo = new PepsiColaResponseInfo();
    try {
      IcScriptUploadTradeResponseEntity responseEntity = unpack(respData);
      String isoRespCode = responseEntity.getRespCode();
      if (!Const.ISO_RESPCODE_OK.equals(isoRespCode)) {
        payCups.setRespCode(isoRespCode);
        isoRespCode = isoRespCode.replace("A", "10");
        payCupsService.updatePayCups(payCups);
        isoRespCode =
            Const.TP_BEGIN_ISO + StringUtils.leftPad("" + Integer.parseInt(isoRespCode), 3, "0");

        logger.error("[pay via cups failed, iso error code:" + isoRespCode + "]");
        throw new TransferFailedException(
            isoRespCode, "[pay via cups failed, so error code:" + isoRespCode + "]");
      }

      // 更新交易流水
      payCups.setTransDate(responseEntity.getTransDate());
      payCups.setTransTime(responseEntity.getTransTime());
      payCups.setSettlementDate(responseEntity.getSettlementDate());
      payCups.setRespCode(responseEntity.getRespCode());
      payCupsService.updatePayCups(payCups);

      pepsiColaResponseInfo.setTransCode(
          Const.TP_BEGIN_ISO + StringUtils.leftPad("" + Integer.parseInt(isoRespCode), 3, "0"));
      // 响应
    } catch (RuntimeException e) {
      throw e;
    }
    logger.info("[PepsiCola渠道IC卡脚本上送结束...]");
    return pepsiColaResponseInfo;
  }