package com.ruoyi.cwgl.service.impl;
|
|
import com.cmbs.client.header.ClientConfig;
|
import com.cmbs.client.util.OutBoundServiceUtils;
|
import com.google.gson.Gson;
|
import com.ruoyi.cwgl.domain.FundFlow;
|
import com.ruoyi.cwgl.mapper.FundFlowMapper;
|
import com.ruoyi.cwgl.service.ICmbsBankSyncService;
|
import com.ruoyi.cwgl.test.GatewayConfigUtils;
|
import com.ruoyi.cwgl.domain.Q7517Request;
|
import com.ruoyi.cwgl.domain.Q7517Response;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* CMBS银行流水同步Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2026-04-15
|
*/
|
@Service
|
@Transactional(rollbackFor = Exception.class)
|
public class CmbsBankSyncServiceImpl implements ICmbsBankSyncService {
|
|
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
|
@Resource
|
private FundFlowMapper fundFlowMapper;
|
|
@Override
|
public String syncFromCmbs(String acctNum, String startDate, String endDate) {
|
if (acctNum == null || acctNum.trim().isEmpty()) {
|
throw new RuntimeException("账号不能为空");
|
}
|
if (startDate == null || endDate == null) {
|
throw new RuntimeException("日期范围不能为空");
|
}
|
|
ClientConfig clientConfig = GatewayConfigUtils.getClientConfig();
|
Gson gson = new Gson();
|
int totalSynced = 0;
|
int totalSkipped = 0;
|
int currentPage = 1;
|
int pageSize = 100;
|
|
try {
|
while (true) {
|
// 构建请求参数
|
Q7517Request request = new Q7517Request();
|
request.setAcctNum(acctNum);
|
request.setTradeStartDate(startDate);
|
request.setTradeEndDate(endDate);
|
request.setCurrentPage(currentPage);
|
request.setPageSize(pageSize);
|
|
String queryBody = gson.toJson(request);
|
String reqSeq = generateReqSeq();
|
|
String response = OutBoundServiceUtils.execute(clientConfig, queryBody,
|
"", "CMBS_Q7517", reqSeq);
|
logger.info("CMBS Q7517 响应 [页{}]: {}", currentPage, response);
|
|
Q7517Response resp = gson.fromJson(response, Q7517Response.class);
|
if (resp == null || resp.getBatchInfo() == null || resp.getBatchInfo().isEmpty()) {
|
break;
|
}
|
|
List<Q7517Response.BatchInfo> batchInfoList = resp.getBatchInfo();
|
List<FundFlow> toInsert = new ArrayList<>();
|
|
for (Q7517Response.BatchInfo info : batchInfoList) {
|
// 按URID去重
|
if (info.getUrid() != null && !info.getUrid().isEmpty()) {
|
FundFlow existing = fundFlowMapper.selectFundFlowByUrid(info.getUrid());
|
if (existing != null) {
|
totalSkipped++;
|
continue;
|
}
|
}
|
|
FundFlow fundFlow = convertToFundFlow(info, acctNum);
|
toInsert.add(fundFlow);
|
}
|
|
if (!toInsert.isEmpty()) {
|
fundFlowMapper.insertFundFlowBatch(toInsert);
|
totalSynced += toInsert.size();
|
}
|
|
// 判断是否还有下一页
|
Number totalNum = resp.getTotalNum();
|
if (totalNum != null && currentPage * pageSize >= totalNum.intValue()) {
|
break;
|
}
|
currentPage++;
|
}
|
|
return String.format("同步完成:新增 %d 条,跳过(已存在) %d 条", totalSynced, totalSkipped);
|
} catch (Exception e) {
|
logger.error("CMBS银行流水同步失败", e);
|
throw new RuntimeException("CMBS银行流水同步失败: " + e.getMessage(), e);
|
}
|
}
|
|
/**
|
* 将 Q7517 响应数据转换为 FundFlow 实体
|
*/
|
private FundFlow convertToFundFlow(Q7517Response.BatchInfo info, String acctNum) {
|
FundFlow fundFlow = new FundFlow();
|
|
// 银行主键
|
fundFlow.setUrid(info.getUrid());
|
// 企业编号
|
fundFlow.setOrgNo(info.getOrgNo());
|
// 银行流水号
|
fundFlow.setBankFlowNo(info.getBankSerialNumber());
|
// 本方账号
|
fundFlow.setOurAccount(info.getPayerAcctNo());
|
// 本方户名
|
fundFlow.setPayerAcctName(info.getPayerAcctName());
|
// 对方账号
|
fundFlow.setCounterpartyAccount(info.getPayeeAcctNo());
|
// 对方户名
|
fundFlow.setCounterpartyName(info.getPayeeAcctName());
|
// 对方银行
|
fundFlow.setCounterpartyBank(info.getPayeeBankNo());
|
// 交易金额
|
if (info.getTransAmount() != null) {
|
fundFlow.setTransactionAmount(new BigDecimal(info.getTransAmount().toString()));
|
}
|
// 账户余额
|
if (info.getCurrentBalance() != null) {
|
fundFlow.setAccountBalance(new BigDecimal(info.getCurrentBalance().toString()));
|
}
|
// 交易币种
|
fundFlow.setCurrency(info.getCurrName());
|
// 币种编号
|
fundFlow.setCurrNo(info.getCurrNo());
|
// 用途
|
fundFlow.setPurpose(info.getPurpose());
|
// 摘要
|
fundFlow.setSummary(info.getMemo());
|
// 款项性质
|
fundFlow.setNatureNames(info.getNatureNames());
|
// 单据唯一标识号
|
fundFlow.setSrcNoteCode(info.getSrcNoteCode());
|
// 是否退汇
|
fundFlow.setIsReturn(info.getIsReturn());
|
// 第三方流水号
|
fundFlow.setCustomizedSerialNum(info.getCustomizedSerialNum());
|
|
// 交易方向转换:Q7517(1-支出 2-收入) → FundFlow(1-支 0-收)
|
if ("1".equals(info.getMoneyWay())) {
|
fundFlow.setIncomeExpenseFlag(1);
|
} else if ("2".equals(info.getMoneyWay())) {
|
fundFlow.setIncomeExpenseFlag(0);
|
}
|
|
// 交易日期:合并 tradeDate + tradeTime
|
try {
|
if (info.getTradeTime() != null && !info.getTradeTime().isEmpty()) {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
fundFlow.setTransactionDate(sdf.parse(info.getTradeTime()));
|
} else if (info.getTradeDate() != null && !info.getTradeDate().isEmpty()) {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
fundFlow.setTransactionDate(sdf.parse(info.getTradeDate()));
|
}
|
} catch (Exception e) {
|
logger.warn("解析交易日期失败: tradeDate={}, tradeTime={}", info.getTradeDate(), info.getTradeTime());
|
}
|
|
// 起息日期
|
try {
|
if (info.getValueDate() != null && !info.getValueDate().isEmpty()) {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
fundFlow.setValueDate(sdf.parse(info.getValueDate()));
|
}
|
} catch (Exception e) {
|
logger.warn("解析起息日期失败: {}", info.getValueDate());
|
}
|
|
// 记账日期
|
try {
|
if (info.getPostdate() != null && !info.getPostdate().isEmpty()) {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
fundFlow.setPostdate(sdf.parse(info.getPostdate()));
|
}
|
} catch (Exception e) {
|
logger.warn("解析记账日期失败: {}", info.getPostdate());
|
}
|
|
// 状态:默认设置为"0"正常(草稿)
|
fundFlow.setStatus("0");
|
// 删除标志
|
fundFlow.setDelFlag("0");
|
|
return fundFlow;
|
}
|
|
/**
|
* 生成请求流水号:10位商户号 + 14位时间 + 8位序号
|
*/
|
private String generateReqSeq() {
|
String merchantNum = "zjjr";
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
String dateTime = sdf.format(new Date());
|
String seq = String.format("%08d", (int) (Math.random() * 100000000));
|
return merchantNum + dateTime + seq;
|
}
|
}
|