package com.tenwa.cgb.controller; import com.amarsoft.are.jbo.*; import com.amarsoft.awe.util.ASResultSet; import com.amarsoft.awe.util.SqlObject; import com.amarsoft.awe.util.Transaction; import com.amarsoft.dict.als.manage.CodeManager; import com.tenwa.cgb.conf.CGBconfProperties; import com.tenwa.cgb.util.CGBLogAssistant; import com.tenwa.cgb.util.HttpAssistant; import com.tenwa.comm.exception.BusinessException; import com.tenwa.comm.util.date.DateAssistant; import com.tenwa.comm.util.jboutil.DataOperatorUtil; import jbo.app.tenwa.calc.LB_ACTUAL_PAYMENT_INFO_TEMP; import jbo.app.tenwa.calc.LC_FUND_INCOME_TEMP; import jbo.com.tenwa.lease.comm.LC_FUND_INCOME_CALLBACK_DETAIL_TEMP; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.math.BigDecimal; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @program: apzl_leasing * @author: yjf * @create: 2021-07-19 11:39 **/ public class OperateOfCGBController { private static final String XMLDECLARE = ""; private static Log log = LogFactory.getLog(OperateOfCGBController.class); private String flowUnid; private String userId; private String orgId; private String contractIds; public void setFlowUnid(String flowUnid) { this.flowUnid = flowUnid; } public void setContractIds(String contractIds) { this.contractIds = contractIds; } public void setUserId(String userId) { this.userId = userId; } public void setOrgId(String orgId) { this.orgId = orgId; } /** * 批量转账 * * @param tx * @return * @throws Exception */ public String batchPayOfCGB(JBOTransaction tx) throws Exception { String retResult = "success发起付款成功!"; contractIds = contractIds.replaceAll("@", "','"); String subjectSql = "SELECT subjectId AS subjectuid FROM lb_contract_info WHERE id IN ('" + contractIds + "') GROUP BY subjectId "; List> lciList = DataOperatorUtil.getDataBySql(subjectSql); if (lciList.size() > 1) { return "放款合同中有多个主体,请检查!!!"; } BizObjectManager actualPaymentMan = JBOFactory.getBizObjectManager(LB_ACTUAL_PAYMENT_INFO_TEMP.CLASS_NAME, tx); BizObject actualBo = actualPaymentMan.createQuery("flowunid=:flowunid").setParameter("flowunid", flowUnid).getSingleResult(false); if (actualBo == null || actualBo.getAttribute("acc_number").getString().length() == 0) { throw new BusinessException("没有匹配的本方账户,请检查!!!"); } String payAccountNum = actualBo.getAttribute("acc_number").getString(); BizObjectManager incomeMan = JBOFactory.getBizObjectManager(LC_FUND_INCOME_TEMP.CLASS_NAME, tx); BizObject singleResult = incomeMan.createQuery("select v.count(1) as v.allCount from O where FLOWUNID=:FLOWUNID and o.contract_id in ('" + contractIds + "') and o.PAY_TYPE = 'pay_type_out' and o.CMB_PAY_LOG is null ").setParameter("FLOWUNID", flowUnid).getSingleResult(false); if (singleResult != null && singleResult.getAttribute("allCount").getInt() > 0) { int start = 0; int maxCount = 200; while (singleResult.getAttribute("allCount").getInt() > start) { String customerBatchNo = "AP" + System.currentTimeMillis(); log.info("CGB FLOWUNID[" + flowUnid + "]---开始第" + start + "至" + (start + maxCount) + "条循环"); List income_all_list = incomeMan.createQuery("select o.ID,o.CMB_PAY_NO,o.FACT_MONEY,o.FLOWUNID,o.CONTRACT_ID,contract_info.CONTRACT_NO,contract_info.ZC_CONTRACT_NUMBER,lul.CUSTOMER_NAME,distributor.distributor_id,distributor.acc_number,distributor.open_bank,distributor.account from o join jbo.com.tenwa.lease.comm.LB_CONTRACT_INFO contract_info on o.CONTRACT_ID = contract_info.id join jbo.com.tenwa.lease.comm.LB_UNION_LESSEE lul on contract_info.id = lul.contract_id join jbo.app.tenwa.customer.DISTRIBUTOR_ACCOUNT distributor on contract_info.distributor_id = distributor.distributor_id and distributor.is_main='Y' " + " where o.FLOWUNID=:FLOWUNID and o.contract_id in ('" + contractIds + "') and o.PAY_TYPE = 'pay_type_out' and o.CMB_PAY_LOG is null ") .setParameter("FLOWUNID", flowUnid).setFirstResult(start).setMaxResults(maxCount).getResultList(false); //批量转账报文 String batchPayMsgXml = createBatchPayMsg(customerBatchNo, payAccountNum, income_all_list); //保存发起日志 CGBLogAssistant.insertCGBlog(flowUnid, "pay", customerBatchNo, null, batchPayMsgXml); HashMap map = new HashMap<>(); map.put("cgb_data", batchPayMsgXml); String retMsg = HttpAssistant.post(CGBconfProperties.CGBURL, map); if (retMsg == null) return "连接前置机异常,请联系管理员!"; log.info("CGB [" + customerBatchNo + "] BATCHPAY RETURN XML : " + retMsg); //更新返回日志 CGBLogAssistant.updateCGBlog(customerBatchNo, null, retMsg); //批量转账报文解析 Map batchPayResult = getBatchPayResult(retMsg); if (batchPayResult.size() > 0 && "000".equals(batchPayResult.get("retCode"))) { for (BizObject incomeObj : income_all_list) { payBackResultHandle(incomeObj, customerBatchNo, batchPayResult, actualBo); } } else { return "发起付款失败,广发返回错误:[" + CodeManager.getItemName("cgb_describe", batchPayResult.get("retCode")) + "]"; } start += 200; } } else { return "选择数据包含付款中数据,请检查!!!"; } return retResult; } /** * 批量查询 * * @param tx * @return * @throws Exception */ public String batchQueryOfCGB(JBOTransaction tx) throws Exception { BizObjectManager bm = JBOFactory.getBizObjectManager(LC_FUND_INCOME_CALLBACK_DETAIL_TEMP.CLASS_NAME); List bizObjects = bm.createQuery(" flowunid = :flowunid and cmb_pay_log is not null and ERRTXT='付款中' ") .setParameter("flowunid", flowUnid).getResultList(false); if (bizObjects.isEmpty()) return "待回盘数据为空,请检查"; String customerBatchNo = null, customerSalarySeq = null; for (BizObject bizObject : bizObjects) { customerBatchNo = bizObject.getAttribute("cmb_pay_log").getString(); customerSalarySeq = bizObject.getAttribute("cmb_pay_no").getString(); String batchPayQueryXml = createBatchPayQueryMsg(customerBatchNo, customerSalarySeq); //保存发起日志 CGBLogAssistant.insertCGBlog(flowUnid, "query", customerBatchNo, customerSalarySeq, batchPayQueryXml); HashMap map = new HashMap<>(); map.put("cgb_data", batchPayQueryXml); String retMsg = HttpAssistant.post(CGBconfProperties.CGBURL, map); if (retMsg == null) return "连接前置机异常,请联系管理员!"; log.info("CGB customerBatchNo[" + customerBatchNo + "] customerSalarySeq[" + customerSalarySeq + "] QUERY RETURN XML : " + retMsg); //更新返回日志 CGBLogAssistant.updateCGBlog(customerBatchNo, customerSalarySeq, retMsg); Map batchQueryResult = getBatchQueryResult(retMsg); JBOTransaction tx1 = null; try { tx1 = JBOFactory.createJBOTransaction(); Transaction sqlca = Transaction.createTransaction(tx1); String retCode = batchQueryResult.get("retCode"); if ("000".equals(retCode)) { String bankstatus = batchQueryResult.get("bankstatus"); String errText = "付款中"; String business_status = null, ebankStatus = null; if ("6,B".indexOf(bankstatus) != -1) { //交易成功 business_status = "31"; ebankStatus = "05"; errText = "付款成功"; } else if ("4,7,9,C,b".indexOf(bankstatus) != -1) { //交易失败 business_status = "32"; ebankStatus = "04"; errText = "付款失败"; } errText = batchQueryResult.get("errorreason") == null ? errText : batchQueryResult.get("errorreason"); //更新回调结果状态 SqlObject sqlObject = new SqlObject("update LC_FUND_INCOME_CALLBACK_DETAIL_TEMP set ERRCOD=:errCode,ERRTXT=:errText,RTNNAR=:rtnNar where id =:id") .setParameter("errCode", bankstatus) .setParameter("errText", errText) .setParameter("rtnNar", getbankstatusMsg(bankstatus)) .setParameter("id", bizObject.getAttribute("id").getString()); sqlca.executeSQL(sqlObject); if (business_status != null) { //插入项目进度表 sqlObject = new SqlObject(""); sqlObject.setOriginalSql("insert into BUSINESS_STATUS select replace(uuid(),'-',''),contract_no,'" + business_status + "','" + userId + "','" + orgId + "','" + DateAssistant.getTodayNow() + "',null,null,null,null from lb_contract_info where id = '" + bizObject.getAttribute("contract_id").getString() + "'"); sqlca.executeSQL(sqlObject); //更新资金实收临时表 sqlObject = new SqlObject("update LC_FUND_INCOME_TEMP set EBANK_STATUS=:ebankStatus,CMB_PAY_NO=:customerSalarySeq,CMB_PAY_LOG=:customerBatchNo where flowunid=:flowunid and contract_id =:contractId ") .setParameter("ebankStatus", ebankStatus) .setParameter("customerSalarySeq", "04".equals(ebankStatus) ? null : customerSalarySeq) .setParameter("customerBatchNo", "04".equals(ebankStatus) ? null : customerBatchNo) .setParameter("flowunid", flowUnid) .setParameter("contractId", bizObject.getAttribute("contract_id").getString()); sqlca.executeSQL(sqlObject); } } else { //更新回调结果状态 SqlObject sqlObject = new SqlObject("update LC_FUND_INCOME_CALLBACK_DETAIL_TEMP set ERRCOD=:errCode,ERRTXT=:errText where id =:id") .setParameter("errCode", retCode) .setParameter("errText", CodeManager.getItemName("cgb_describe", retCode)) .setParameter("id", bizObject.getAttribute("id").getString()); sqlca.executeSQL(sqlObject); } tx1.commit(); } catch (Exception e) { log.error("customerBatchNo:[" + customerBatchNo + "] customerSalarySeq:[" + customerSalarySeq + "] 查询结果处理异常:", e); if (tx1 != null) try { tx1.rollback(); } catch (JBOException e1) { e1.printStackTrace(); } } } return "success查询付款结果成功"; } /** * 批量转账报文 * * @param tx * @return * @throws Exception */ private String createBatchPayMsg(String customerBatchNo, String accountNo, List payObjs) throws Exception { StringBuilder sb = new StringBuilder(); sb.append(XMLDECLARE); sb.append(""); sb.append(""); sb.append(commonMseeage("0033")); sb.append(""); sb.append("").append(customerBatchNo).append("");//客户批次号 企业内唯一[必输] 长度20 sb.append("").append(accountNo).append("");//付款账号 [必输] int allCount = 0; BigDecimal allSalary = new BigDecimal(0); for (BizObject payObj : payObjs) { allSalary = allSalary.add(BigDecimal.valueOf(payObj.getAttribute("fact_money").getDouble())); allCount++; } sb.append("").append(allCount).append("");//总笔数 [必输] sb.append("").append(allSalary.toString()).append("");//总金额 单位:元[必输] sb.append(""); int i = 0; String customerSalarySeq = null, customerName = null, contractNo = null, contractNoZC = null, remark = null; for (BizObject payObj : payObjs) { customerSalarySeq = customerBatchNo + String.format("%04d", ++i); customerName = payObj.getAttribute("CUSTOMER_NAME").getString(); contractNo = payObj.getAttribute("contract_no").getString(); contractNoZC = payObj.getAttribute("ZC_CONTRACT_NUMBER").getString(); remark = "".equals(contractNoZC) ? customerName + "-" + contractNo : customerName + "-" + contractNoZC + "-" + contractNo; sb.append(""); sb.append("").append(customerSalarySeq).append("");//客户批次子流水号 企业内唯一[必输] 长度20 sb.append("").append(checkCGB(payObj.getAttribute("open_bank").getString()) ? "0" : "1").append(""); //交易类型 0:行内 1:跨行 [必输] sb.append("").append(payObj.getAttribute("account")).append(""); //收款人 [必输] sb.append("").append(payObj.getAttribute("acc_number")).append(""); //收款账号 [必输] sb.append("").append(payObj.getAttribute("open_bank").getString()).append(""); //收款银行 [必输] sb.append("").append("").append(""); //收款银行地址 sb.append("").append("").append(""); //联行号 跨行时 [必输] 广发自动根据银行名称匹配--技术回复 sb.append("").append(payObj.getAttribute("fact_money").getString()).append(""); //金额 单位:元 [必输] sb.append("").append(remark).append(""); //备注 客户名+合作方合同号+安鹏合同号 sb.append("").append(payObj.getAttribute("id").getString()).append(""); //附言 绑定支付对象主键 sb.append(""); payObj.setAttributeValue("CMB_PAY_NO", customerSalarySeq); } sb.append(""); sb.append(""); sb.append(""); sb.append(""); log.info("CGB [" + customerBatchNo + "] BATCHPAY SEND XML : " + sb.toString()); return sb.toString(); } /** * 解析批量转账结果 * * @param strXML * @return */ private Map getBatchPayResult(String strXML) { Map res = new HashMap(); //获取批次号 Pattern pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); Matcher mm = pm.matcher(strXML); if (mm.find()) { res.put("customerBatchNo", mm.group()); } pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); mm = pm.matcher(strXML); if (mm.find()) { res.put("retCode", mm.group()); } return res; } /** * 批量转账查询报文 * * @param customerBatchNo * @param customerSalarySeq * @return * @throws Exception */ private String createBatchPayQueryMsg(String customerBatchNo, String customerSalarySeq) throws Exception { StringBuilder sb = new StringBuilder(); sb.append(XMLDECLARE); sb.append(""); sb.append(""); sb.append(commonMseeage("0034")); sb.append(""); sb.append("").append(customerBatchNo).append(""); //客户批次号 [必输] sb.append("").append(customerSalarySeq == null ? "" : customerSalarySeq).append(""); //客户批次子流水号 sb.append(""); sb.append(""); sb.append(""); log.info("CGB customerBatchNo[" + customerBatchNo + "] customerSalarySeq[" + customerSalarySeq + "] QUERY SEND XML : " + sb.toString()); return sb.toString(); } /** * 解析查询结果 * * @param strXML * @return */ private Map getBatchQueryResult(String strXML) { Map res = new HashMap(); Pattern pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); Matcher mm = pm.matcher(strXML); if (mm.find()) { res.put("retCode", mm.group()); } //获取批次号 pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); mm = pm.matcher(strXML); if (mm.find()) { res.put("customerSalarySeq", mm.group()); } pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); mm = pm.matcher(strXML); if (mm.find()) { res.put("bankstatus", mm.group()); } pm = Pattern.compile("(?<=)([\\S\\s]*?)(?=)"); mm = pm.matcher(strXML); if (mm.find()) { if (mm.group().length() > 0) res.put("errorreason", mm.group()); } return res; } /** * 公共报文头拼接 * * @param tranCode 交易码 * @return */ private String commonMseeage(String tranCode) throws Exception { StringBuilder sb = new StringBuilder(); sb.append(""); sb.append("").append(tranCode).append("");//交易码 sb.append("").append(CGBconfProperties.CIFMASTER).append("");//客户号 sb.append("").append("CGB").append(System.currentTimeMillis()).append("");//企业财务系统流水号 企业财务系统自己产生的流水号,每天唯一 长度20 sb.append("").append(DateAssistant.getFormatDate("yyyyMMdd")).append("");//日期 sb.append("").append(DateAssistant.getFormatDate("HHmmss")).append("");//时间 sb.append("");//返回码,请求报文是,默认为空 sb.append("").append(CGBconfProperties.ENTUSERID).append("");//操作员 sb.append(" ");//操作密码 sb.append(""); return sb.toString(); } /** * 检查是否广发银行账号 * * @param str * @return */ private boolean checkCGB(String str) { if (str.indexOf("广发") != -1) { return true; } else { return false; } } /** * 支付回调结果处理 */ private void payBackResultHandle(BizObject payObj, String customerBatchNo, Map retResult, BizObject actualObj) { JBOTransaction tx = null; String serialNum = null; try { serialNum = payObj.getAttribute("CMB_PAY_NO").getString(); tx = JBOFactory.createJBOTransaction(); Transaction sqlca = Transaction.createTransaction(tx); //修改上次扣款记录,避免显示多条数据 SqlObject sqlObject = new SqlObject("update LC_FUND_INCOME_CALLBACK_DETAIL_TEMP set contract_id = null where flowunid=:flowunid and contract_id =:contractId") .setParameter("flowunid", flowUnid).setParameter("contractId", payObj.getAttribute("contract_id").getString()); sqlca.executeSQL(sqlObject); //添加新的扣款记录 sqlObject = new SqlObject("insert into LC_FUND_INCOME_CALLBACK_DETAIL_TEMP (id,FLOWUNID,CMB_PAY_LOG,CMB_PAY_NO,ERRTXT,CONTRACT_ID,DISTRIBUTOR_ID,INPUTUSERID,INPUTORGID,INPUTTIME) " + " values (replace(uuid(),'-',''),:flowunid,:cmbPayLog,:serialNum,'付款中',:contractId,:distributorId,:userId,:orgId,:inputTime)") .setParameter("flowunid", flowUnid) .setParameter("cmbPayLog", customerBatchNo) //批次号 .setParameter("serialNum", serialNum) //序号 .setParameter("contractId", payObj.getAttribute("contract_id").getString()) //合同id .setParameter("distributorId", payObj.getAttribute("distributor_id").getString())//经销商id .setParameter("userId", userId) .setParameter("orgId", orgId) .setParameter("inputTime", DateAssistant.getTodayNow()); sqlca.executeSQL(sqlObject); //更新批次号,序号到支付明细数据 sqlObject = new SqlObject("update LC_FUND_INCOME_TEMP set CMB_PAY_LOG=:customerBatchNo,CMB_PAY_NO=:serialNum,bank=:bank,account=:account,acc_number=:accNumber where id = :id ") .setParameter("customerBatchNo", customerBatchNo) .setParameter("serialNum", serialNum) .setParameter("bank", actualObj.getAttribute("bank").getString())//本方银行 .setParameter("account", actualObj.getAttribute("account").getString())//本方账户 .setParameter("accNumber", actualObj.getAttribute("acc_number").getString())//本方账号 .setParameter("id", payObj.getAttribute("id").getString()); sqlca.executeSQL(sqlObject); tx.commit(); } catch (Exception e) { log.error("customerBatchNo:[" + customerBatchNo + "] customerSalarySeq:[" + serialNum + "] 批量转账结果处理异常!", e); if (tx != null) try { tx.rollback(); } catch (JBOException e1) { e1.printStackTrace(); } } } /** * 交易处理状态 * * @param bankstatus * @return */ private String getbankstatusMsg(String bankstatus) { String msg = null; //行内汇款:6,7,8 跨行汇款:A,B,C,E switch (bankstatus) { case "6": msg = "主机交易成功"; break; case "7": msg = "主机交易失败"; break; case "8": msg = "状态未知,没有收到后台系统返回的应答"; break; case "A": msg = "支付系统正在处理"; break; case "B": msg = "处理成功"; break; case "C": msg = "处理失败"; break; case "E": msg = "大额查证"; break; case "9": msg = "查证取消交易"; break; default: msg = bankstatus; } return msg; } public String vaildate(Transaction sqlCa) throws Exception { ASResultSet as = sqlCa.getASResultSet("select count(1) as nums," + "sum(case when cmb_pay_log is not null or locate(RTNFLG,'F')>0 and length(RTNFLG)>0 then 0 else 1 end ) cmb_succ_num," + "sum(case when cmb_pay_log is null or locate(ERRCOD,'4,7,9,C,b,W')>0 and length(ERRCOD)>0 then 0 else 1 end ) cgb_succ_num" + " from LC_FUND_INCOME_CALLBACK_DETAIL_TEMP where flowunid = '" + flowUnid + "'"); if (as.next()) { int nums = as.getInt("nums"); int CMBNums = as.getInt("cmb_succ_num"); //招商发起成功数 int CGBNums = as.getInt("cgb_succ_num"); //广发发起成功数 if (nums > 0 && (CMBNums > 0 || CGBNums > 0)) { return "已发起支付,禁止变更"; } } return "succ"; } }