package com.billpaymentservice.bbps.serviceImpl; import com.billpaymentservice.bbps.dto.GeneralResp; import com.billpaymentservice.bbps.dto.GeneralResponse; 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.response.BillDataResponse; import com.billpaymentservice.bbps.dto.response.BillerDataResponse; import com.billpaymentservice.bbps.dto.response.FetchBillResponse; import com.billpaymentservice.bbps.entites.BeneficiaryDetails; import com.billpaymentservice.bbps.exception.CustomException; import com.billpaymentservice.bbps.repository.BeneficiaryDetailsRepository; 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.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.RestClient; import org.springframework.web.servlet.function.ServerRequest.Headers; @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 BeneficiaryDetailsRepository beneficiaryDetailsRepository; public AgentServiceImpl(RestClient restClient,HttpService httpService,Helper helper, BeneficiaryDetailsRepository beneficiaryDetailsRepository) { this.restClient=restClient; this.httpService=httpService; this.helper=helper; this.beneficiaryDetailsRepository=beneficiaryDetailsRepository; } @Override public ResponseModel initiateBillFetch(FetchBillRequest fetchBillRequest) { String url = agentDtaUrl+BBPSConstant.BILL_FETCH_INTI; System.out.println(url); BeneficiaryDetails 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); ResponseModel responseModel = new ResponseModel(); try { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // ✅ Convert request to JSON String json = objectMapper.writeValueAsString(fetchBillRequest); // ✅ Call the API using httpService 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 FetchBillResponse fetchBillResponse = objectMapper.convertValue(dataMap, FetchBillResponse.class); GeneralResponse generalResponse = fetchBillResponse.getGenericResponse(); // //start a new thread here helper.startPolling(fetchBillResponse, res -> { BillFetchByBillIdRequest pollReq = new BillFetchByBillIdRequest(); pollReq.setBillId(res.getBillId()); return fetchBillById(pollReq); }, 3, // interval in seconds 15 // total time in seconds ); // ✅ Build final ResponseModel responseModel = new ResponseModel( generalResponse.getMessage(), generalResponse.getStatus(), Integer.parseInt(generalResponse.getStatusCode()), fetchBillResponse ); } 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 fetchBillById(BillFetchByBillIdRequest billFetchByBillIdRequest) { String billId = billFetchByBillIdRequest.getBillId(); String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID+billId; System.out.print(fullUrl); BeneficiaryDetails 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(); try { Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); 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"); } } }