|
|
|
@@ -13,6 +13,7 @@ import org.springframework.http.HttpHeaders;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.GeneralResp;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.ResponseModel;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.TransactionDTO;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.request.BillPaymentRequest;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.request.TransactionStatusRequest;
|
|
|
|
|
import com.billpaymentservice.bbps.dto.request.TrasactionStatusByClientReqIdRequest;
|
|
|
|
@@ -115,22 +116,23 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
// save here should not prevent the outgoing request, so we catch and log errors.
|
|
|
|
|
try {
|
|
|
|
|
TransactionMaster preTransaction = new TransactionMaster();
|
|
|
|
|
preTransaction.setBankTxnId("INITIATED_" + txnId);
|
|
|
|
|
preTransaction.setBankTxnId(txnId+"bank");
|
|
|
|
|
preTransaction.setTxnId(txnId);
|
|
|
|
|
preTransaction.setInitiatorTxnId(txnId);
|
|
|
|
|
preTransaction.setReqId(requestId);
|
|
|
|
|
preTransaction.setMid(billPaymentRequest.getMid());
|
|
|
|
|
preTransaction.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
preTransaction.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
preTransaction.setUserId(userId);
|
|
|
|
|
preTransaction.setStatus("INITIATED");
|
|
|
|
|
preTransaction.setStatus("PENDING");
|
|
|
|
|
EntityRelationshipUtil.linkTransactionMasterRelationships(preTransaction);
|
|
|
|
|
saveTransactionMasterWithRetry(preTransaction);
|
|
|
|
|
// ensure txnId exists (no uniqueness suffixing)
|
|
|
|
|
preTransaction.setTxnId(ensureTxnId(preTransaction.getTxnId()));
|
|
|
|
|
transactionMasterRepository.save(preTransaction);
|
|
|
|
|
LOGGER.info("Pre-request TransactionMaster saved with status=INITIATED for txnId={}", txnId);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.warn("Failed to persist pre-request TransactionMaster for txnId={}: {}", txnId, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
LOGGER.info("Calling BBPS payment URL: {}", url);
|
|
|
|
|
Map<String, String> responseMap = httpService.postRequest(url, forwardjson, headers);
|
|
|
|
|
String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY);
|
|
|
|
@@ -139,139 +141,47 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
helper.updateOutboundLogResponse(outboundLog, responseData);
|
|
|
|
|
LOGGER.debug("Outbound log response updated for txnId={}", txnId);
|
|
|
|
|
|
|
|
|
|
if (responseData == null || responseData.isEmpty()) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, BBPSConstant.EMPTY_RESPONSE_FROM_BBPS,
|
|
|
|
|
BBPSConstant.FAILED_STR);
|
|
|
|
|
LOGGER.warn("Empty response received from BBPS for txnId={}", txnId);
|
|
|
|
|
// Persist a TransactionMaster placeholder so scheduler can pick it up later
|
|
|
|
|
TransactionMaster tm = new TransactionMaster();
|
|
|
|
|
tm.setBankTxnId("PENDING_" + txnId);
|
|
|
|
|
tm.setTxnId(txnId);
|
|
|
|
|
tm.setReqId(requestId);
|
|
|
|
|
tm.setMid(billPaymentRequest.getMid());
|
|
|
|
|
tm.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
tm.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
tm.setUserId(userId);
|
|
|
|
|
tm.setStatus("PENDING_UPSTREAM");
|
|
|
|
|
transactionMasterRepository.save(tm);
|
|
|
|
|
LOGGER.info("TransactionMaster placeholder saved with status=PENDING_UPSTREAM for txnId={}", txnId);
|
|
|
|
|
return new ResponseModel(BBPSConstant.EMPTY_RESPONSE_FROM_BBPS, "PENDING_UPSTREAM", 502, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, Object> dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
Map<String, Object> dataMap;
|
|
|
|
|
try {
|
|
|
|
|
dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERIC_KEY)) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_STRUCTURE);
|
|
|
|
|
LOGGER.warn("Invalid response structure received for txnId={}", txnId);
|
|
|
|
|
// Save a TransactionMaster placeholder so scheduler/admin can reconcile later
|
|
|
|
|
TransactionMaster tm = new TransactionMaster();
|
|
|
|
|
tm.setBankTxnId("INVALID_" + txnId);
|
|
|
|
|
tm.setTxnId(txnId);
|
|
|
|
|
tm.setReqId(requestId);
|
|
|
|
|
tm.setMid(billPaymentRequest.getMid());
|
|
|
|
|
tm.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
tm.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
tm.setUserId(userId);
|
|
|
|
|
tm.setStatus("INVALID_RESPONSE_FROM_BBPS");
|
|
|
|
|
transactionMasterRepository.save(tm);
|
|
|
|
|
LOGGER.info("TransactionMaster placeholder saved with status=INVALID_RESPONSE_FROM_BBPS for txnId={}", txnId);
|
|
|
|
|
return new ResponseModel(BBPSConstant.INVALID_STRUCTURE, "INVALID_RESPONSE_FROM_BBPS", 502, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BillPaymentResponse billPaymentResponse = objectMapper.convertValue(dataMap, BillPaymentResponse.class);
|
|
|
|
|
|
|
|
|
|
GeneralResp generalResponse = billPaymentResponse.getGenericResponse();
|
|
|
|
|
LOGGER.info("genric Response" + generalResponse);
|
|
|
|
|
if(generalResponse.getStatus().equalsIgnoreCase("Failed")) {
|
|
|
|
|
// Save TransactionMaster with failed status so it can be reconciled later
|
|
|
|
|
TransactionMaster tm = new TransactionMaster();
|
|
|
|
|
tm.setBankTxnId(billPaymentResponse.getTxnId());
|
|
|
|
|
tm.setTxnId(txnId);
|
|
|
|
|
tm.setReqId(requestId);
|
|
|
|
|
tm.setMid(billPaymentRequest.getMid());
|
|
|
|
|
tm.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
tm.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
tm.setUserId(userId);
|
|
|
|
|
tm.setStatus(generalResponse.getStatus());
|
|
|
|
|
// ensure internal txnId uniqueness and save
|
|
|
|
|
tm.setTxnId(makeUniqueTxnId(tm.getTxnId()));
|
|
|
|
|
saveTransactionMasterWithRetry(tm);
|
|
|
|
|
LOGGER.info("TransactionMaster saved with failed status={} for txnId={}", generalResponse.getStatus(), txnId);
|
|
|
|
|
return new ResponseModel(generalResponse.getMessage(), generalResponse.getStatus(),
|
|
|
|
|
Integer.parseInt(generalResponse.getStatusCode()), billPaymentResponse);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BillPayment entity = modelMapper.map(billPaymentResponse, BillPayment.class);
|
|
|
|
|
paymentRepository.save(entity);
|
|
|
|
|
LOGGER.info("BillPayment entity saved successfully for txnId={}", txnId);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
helper.updateInboundLogSuccess(inboundLog, responseData, generalResponse.getStatus());
|
|
|
|
|
// Create and save TransactionMaster for this initiate flow so everything is stored in the same table
|
|
|
|
|
try {
|
|
|
|
|
TransactionMaster transactionMaster = new TransactionMaster();
|
|
|
|
|
// bankTxnId is BBPS txn id (primary key)
|
|
|
|
|
transactionMaster.setBankTxnId(billPaymentResponse.getTxnId());
|
|
|
|
|
// use internal txnId generated earlier for tracing
|
|
|
|
|
transactionMaster.setTxnId(txnId);
|
|
|
|
|
transactionMaster.setReqId(requestId);
|
|
|
|
|
transactionMaster.setMid(billPaymentRequest.getMid());
|
|
|
|
|
transactionMaster.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
transactionMaster.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
transactionMaster.setUserId(userId);
|
|
|
|
|
transactionMaster.setBillerId(billPaymentResponse.getBillerId());
|
|
|
|
|
transactionMaster.setTxnAmount(billPaymentResponse.getTxnAmount());
|
|
|
|
|
transactionMaster.setStatus(billPaymentResponse.getStatus());
|
|
|
|
|
EntityRelationshipUtil.linkTransactionMasterRelationships(transactionMaster);
|
|
|
|
|
// ensure internal txnId uniqueness and save (handles collisions)
|
|
|
|
|
transactionMaster.setTxnId(makeUniqueTxnId(transactionMaster.getTxnId()));
|
|
|
|
|
saveTransactionMasterWithRetry(transactionMaster);
|
|
|
|
|
LOGGER.info("TransactionMaster created during initiatePayment for internalTxnId={} bankTxnId={}", transactionMaster.getTxnId(), transactionMaster.getBankTxnId());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.warn("Failed to persist TransactionMaster during initiatePayment for txnId={}: {}", txnId, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
TransactionStatusRequest transactionStatusRequest = new TransactionStatusRequest();
|
|
|
|
|
transactionStatusRequest.setTxnId(billPaymentResponse.getTxnId());
|
|
|
|
|
transactionStatusRequest.setReqId(requestId);
|
|
|
|
|
transactionStatusRequest.setMid(billPaymentRequest.getMid());
|
|
|
|
|
transactionStatusRequest.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Thread.sleep((long) BBPSConstant.PAYMENT_STATUS_DELAY_MS);
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
|
|
Thread.currentThread().interrupt();
|
|
|
|
|
LOGGER.warn("Thread interrupted during payment delay: {}", e.getMessage());
|
|
|
|
|
transactionStatusRequest.setReqId(billPaymentRequest.getReqId());
|
|
|
|
|
transactionStatusRequest.setTxnId(entity.getTxnId());
|
|
|
|
|
ResponseModel responseModel = checkTrasactionStatus(transactionStatusRequest, inboundLog);
|
|
|
|
|
return responseModel;
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
|
|
|
|
throw new CustomException(BBPSConstant.MSG_INVALID_JSON_FROM_UPSTREAM,BBPSConstant.FAILED_STATUS, BBPSConstant.INVALID_JSON_STATUS_CODE, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
LOGGER.info("Checking transaction status for txnId={}", billPaymentResponse.getTxnId());
|
|
|
|
|
LOGGER.info("[{}] END | reqId={} | txnId={}", apiName, requestId, txnId);
|
|
|
|
|
return checkTrasactionStatus(transactionStatusRequest, inboundLog);
|
|
|
|
|
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
LOGGER.error("JSON Parsing Error in initiatePayment: {}", e.getMessage(), e);
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
|
|
|
|
// Persist TransactionMaster placeholder so admin/scheduler can reconcile later
|
|
|
|
|
TransactionMaster tm = new TransactionMaster();
|
|
|
|
|
tm.setBankTxnId("INVALID_JSON_" + txnId);
|
|
|
|
|
tm.setTxnId(txnId);
|
|
|
|
|
tm.setUserId(billPaymentRequest.getClientReqId());
|
|
|
|
|
tm.setReqId(billPaymentRequest.getReqId());
|
|
|
|
|
tm.setMid(billPaymentRequest.getMid());
|
|
|
|
|
tm.setClientUserId(billPaymentRequest.getClientUserId());
|
|
|
|
|
tm.setClientReqId(billPaymentRequest.getClientReqId());
|
|
|
|
|
tm.setStatus("INVALID_JSON_FROM_UPSTREAM");
|
|
|
|
|
transactionMasterRepository.save(tm);
|
|
|
|
|
LOGGER.info("TransactionMaster saved with status=INVALID_JSON_FROM_UPSTREAM for txnId={}", txnId);
|
|
|
|
|
throw new CustomException(BBPSConstant.MSG_INVALID_JSON_FROM_UPSTREAM, BBPSConstant.FAILED_STATUS, BBPSConstant.INVALID_JSON_STATUS_CODE, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ResponseModel checkTrasactionStatus(TransactionStatusRequest transactionStatusRequest,
|
|
|
|
|
InboundTraceLog inboundLog) {
|
|
|
|
|
String apiName = BBPSConstant.API_CHECK_TRANSACTION_STATUS;
|
|
|
|
|
String txnId = helper.generateTxnId(15);
|
|
|
|
|
String checkerTxnId = helper.generateTxnId(15);
|
|
|
|
|
String requestId = transactionStatusRequest.getReqId();
|
|
|
|
|
// START log for internal transaction status check
|
|
|
|
|
LOGGER.info("[{}] START (internal) | checkTxnId={} | reqId={} | bankTxnId={}", apiName, txnId, requestId,
|
|
|
|
|
LOGGER.info("[{}] START (internal) | checkTxnId={} | reqId={} | bankTxnId={}", apiName, checkerTxnId, requestId,
|
|
|
|
|
transactionStatusRequest.getTxnId());
|
|
|
|
|
|
|
|
|
|
String url = paymentUrl + BBPSConstant.CHECK_TRANSACTION_URL + transactionStatusRequest.getTxnId();
|
|
|
|
@@ -282,21 +192,20 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
|
|
|
|
|
HttpHeaders headers = helper.buildHeaders(headersData);
|
|
|
|
|
|
|
|
|
|
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, url, BBPSConstant.HTTP_GET,
|
|
|
|
|
OutboundTraceLog outboundLog = helper.createOutboundLog(checkerTxnId, requestId, apiName, url, BBPSConstant.HTTP_GET,
|
|
|
|
|
null);
|
|
|
|
|
LOGGER.debug("Outbound log created for internal status check | txnId={} | reqId={}", txnId, requestId);
|
|
|
|
|
LOGGER.debug("Outbound log created for internal status check | txnId={} | reqId={}", checkerTxnId, requestId);
|
|
|
|
|
|
|
|
|
|
Map<String, String> responseMap = httpService.getRequest(url, headers);
|
|
|
|
|
String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY);
|
|
|
|
|
LOGGER.info("Transaction status response: {}", responseData);
|
|
|
|
|
|
|
|
|
|
helper.updateOutboundLogResponse(outboundLog, responseData);
|
|
|
|
|
LOGGER.debug("Outbound log response updated for internal status check | txnId={}", txnId);
|
|
|
|
|
LOGGER.debug("Outbound log response updated for internal status check | txnId={}", checkerTxnId);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Map<String, Object> dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE);
|
|
|
|
|
LOGGER.warn("Invalid transaction status response for txnId={}", transactionStatusRequest.getTxnId());
|
|
|
|
@@ -306,38 +215,83 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TransactionStatusResponse responseWrapper = objectMapper.convertValue(dataMap,
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
GeneralResp generalResp = responseWrapper.getGeneralResp();
|
|
|
|
|
LOGGER.info("Transaction status received: {}", generalResp.getStatus());
|
|
|
|
|
|
|
|
|
|
TransactionMaster transactionMaster = modelMapper.map(responseWrapper.getTransactionDAO(),
|
|
|
|
|
// Map DTO -> Entity, but explicitly copy bankTxnId from DTO to entity to avoid mapping gaps
|
|
|
|
|
TransactionDTO txDao = responseWrapper.getTransactionDAO();
|
|
|
|
|
|
|
|
|
|
TransactionMaster transactionMaster = modelMapper.map(txDao,
|
|
|
|
|
TransactionMaster.class);
|
|
|
|
|
transactionMaster.setTxnId(txnId);
|
|
|
|
|
LOGGER.info("INBOPUND TRANSACTION ID:{}",inboundLog.getTxnId());
|
|
|
|
|
TransactionMaster
|
|
|
|
|
existingTransaction=transactionMasterRepository.findByInitiatorTxnId(
|
|
|
|
|
inboundLog.getTxnId());
|
|
|
|
|
LOGGER.info("existingTransaction :{}",existingTransaction);
|
|
|
|
|
|
|
|
|
|
if(existingTransaction != null) {
|
|
|
|
|
LOGGER.info("Existing TransactionMaster found for bankTxnId");
|
|
|
|
|
// Merge incoming non-null fields into the existing DB entity so we preserve DB values
|
|
|
|
|
mergeNonNullFields(transactionMaster, existingTransaction);
|
|
|
|
|
transactionMaster = existingTransaction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ensure bankTxnId from DTO is set if provided
|
|
|
|
|
if (txDao != null && txDao.getBankTxnId() != null && !txDao.getBankTxnId().isBlank()) {
|
|
|
|
|
transactionMaster.setBankTxnId(txDao.getBankTxnId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do not overwrite existing txnId if present; set checker txn id when missing
|
|
|
|
|
if (transactionMaster.getTxnId() == null || transactionMaster.getTxnId().isBlank()) {
|
|
|
|
|
transactionMaster.setTxnId(checkerTxnId);
|
|
|
|
|
}
|
|
|
|
|
transactionMaster.setCheckerTxnId(checkerTxnId);
|
|
|
|
|
transactionMaster.setReqId(transactionStatusRequest.getReqId());
|
|
|
|
|
transactionMaster.setMid(transactionStatusRequest.getMid());
|
|
|
|
|
transactionMaster.setClientUserId(transactionStatusRequest.getClientUserId());
|
|
|
|
|
EntityRelationshipUtil.linkTransactionMasterRelationships(transactionMaster);
|
|
|
|
|
// Ensure internal txnId is unique; if collisions occur append suffix (_1, _2...)
|
|
|
|
|
transactionMaster.setTxnId(makeUniqueTxnId(transactionMaster.getTxnId()));
|
|
|
|
|
saveTransactionMasterWithRetry(transactionMaster);
|
|
|
|
|
LOGGER.info("TransactionMaster saved successfully for txnId={}", txnId);
|
|
|
|
|
// Ensure internal txnId exists
|
|
|
|
|
transactionMaster.setTxnId(ensureTxnId(transactionMaster.getTxnId()));
|
|
|
|
|
|
|
|
|
|
AgentFundTransfer agentFundTransfer = modelMapper.map(responseWrapper.getAgentFundTransfer(),
|
|
|
|
|
AgentFundTransfer.class);
|
|
|
|
|
agentFundTransfer.setTxnId(txnId);
|
|
|
|
|
agentFundTransfer.setReqId(transactionStatusRequest.getReqId());
|
|
|
|
|
agentFundTransfer.setTransactionMasterId(transactionMaster.getBankTxnId());
|
|
|
|
|
agentFundTransferRepository.save(agentFundTransfer);
|
|
|
|
|
LOGGER.info("AgentFundTransfer entry saved successfully for txnId={}", txnId);
|
|
|
|
|
// If bankTxnId (primary key) is missing, assign a placeholder so the entity can be saved
|
|
|
|
|
if (transactionMaster.getBankTxnId() == null || transactionMaster.getBankTxnId().isBlank()) {
|
|
|
|
|
String placeholderBankId = "GEN_" + transactionMaster.getTxnId();
|
|
|
|
|
transactionMaster.setBankTxnId(placeholderBankId);
|
|
|
|
|
LOGGER.warn("bankTxnId missing in response; assigning placeholder bankTxnId={} for txnId={}", placeholderBankId, transactionMaster.getTxnId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Map and persist AgentFundTransfer if present
|
|
|
|
|
AgentFundTransfer agentFundTransfer = null;
|
|
|
|
|
try {
|
|
|
|
|
if (responseWrapper.getAgentFundTransfer() != null) {
|
|
|
|
|
agentFundTransfer = modelMapper.map(responseWrapper.getAgentFundTransfer(), AgentFundTransfer.class);
|
|
|
|
|
} else {
|
|
|
|
|
agentFundTransfer = new AgentFundTransfer();
|
|
|
|
|
}
|
|
|
|
|
agentFundTransfer.setTxnId(transactionMaster.getTxnId());
|
|
|
|
|
agentFundTransfer.setReqId(transactionStatusRequest.getReqId());
|
|
|
|
|
agentFundTransfer.setTransactionMasterId(transactionMaster.getBankTxnId());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.debug("No AgentFundTransfer in response or mapping failed: {}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Persist updated transaction master and agent fund transfer so DB reflects merged non-null fields
|
|
|
|
|
try {
|
|
|
|
|
transactionMasterRepository.save(transactionMaster);
|
|
|
|
|
if (agentFundTransfer != null) { agentFundTransferRepository.save(agentFundTransfer); }
|
|
|
|
|
LOGGER.info("Persisted TransactionMaster and AgentFundTransfer for txnId={} bankTxnId={}"
|
|
|
|
|
, transactionMaster.getTxnId(), transactionMaster.getBankTxnId());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.warn("Failed to persist TransactionMaster/AgentFundTransfer for txnId={}: {}", transactionMaster.getTxnId(), e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
|
|
|
|
|
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
|
|
|
|
|
|
|
|
|
|
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
|
|
|
|
|
LOGGER.info("[{}] END (internal) | checkTxnId={} | reqId={} | status={}", apiName, txnId, requestId,
|
|
|
|
|
generalResp.getStatus());
|
|
|
|
|
LOGGER.info("[{}] END (internal) | checkTxnId={} | reqId={} | status={}", apiName, checkerTxnId, requestId, generalResp.getStatus());
|
|
|
|
|
return responseModel;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
LOGGER.error("Error parsing transaction status JSON: {}", e.getMessage(), e);
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
|
|
|
@@ -348,68 +302,141 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
@Override
|
|
|
|
|
public ResponseModel checkTrasactionStatus(TransactionStatusRequest transactionStatusRequest) {
|
|
|
|
|
helper.validateMerchant(transactionStatusRequest.getMid());
|
|
|
|
|
String txnID = helper.generateTxnId(15);
|
|
|
|
|
String apiName = BBPSConstant.API_CHECK_TRANSACTION_PUBLIC;
|
|
|
|
|
String requestId = transactionStatusRequest.getReqId();
|
|
|
|
|
LOGGER.info("[{}] START (public) | reqId={} | mid={} | checkBankTxnId={}", apiName, requestId,
|
|
|
|
|
transactionStatusRequest.getMid(), transactionStatusRequest.getTxnId());
|
|
|
|
|
String requestJson = helper.convertObjectToJson(transactionStatusRequest);
|
|
|
|
|
String url = paymentUrl + BBPSConstant.CHECK_TRANSACTION_URL + transactionStatusRequest.getTxnId();
|
|
|
|
|
String txnID = helper.generateTxnId(15);
|
|
|
|
|
String apiName = BBPSConstant.API_CHECK_TRANSACTION_PUBLIC;
|
|
|
|
|
String requestId = transactionStatusRequest.getReqId();
|
|
|
|
|
LOGGER.info("[{}] START (public) | reqId={} | mid={} | checkBankTxnId={}", apiName, requestId,
|
|
|
|
|
transactionStatusRequest.getMid(), transactionStatusRequest.getTxnId());
|
|
|
|
|
String requestJson = helper.convertObjectToJson(transactionStatusRequest);
|
|
|
|
|
String url = paymentUrl + BBPSConstant.CHECK_TRANSACTION_URL + transactionStatusRequest.getTxnId();
|
|
|
|
|
|
|
|
|
|
LOGGER.info("Checking transaction status (public) for txnId={} and reqId={}",
|
|
|
|
|
transactionStatusRequest.getTxnId(), requestId);
|
|
|
|
|
LOGGER.info("Checking transaction status (public) for txnId={} and reqId{}",
|
|
|
|
|
transactionStatusRequest.getTxnId(), requestId);
|
|
|
|
|
|
|
|
|
|
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
|
|
|
|
|
HttpHeaders headers = helper.buildHeaders(headersData);
|
|
|
|
|
// First, attempt to find an existing TransactionMaster by initiatorTxnId and update it
|
|
|
|
|
try {
|
|
|
|
|
String initiatorTxnId = transactionStatusRequest.getTxnId();
|
|
|
|
|
if (initiatorTxnId != null && !initiatorTxnId.isBlank()) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
// Log but continue to fallback behavior
|
|
|
|
|
LOGGER.warn("Error while updating by initiatorTxnId: {}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
InboundTraceLog inboundLog = helper.createInboundLog(requestId, txnID, apiName,
|
|
|
|
|
transactionStatusRequest.getMid(), BBPSConstant.HTTP_POST, requestJson);
|
|
|
|
|
LOGGER.debug("Inbound log created for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
OutboundTraceLog outboundLog = helper.createOutboundLog(txnID, requestId, apiName, url, BBPSConstant.HTTP_GET,
|
|
|
|
|
null);
|
|
|
|
|
LOGGER.debug("Outbound log created for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
LOGGER.info("Falling back to external BBPS status check URL={}", url);
|
|
|
|
|
|
|
|
|
|
Map<String, String> responseMap = httpService.getRequest(url, headers);
|
|
|
|
|
String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY);
|
|
|
|
|
LOGGER.info("Transaction status response data: {}", responseData);
|
|
|
|
|
helper.updateOutboundLogResponse(outboundLog, responseData);
|
|
|
|
|
LOGGER.debug("Outbound log response updated for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
|
|
|
|
|
HttpHeaders headers = helper.buildHeaders(headersData);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
Map<String, Object> dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, responseData,
|
|
|
|
|
String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)));
|
|
|
|
|
LOGGER.warn("Invalid transaction status response for txnId={} from BBPS",
|
|
|
|
|
transactionStatusRequest.getTxnId());
|
|
|
|
|
throw new CustomException(String.valueOf(dataMap.get("message")), String.valueOf(dataMap.get("status")),
|
|
|
|
|
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))),
|
|
|
|
|
String.valueOf(dataMap.get("remarks")));
|
|
|
|
|
}
|
|
|
|
|
InboundTraceLog inboundLog = helper.createInboundLog(requestId, txnID, apiName,
|
|
|
|
|
transactionStatusRequest.getMid(), BBPSConstant.HTTP_POST, requestJson);
|
|
|
|
|
LOGGER.debug("Inbound log created for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
OutboundTraceLog outboundLog = helper.createOutboundLog(txnID, requestId, apiName, url, BBPSConstant.HTTP_GET,
|
|
|
|
|
null);
|
|
|
|
|
LOGGER.debug("Outbound log created for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
|
|
|
|
|
TransactionStatusResponse responseWrapper = objectMapper.convertValue(dataMap,
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
GeneralResp generalResp = responseWrapper.getGeneralResp();
|
|
|
|
|
Map<String, String> responseMap = httpService.getRequest(url, headers);
|
|
|
|
|
String responseData = responseMap.get(BBPSConstant.RESPONSE_DATA_KEY);
|
|
|
|
|
LOGGER.info("Transaction status response data: {}", responseData);
|
|
|
|
|
helper.updateOutboundLogResponse(outboundLog, responseData);
|
|
|
|
|
LOGGER.debug("Outbound log response updated for public status check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
|
|
|
|
|
String status = generalResp.getStatus();
|
|
|
|
|
LOGGER.info("Current transaction status: {}", status);
|
|
|
|
|
try {
|
|
|
|
|
Map<String, Object> dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, responseData,
|
|
|
|
|
String.valueOf(dataMap.get(BBPSConstant.RESPONSE_STATUS_KEY)));
|
|
|
|
|
LOGGER.warn("Invalid transaction status response for txnId={} from BBPS",
|
|
|
|
|
transactionStatusRequest.getTxnId());
|
|
|
|
|
throw new CustomException(String.valueOf(dataMap.get("message")), String.valueOf(dataMap.get("status")),
|
|
|
|
|
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))),
|
|
|
|
|
String.valueOf(dataMap.get("remarks")));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
|
|
|
|
|
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
|
|
|
|
|
TransactionStatusResponse responseWrapper = objectMapper.convertValue(dataMap,
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
GeneralResp generalResp = responseWrapper.getGeneralResp();
|
|
|
|
|
|
|
|
|
|
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
|
|
|
|
|
LOGGER.info("[{}] END (public) | reqId={} | txnId={} | status={}", apiName, requestId, txnID,
|
|
|
|
|
generalResp.getStatus());
|
|
|
|
|
return responseModel;
|
|
|
|
|
String status = generalResp.getStatus();
|
|
|
|
|
LOGGER.info("Current transaction status: {}", status);
|
|
|
|
|
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
LOGGER.error("Error parsing responseData JSON: {}", e.getMessage(), e);
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
|
|
|
|
throw new CustomException(BBPSConstant.MSG_INVALID_JSON_FROM_UPSTREAM,BBPSConstant.FAILED_STATUS, BBPSConstant.INVALID_JSON_STATUS_CODE, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// --- NEW: attempt to persist/update TransactionMaster so DB reflects new status/bankTxnId ---
|
|
|
|
|
try {
|
|
|
|
|
TransactionDTO txDao = responseWrapper.getTransactionDAO();
|
|
|
|
|
TransactionMaster updatedEntity = null;
|
|
|
|
|
|
|
|
|
|
// 1) Try to find by initiatorTxnId (client may pass initiator txn id)
|
|
|
|
|
if (transactionStatusRequest.getTxnId() != null && !transactionStatusRequest.getTxnId().isBlank()) {
|
|
|
|
|
TransactionMaster byInitiator = transactionMasterRepository.findByInitiatorTxnId(transactionStatusRequest.getTxnId());
|
|
|
|
|
if (byInitiator != null) {
|
|
|
|
|
updatedEntity = byInitiator;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2) If not found, try find by internal txnId (txn_id column)
|
|
|
|
|
if (updatedEntity == null && txDao != null && txDao.getBankTxnId() != null && !txDao.getBankTxnId().isBlank()) {
|
|
|
|
|
try {
|
|
|
|
|
java.util.List<TransactionMaster> byTxnIdList = transactionMasterRepository.findByTxnId(txDao.getBankTxnId());
|
|
|
|
|
if (byTxnIdList != null && !byTxnIdList.isEmpty()) {
|
|
|
|
|
updatedEntity = byTxnIdList.get(0);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
|
LOGGER.debug("Error while searching by txnId: {}", ignore.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3) As a last attempt, if request passed an id that matches internal txnId column
|
|
|
|
|
if (updatedEntity == null && transactionStatusRequest.getTxnId() != null && !transactionStatusRequest.getTxnId().isBlank()) {
|
|
|
|
|
try {
|
|
|
|
|
java.util.List<TransactionMaster> byTxnIdList2 = transactionMasterRepository.findByTxnId(transactionStatusRequest.getTxnId());
|
|
|
|
|
if (byTxnIdList2 != null && !byTxnIdList2.isEmpty()) {
|
|
|
|
|
updatedEntity = byTxnIdList2.get(0);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception ignore) {
|
|
|
|
|
LOGGER.debug("Error while searching by txnId (fallback): {}", ignore.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we found an entity, merge non-null fields from DTO and save
|
|
|
|
|
if (updatedEntity != null) {
|
|
|
|
|
TransactionMaster mapped = modelMapper.map(txDao, TransactionMaster.class);
|
|
|
|
|
mergeNonNullFields(mapped, updatedEntity);
|
|
|
|
|
// ensure internal txnId exists
|
|
|
|
|
updatedEntity.setTxnId(ensureTxnId(updatedEntity.getTxnId()));
|
|
|
|
|
EntityRelationshipUtil.linkTransactionMasterRelationships(updatedEntity);
|
|
|
|
|
try {
|
|
|
|
|
transactionMasterRepository.save(updatedEntity);
|
|
|
|
|
LOGGER.info("Updated TransactionMaster in DB for initiatorTxnId={} (bankTxnId={})",
|
|
|
|
|
updatedEntity.getInitiatorTxnId(), updatedEntity.getBankTxnId());
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.warn("Failed to persist updated TransactionMaster: {}", e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
LOGGER.debug("No matching TransactionMaster found to update for txnId={}", transactionStatusRequest.getTxnId());
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
LOGGER.warn("Error while attempting to persist transaction status update: {}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
// --- END NEW PERSISTENCE BLOCK ---
|
|
|
|
|
|
|
|
|
|
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
|
|
|
|
|
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
|
|
|
|
|
|
|
|
|
|
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
|
|
|
|
|
LOGGER.info("[{}] END (public) | reqId={} | txnId={} | status={}", apiName, requestId, txnID,
|
|
|
|
|
generalResp.getStatus());
|
|
|
|
|
return responseModel;
|
|
|
|
|
|
|
|
|
|
} catch (JsonProcessingException e) {
|
|
|
|
|
LOGGER.error("Error parsing responseData JSON: {}", e.getMessage(), e);
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
|
|
|
|
throw new CustomException(BBPSConstant.MSG_INVALID_JSON_FROM_UPSTREAM,BBPSConstant.FAILED_STATUS, BBPSConstant.INVALID_JSON_STATUS_CODE, e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public ResponseModel checkTrasactionStatusByClientReqId(
|
|
|
|
@@ -471,14 +498,14 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
LOGGER.debug("Outbound log response updated for clientReqId check | reqId={} | txnId={}", requestId, txnID);
|
|
|
|
|
|
|
|
|
|
Map<String, Object> dataMap = objectMapper.readValue(responseData,
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
new TypeReference<Map<String, Object>>() {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!dataMap.containsKey(BBPSConstant.RESPONSE_GENERAL_RESP)) {
|
|
|
|
|
helper.updateInboundLogFailure(inboundLog, responseData, BBPSConstant.INVALID_RESPONSE);
|
|
|
|
|
|
|
|
|
|
LOGGER.warn("Invalid transaction status response for clientReqId={} | Response={}", clientReqId,
|
|
|
|
|
responseData);
|
|
|
|
|
responseData);
|
|
|
|
|
|
|
|
|
|
throw new CustomException(String.valueOf(dataMap.get("message")), String.valueOf(dataMap.get("status")),
|
|
|
|
|
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))),
|
|
|
|
@@ -486,7 +513,7 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TransactionStatusResponse responseWrapper = objectMapper.convertValue(dataMap,
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
TransactionStatusResponse.class);
|
|
|
|
|
|
|
|
|
|
GeneralResp generalResp = responseWrapper.getGeneralResp();
|
|
|
|
|
|
|
|
|
@@ -494,7 +521,7 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
|
|
|
|
|
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
|
|
|
|
|
LOGGER.info("[{}] END | reqId={} | clientReqId={} | status={}", apiName, requestId, clientReqId,
|
|
|
|
|
generalResp.getStatus());
|
|
|
|
|
generalResp.getStatus());
|
|
|
|
|
return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
|
|
|
|
|
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
|
|
|
|
|
|
|
|
|
@@ -506,51 +533,78 @@ public class PaymentServiceImpl implements PaymentService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Ensure the provided internal txnId is unique in bbps_transaction_master.txn_id.
|
|
|
|
|
* If a record already exists with the same txnId, append _1, _2, ... until unique.
|
|
|
|
|
* Return the provided txnId or generate a new one when the provided value is null/blank.
|
|
|
|
|
* This intentionally does NOT try to ensure database-level uniqueness (no suffixing or retries).
|
|
|
|
|
*/
|
|
|
|
|
private String makeUniqueTxnId(String baseTxnId) {
|
|
|
|
|
if (baseTxnId == null || baseTxnId.isBlank()) return baseTxnId;
|
|
|
|
|
List<TransactionMaster> existing = transactionMasterRepository.findByTxnId(baseTxnId);
|
|
|
|
|
if (existing == null || existing.isEmpty()) {
|
|
|
|
|
return baseTxnId;
|
|
|
|
|
}
|
|
|
|
|
int suffix = 1;
|
|
|
|
|
String candidate;
|
|
|
|
|
while (true) {
|
|
|
|
|
candidate = baseTxnId + "_" + suffix;
|
|
|
|
|
List<TransactionMaster> coll = transactionMasterRepository.findByTxnId(candidate);
|
|
|
|
|
if (coll == null || coll.isEmpty()) {
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
suffix++;
|
|
|
|
|
private String ensureTxnId(String txnId) {
|
|
|
|
|
if (txnId == null || txnId.isBlank()) {
|
|
|
|
|
return helper.generateTxnId(15);
|
|
|
|
|
}
|
|
|
|
|
return txnId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Try to save TransactionMaster and handle unique txnId collisions that may occur under concurrency.
|
|
|
|
|
* This method will attempt to save up to maxAttempts; on duplicate collision it will append a numeric suffix.
|
|
|
|
|
* Merge non-null fields from src into dest. This keeps existing DB fields when the incoming
|
|
|
|
|
* payload doesn't provide them. Only non-null (and for Strings, non-blank) fields from src
|
|
|
|
|
* will overwrite dest fields.
|
|
|
|
|
*/
|
|
|
|
|
private void saveTransactionMasterWithRetry(TransactionMaster transactionMaster) {
|
|
|
|
|
final int maxAttempts = 5;
|
|
|
|
|
String baseTxnId = transactionMaster.getTxnId();
|
|
|
|
|
for (int attempt = 0; attempt < maxAttempts; attempt++) {
|
|
|
|
|
try {
|
|
|
|
|
if (attempt == 0) {
|
|
|
|
|
transactionMaster.setTxnId(makeUniqueTxnId(baseTxnId));
|
|
|
|
|
} else {
|
|
|
|
|
transactionMaster.setTxnId(baseTxnId + "_" + attempt);
|
|
|
|
|
}
|
|
|
|
|
transactionMasterRepository.save(transactionMaster);
|
|
|
|
|
return; // success
|
|
|
|
|
} catch (org.springframework.dao.DataIntegrityViolationException dex) {
|
|
|
|
|
LOGGER.warn("Duplicate txnId detected when saving TransactionMaster (attempt {}) for baseTxnId={}: {}", attempt, baseTxnId, dex.getMessage());
|
|
|
|
|
// retry with next suffix
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// if we reach here, all attempts failed
|
|
|
|
|
LOGGER.error("Failed to save TransactionMaster after {} attempts for baseTxnId={}", maxAttempts, transactionMaster.getTxnId());
|
|
|
|
|
throw new CustomException("Unable to save TransactionMaster due to txnId collisions", BBPSConstant.FAILED_STATUS, 500, "Duplicate txnId");
|
|
|
|
|
private void mergeNonNullFields(TransactionMaster src, TransactionMaster dest) {
|
|
|
|
|
/*
|
|
|
|
|
* LOGGER.info("TransactionMaster src: {}", src);
|
|
|
|
|
*/ // Only copy values that are non-null (and non-blank for Strings)
|
|
|
|
|
|
|
|
|
|
if (src.getTxnId() != null && !src.getTxnId().isBlank()) dest.setTxnId(src.getTxnId());
|
|
|
|
|
if (src.getInitiatorTxnId() != null && !src.getInitiatorTxnId().isBlank()) dest.setInitiatorTxnId(src.getInitiatorTxnId());
|
|
|
|
|
if (src.getCheckerTxnId() != null && !src.getCheckerTxnId().isBlank()) dest.setCheckerTxnId(src.getCheckerTxnId());
|
|
|
|
|
if (src.getReqId() != null && !src.getReqId().isBlank()) dest.setReqId(src.getReqId());
|
|
|
|
|
if (src.getMid() != null && !src.getMid().isBlank()) dest.setMid(src.getMid());
|
|
|
|
|
if (src.getClientUserId() != null && !src.getClientUserId().isBlank()) dest.setClientUserId(src.getClientUserId());
|
|
|
|
|
if (src.getClientReqId() != null && !src.getClientReqId().isBlank()) dest.setClientReqId(src.getClientReqId());
|
|
|
|
|
if (src.getUserId() != null && !src.getUserId().isBlank()) dest.setUserId(src.getUserId());
|
|
|
|
|
if (src.getBillerId() != null && !src.getBillerId().isBlank()) dest.setBillerId(src.getBillerId());
|
|
|
|
|
if (src.getTxnAmount() != null) dest.setTxnAmount(src.getTxnAmount());
|
|
|
|
|
if (src.getStatus() != null && !src.getStatus().isBlank()) dest.setStatus(src.getStatus());
|
|
|
|
|
if (src.getPaymentInformation() != null && !src.getPaymentInformation().isBlank()) dest.setPaymentInformation(src.getPaymentInformation());
|
|
|
|
|
if (src.getCreationDateBank() != null) dest.setCreationDateBank(src.getCreationDateBank());
|
|
|
|
|
if (src.getModifiedDateBank() != null) dest.setModifiedDateBank(src.getModifiedDateBank());
|
|
|
|
|
if (src.getCreatedEpochDateBank() != null) dest.setCreatedEpochDateBank(src.getCreatedEpochDateBank());
|
|
|
|
|
if (src.getModifiedEpochDateBank() != null) dest.setModifiedEpochDateBank(src.getModifiedEpochDateBank());
|
|
|
|
|
|
|
|
|
|
/* ---- additional fields ---- */
|
|
|
|
|
if (src.getRefId() != null && !src.getRefId().isBlank()) dest.setRefId(src.getRefId());
|
|
|
|
|
if (src.getPaymentRefId() != null && !src.getPaymentRefId().isBlank()) dest.setPaymentRefId(src.getPaymentRefId());
|
|
|
|
|
if (src.getRemitterName() != null && !src.getRemitterName().isBlank()) dest.setRemitterName(src.getRemitterName());
|
|
|
|
|
if (src.getOrderId() != null && !src.getOrderId().isBlank()) dest.setOrderId(src.getOrderId());
|
|
|
|
|
if (src.getBillId() != null && !src.getBillId().isBlank()) dest.setBillId(src.getBillId());
|
|
|
|
|
if (src.getUserType() != null && !src.getUserType().isBlank()) dest.setUserType(src.getUserType());
|
|
|
|
|
if (src.getTotalTxnAmount() != null) dest.setTotalTxnAmount(src.getTotalTxnAmount());
|
|
|
|
|
if (src.getBillerCategory() != null && !src.getBillerCategory().isBlank()) dest.setBillerCategory(src.getBillerCategory());
|
|
|
|
|
if (src.getBillerName() != null && !src.getBillerName().isBlank()) dest.setBillerName(src.getBillerName());
|
|
|
|
|
if (src.getOffUsPay() != null) dest.setOffUsPay(src.getOffUsPay());
|
|
|
|
|
if (src.getSplitPay() != null) dest.setSplitPay(src.getSplitPay());
|
|
|
|
|
if (src.getQuickPay() != null) dest.setQuickPay(src.getQuickPay());
|
|
|
|
|
if (src.getPaymentMode() != null && !src.getPaymentMode().isBlank()) dest.setPaymentMode(src.getPaymentMode());
|
|
|
|
|
if (src.getAgentPaymentInformation() != null && !src.getAgentPaymentInformation().isBlank()) dest.setAgentPaymentInformation(src.getAgentPaymentInformation());
|
|
|
|
|
if (src.getCustConvFee() != null) dest.setCustConvFee(src.getCustConvFee());
|
|
|
|
|
if (src.getCurrency() != null && !src.getCurrency().isBlank()) dest.setCurrency(src.getCurrency());
|
|
|
|
|
if (src.getRequestedIp() != null && !src.getRequestedIp().isBlank()) dest.setRequestedIp(src.getRequestedIp());
|
|
|
|
|
if (src.getCustomerMobNo() != null && !src.getCustomerMobNo().isBlank()) dest.setCustomerMobNo(src.getCustomerMobNo());
|
|
|
|
|
if (src.getMacAddress() != null && !src.getMacAddress().isBlank()) dest.setMacAddress(src.getMacAddress());
|
|
|
|
|
if (src.getSplitPayAmount() != null) dest.setSplitPayAmount(src.getSplitPayAmount());
|
|
|
|
|
if (src.getCouCustConvFee() != null) dest.setCouCustConvFee(src.getCouCustConvFee());
|
|
|
|
|
if (src.getSettlementVerification() != null) dest.setSettlementVerification(src.getSettlementVerification());
|
|
|
|
|
if (src.getFundTxnType() != null && !src.getFundTxnType().isBlank()) dest.setFundTxnType(src.getFundTxnType());
|
|
|
|
|
if (src.getReason() != null && !src.getReason().isBlank()) dest.setReason(src.getReason());
|
|
|
|
|
if (src.getAmountTags() != null && !src.getAmountTags().isBlank()) dest.setAmountTags(src.getAmountTags());
|
|
|
|
|
if (src.getPlanId() != null && !src.getPlanId().isBlank()) dest.setPlanId(src.getPlanId());
|
|
|
|
|
if (src.getPlanType() != null && !src.getPlanType().isBlank()) dest.setPlanType(src.getPlanType());
|
|
|
|
|
if (src.getTxnNpciId() != null && !src.getTxnNpciId().isBlank()) dest.setTxnNpciId(src.getTxnNpciId());
|
|
|
|
|
|
|
|
|
|
/* ---- lists (direct replace when provided) ---- */
|
|
|
|
|
if (src.getDeviceBlockTags() != null && !src.getDeviceBlockTags().isEmpty()) dest.setDeviceBlockTags(src.getDeviceBlockTags());
|
|
|
|
|
if (src.getCustomerParams() != null && !src.getCustomerParams().isEmpty()) dest.setCustomerParams(src.getCustomerParams());
|
|
|
|
|
|
|
|
|
|
LOGGER.info("TransactionMaster dest after merge: {}", dest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|