added database for bill intitate and bill payment and removed the polling logic

This commit is contained in:
Lincpay Tech
2025-11-06 18:06:12 +05:30
parent 3497d4f288
commit 58db98cc06
13 changed files with 533 additions and 182 deletions
@@ -9,7 +9,7 @@ import lombok.Setter;
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class AdditionalInfoBill {
public class AdditionalInfoBillDTO {
private String additionalInfoId;
private String name;
private String value;
@@ -2,7 +2,7 @@ package com.billpaymentservice.bbps.dto.response;
import java.util.List;
import com.billpaymentservice.bbps.dto.AdditionalInfoBill;
import com.billpaymentservice.bbps.dto.AdditionalInfoBillDTO;
import com.billpaymentservice.bbps.dto.BillerResponseBill;
import com.billpaymentservice.bbps.dto.CustomerParamDAO;
import com.billpaymentservice.bbps.dto.GeneralResp;
@@ -31,7 +31,7 @@ public class BillDataResponse {
private String userId;
private BillerResponseBill billerResponse; // nested object
private List<AdditionalInfoBill> additionalInfo; // array of objects
private List<AdditionalInfoBillDTO> additionalInfo; // array of objects
private List<CustomerParamDAO> customerParams; // array of objects
private String creationDate;
@@ -0,0 +1,30 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "additional_info_bill")
@Getter
@Setter
public class AdditionalInfoBill {
@Id
@GeneratedValue
private Long id;
private String name;
private String value;
@ManyToOne
@JoinColumn(name = "bill_master_id")
private BillMaster billMaster;
}
@@ -0,0 +1,21 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.*;
import lombok.*;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "bill_initiate")
public class BillInitiate {
@Id
@Column(name = "req_id")
private String reqId;
@Column(name = "bill_id", nullable = false)
private String billId;
@Column(name = "txn_id")
private String txnId;
}
@@ -0,0 +1,52 @@
package com.billpaymentservice.bbps.entites;
import java.time.LocalDateTime;
import java.util.List;
import com.billpaymentservice.bbps.dto.BillerResponseBill;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Entity
@Table(name = "bill_master")
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class BillMaster {
@Id
private String billId; // primary key
private String reqId; // client se aaya hua
private String txnId; // system-generated
private String refId;
private String billerId;
private String status;
private String actionType;
private String userId;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "biller_response_id")
private BillerResponse billerResponse;
@OneToMany(mappedBy = "billMaster", cascade = CascadeType.ALL)
private List<AdditionalInfoBill> additionalInfo;
@OneToMany(mappedBy = "billMaster", cascade = CascadeType.ALL)
private List<CustomerParamBill> customerParams;
private String creationDate;
private String modifiedDate;
private Long createdEpochDate;
private Long modifiedEpochDate;
// getters and setters
}
@@ -17,7 +17,6 @@ import java.util.List;
@ToString
@Table(name = "biller_plan_response_params")
public class BillerPlanResponseParams {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // Primary Key
@@ -25,7 +24,6 @@ public class BillerPlanResponseParams {
@Column(name = "biller_plan_response_id", nullable = false, unique = true)
@NotBlank(message = "Biller Plan Response ID cannot be blank")
private String billerPlanResponseId;
// ✅ params list — since it's not a separate table, we can store as JSON or text
@Column(name = "params", columnDefinition = "TEXT")
private String paramsJson;
@@ -0,0 +1,60 @@
package com.billpaymentservice.bbps.entites;
import java.time.LocalDate;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "biller_response")
@Getter
@Setter
public class BillerResponse {
@Id
@GeneratedValue
private Long id;
@Column(name = "amount")
private String amount;
@Column(name = "bill_date")
private String billDate;
@Column(name = "bill_id")
private String billId;
@Column(name = "bill_number")
private String billNumber;
@Column(name = "bill_period")
private String billPeriod;
@Column(name = "cust_conv_fee")
private String custConvFee;
@Column(name = "cou_cust_conv_fee")
private String couCustConvFee;
@Column(name = "due_date")
private String dueDate;
@Column(name = "customer_name")
private String customerName;
@Column(name = "amount_option")
private Boolean amountOption;
@ManyToOne
@JoinColumn(name = "bill_master_id")
private BillMaster billMaster;
// getters and setters
}
@@ -17,7 +17,7 @@ public class BillerResponseParams {
@Column(name = "biller_response_id", nullable = false, unique = true)
@NotBlank(message = "Biller Response ID is required")
private String billerResponseId;
// 🔗 One-to-One Relationship with BillerDAO
@OneToOne
@JoinColumn(name = "biller_id", nullable = false)
@@ -0,0 +1,31 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
@Table(name = "customer_param_bill")
public class CustomerParamBill {
@Id
@GeneratedValue
private Long id;
private String name;
private String value;
private String type;
@ManyToOne
@JoinColumn(name = "bill_master_id")
private BillMaster billMaster;
// getters and setters
}
@@ -0,0 +1,11 @@
package com.billpaymentservice.bbps.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.billpaymentservice.bbps.entites.BillInitiate;
@Repository
public interface BillInitateRepository extends JpaRepository<BillInitiate, String> {
}
@@ -0,0 +1,9 @@
package com.billpaymentservice.bbps.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.billpaymentservice.bbps.entites.BillMaster;
public interface BillMasterRepository extends JpaRepository<BillMaster, String> {
}
@@ -18,10 +18,14 @@ 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.BillInitiate;
import com.billpaymentservice.bbps.entites.BillMaster;
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.BillInitateRepository;
import com.billpaymentservice.bbps.repository.BillMasterRepository;
import com.billpaymentservice.bbps.repository.InboundTraceLogRepository;
import com.billpaymentservice.bbps.repository.OutboundTraceLogRepository;
import com.billpaymentservice.bbps.service.AgentService;
@@ -45,14 +49,18 @@ public class AgentServiceImpl implements AgentService {
private final HttpService httpService;
private final Helper helper;
private final BharatConnectMasterRepository beneficiaryDetailsRepository;
private final BillMasterRepository billMasterRepository;
private final BillInitateRepository billIntiateRepository;
public AgentServiceImpl(RestClient restClient, HttpService httpService, Helper helper,
BharatConnectMasterRepository beneficiaryDetailsRepository,InboundTraceLogRepository inboundTraceLogRepository,
OutboundTraceLogRepository outboundTraceLogRepository) {
OutboundTraceLogRepository outboundTraceLogRepository, BillMasterRepository billMasterRepository,BillInitateRepository billIntiateRepository) {
this.restClient = restClient;
this.httpService = httpService;
this.helper = helper;
this.beneficiaryDetailsRepository = beneficiaryDetailsRepository;
this.billMasterRepository = billMasterRepository;
this. billIntiateRepository= billIntiateRepository;
}
@@ -88,41 +96,47 @@ public class AgentServiceImpl implements AgentService {
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");
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"))
);
}
BillMaster billMaster = new BillMaster();
billMaster.setBillId((String) dataMap.get("billId"));
billMaster.setReqId(fetchBillRequest.getReqId());
billMaster.setTxnId(txnId);
billMasterRepository.save(billMaster);
FetchBillResponse fetchBillResponse = objectMapper.convertValue(dataMap, FetchBillResponse.class);
GeneralResp generalResponse = fetchBillResponse.getGenericResponse();
helper.updateInboundLogSuccess(inboundLog, responseData, generalResponse.getStatus());
// ✅ Directly call fetchBillById (no polling)
//save intitate bill here
BillInitiate billInitiate = new BillInitiate();
billInitiate.setBillId((String) dataMap.get("billId"));
billInitiate.setReqId(fetchBillRequest.getReqId());
billInitiate.setTxnId(txnId);
billIntiateRepository.save(billInitiate);
BillFetchByBillIdRequest billFetchByBillIdRequest = new BillFetchByBillIdRequest();
billFetchByBillIdRequest.setBillId(fetchBillResponse.getBillId());
billFetchByBillIdRequest.setMid(fetchBillRequest.getMid());
billFetchByBillIdRequest.setReqId(requestId);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // restore interrupted flag
log.warn("Thread interrupted during delay: {}", e.getMessage());
}
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());
}
}
}
@@ -131,7 +145,7 @@ public class AgentServiceImpl implements AgentService {
public ResponseModel fetchBillById(BillFetchByBillIdRequest billFetchByBillIdRequest, InboundTraceLog inboundLog) {
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String requestId = billFetchByBillIdRequest.getReqId();
String reqId = billFetchByBillIdRequest.getReqId();
String billId = billFetchByBillIdRequest.getBillId();
String url = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + "1ced7566-1add-4e01-9ed6-04cd67ac9684";
@@ -145,14 +159,9 @@ public class AgentServiceImpl implements AgentService {
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectMapper objectMapper = new ObjectMapper();
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, url, "GET", null);
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, reqId, 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");
@@ -177,66 +186,46 @@ public class AgentServiceImpl implements AgentService {
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());
helper.saveOrUpdateBillerData(responseWrapper,billFetchByBillIdRequest);
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) {
String apiName = "FetchBillById";
String txnId = helper.generateTxnId(15);
String reqId = billFetchByBillIdRequest.getReqId();
String billId = billFetchByBillIdRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + "1ced7566-1add-4e01-9ed6-04cd67ac9684";
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>>() {
});
@@ -246,159 +235,226 @@ public class AgentServiceImpl implements AgentService {
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);
helper.saveOrUpdateBillerData(responseWrapper,billFetchByBillIdRequest);
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;
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) {
// TODO Auto-generated method stub
return null;
}
/*
* @Override public ResponseModel
* initiateBillValidate(FetchBillValidatestRequest fetchBillValidateRequest) {
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;
}
/* POLLING METHOD
* public ResponseModel fetchBillById(BillFetchByBillIdRequest
* billFetchByBillIdRequest, InboundTraceLog inboundLog) { String apiName =
* "FetchBillById"; String txnId = helper.generateTxnId(15); String reqId =
* billFetchByBillIdRequest.getReqId(); String billId =
* billFetchByBillIdRequest.getBillId(); String url = agentDtaUrl +
* BBPSConstant.BILL_FETCH_BY_ID + "1ced7566-1add-4e01-9ed6-04cd67ac9684";
*
* ResponseModel responseModel = new ResponseModel(); try {
*
* helper.validateMerchant(fetchBillValidateRequest.getMid());
* helper.validateMerchant(billFetchByBillIdRequest.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
* 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
* 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");
* ObjectMapper objectMapper = new ObjectMapper(); OutboundTraceLog outboundLog
* = helper.createOutboundLog(txnId, reqId, apiName, url, "GET", null);
*
* log.info("📦 Bill Fetch API Response: {}", responseData);
* // ✅ Loop setup long startTime = System.currentTimeMillis(); long
* maxWaitTimeMs = 40000; // 40 seconds long intervalMs = 5000; // 5 seconds
*
* 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 =
* while (true) { try { Map<String, String> responseMap =
* httpService.getRequest(url, headers); String responseData =
* responseMap.get("data");
* responseMap.get("data"); log.info("📦 Bill FetchById Response: {}",
* responseData);
*
* log.info("📦 Bill Fetch API Response: {}", responseData);
* helper.updateOutboundLogResponse(outboundLog, responseData);
*
* if (responseData == null || responseData.isEmpty()) { throw new
* CustomException("Empty response from BBPS server"); }
* Map<String, Object> dataMap = objectMapper.readValue(responseData, new
* TypeReference<Map<String, Object>>() {});
*
* // ✅ Convert JSON string → Map 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")) ); }
*
* // ✅ 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;
* 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"); } }
* }
*/
@@ -2,24 +2,38 @@ package com.billpaymentservice.bbps.util;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import org.modelmapper.ModelMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.billpaymentservice.bbps.dto.AdditionalInfoBillDTO;
import com.billpaymentservice.bbps.dto.AdditionalInfoDTO;
import com.billpaymentservice.bbps.dto.CustomerParamDAO;
import com.billpaymentservice.bbps.dto.CustomerParamDTO;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.entites.AdditionalInfoBill;
import com.billpaymentservice.bbps.entites.BBPSMastersData;
import com.billpaymentservice.bbps.exception.CustomException;
import com.billpaymentservice.bbps.repository.BBPSMasterDataRepo;
import com.billpaymentservice.bbps.repository.BillMasterRepository;
import com.billpaymentservice.bbps.repository.BillerDataRepository;
import com.billpaymentservice.bbps.repository.InboundTraceLogRepository;
import com.billpaymentservice.bbps.dto.request.BillFetchByBillIdRequest;
import com.billpaymentservice.bbps.dto.request.BillerDetailRequest;
import com.billpaymentservice.bbps.dto.request.MerchantRequestModel;
import com.billpaymentservice.bbps.dto.response.BillDataResponse;
import com.billpaymentservice.bbps.entites.BBPSMerchantValidation;
import com.billpaymentservice.bbps.entites.BillMaster;
import com.billpaymentservice.bbps.entites.BillerDetails;
import com.billpaymentservice.bbps.entites.BillerResponse;
import com.billpaymentservice.bbps.entites.CustomerParamBill;
import com.billpaymentservice.bbps.entites.InboundTraceLog;
import com.billpaymentservice.bbps.entites.OutboundTraceLog;
import com.billpaymentservice.bbps.entites.PaymentChannel;
@@ -43,14 +57,17 @@ public class Helper {
private final BBPSMasterDataRepo bbpsMasterDataRepo;
private final BillerDataRepository billerDataRespository;
private final BillMasterRepository billMasterRepository;
// Constructor Injection
public Helper(BBPSMasterDataRepo bbpsMasterDataRepo, InboundTraceLogRepository inboundTraceLogRepository,
OutboundTraceLogRepository outboundTraceLogRepository,BillerDataRepository billerDataRepository) {
OutboundTraceLogRepository outboundTraceLogRepository,BillerDataRepository billerDataRepository,
BillMasterRepository billMasterRepository) {
this.bbpsMasterDataRepo = bbpsMasterDataRepo;
this.inboundTraceLogRepository = inboundTraceLogRepository;
this.outboundTraceLogRepository = outboundTraceLogRepository;
this.billerDataRespository=billerDataRepository;
this.billMasterRepository=billMasterRepository;
}
/**
@@ -229,5 +246,71 @@ public class Helper {
}
}
public void saveOrUpdateBillerData(BillDataResponse responseWrapper,
BillFetchByBillIdRequest billFetchByBillIdRequest) {
BillMaster billMaster =new BillMaster();
billMaster.setBillId("12333333hjsdfjsfdj");
billMaster.setRefId(responseWrapper.getRefId());
billMaster.setBillerId(responseWrapper.getBillerId());
billMaster.setStatus(responseWrapper.getStatus());
billMaster.setActionType(responseWrapper.getActionType());
billMaster.setUserId(responseWrapper.getUserId());
billMaster.setReqId(billFetchByBillIdRequest.getReqId()); // if available from your API request
billMaster.setTxnId("jhnjhbhj"); // give it from method
// ---- BILLER RESPONSE ----
BillerResponse billerResponse = new BillerResponse();
if (responseWrapper.getBillerResponse() != null) {
billerResponse.setBillId(responseWrapper.getBillerResponse().getBillId());
billerResponse.setAmount(responseWrapper.getBillerResponse().getAmount());
billerResponse.setBillDate(responseWrapper.getBillerResponse().getBillDate());
billerResponse.setBillNumber(responseWrapper.getBillerResponse().getBillNumber());
billerResponse.setBillPeriod(responseWrapper.getBillerResponse().getBillPeriod());
billerResponse.setCustConvFee(responseWrapper.getBillerResponse().getCustConvFee());
billerResponse.setCouCustConvFee(responseWrapper.getBillerResponse().getCouCustConvFee());
billerResponse.setDueDate(responseWrapper.getBillerResponse().getDueDate());
billerResponse.setCustomerName(responseWrapper.getBillerResponse().getCustomerName());
billerResponse.setAmountOption(responseWrapper.getBillerResponse().isAmountOption());
billerResponse.setBillMaster(billMaster); // maintain mapping
}
billMaster.setBillerResponse(billerResponse);
// ---- ADDITIONAL INFO ----
List<AdditionalInfoBill> additionalInfos = new ArrayList<>();
if (responseWrapper.getAdditionalInfo() != null) {
for (AdditionalInfoBillDTO info : responseWrapper.getAdditionalInfo()) {
AdditionalInfoBill entity = new AdditionalInfoBill();
entity.setName(info.getName());
entity.setValue(info.getValue());
entity.setBillMaster(billMaster); // maintain mapping
additionalInfos.add(entity);
}
}
billMaster.setAdditionalInfo(additionalInfos);
// ---- CUSTOMER PARAMS ----
List<CustomerParamBill> customerParams = new ArrayList<>();
if (responseWrapper.getCustomerParams() != null) {
for (CustomerParamDAO param : responseWrapper.getCustomerParams()) {
CustomerParamBill entity = new CustomerParamBill();
entity.setName(param.getName());
entity.setValue(param.getValue());
entity.setType(param.getType());
entity.setBillMaster(billMaster);
customerParams.add(entity);
}
}
billMaster.setCustomerParams(customerParams);
// ---- DATES ----
billMaster.setCreationDate(responseWrapper.getCreationDate());
billMaster.setModifiedDate(responseWrapper.getModifiedDate());
billMaster.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
billMaster.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
billMasterRepository.save(billMaster);
}
}