Files
bbps-backend/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java
T

406 lines
17 KiB
Java

package com.billpaymentservice.bbps.serviceImpl;
import java.time.LocalDateTime;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import com.billpaymentservice.bbps.dto.GeneralResp;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.BillFetchByBillIdRequest;
import com.billpaymentservice.bbps.dto.request.FetchBillRequest;
import com.billpaymentservice.bbps.dto.request.FetchBillValidatestRequest;
import com.billpaymentservice.bbps.dto.response.BillDataResponse;
import com.billpaymentservice.bbps.dto.response.FetchBillResponse;
import com.billpaymentservice.bbps.dto.response.FetchBillValidatestResponse;
import com.billpaymentservice.bbps.entites.BharatConnectMaster;
import com.billpaymentservice.bbps.entites.InboundTraceLog;
import com.billpaymentservice.bbps.entites.OutboundTraceLog;
import com.billpaymentservice.bbps.exception.CustomException;
import com.billpaymentservice.bbps.repository.BharatConnectMasterRepository;
import com.billpaymentservice.bbps.repository.InboundTraceLogRepository;
import com.billpaymentservice.bbps.repository.OutboundTraceLogRepository;
import com.billpaymentservice.bbps.service.AgentService;
import com.billpaymentservice.bbps.util.BBPSConstant;
import com.billpaymentservice.bbps.util.Helper;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class AgentServiceImpl implements AgentService {
@Value("${agent.data.url}")
private String agentDtaUrl;
private final RestClient restClient;
private final HttpService httpService;
private final Helper helper;
private final BharatConnectMasterRepository beneficiaryDetailsRepository;
public AgentServiceImpl(RestClient restClient, HttpService httpService, Helper helper,
BharatConnectMasterRepository beneficiaryDetailsRepository,InboundTraceLogRepository inboundTraceLogRepository,
OutboundTraceLogRepository outboundTraceLogRepository) {
this.restClient = restClient;
this.httpService = httpService;
this.helper = helper;
this.beneficiaryDetailsRepository = beneficiaryDetailsRepository;
}
@Override
public ResponseModel initiateBillFetch(FetchBillRequest fetchBillRequest) {
String apiName = "InitiateBillFetch";
String txnId = helper.generateTxnId(15);
String requestId = fetchBillRequest.getReqId();
String url = agentDtaUrl + BBPSConstant.BILL_FETCH_INTI;
helper.validateMerchant(fetchBillRequest.getMid());
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
String requestJson = helper.convertObjectToJson(fetchBillRequest);
// ✅ Create inbound & outbound logs
InboundTraceLog inboundLog = helper.createInboundLog(requestId, txnId, apiName, fetchBillRequest.getMid(), "POST", requestJson);
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, url, "POST", requestJson);
try {
Map<String, String> responseMap = httpService.postRequest(url, requestJson, headers);
String responseData = responseMap.get("data");
log.info("📦 Bill Fetch API Response: {}", responseData);
helper.updateOutboundLogResponse(outboundLog, responseData);
if (responseData == null || responseData.isEmpty()) {
helper.updateInboundLogFailure(inboundLog, "Empty response from BBPS", "FAILED");
throw new CustomException("Empty response from BBPS server");
}
Map<String, Object> dataMap = objectMapper.readValue(responseData, new TypeReference<Map<String, Object>>() {});
if (!dataMap.containsKey("genericResponse")) {
helper.updateInboundLogFailure(inboundLog, responseData, "INVALID_STRUCTURE");
throw new CustomException("Invalid response structure from BBPS");
}
FetchBillResponse fetchBillResponse = objectMapper.convertValue(dataMap, FetchBillResponse.class);
GeneralResp generalResponse = fetchBillResponse.getGenericResponse();
helper.updateInboundLogSuccess(inboundLog, responseData, generalResponse.getStatus());
// ✅ Directly call fetchBillById (no polling)
BillFetchByBillIdRequest billFetchByBillIdRequest = new BillFetchByBillIdRequest();
billFetchByBillIdRequest.setBillId(fetchBillResponse.getBillId());
billFetchByBillIdRequest.setMid(fetchBillRequest.getMid());
billFetchByBillIdRequest.setReqId(requestId);
return fetchBillById(billFetchByBillIdRequest, inboundLog);
} catch (JsonProcessingException e) {
log.error("❌ JSON Parsing Error: {}", e.getMessage());
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR");
throw new CustomException("Invalid JSON received from API");
} catch (CustomException ce) {
throw ce;
} catch (Exception e) {
log.error("❌ Exception in initiateBillFetch(): {}", e.getMessage(), e);
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "EXCEPTION");
throw new CustomException("Bill Fetch initiation failed: " + e.getMessage());
}
}
public ResponseModel fetchBillById(BillFetchByBillIdRequest billFetchByBillIdRequest, InboundTraceLog inboundLog) {
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String requestId = billFetchByBillIdRequest.getReqId();
String billId = billFetchByBillIdRequest.getBillId();
String url = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + "1ced7566-1add-4e01-9ed6-04cd67ac9684";
helper.validateMerchant(billFetchByBillIdRequest.getMid());
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper objectMapper = new ObjectMapper();
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, url, "GET", null);
// ✅ Loop setup
long startTime = System.currentTimeMillis();
long maxWaitTimeMs = 40000; // 40 seconds
long intervalMs = 5000; // 5 seconds
while (true) {
try {
Map<String, String> responseMap = httpService.getRequest(url, headers);
String responseData = responseMap.get("data");
log.info("📦 Bill FetchById Response: {}", responseData);
helper.updateOutboundLogResponse(outboundLog, responseData);
Map<String, Object> dataMap = objectMapper.readValue(responseData, new TypeReference<Map<String, Object>>() {});
if (!dataMap.containsKey("genericResponse")) {
helper.updateInboundLogFailure(inboundLog, responseData, "INVALID_RESPONSE");
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"))
);
}
BillDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillDataResponse.class);
GeneralResp generalResp = responseWrapper.getGenericResponse();
String status = generalResp.getStatus();
log.info("📡 Current Bill Status: {}", status);
// ✅ Check for "INPROGRESS" or pending state
if ("INPROGRESS".equalsIgnoreCase(status)) {
if (System.currentTimeMillis() - startTime > maxWaitTimeMs) {
helper.updateInboundLogFailure(inboundLog, "Timeout after 40 seconds", "FAILED");
throw new CustomException("Timeout", "FAILED", 408, "Bill fetch still in progress");
}
Thread.sleep(intervalMs);
continue; // retry again
}
// ✅ Final successful response
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
return new ResponseModel(
generalResp.getMessage(),
generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()),
responseWrapper
);
} catch (JsonProcessingException e) {
log.error("Error parsing BillById JSON: {}", e.getMessage());
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR");
throw new CustomException("Invalid JSON received from API");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "INTERRUPTED");
throw new CustomException("Thread interrupted during bill status check");
}
}
}
@Override
public ResponseModel fetchBillById(BillFetchByBillIdRequest billFetchByBillIdRequest) {
try {
helper.validateMerchant(billFetchByBillIdRequest.getMid());
String billId = billFetchByBillIdRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + billId;
System.out.print(fullUrl);
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001");
HttpHeaders headers = new HttpHeaders();
headers.set("x-digiledge-key", headersData.getXDigiledgeKey());
headers.set("agentId", headersData.getAgentId());
headers.set("tenantId", headersData.getTenantId());
headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> responseMap = httpService.getRequest(fullUrl, headers);
String responseData = responseMap.get("data");
log.info("data is :{}", responseData);
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> dataMap = objectMapper.readValue(responseData,
new TypeReference<Map<String, Object>>() {
});
if (!dataMap.containsKey("genericResponse")) {
throw new CustomException(String.valueOf(dataMap.get("message")), // message
String.valueOf(dataMap.get("status")), // status
Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int)
String.valueOf(dataMap.get("remarks")));
}
BillDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillDataResponse.class);
GeneralResp generalResp = responseWrapper.getGenericResponse();
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
return responseModel;
} catch (JsonProcessingException e) {
log.error("Error parsing responseData JSON: {}", e.getMessage());
throw new CustomException("Invalid JSON received from API");
} catch (CustomException ex) {
log.warn("Merchant validation failed: {}", ex.getMessage());
return ex.getResponseModel(); // Directly return ResponseModel from exception
}
}
@Override
public ResponseModel initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
// TODO Auto-generated method stub
return null;
}
@Override
public ResponseModel initiateBillValidateByBillId(BillFetchByBillIdRequest billRequest) {
// TODO Auto-generated method stub
return null;
}
/*
* @Override public ResponseModel
* initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
*
* ResponseModel responseModel = new ResponseModel(); try {
*
* helper.validateMerchant(fetchBillValidateRequest.getMid());
*
* BharatConnectMaster headersData =
* beneficiaryDetailsRepository.findByOrgId("ORG001");
*
* if (headersData == null) { responseModel = new
* ResponseModel("Tenant Id Is Null", "Not Found", BBPSConstant.BADREQUEST,
* headersData); return responseModel; } HttpHeaders headers = new
* HttpHeaders(); headers.set("x-digiledge-key",
* headersData.getXDigiledgeKey()); headers.set("agentId",
* headersData.getAgentId()); headers.set("tenantId",
* headersData.getTenantId());
* headers.setContentType(MediaType.APPLICATION_JSON);
*
* ObjectMapper objectMapper = new ObjectMapper();
* objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String
* json = objectMapper.writeValueAsString(fetchBillValidateRequest); String url
* = agentDtaUrl + BBPSConstant.BILLER_VALIDATE_URL; Map<String, String>
* responseMap = httpService.postRequest(url, json, headers); String
* responseData = responseMap.get("data");
*
* log.info("📦 Bill Fetch API Response: {}", responseData);
*
* if (responseData == null || responseData.isEmpty()) { throw new
* CustomException("Empty response from BBPS server"); }
*
* // ✅ Convert JSON string → Map Map<String, Object> dataMap =
* objectMapper.readValue(responseData, new TypeReference<Map<String, Object>>()
* { });
*
* // ✅ Validate generalResp if (!dataMap.containsKey("genericResponse")) {
* throw new CustomException("Invalid response structure from BBPS"); }
*
* // ✅ Convert to your custom DTO FetchBillValidatestResponse fetchBillResponse
* = objectMapper.convertValue(dataMap, FetchBillValidatestResponse.class);
* GeneralResp generalResponse = fetchBillResponse.getGenericResponse();
*
* // ✅ Build final ResponseModel responseModel = new
* ResponseModel(generalResponse.getMessage(), generalResponse.getStatus(),
* Integer.parseInt(generalResponse.getStatusCode()), fetchBillResponse);
*
* } catch (CustomException ex) { log.warn("Merchant validation failed: {}",
* ex.getMessage()); return ex.getResponseModel(); // Directly return
* ResponseModel from exception } catch (Exception e) {
* log.error("❌ Exception in initiateBillFetch(): {}", e.getMessage(), e);
* responseModel.setStatus("500");
* responseModel.setMessage("Exception occurred");
* responseModel.setData(e.getMessage()); }
*
* return responseModel; }
*
* @Override public ResponseModel
* initiateBillValidateByBillId(BillFetchByBillIdRequest billRequest) {
*
* ResponseModel responseModel = new ResponseModel(); try {
* helper.validateMerchant(billRequest.getMid());
*
* BharatConnectMaster headersData =
* beneficiaryDetailsRepository.findByOrgId("ORG001");
*
* if (headersData == null) { responseModel = new
* ResponseModel("Tenant Id Is Null", "Not Found", BBPSConstant.BADREQUEST,
* headersData); return responseModel; }
*
* HttpHeaders headers = new HttpHeaders(); headers.set("x-digiledge-key",
* headersData.getXDigiledgeKey()); headers.set("agentId",
* headersData.getAgentId()); headers.set("tenantId",
* headersData.getTenantId());
* headers.setContentType(MediaType.APPLICATION_JSON); ObjectMapper objectMapper
* = new ObjectMapper();
* objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); String
* json = objectMapper.writeValueAsString(billRequest); String url = agentDtaUrl
* + BBPSConstant.BILL_ID_URL + billRequest.getBillId();
*
* log.info("Full URL" + url);
* objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
*
* // ✅ Call the API using httpService Map<String, String> responseMap =
* httpService.getRequest(url, headers); String responseData =
* responseMap.get("data");
*
* log.info("📦 Bill Fetch API Response: {}", responseData);
*
* if (responseData == null || responseData.isEmpty()) { throw new
* CustomException("Empty response from BBPS server"); }
*
* // ✅ Convert JSON string → Map Map<String, Object> dataMap =
* objectMapper.readValue(responseData, new TypeReference<Map<String, Object>>()
* { });
*
* // ✅ Validate generalResp if (!dataMap.containsKey("genericResponse")) {
* throw new CustomException("Invalid response structure from BBPS"); }
*
* // ✅ Convert to your custom DTO BillDataResponse fetchBillResponse =
* objectMapper.convertValue(dataMap, BillDataResponse.class); GeneralResp
* generalResponse = fetchBillResponse.getGenericResponse();
*
* // ✅ Build final ResponseModel responseModel = new
* ResponseModel(generalResponse.getRemarks(), generalResponse.getStatus(),
* Integer.parseInt(generalResponse.getStatusCode()), fetchBillResponse);
*
* } catch (CustomException ex) { log.warn("Merchant validation failed: {}",
* ex.getMessage()); return ex.getResponseModel(); // Directly return
* ResponseModel from exception } catch (Exception e) {
* log.error("❌ Exception in initiateBillFetch(): {}", e.getMessage(), e);
* responseModel.setStatus("500");
* responseModel.setMessage("Exception occurred");
* responseModel.setData(e.getMessage()); }
*
* return responseModel;
*
* }
*/
}