diff --git a/src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBill.java b/src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBillDTO.java similarity index 88% rename from src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBill.java rename to src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBillDTO.java index cd0d36b..488e618 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBill.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/AdditionalInfoBillDTO.java @@ -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; diff --git a/src/main/java/com/billpaymentservice/bbps/dto/response/BillDataResponse.java b/src/main/java/com/billpaymentservice/bbps/dto/response/BillDataResponse.java index 8f6faef..42470b2 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/response/BillDataResponse.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/response/BillDataResponse.java @@ -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 additionalInfo; // array of objects + private List additionalInfo; // array of objects private List customerParams; // array of objects private String creationDate; diff --git a/src/main/java/com/billpaymentservice/bbps/entites/AdditionalInfoBill.java b/src/main/java/com/billpaymentservice/bbps/entites/AdditionalInfoBill.java new file mode 100644 index 0000000..d80e79e --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/AdditionalInfoBill.java @@ -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; + +} diff --git a/src/main/java/com/billpaymentservice/bbps/entites/BillInitiate.java b/src/main/java/com/billpaymentservice/bbps/entites/BillInitiate.java new file mode 100644 index 0000000..c53cbe1 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/BillInitiate.java @@ -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; + +} diff --git a/src/main/java/com/billpaymentservice/bbps/entites/BillMaster.java b/src/main/java/com/billpaymentservice/bbps/entites/BillMaster.java new file mode 100644 index 0000000..48d597d --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/BillMaster.java @@ -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 additionalInfo; + @OneToMany(mappedBy = "billMaster", cascade = CascadeType.ALL) + private List customerParams; + private String creationDate; + private String modifiedDate; + private Long createdEpochDate; + private Long modifiedEpochDate; + + // getters and setters +} diff --git a/src/main/java/com/billpaymentservice/bbps/entites/BillerPlanResponseParams.java b/src/main/java/com/billpaymentservice/bbps/entites/BillerPlanResponseParams.java index ac919a9..3415f7e 100644 --- a/src/main/java/com/billpaymentservice/bbps/entites/BillerPlanResponseParams.java +++ b/src/main/java/com/billpaymentservice/bbps/entites/BillerPlanResponseParams.java @@ -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; diff --git a/src/main/java/com/billpaymentservice/bbps/entites/BillerResponse.java b/src/main/java/com/billpaymentservice/bbps/entites/BillerResponse.java new file mode 100644 index 0000000..4a02e35 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/BillerResponse.java @@ -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 +} diff --git a/src/main/java/com/billpaymentservice/bbps/entites/BillerResponseParams.java b/src/main/java/com/billpaymentservice/bbps/entites/BillerResponseParams.java index ee810da..dafef13 100644 --- a/src/main/java/com/billpaymentservice/bbps/entites/BillerResponseParams.java +++ b/src/main/java/com/billpaymentservice/bbps/entites/BillerResponseParams.java @@ -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) diff --git a/src/main/java/com/billpaymentservice/bbps/entites/CustomerParamBill.java b/src/main/java/com/billpaymentservice/bbps/entites/CustomerParamBill.java new file mode 100644 index 0000000..870ee57 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/CustomerParamBill.java @@ -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 +} diff --git a/src/main/java/com/billpaymentservice/bbps/repository/BillInitateRepository.java b/src/main/java/com/billpaymentservice/bbps/repository/BillInitateRepository.java new file mode 100644 index 0000000..3c7cd69 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/repository/BillInitateRepository.java @@ -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 { + +} diff --git a/src/main/java/com/billpaymentservice/bbps/repository/BillMasterRepository.java b/src/main/java/com/billpaymentservice/bbps/repository/BillMasterRepository.java new file mode 100644 index 0000000..161a85a --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/repository/BillMasterRepository.java @@ -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 { + +} diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java index 01d4bf5..d568d40 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java @@ -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 dataMap = objectMapper.readValue(responseData, new TypeReference>() {}); 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 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 responseMap = httpService.getRequest(fullUrl, headers); String responseData = responseMap.get("data"); log.info("data is :{}", responseData); - ObjectMapper objectMapper = new ObjectMapper(); - Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); @@ -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 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 dataMap = objectMapper.readValue(responseData, new TypeReference>() {}); + + // ✅ 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 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 dataMap = objectMapper.readValue(responseData, new TypeReference>() {}); + + // ✅ 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 - * 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 dataMap = - * objectMapper.readValue(responseData, new TypeReference>() - * { }); - * - * // ✅ 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 responseMap = + * while (true) { try { Map 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 dataMap = objectMapper.readValue(responseData, new + * TypeReference>() {}); * - * // ✅ Convert JSON string → Map Map dataMap = - * objectMapper.readValue(responseData, new TypeReference>() - * { }); + * 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"); } } * } */ diff --git a/src/main/java/com/billpaymentservice/bbps/util/Helper.java b/src/main/java/com/billpaymentservice/bbps/util/Helper.java index 32b3a25..6ce0849 100644 --- a/src/main/java/com/billpaymentservice/bbps/util/Helper.java +++ b/src/main/java/com/billpaymentservice/bbps/util/Helper.java @@ -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 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 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); + + } + }