public void generateTransferRepay( List<InvestRepay> investRepays, Invest invest, double corpusRate) { for (Iterator iterator = investRepays.iterator(); iterator.hasNext(); ) { InvestRepay ir = (InvestRepay) iterator.next(); if (ir.getStatus().equals(RepayStatus.WAIT_REPAY_VERIFY) || ir.getStatus().equals(RepayStatus.OVERDUE) || ir.getStatus().equals(RepayStatus.BAD_DEBT)) { throw new RuntimeException( "investRepay with status " + RepayStatus.WAIT_REPAY_VERIFY + "exist!"); } else if (ir.getStatus().equals(RepayStatus.REPAYING)) { // 根据购买本金比例,生成债权还款信息 InvestRepay irNew = new InvestRepay(); try { BeanUtils.copyProperties(irNew, ir); } catch (Exception e) { throw new RuntimeException(e); } irNew.setId(IdGenerator.randomUUID()); irNew.setCorpus(ArithUtil.mul(ir.getCorpus(), corpusRate, 2)); irNew.setDefaultInterest(ArithUtil.mul(ir.getDefaultInterest(), corpusRate, 2)); irNew.setFee(ArithUtil.mul(ir.getFee(), corpusRate, 2)); irNew.setInterest(ArithUtil.mul(ir.getInterest(), corpusRate, 2)); irNew.setInvest(invest); // 修改原投资的还款信息 ir.setCorpus(ArithUtil.sub(ir.getCorpus(), irNew.getCorpus())); ir.setDefaultInterest(ArithUtil.sub(ir.getDefaultInterest(), irNew.getDefaultInterest())); ir.setFee(ArithUtil.sub(ir.getFee(), irNew.getFee())); ir.setInterest(ArithUtil.sub(ir.getInterest(), irNew.getInterest())); ht.merge(irNew); if (corpusRate == 1) { ht.delete(ir); iterator.remove(); } else { ht.update(ir); } } } }
@Override @Transactional(rollbackFor = Exception.class) public TrusteeshipOperation createOperation(Invest invest, FacesContext fc) throws IOException { String transferApplyId = invest.getTransferApply().getId(); // 购买债权人的id String userId = invest.getUser().getId(); // 购买的债权本金 transferCorpus(投资时填写的投资额) double transferCorpus = invest.getInvestMoney(); double remainCorpus = transferService.calculateRemainCorpus(transferApplyId); if (transferCorpus <= 0 || transferCorpus > remainCorpus) { throw new YeePayOperationException("购买本金必须小于等于" + remainCorpus + "且大于0"); } TransferApply ta = ht.get(TransferApply.class, transferApplyId); // 购买的本金占剩余本金的比例corpusRate double corpusRate = ArithUtil.div(transferCorpus, remainCorpus); // 购买的本金占所有转让本金的比例corpusRateInAll double corpusRateInAll = ArithUtil.div(transferCorpus, ta.getCorpus()); // 投资人实际出的钱=债权的购买金额=债权转出价格*corpusRateInAll (债权转出价格=本金-折让金) double buyPrice = ArithUtil.mul(ta.getPrice(), corpusRateInAll, 2); if (buyPrice > userBillBO.getBalance(userId)) { throw new YeePayOperationException("余额不足。"); } // 购买时候,扣除手续费,从转让人收到的金额中扣除。费用根据购买价格计算 double fee = feeConfigBO.getFee(FeePoint.TRANSFER, FeeType.FACTORAGE, null, null, buyPrice); Invest investNew = new Invest(); investNew.setId(IdGenerator.randomUUID()); investNew.setMoney(transferCorpus); investNew.setStatus(InvestConstants.InvestStatus.CANCEL); investNew.setRate(ta.getInvest().getRate()); investNew.setTransferApply(ta); investNew.setLoan(ta.getInvest().getLoan()); investNew.setTime(new Date()); investNew.setUser(new User(userId)); investNew.setInvestMoney(transferCorpus); // 在这里添加投标状态是手动投标 investNew.setIsAutoInvest(false); ht.save(investNew); ht.update(ta); DecimalFormat currentNumberFormat = new DecimalFormat("#0.00"); // 构建投资参数实体 CPTransaction cp = new CPTransaction(); cp.setNotifyUrl( YeePayConstants.ResponseS2SUrl.PRE_RESPONSE_URL + YeePayConstants.OperationType.TRANSFER); cp.setCallbackUrl( YeePayConstants.ResponseWebUrl.PRE_RESPONSE_URL + YeePayConstants.OperationType.TRANSFER); // cp.setExpired(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(DateUtil.addMinute(new // Date(), 10))); cp.setRequestNo(YeePayConstants.RequestNoPre.TRANSFER + investNew.getId()); cp.setPlateformNo(YeePayConstants.Config.MER_CODE); cp.setPlatformUserNo(userId); cp.setBizType(YeepayCpTransactionConstant.CREDIT_ASSIGNMENT.name()); cp.setUserType("MEMBER"); // 资金明细 FundDetail fd = new FundDetail(); // 给转让债权的人的钱 fd.setAmount(currentNumberFormat.format(buyPrice - fee)); fd.setTargetPlatformUserNo(ta.getInvest().getUser().getId()); fd.setTargetUserType("MEMBER"); fd.setBizType(YeepayCpTransactionConstant.CREDIT_ASSIGNMENT.name()); cp.getFundDetails().add(fd); // 平台分润 if (fee > 0.0) { fd = new FundDetail(); // 投资人给平台的钱=fee fd.setAmount(currentNumberFormat.format(fee)); fd.setTargetPlatformUserNo(YeePayConstants.Config.MER_CODE); fd.setTargetUserType("MERCHANT"); fd.setBizType(YeepayCpTransactionConstant.COMMISSION.name()); cp.getFundDetails().add(fd); } // 扩展参数 Extend extend = new Extend(); Loan loan = ta.getInvest().getLoan(); extend.setTenderOrderNo(loan.getId()); extend.setCreditorPlatformUserNo(ta.getInvest().getUser().getId()); // 判断购买的债券是否是自动投标 if (ta.getInvest().getIsAutoInvest()) { extend.setOriginalRequestNo( YeePayConstants.RequestNoPre.AUTO_INVEST + ta.getInvest().getId()); } else { extend.setOriginalRequestNo(YeePayConstants.RequestNoPre.INVEST + ta.getInvest().getId()); } cp.setExtend(extend); log.debug(cp.toString()); Map<String, String> params = new HashMap<String, String>(); params.put("req", cp.toString()); String sign = CFCASignUtil.sign(cp.toString()); params.put("sign", sign); // 保存本地 TrusteeshipOperation to = new TrusteeshipOperation(); to.setId(IdGenerator.randomUUID()); to.setMarkId(investNew.getId()); to.setOperator(Double.toString(buyPrice) + "&" + Double.toString(corpusRate) + "&" + userId); to.setRequestUrl(YeePayConstants.RequestUrl.TRANSFER); to.setRequestData(MapUtil.mapToString(params)); to.setStatus(TrusteeshipConstants.Status.UN_SEND); to.setType(YeePayConstants.OperationType.TRANSFER); to.setTrusteeship("yeepay"); trusteeshipOperationBO.save(to); try { // 发送信息 sendOperation(to.getId(), "utf-8", fc); } catch (IOException e) { e.printStackTrace(); } return null; }
@Transactional(readOnly = false, rollbackFor = Exception.class) public void normalRepay(LoanRepay repay, String repayerId) throws InsufficientBalance, NormalRepayException { ht.evict(repay); repay = ht.get(LoanRepay.class, repay.getId(), LockMode.UPGRADE); // 正常还款 if (!(repay.getStatus().equals(LoanConstants.RepayStatus.REPAYING) && !(repay.getStatus().equals(LoanConstants.RepayStatus.REPAYING_BACK)))) { // 该还款不处于正常还款状态。 throw new NormalRepayException("还款:" + repay.getId() + "不处于正常还款状态。"); } List<InvestRepay> irs = ht.find( "from InvestRepay ir where ir.invest.loan.id=? and ir.period=?", new Object[] {repay.getLoan().getId(), repay.getPeriod()}); // TODO:投资的所有还款信息加和,判断是否等于借款的还款信息,如果不相等,抛异常 // 更改投资的还款信息 for (InvestRepay ir : irs) { ir.setStatus(LoanConstants.RepayStatus.COMPLETE); ir.setTime(new Date()); ht.update(ir); userBillBO.transferIntoBalance( ir.getInvest().getUser().getId(), ArithUtil.add(ir.getCorpus(), ir.getInterest()), OperatorInfo.NORMAL_REPAY, "投资:" + ir.getInvest().getId() + "收到还款, 还款ID:" + repay.getId() + " 借款ID:" + repay.getLoan().getId() + " 本金:" + ir.getCorpus() + " 利息:" + ir.getInterest()); if (ir.getCorpusToSystem() != null && ir.getCorpusToSystem() != 0) { // 系统回收体验金 systemBillService.transferInto( ir.getCorpusToSystem(), OperatorInfo.NORMAL_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,回收体验金, 还款ID:" + repay.getId()); } // 投资者手续费 userBillBO.transferOutFromBalance( ir.getInvest().getUser().getId(), ir.getFee(), OperatorInfo.NORMAL_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,扣除手续费, 还款ID:" + repay.getId()); systemBillService.transferInto( ir.getFee(), OperatorInfo.NORMAL_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,扣除手续费, 还款ID:" + repay.getId() + ",项目ID:" + ir.getInvest().getLoan().getId()); } try { cancelTransfering(repay.getLoan().getId()); } catch (RepayException e) { throw new NormalRepayException(e.getMessage(), e.getCause()); } // 更改借款的还款信息 double payMoney = ArithUtil.add(ArithUtil.add(repay.getCorpus(), repay.getInterest()), repay.getFee()); repay.setTime(new Date()); repay.setStatus(LoanConstants.RepayStatus.COMPLETE); // 记录repayWay信息,还款者id,如果有此id,则为代偿 repay.setRepayWay(repayerId); // 借款者的账户,扣除还款。 userBillBO.transferOutFromBalance( repayerId, payMoney, OperatorInfo.NORMAL_REPAY, "借款:" + repay.getLoan().getId() + "正常还款, 还款ID:" + repay.getId() + " 本金:" + repay.getCorpus() + " 利息:" + repay.getInterest() + " 手续费:" + repay.getFee()); // 借款者手续费 systemBillService.transferInto( repay.getFee(), OperatorInfo.NORMAL_REPAY, "项目ID:" + repay.getLoan().getId() + "正常还款,扣除手续费, 还款ID:" + repay.getId()); ht.merge(repay); // 如果不是自己还款,则产生代偿 if (!repay.getLoan().getUser().getId().equals(repayerId)) { RepayCompensation rc = new RepayCompensation(); rc.setId(IdGenerator.randomUUID()); rc.setLoanRepay(repay); rc.setRepayer(new User(repayerId)); rc.setCompensateTime(new Date()); rc.setStatus(CompensationStatus.COMPENSATED); ht.save(rc); } // 判断是否所有还款结束,更改等待还款的投资状态和还款状态,还有项目状态。 loanService.dealComplete(repay.getLoan().getId()); }
@Transactional(rollbackFor = Exception.class) public void overdueRepay(String repayId, String repayerId) throws InsufficientBalance, OverdueRepayException { LoanRepay lr = ht.get(LoanRepay.class, repayId); ht.evict(lr); lr = ht.get(LoanRepay.class, repayId, LockMode.UPGRADE); if (lr.getStatus().equals(LoanConstants.RepayStatus.OVERDUE) || lr.getStatus().equals(LoanConstants.RepayStatus.BAD_DEBT) || lr.getStatus().equals(RepayStatus.WAIT_REPAY_VERIFY)) { List<InvestRepay> irs = ht.find( "from InvestRepay ir where ir.invest.loan.id=? and ir.period=?", new Object[] {lr.getLoan().getId(), lr.getPeriod()}); double defaultInterest = lr.getDefaultInterest(); HashSet<Invest> invests = new HashSet<Invest>(); // 更改投资的还款信息 for (InvestRepay ir : irs) { ir.setStatus(LoanConstants.RepayStatus.COMPLETE); ir.setTime(new Date()); ht.update(ir); invests.add(ir.getInvest()); userBillBO.transferIntoBalance( ir.getInvest().getUser().getId(), ArithUtil.add(ir.getCorpus(), ir.getInterest(), ir.getDefaultInterest()), OperatorInfo.OVERDUE_REPAY, "投资:" + ir.getInvest().getId() + "收到还款, 还款ID:" + lr.getId() + " 借款ID:" + lr.getLoan().getId() + " 本金:" + ir.getCorpus() + " 利息:" + ir.getInterest() + " 罚息:" + ir.getDefaultInterest()); // 系统回收体验金 if (ir.getCorpusToSystem() != null && ir.getCorpusToSystem() > 0) { systemBillService.transferInto( ir.getCorpusToSystem(), OperatorInfo.OVERDUE_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,回收体验金, 还款ID:" + ir.getId()); } defaultInterest = ArithUtil.sub(defaultInterest, ir.getDefaultInterest()); // 投资者手续费 userBillBO.transferOutFromBalance( ir.getInvest().getUser().getId(), ir.getFee(), OperatorInfo.OVERDUE_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,扣除手续费, 还款ID:" + lr.getId()); systemBillService.transferInto( ir.getFee(), OperatorInfo.OVERDUE_REPAY, "投资:" + ir.getInvest().getId() + "收到还款,扣除手续费, 还款ID:" + lr.getId() + ",项目ID:" + ir.getInvest().getLoan().getId()); } // 更改借款的还款信息 double payMoney = ArithUtil.add( ArithUtil.add(lr.getCorpus(), lr.getInterest()), lr.getFee(), lr.getDefaultInterest()); lr.setTime(new Date()); lr.setStatus(LoanConstants.RepayStatus.COMPLETE); // 记录repayWay信息,还款者id,如果有此id,则为代偿 lr.setRepayWay(repayerId); // 代偿账户,扣除还款。 userBillBO.transferOutFromBalance( repayerId, payMoney, OperatorInfo.OVERDUE_REPAY, "借款:" + lr.getLoan().getId() + "逾期还款, 还款ID:" + lr.getId() + " 本金:" + lr.getCorpus() + " 利息:" + lr.getInterest() + " 手续费:" + lr.getFee() + " 罚息:" + lr.getDefaultInterest()); // 借款者手续费 systemBillService.transferInto( lr.getFee(), OperatorInfo.OVERDUE_REPAY, "项目ID:" + lr.getLoan().getId() + "逾期还款,扣除手续费, 还款ID:" + lr.getId()); // 罚息转入网站账户 systemBillService.transferInto( defaultInterest, OperatorInfo.OVERDUE_REPAY, "项目ID:" + lr.getLoan().getId() + "逾期还款,扣除罚金, 还款ID:" + lr.getId()); ht.merge(lr); Long count = (Long) ht.find( "select count(repay) from LoanRepay repay where repay.loan.id=? and (repay.status=? or repay.status=?)", lr.getLoan().getId(), RepayStatus.OVERDUE, RepayStatus.BAD_DEBT) .get(0); if (count == 0) { // 如果没有逾期或者坏账的还款,则更改借款状态。 lr.getLoan().setStatus(LoanStatus.REPAYING); ht.update(lr.getLoan()); for (Invest invest : invests) { invest.setStatus(InvestStatus.REPAYING); ht.update(invest); } } // 如果不是自己还款,则产生代偿 if (!lr.getLoan().getUser().getId().equals(repayerId)) { RepayCompensation rc = new RepayCompensation(); rc.setId(IdGenerator.randomUUID()); rc.setLoanRepay(lr); rc.setRepayer(new User(repayerId)); rc.setCompensateTime(new Date()); rc.setStatus(CompensationStatus.COMPENSATED); ht.save(rc); } // 判断是否所有还款结束,更改等待还款的投资状态和还款状态,还有项目状态。 loanService.dealComplete(lr.getLoan().getId()); try { cancelTransfering(lr.getLoan().getId()); } catch (RepayException e) { throw new OverdueRepayException(e.getMessage(), e.getCause()); } } else { throw new OverdueRepayException("还款不处于逾期还款状态"); } }
@Override @Transactional(rollbackFor = Exception.class) public TrusteeshipOperation createOperation(BankCard bankCard, FacesContext fc) throws IOException { // String resquestNo = IdGenerator.randomUUID(); String userId = bankCard.getUser().getId(); String hql = "from BankCard bc where bc.user.id = ? and bc.status = ?"; List l = ht.find(hql, new String[] {userId, "VERIFIED"}); BankCard bc = null; if (l.size() > 0) { bc = (BankCard) l.get(0); } else { FacesUtil.addErrorMessage("未找到银行卡信息。"); return null; } StringBuffer content = new StringBuffer(); content.append("<?xml version='1.0' encoding='utf-8'?>"); // 商户编号:商户在易宝唯一标识 content.append("<request platformNo='" + YeePayConstants.Config.MER_CODE + "'>"); // 商户平台会员标识:会员在商户平台唯一标识 content.append("<platformUserNo>" + userId + "</platformUserNo>"); // 请求流水号 银行卡的 id content.append( "<requestNo>" + YeePayConstants.RequestNoPre.UNBINDING_YEEPAY_BANKCARD + bc.getId() + "</requestNo>"); // 页面回跳URL content.append( "<callbackUrl>" + YeePayConstants.ResponseWebUrl.PRE_RESPONSE_URL + YeePayConstants.OperationType.UNBINDING_YEEPAY_BANKCARD + "</callbackUrl>"); // 服务器通知 URL:服务器通知 URL content.append( "<notifyUrl>" + YeePayConstants.ResponseS2SUrl.PRE_RESPONSE_URL + YeePayConstants.OperationType.UNBINDING_YEEPAY_BANKCARD + "</notifyUrl>"); content.append("</request>"); // 包装参数 Map<String, String> params = new HashMap<String, String>(); params.put("req", content.toString()); String sign = CFCASignUtil.sign(content.toString()); params.put("sign", sign); log.debug(content.toString()); log.debug(sign); // 保存本地 TrusteeshipOperation to = new TrusteeshipOperation(); to.setId(IdGenerator.randomUUID()); to.setMarkId(bc.getId()); to.setOperator(bc.getId()); to.setRequestUrl(YeePayConstants.RequestUrl.UNBINDING_YEEPAY_BANKCARD); to.setRequestData(MapUtil.mapToString(params)); to.setStatus(TrusteeshipConstants.Status.UN_SEND); to.setType(YeePayConstants.OperationType.UNBINDING_YEEPAY_BANKCARD); to.setTrusteeship("yeepay"); trusteeshipOperationBO.save(to); try { sendOperation(to.getId(), "utf-8", fc); } catch (IOException e) { e.printStackTrace(); } return null; }