From f7c2669d11fd5cf5a1528c7512ee130c97cbd100 Mon Sep 17 00:00:00 2001 From: himanshu Date: Mon, 3 Nov 2025 18:13:10 +0530 Subject: [PATCH 1/2] added log tracing classes --- pom.xml | 6 +- .../bbps/controller/MasterDataController.java | 5 +- .../bbps/dto/request/BaseClass.java | 18 +-- .../bbps/dto/request/BillerDetailRequest.java | 2 + .../bbps/entites/InboundTraceLog.java | 57 +++++++++ .../bbps/entites/OutboundTraceLog.java | 54 ++++++++ .../exception/GlobalExceptionHandler.java | 31 ++++- .../repository/InboundTraceLogRepository.java | 8 ++ .../OutboundTraceLogRepository.java | 9 ++ .../serviceImpl/MasterDataServiceImpl.java | 115 ++++++++++++------ .../bbps/serviceImpl/PaymentServiceImpl.java | 2 +- .../billpaymentservice/bbps/util/Helper.java | 14 +++ src/main/resources/application.properties | 6 +- 13 files changed, 276 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java create mode 100644 src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java create mode 100644 src/main/java/com/billpaymentservice/bbps/repository/InboundTraceLogRepository.java create mode 100644 src/main/java/com/billpaymentservice/bbps/repository/OutboundTraceLogRepository.java diff --git a/pom.xml b/pom.xml index 19bf1de..8ea65ce 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,11 @@ org.springframework.boot spring-boot-starter - + + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot spring-boot-starter-web diff --git a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java index d485d41..fbde124 100644 --- a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java +++ b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java @@ -17,8 +17,11 @@ import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.service.MasterDataService; +import jakarta.validation.Valid; + @RequestMapping("/masterData") @RestController +@Validated public class MasterDataController { private static final Logger log = LoggerFactory.getLogger(MasterDataController.class); @@ -32,7 +35,7 @@ public class MasterDataController { /** Get Details of the biller by billId **/ @PostMapping(value = "/getBillerDetails", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getBillerDetails( - @Validated @RequestBody BillerDetailRequest billerDetailRequest) { + @Valid @RequestBody BillerDetailRequest billerDetailRequest) { log.info("Received biller details request for billerId: {}", billerDetailRequest.getBillerId()); diff --git a/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java b/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java index b150d3a..41f09ff 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java @@ -3,27 +3,31 @@ package com.billpaymentservice.bbps.dto.request; import com.billpaymentservice.bbps.dto.DeviceDetail; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; @Getter @Setter @AllArgsConstructor @NoArgsConstructor +@ToString public abstract class BaseClass { - // ✅ Request me required, response me hide honge - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + @NotBlank(message = "MID cannot be null or blank") private String mid; - - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) - private String secretKey; - + + @NotBlank(message = "Secret key cannot be null or blank") + private String secretKey; + @NotBlank(message = "Request ID cannot be null or blank") + private String reqId; + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String txnId; - + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private DeviceDetail deviceDetial; diff --git a/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java b/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java index 7f4a81d..9d2ba0d 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java @@ -3,9 +3,11 @@ package com.billpaymentservice.bbps.dto.request; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import lombok.ToString; @Getter @Setter +@ToString public class BillerDetailRequest extends BaseClass{ @NotNull diff --git a/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java b/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java new file mode 100644 index 0000000..e2f92a7 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java @@ -0,0 +1,57 @@ +package com.billpaymentservice.bbps.entites; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Entity +@Getter @Setter @NoArgsConstructor @ToString +public class InboundTraceLog { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + // 🔹 Identifiers + @Column(length = 50, unique = true) + private String requestId; // external requestId (from client) + @Column(length = 35) + private String txnId; // internally generated transaction id + + // 🔹 Source & API info + private String orgId; // tumhara org code (like ORG001) + private String mid; // merchant id from request + private String apiName; // e.g. getBillerByBillerId + private String httpMethod; // GET / POST + + // 🔹 Request/Response data + @Column(columnDefinition = "TEXT") + private String requestPayload; // jo external ne bheja + @Column(columnDefinition = "TEXT") + private String responsePayload; // jo tumne wapas bheja + + // 🔹 Status & timing + private String status; // SUCCESS / FAILED + private String responseCode; // like 200, 400 etc. + private LocalDateTime requestTime; // jab request aayi + private LocalDateTime responseTime; // jab response gaya + private LocalDateTime createdAt = LocalDateTime.now(); + + @Column(length = 255) + private String remark; // error ya note + public InboundTraceLog(String requestId, String txnId, String apiName, String requestPayload) { + this.requestId = requestId; + this.txnId = txnId; + this.apiName = apiName; + this.requestPayload = requestPayload; + this.requestTime = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java b/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java new file mode 100644 index 0000000..3fe1ff1 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java @@ -0,0 +1,54 @@ +package com.billpaymentservice.bbps.entites; + +import java.time.LocalDateTime; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Entity +@Getter @Setter @NoArgsConstructor @ToString +public class OutboundTraceLog { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + // 🔹 Linking fields + private String requestId; // same as inbound ka requestId + private String txnId; // same txnId for full trace + + // 🔹 API / endpoint info + private String apiName; // e.g. fetchBillerData + private String endpointUrl; // full URL of external API + private String httpMethod; // GET / POST + + // 🔹 Request/Response payloads + @Column(columnDefinition = "TEXT") + private String requestPayload; // jo tumne bheja external ko + @Column(columnDefinition = "TEXT") + private String responsePayload; // jo external ne bheja + + // 🔹 Response/status + private String responseCode; // HTTP status code (200, 500, etc.) + private String status; // SUCCESS / FAILED + private LocalDateTime sendTime; // jab request gayi + private LocalDateTime responseReceiveTime; // jab response aaya + private LocalDateTime createdAt = LocalDateTime.now(); + + @Column(length = 255) + private String remark; + public OutboundTraceLog(String txnId, String apiName, String endpointUrl, String requestPayload) { + this.txnId = txnId; + this.apiName = apiName; + this.endpointUrl = endpointUrl; + this.requestPayload = requestPayload; + this.sendTime = LocalDateTime.now(); + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java b/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java index 6dcd370..a695c69 100644 --- a/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java @@ -2,16 +2,41 @@ package com.billpaymentservice.bbps.exception; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import com.billpaymentservice.bbps.dto.GeneralResp; + import com.billpaymentservice.bbps.dto.ResponseModel; +import java.util.HashMap; +import java.util.Map; + @ControllerAdvice public class GlobalExceptionHandler { + // ✅ Handle CustomException @ExceptionHandler(CustomException.class) - public ResponseEntity handleCustomException(CustomException ex) { + public ResponseEntity> handleCustomException(CustomException ex) { return new ResponseEntity<>(ex.getResponseModel(), HttpStatus.BAD_REQUEST); } -} \ No newline at end of file + + // ✅ Handle validation errors + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidationExceptions(MethodArgumentNotValidException ex) { + + Map errors = new HashMap<>(); + + ex.getBindingResult().getFieldErrors().forEach(error -> { + errors.put(error.getField(), error.getDefaultMessage()); + }); + + ResponseModel response = new ResponseModel<>( + "Validation Failed", + "FAILED", + HttpStatus.BAD_REQUEST.value(), + errors + ); + + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/repository/InboundTraceLogRepository.java b/src/main/java/com/billpaymentservice/bbps/repository/InboundTraceLogRepository.java new file mode 100644 index 0000000..c5d8313 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/repository/InboundTraceLogRepository.java @@ -0,0 +1,8 @@ +package com.billpaymentservice.bbps.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.billpaymentservice.bbps.entites.InboundTraceLog; +public interface InboundTraceLogRepository extends JpaRepository { + +} diff --git a/src/main/java/com/billpaymentservice/bbps/repository/OutboundTraceLogRepository.java b/src/main/java/com/billpaymentservice/bbps/repository/OutboundTraceLogRepository.java new file mode 100644 index 0000000..f39d8cc --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/repository/OutboundTraceLogRepository.java @@ -0,0 +1,9 @@ +package com.billpaymentservice.bbps.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.billpaymentservice.bbps.entites.OutboundTraceLog; + +public interface OutboundTraceLogRepository extends JpaRepository { + +} diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java index be989f0..0c243af 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java @@ -1,16 +1,15 @@ package com.billpaymentservice.bbps.serviceImpl; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; - import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; - import com.billpaymentservice.bbps.dto.GeneralResp; import com.billpaymentservice.bbps.dto.MasterApiResponse; import com.billpaymentservice.bbps.dto.ResponseModel; @@ -30,11 +29,15 @@ import com.billpaymentservice.bbps.dto.response.PlaneCategoriesResponse; import com.billpaymentservice.bbps.entites.BharatConnectMaster; import com.billpaymentservice.bbps.entites.BillerDetails; import com.billpaymentservice.bbps.entites.DispositionDetails; +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.BillerDataRepository; import com.billpaymentservice.bbps.repository.DispositionRepository; +import com.billpaymentservice.bbps.repository.InboundTraceLogRepository; import com.billpaymentservice.bbps.repository.MerchantRepository; +import com.billpaymentservice.bbps.repository.OutboundTraceLogRepository; import com.billpaymentservice.bbps.service.MasterDataService; import com.billpaymentservice.bbps.util.BBPSConstant; import com.billpaymentservice.bbps.util.EntityRelationshipUtil; @@ -59,11 +62,16 @@ public class MasterDataServiceImpl implements MasterDataService { private final BillerDataRepository billerDataRespository; private static final Logger log = LoggerFactory.getLogger(MasterDataServiceImpl.class); private final HttpService httpService; + private final InboundTraceLogRepository inboundTraceLogRepository; + private final OutboundTraceLogRepository outboundTraceLogRepository; private final ObjectMapper objectMapper = new ObjectMapper(); + public MasterDataServiceImpl(MerchantRepository merchantRegisterRepo, HttpService httpService, HttpClientApi httpClientApi, Helper helper, BillerDataRepository billerDataRespository, - DispositionRepository dispositionRepository, BharatConnectMasterRepository beneficiaryDetailsRepository) { + DispositionRepository dispositionRepository, BharatConnectMasterRepository beneficiaryDetailsRepository, + InboundTraceLogRepository inboundTraceLogRepository, + OutboundTraceLogRepository outboundTraceLogRepository) { this.merchantRegisterRepo = merchantRegisterRepo; this.httpService = httpService; this.httpClientApi = httpClientApi; @@ -71,7 +79,10 @@ public class MasterDataServiceImpl implements MasterDataService { this.billerDataRespository = billerDataRespository; this.dispositionRepository = dispositionRepository; this.beneficiaryDetailsRepository = beneficiaryDetailsRepository; - + this.inboundTraceLogRepository = inboundTraceLogRepository; + this.outboundTraceLogRepository = outboundTraceLogRepository; + + } @Override @@ -92,7 +103,7 @@ public class MasterDataServiceImpl implements MasterDataService { Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); LOGGER.info("Response Data: {}", responseData); - + ObjectMapper objectMapper = new ObjectMapper(); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { @@ -124,42 +135,76 @@ public class MasterDataServiceImpl implements MasterDataService { @Override public ResponseModel getBillerByBillerId(BillerDetailRequest billerDetailRequest) { - String billerId = billerDetailRequest.getBillerId(); - String fullUrl = masterRegisterUrl + BBPSConstant.BILLER_DATA_FETCH_URL + billerId; + String txnID = helper.generateTxnId(15); + String apiName = "GetBillerByBillerId"; + String requestId = billerDetailRequest.getReqId(); + String fullUrl = masterRegisterUrl + BBPSConstant.BILLER_DATA_FETCH_URL + billerDetailRequest.getBillerId(); - Map responseMap = httpService.getRequest(fullUrl); - String responseData = responseMap.get("data"); - log.info("data is :{}", responseData); + // 🔹 Inbound Log (request received) + InboundTraceLog inboundLog = new InboundTraceLog(requestId, txnID, apiName, billerDetailRequest.toString()); + inboundTraceLogRepository.save(inboundLog); - ObjectMapper objectMapper = new ObjectMapper(); + // 🔹 Outbound Log (before sending external API request) + OutboundTraceLog outboundLog = new OutboundTraceLog(txnID, apiName, fullUrl, "N/A"); + outboundTraceLogRepository.save(outboundLog); - try { - Map dataMap = objectMapper.readValue(responseData, - new TypeReference>() { - }); - if (!dataMap.containsKey("generalResp")) { - 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"))); - } - BillerDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillerDataResponse.class); - GeneralResp generalResp = responseWrapper.getGeneralResp(); - ModelMapper mapper = new ModelMapper(); - mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - BillerDetails entity = mapper.map(responseWrapper.getBillerDAO(), BillerDetails.class); - EntityRelationshipUtil.linkBillerRelationships(entity); - // billerDataRespository.save(entity); - ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), - Integer.parseInt(generalResp.getStatusCode()), responseWrapper); - return responseModel; + // 🔹 Send request + Map responseMap = httpService.getRequest(fullUrl); + String responseData = responseMap.get("data"); - } catch (JsonProcessingException e) { - log.error("Error parsing responseData JSON: {}", e.getMessage()); - throw new CustomException("Invalid JSON received from API"); - } + outboundLog.setResponsePayload(responseData); + outboundLog.setResponseReceiveTime(LocalDateTime.now()); + outboundTraceLogRepository.save(outboundLog); + + // 🔹 Parse the response + ObjectMapper objectMapper = new ObjectMapper(); + Map dataMap; + + try { + dataMap = objectMapper.readValue(responseData, new TypeReference>() {}); + } catch (Exception e) { + // 🟥 Invalid JSON case — update inbound log before throwing + inboundLog.setResponsePayload("Invalid JSON: " + e.getMessage()); + inboundLog.setResponseCode("FAILED"); + inboundLog.setResponseTime(LocalDateTime.now()); + inboundTraceLogRepository.save(inboundLog); + throw new CustomException("Invalid JSON received from upstream", "FAILED", 400, e.getMessage()); + } + + // 🔹 If generalResp is missing — API returned error response + if (!dataMap.containsKey("generalResp")) { + // 🟥 Update inbound log before throwing + inboundLog.setResponsePayload(responseData); + inboundLog.setResponseCode(String.valueOf(dataMap.get("status"))); + inboundLog.setResponseTime(LocalDateTime.now()); + inboundTraceLogRepository.save(inboundLog); + + 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")) + ); + } + + // 🔹 Otherwise, success flow + BillerDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillerDataResponse.class); + GeneralResp generalResp = responseWrapper.getGeneralResp(); + + inboundLog.setResponsePayload(responseData); + inboundLog.setResponseCode(generalResp.getStatus()); + inboundLog.setResponseTime(LocalDateTime.now()); + inboundTraceLogRepository.save(inboundLog); + + return new ResponseModel( + generalResp.getMessage(), + generalResp.getStatus(), + Integer.parseInt(generalResp.getStatusCode()), + responseWrapper + ); } + @Override public ResponseModel getCustomerParamByBillerId(CustomParamRequest customerParamRequest) { diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/PaymentServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/PaymentServiceImpl.java index f758fdd..3d0b1d8 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/PaymentServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/PaymentServiceImpl.java @@ -117,7 +117,7 @@ public class PaymentServiceImpl implements PaymentService { paymentRepository.save(entity); TransactionStatusRequest transactionStatusRequest=new TransactionStatusRequest(); //call the checkTransactionStatus - transactionStatusRequest.setTxnId(billPaymentResponse.getTxnId()); + transactionStatusRequest.setTxnId(helper.generateTxnId(15)); System.out.println(transactionStatusRequest); responseModel= checkTrasactionStatus(transactionStatusRequest); } catch (Exception e) { diff --git a/src/main/java/com/billpaymentservice/bbps/util/Helper.java b/src/main/java/com/billpaymentservice/bbps/util/Helper.java index da8b545..c52096a 100644 --- a/src/main/java/com/billpaymentservice/bbps/util/Helper.java +++ b/src/main/java/com/billpaymentservice/bbps/util/Helper.java @@ -1,5 +1,6 @@ package com.billpaymentservice.bbps.util; +import java.security.SecureRandom; import java.util.function.Function; import org.slf4j.Logger; @@ -19,6 +20,9 @@ import com.billpaymentservice.bbps.repository.MerchantRepository; public class Helper { private static final Logger LOGGER = LoggerFactory.getLogger(Helper.class); + + private static final String CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final SecureRandom secureRandom = new SecureRandom(); @Autowired private MerchantRepository merchantRegisterRepo; @@ -111,4 +115,14 @@ public class Helper { // LOGGER.info("Merchant is valid and active for MID: {}", requestModel.getMid()); return "Valid"; // Success message } + + public static String generateTxnId(int n) { + StringBuilder sb = new StringBuilder(n); + + for (int i = 0; i < n; i++) { + int index = secureRandom.nextInt(CHARACTERS.length()); + sb.append(CHARACTERS.charAt(index)); + } + return sb.toString(); // Prefix + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1f1c54e..44ff981 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -2,7 +2,7 @@ spring.application.name=bbps # Server port -server.port=8080 +server.port=9090 # JPA & Hibernate spring.jpa.hibernate.ddl-auto=update @@ -11,9 +11,9 @@ spring.jpa.properties.hibernate.default_schema=public # DataSource -spring.datasource.url=jdbc:postgresql://localhost:5432/TestingDB +spring.datasource.url=jdbc:postgresql://localhost:5432/BBPS spring.datasource.username=postgres -spring.datasource.password=UAT@DB_2025 +spring.datasource.password=thakur@123 spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource From 7d6db124e7b62ef3a0f4d529f4e28ef05b3e5817 Mon Sep 17 00:00:00 2001 From: himanshu Date: Tue, 4 Nov 2025 02:59:38 +0530 Subject: [PATCH 2/2] added logs in masterdataserviceimpl --- .../bbps/controller/MasterDataController.java | 5 +- .../bbps/dto/DeviceDetail.java | 2 + .../bbps/dto/request/BaseClass.java | 13 +- .../bbps/dto/request/BillerDetailRequest.java | 2 +- .../bbps/entites/InboundTraceLog.java | 20 +- .../bbps/entites/OutboundTraceLog.java | 18 +- .../exception/GlobalExceptionHandler.java | 21 +- .../bbps/service/MasterDataService.java | 3 +- .../serviceImpl/MasterDataServiceImpl.java | 290 +++++++++++++----- .../billpaymentservice/bbps/util/Helper.java | 18 +- 10 files changed, 282 insertions(+), 110 deletions(-) diff --git a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java index fbde124..336ce90 100644 --- a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java +++ b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java @@ -13,6 +13,7 @@ import com.billpaymentservice.bbps.dto.ResponseModel; import com.billpaymentservice.bbps.dto.request.BillerDetailRequest; import com.billpaymentservice.bbps.dto.request.ContactMasterRequest; import com.billpaymentservice.bbps.dto.request.CustomParamRequest; +import com.billpaymentservice.bbps.dto.request.DispositionRequest; import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.service.MasterDataService; @@ -52,8 +53,8 @@ public class MasterDataController { @PostMapping(value = "/getDispostionDetail", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getDispostionDetail( - @Validated @RequestBody ContactMasterRequest contactMasterRequest) { - return ResponseEntity.ok(masterDataService.getDispositionDetails()); + @Validated @RequestBody DispositionRequest dispositionDetailRequest) { + return ResponseEntity.ok(masterDataService.getDispositionDetails(dispositionDetailRequest)); } /** diff --git a/src/main/java/com/billpaymentservice/bbps/dto/DeviceDetail.java b/src/main/java/com/billpaymentservice/bbps/dto/DeviceDetail.java index a8505e6..1b2676c 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/DeviceDetail.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/DeviceDetail.java @@ -5,10 +5,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; @Getter @Setter @NoArgsConstructor @AllArgsConstructor +@ToString public class DeviceDetail { private List detail; diff --git a/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java b/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java index 41f09ff..880ae88 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/request/BaseClass.java @@ -25,41 +25,30 @@ public abstract class BaseClass { @NotBlank(message = "Request ID cannot be null or blank") private String reqId; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String txnId; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private DeviceDetail deviceDetial; // ✅ 10 User Defined Fields (UDF1–UDF10) - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf1; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf2; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf3; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf4; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf5; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf6; - - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) + private String udf7; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf8; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf9; - @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String udf10; } diff --git a/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java b/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java index 9d2ba0d..867638c 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/request/BillerDetailRequest.java @@ -7,7 +7,7 @@ import lombok.ToString; @Getter @Setter -@ToString +@ToString(callSuper = true) public class BillerDetailRequest extends BaseClass{ @NotNull diff --git a/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java b/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java index e2f92a7..15a1b3c 100644 --- a/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java +++ b/src/main/java/com/billpaymentservice/bbps/entites/InboundTraceLog.java @@ -47,11 +47,17 @@ public class InboundTraceLog { @Column(length = 255) private String remark; // error ya note - public InboundTraceLog(String requestId, String txnId, String apiName, String requestPayload) { - this.requestId = requestId; - this.txnId = txnId; - this.apiName = apiName; - this.requestPayload = requestPayload; - this.requestTime = LocalDateTime.now(); - } + + public InboundTraceLog(String requestId, String txnId, String apiName, String mid, + String orgId, String httpMethod, String requestPayload) { +this.requestId = requestId; +this.txnId = txnId; +this.apiName = apiName; +this.mid = mid; +this.orgId = orgId; +this.httpMethod = httpMethod; +this.requestPayload = requestPayload; +this.requestTime = LocalDateTime.now(); +this.createdAt = LocalDateTime.now(); +} } diff --git a/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java b/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java index 3fe1ff1..06a2088 100644 --- a/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java +++ b/src/main/java/com/billpaymentservice/bbps/entites/OutboundTraceLog.java @@ -44,11 +44,15 @@ public class OutboundTraceLog { @Column(length = 255) private String remark; - public OutboundTraceLog(String txnId, String apiName, String endpointUrl, String requestPayload) { - this.txnId = txnId; - this.apiName = apiName; - this.endpointUrl = endpointUrl; - this.requestPayload = requestPayload; - this.sendTime = LocalDateTime.now(); - } + public OutboundTraceLog(String txnId, String requestId, String apiName, + String endpointUrl, String httpMethod, String requestPayload) { +this.txnId = txnId; +this.requestId = requestId; +this.apiName = apiName; +this.endpointUrl = endpointUrl; +this.httpMethod = httpMethod; +this.requestPayload = requestPayload; +this.sendTime = LocalDateTime.now(); +this.createdAt = LocalDateTime.now(); +} } diff --git a/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java b/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java index a695c69..6007b09 100644 --- a/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/billpaymentservice/bbps/exception/GlobalExceptionHandler.java @@ -39,4 +39,23 @@ public class GlobalExceptionHandler { return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } -} + + // ✅ NEW: Handle ALL other exceptions (Generic Handler) + @ExceptionHandler(Exception.class) + public ResponseEntity> handleAllExceptions(Exception ex) { + + // ✅ Internal logging (tumhare system ko pata chale) + System.err.println("INTERNAL SERVER ERROR: " + ex.getMessage()); + ex.printStackTrace(); // Stack trace for debugging + + // ✅ Client ko generic message + ResponseModel response = new ResponseModel<>( + "Service temporarily unavailable. Please try again later.", + "FAILED", + HttpStatus.INTERNAL_SERVER_ERROR.value(), + null + ); + + return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + } +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java b/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java index ec815bf..e4be315 100644 --- a/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java +++ b/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java @@ -4,6 +4,7 @@ import com.billpaymentservice.bbps.dto.ResponseModel; import com.billpaymentservice.bbps.dto.request.BillerDetailRequest; import com.billpaymentservice.bbps.dto.request.ContactMasterRequest; import com.billpaymentservice.bbps.dto.request.CustomParamRequest; +import com.billpaymentservice.bbps.dto.request.DispositionRequest; import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.dto.request.MerchantRequestModel; @@ -29,6 +30,6 @@ public interface MasterDataService { public ResponseModel fetchInitiatingChannel(BillerDetailRequest requestModel); - public ResponseModel getDispositionDetails(); + public ResponseModel getDispositionDetails(DispositionRequest dispositionDetailRequest); } diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java index 0c243af..f618bf6 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java @@ -1,3 +1,4 @@ +// java package com.billpaymentservice.bbps.serviceImpl; import java.time.LocalDateTime; @@ -16,6 +17,7 @@ import com.billpaymentservice.bbps.dto.ResponseModel; import com.billpaymentservice.bbps.dto.request.BillerDetailRequest; import com.billpaymentservice.bbps.dto.request.ContactMasterRequest; import com.billpaymentservice.bbps.dto.request.CustomParamRequest; +import com.billpaymentservice.bbps.dto.request.DispositionRequest; import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.dto.response.AmountOptionsResponse; @@ -62,16 +64,16 @@ public class MasterDataServiceImpl implements MasterDataService { private final BillerDataRepository billerDataRespository; private static final Logger log = LoggerFactory.getLogger(MasterDataServiceImpl.class); private final HttpService httpService; + private final ObjectMapper objectMapper = new ObjectMapper(); private final InboundTraceLogRepository inboundTraceLogRepository; private final OutboundTraceLogRepository outboundTraceLogRepository; - private final ObjectMapper objectMapper = new ObjectMapper(); public MasterDataServiceImpl(MerchantRepository merchantRegisterRepo, HttpService httpService, HttpClientApi httpClientApi, Helper helper, BillerDataRepository billerDataRespository, DispositionRepository dispositionRepository, BharatConnectMasterRepository beneficiaryDetailsRepository, - InboundTraceLogRepository inboundTraceLogRepository, - OutboundTraceLogRepository outboundTraceLogRepository) { + InboundTraceLogRepository inboundTraceLogRepository, + OutboundTraceLogRepository outboundTraceLogRepository) { this.merchantRegisterRepo = merchantRegisterRepo; this.httpService = httpService; this.httpClientApi = httpClientApi; @@ -82,35 +84,84 @@ public class MasterDataServiceImpl implements MasterDataService { this.inboundTraceLogRepository = inboundTraceLogRepository; this.outboundTraceLogRepository = outboundTraceLogRepository; - } + /* ---------- Trace helper methods ---------- */ + private InboundTraceLog createInboundLog(String requestId, String txnId, String apiName, String mid, String httpMethod, String requestPayload) { + InboundTraceLog inboundLog = new InboundTraceLog(requestId, txnId, apiName, mid == null ? "N/A" : mid, "BBPS_ORG", httpMethod, requestPayload == null ? "N/A" : requestPayload); + inboundTraceLogRepository.save(inboundLog); + return inboundLog; + } + + private void updateInboundLogSuccess(InboundTraceLog inboundLog, String responsePayload, String responseCode) { + if (inboundLog == null) return; + inboundLog.setResponsePayload(responsePayload); + inboundLog.setResponseCode(responseCode); + inboundLog.setStatus("SUCCESS"); + inboundLog.setResponseTime(LocalDateTime.now()); + inboundTraceLogRepository.save(inboundLog); + } + + private void updateInboundLogFailure(InboundTraceLog inboundLog, String responsePayload, String responseCode) { + if (inboundLog == null) return; + inboundLog.setResponsePayload(responsePayload); + inboundLog.setResponseCode(responseCode); + inboundLog.setStatus("FAILED"); + inboundLog.setResponseTime(LocalDateTime.now()); + inboundTraceLogRepository.save(inboundLog); + } + + private OutboundTraceLog createOutboundLog(String txnId, String requestId, String apiName, String url, String httpMethod, String requestPayload) { + OutboundTraceLog outboundLog = new OutboundTraceLog(txnId, requestId, apiName, url, httpMethod, requestPayload == null ? "N/A" : requestPayload); + outboundTraceLogRepository.save(outboundLog); + return outboundLog; + } + + private void updateOutboundLogResponse(OutboundTraceLog outboundLog, String responsePayload) { + if (outboundLog == null) return; + outboundLog.setResponsePayload(responsePayload); + outboundLog.setResponseReceiveTime(LocalDateTime.now()); + outboundTraceLogRepository.save(outboundLog); + } + + /* ---------- End helpers ---------- */ + @Override public ResponseModel getMasterData(MasterRequest masterRequest) { LOGGER.info("Request DTO: {}", masterRequest); + String txnID = helper.generateTxnId(15); + String apiName = "GetMasterData"; + String requestId =masterRequest.getReqId(); + String requestJson = helper.convertObjectToJson(masterRequest); + + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName, masterRequest.getMid(), "POST", requestJson); + try { BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId("ORG001"); log.info("ResPONSE" + headersData); if (headersData == null) { - ResponseModel responseModel = new ResponseModel("Tenant Id Is Null", "Not Found", + updateInboundLogFailure(inboundLog, "Tenant Id Is Null", "NOT_FOUND"); + return new ResponseModel("Tenant Id Is Null", "Not Found", BBPSConstant.BADREQUEST, headersData); - return responseModel; } String fullUrl = masterRegisterUrl + BBPSConstant.MASTER_CATEGORY_URL + headersData.getTenantId(); LOGGER.info("Calling external API: {}", fullUrl); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); + Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); LOGGER.info("Response Data: {}", responseData); - - ObjectMapper objectMapper = new ObjectMapper(); + + updateOutboundLogResponse(outboundLog, responseData); + Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); - // ✅ Same check as in getBillerByBillerId() if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode @@ -124,105 +175,102 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } } @Override public ResponseModel getBillerByBillerId(BillerDetailRequest billerDetailRequest) { - String txnID = helper.generateTxnId(15); String apiName = "GetBillerByBillerId"; String requestId = billerDetailRequest.getReqId(); - String fullUrl = masterRegisterUrl + BBPSConstant.BILLER_DATA_FETCH_URL + billerDetailRequest.getBillerId(); + String billerId = billerDetailRequest.getBillerId(); + String fullUrl = masterRegisterUrl + BBPSConstant.BILLER_DATA_FETCH_URL + billerId; + + String requestJson = helper.convertObjectToJson(billerDetailRequest); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName, billerDetailRequest.getMid(), "POST", requestJson); - // 🔹 Inbound Log (request received) - InboundTraceLog inboundLog = new InboundTraceLog(requestId, txnID, apiName, billerDetailRequest.toString()); - inboundTraceLogRepository.save(inboundLog); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); - // 🔹 Outbound Log (before sending external API request) - OutboundTraceLog outboundLog = new OutboundTraceLog(txnID, apiName, fullUrl, "N/A"); - outboundTraceLogRepository.save(outboundLog); - - // 🔹 Send request Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); + log.info("data is :{}", responseData); - outboundLog.setResponsePayload(responseData); - outboundLog.setResponseReceiveTime(LocalDateTime.now()); - outboundTraceLogRepository.save(outboundLog); - - // 🔹 Parse the response - ObjectMapper objectMapper = new ObjectMapper(); - Map dataMap; + updateOutboundLogResponse(outboundLog, responseData); try { - dataMap = objectMapper.readValue(responseData, new TypeReference>() {}); - } catch (Exception e) { - // 🟥 Invalid JSON case — update inbound log before throwing - inboundLog.setResponsePayload("Invalid JSON: " + e.getMessage()); - inboundLog.setResponseCode("FAILED"); - inboundLog.setResponseTime(LocalDateTime.now()); - inboundTraceLogRepository.save(inboundLog); - throw new CustomException("Invalid JSON received from upstream", "FAILED", 400, e.getMessage()); + Map dataMap = objectMapper.readValue(responseData, + new TypeReference>() {}); + + if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); + 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")) + ); + } + + BillerDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillerDataResponse.class); + GeneralResp generalResp = responseWrapper.getGeneralResp(); + + ModelMapper mapper = new ModelMapper(); + mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + BillerDetails entity = mapper.map(responseWrapper.getBillerDAO(), BillerDetails.class); + EntityRelationshipUtil.linkBillerRelationships(entity); + + ResponseModel responseModel = new ResponseModel( + generalResp.getMessage(), + generalResp.getStatus(), + Integer.parseInt(generalResp.getStatusCode()), + responseWrapper + ); + + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + + return responseModel; + } catch (JsonProcessingException e) { + log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); + throw new CustomException("Invalid JSON received from API"); } - - // 🔹 If generalResp is missing — API returned error response - if (!dataMap.containsKey("generalResp")) { - // 🟥 Update inbound log before throwing - inboundLog.setResponsePayload(responseData); - inboundLog.setResponseCode(String.valueOf(dataMap.get("status"))); - inboundLog.setResponseTime(LocalDateTime.now()); - inboundTraceLogRepository.save(inboundLog); - - 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")) - ); - } - - // 🔹 Otherwise, success flow - BillerDataResponse responseWrapper = objectMapper.convertValue(dataMap, BillerDataResponse.class); - GeneralResp generalResp = responseWrapper.getGeneralResp(); - - inboundLog.setResponsePayload(responseData); - inboundLog.setResponseCode(generalResp.getStatus()); - inboundLog.setResponseTime(LocalDateTime.now()); - inboundTraceLogRepository.save(inboundLog); - - return new ResponseModel( - generalResp.getMessage(), - generalResp.getStatus(), - Integer.parseInt(generalResp.getStatusCode()), - responseWrapper - ); } - @Override public ResponseModel getCustomerParamByBillerId(CustomParamRequest customerParamRequest) { + String txnID = helper.generateTxnId(15); + String apiName = "GetCustomerParamByBillerId"; + String requestId = customerParamRequest.getReqId(); + String requestJson = helper.convertObjectToJson(customerParamRequest); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName,customerParamRequest.getMid(), "POST", requestJson); + try { String billerId = customerParamRequest.getBillerId(); String fullUrl = masterRegisterUrl + BBPSConstant.CUSTOMPARAM_URL + billerId; + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); + Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); log.info("data is :{}", responseData); - ObjectMapper objectMapper = new ObjectMapper(); + updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -235,9 +283,12 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } @@ -245,7 +296,17 @@ public class MasterDataServiceImpl implements MasterDataService { @Override public ResponseModel getContactMaster(ContactMasterRequest contactMasterRequest) { - + /* + * String txnID = helper.generateTxnId(15); String apiName = "GetContactMaster"; + * String requestId = contactMasterRequest != null ? + * contactMasterRequest.getReqId() : "N/A"; String requestJson = + * helper.convertObjectToJson(contactMasterRequest); InboundTraceLog inboundLog + * = createInboundLog(requestId, txnID, apiName, contactMasterRequest != null ? + * contactMasterRequest.getMid() : "N/A", "POST", requestJson); + * + * // Implementation not present previously - create inbound log and return + * empty response updateInboundLogSuccess(inboundLog, "N/A", "SUCCESS"); + */ return new ResponseModel(); } @@ -253,12 +314,19 @@ public class MasterDataServiceImpl implements MasterDataService { public ResponseModel fetchMasterDataCategoryWise(MasterCategoryRequest masterRequest) { LOGGER.info("Fetching Master Data Category-wise " + masterRequest); + String txnID = helper.generateTxnId(15); + String apiName = "FetchMasterDataCategoryWise"; + String requestId = masterRequest.getReqId(); + String requestJson = helper.convertObjectToJson(masterRequest); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName,masterRequest.getMid(), "POST", requestJson); + try { String validateMerchant = helper.validateMerchant(masterRequest); if (!"Valid".equalsIgnoreCase(validateMerchant)) { LOGGER.warn("Merchant validation failed: {}", validateMerchant); + updateInboundLogFailure(inboundLog, validateMerchant, "INVALID_MERCHANT"); return new ResponseModel("Merchant validation failed", validateMerchant, BBPSConstant.BADREQUEST, null); } @@ -266,18 +334,20 @@ public class MasterDataServiceImpl implements MasterDataService { BBPSConstant.BILLER_URL, masterRequest.getBillerName(), masterRequest.getCategory(), masterRequest.getPageStart(), masterRequest.getPageEnd()); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); + Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); LOGGER.info("Response Data: {}", responseData); - ObjectMapper objectMapper = new ObjectMapper(); + updateOutboundLogResponse(outboundLog, responseData); Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); - // ✅ Same check as in getBillerByBillerId() if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode @@ -291,27 +361,36 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } - } @Override - public ResponseModel getDispositionDetails() { + public ResponseModel getDispositionDetails(DispositionRequest dispositionDetailRequest) { + String txnID = helper.generateTxnId(15); + String apiName = "GetDispositionDetails"; + String requestId = dispositionDetailRequest.getReqId();; + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName,dispositionDetailRequest.getMid() , "GET", "N/A"); + String fullUrl = masterRegisterUrl + BBPSConstant.DISPOSTION_URL; + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); Map responseMap = httpService.getRequest(fullUrl); String responseData = responseMap.get("data"); - ObjectMapper objectMapper = new ObjectMapper(); + updateOutboundLogResponse(outboundLog, responseData); try { Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -337,37 +416,48 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } - } @Override public ResponseModel fetchCustomerParamGroup(BillerDetailRequest requestModel) { LOGGER.info("Fetching Master Data Category-wise for MID={}", requestModel.getMid()); + String txnID = helper.generateTxnId(15); + String apiName = "FetchCustomerParamGroup"; + String requestId = requestModel.getReqId(); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName,requestModel.getMid() , "POST", helper.convertObjectToJson(requestModel)); + try { String validateMerchant = helper.validateMerchant(requestModel); if (!"Valid".equalsIgnoreCase(validateMerchant)) { LOGGER.warn("Merchant validation failed: {}", validateMerchant); + updateInboundLogFailure(inboundLog, validateMerchant, "INVALID_MERCHANT"); return new ResponseModel("Merchant validation failed", validateMerchant, BBPSConstant.BADREQUEST, null); } String fullUrl = masterRegisterUrl + BBPSConstant.CUSTOMER_PARAM_GROUP + requestModel.getBillerId(); - // LOGGER.info("Calling Master API: {}", fullUrl); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); Map apiResponse = httpService.getRequest(fullUrl); String responseData = apiResponse.get("data").toString(); + updateOutboundLogResponse(outboundLog, responseData); + Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -381,10 +471,13 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } @@ -393,26 +486,36 @@ public class MasterDataServiceImpl implements MasterDataService { @Override public ResponseModel fetchAllMasterAmountOption(BillerDetailRequest requestModel) { LOGGER.info("Fetching Master Data Amount List for MID={}", requestModel.getMid()); + + String txnID = helper.generateTxnId(15); + String apiName = "FetchAllMasterAmountOption"; + String requestId = requestModel.getReqId(); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName, requestModel.getMid(), "POST", helper.convertObjectToJson(requestModel)); + try { String validateMerchant = helper.validateMerchant(requestModel); if (!"Valid".equalsIgnoreCase(validateMerchant)) { LOGGER.warn("Merchant validation failed: {}", validateMerchant); + updateInboundLogFailure(inboundLog, validateMerchant, "INVALID_MERCHANT"); return new ResponseModel("Merchant validation failed", validateMerchant, BBPSConstant.BADREQUEST, null); } String fullUrl = masterRegisterUrl + BBPSConstant.AMOUNT_OPTIONS + requestModel.getBillerId(); - // LOGGER.info("Calling Master API: {}", fullUrl); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); Map apiResponse = httpService.getRequest(fullUrl); log.info("Response" + apiResponse); String responseData = apiResponse.get("data").toString(); + updateOutboundLogResponse(outboundLog, responseData); + Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -425,10 +528,13 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } catch (CustomException e) { LOGGER.error("Custom Exception: {}", e.getMessage()); @@ -439,26 +545,36 @@ public class MasterDataServiceImpl implements MasterDataService { @Override public ResponseModel fetchPlanCategorie(BillerDetailRequest requestModel) { LOGGER.info("Fetching Master Data Amount List for MID={}", requestModel.getMid()); + + String txnID = helper.generateTxnId(15); + String apiName = "FetchPlanCategorie"; + String requestId = requestModel.getReqId(); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName, requestModel.getMid() , "POST", helper.convertObjectToJson(requestModel)); + try { String validateMerchant = helper.validateMerchant(requestModel); if (!"Valid".equalsIgnoreCase(validateMerchant)) { LOGGER.warn("Merchant validation failed: {}", validateMerchant); + updateInboundLogFailure(inboundLog, validateMerchant, "INVALID_MERCHANT"); return new ResponseModel("Merchant validation failed", validateMerchant, BBPSConstant.BADREQUEST, null); } String fullUrl = masterRegisterUrl + BBPSConstant.PLAN_CATEGORIES + requestModel.getBillerId(); - // LOGGER.info("Calling Master API: {}", fullUrl); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); Map apiResponse = httpService.getRequest(fullUrl); log.info("Response" + apiResponse); String responseData = apiResponse.get("data").toString(); + updateOutboundLogResponse(outboundLog, responseData); + Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -471,10 +587,13 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } catch (CustomException e) { LOGGER.error("Custom Exception: {}", e.getMessage()); @@ -485,26 +604,38 @@ public class MasterDataServiceImpl implements MasterDataService { @Override public ResponseModel fetchInitiatingChannel(BillerDetailRequest requestModel) { LOGGER.info("Fetching Initiating Channel List for MID={}", requestModel.getMid()); + + String txnID = helper.generateTxnId(15); + String apiName = "FetchInitiatingChannel"; + String requestId =requestModel.getReqId(); + InboundTraceLog inboundLog = createInboundLog(requestId, txnID, apiName, requestModel.getMid(), "POST", helper.convertObjectToJson(requestModel)); + try { String validateMerchant = helper.validateMerchant(requestModel); if (!"Valid".equalsIgnoreCase(validateMerchant)) { LOGGER.warn("Merchant validation failed: {}", validateMerchant); + updateInboundLogFailure(inboundLog, validateMerchant, "INVALID_MERCHANT"); return new ResponseModel("Merchant validation failed", validateMerchant, BBPSConstant.BADREQUEST, null); } String fullUrl = masterRegisterUrl + BBPSConstant.INITIATING_CHANNEL; LOGGER.info("Calling Master API: {}", fullUrl); + OutboundTraceLog outboundLog = createOutboundLog(txnID, requestId, apiName, fullUrl, "GET", null); + Map apiResponse = httpService.getRequest(fullUrl); log.info("Response" + apiResponse); String responseData = apiResponse.get("data").toString(); + updateOutboundLogResponse(outboundLog, responseData); + Map dataMap = objectMapper.readValue(responseData, new TypeReference>() { }); if (!dataMap.containsKey("generalResp")) { + updateInboundLogFailure(inboundLog, responseData, String.valueOf(dataMap.get("status"))); throw new CustomException(String.valueOf(dataMap.get("message")), // message String.valueOf(dataMap.get("status")), // status Integer.parseInt(String.valueOf(dataMap.get("statusCode"))), // statusCode (int) @@ -517,10 +648,13 @@ public class MasterDataServiceImpl implements MasterDataService { ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); + updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); + return responseModel; } catch (JsonProcessingException e) { log.error("Error parsing responseData JSON: {}", e.getMessage()); + updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR"); throw new CustomException("Invalid JSON received from API"); } catch (CustomException e) { LOGGER.error("Custom Exception: {}", e.getMessage()); diff --git a/src/main/java/com/billpaymentservice/bbps/util/Helper.java b/src/main/java/com/billpaymentservice/bbps/util/Helper.java index c52096a..0ad1b43 100644 --- a/src/main/java/com/billpaymentservice/bbps/util/Helper.java +++ b/src/main/java/com/billpaymentservice/bbps/util/Helper.java @@ -9,10 +9,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.billpaymentservice.bbps.dto.ResponseModel; +import com.billpaymentservice.bbps.dto.request.BillerDetailRequest; import com.billpaymentservice.bbps.dto.request.MerchantRequestModel; import com.billpaymentservice.bbps.entites.BBPSMerchantValidation; import com.billpaymentservice.bbps.exception.CustomException; import com.billpaymentservice.bbps.repository.MerchantRepository; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; @Component @@ -23,6 +26,8 @@ public class Helper { private static final String CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; private static final SecureRandom secureRandom = new SecureRandom(); + private final ObjectMapper objectMapper = new ObjectMapper(); + @Autowired private MerchantRepository merchantRegisterRepo; @@ -125,4 +130,15 @@ public class Helper { } return sb.toString(); // Prefix } -} + public String convertObjectToJson(Object obj) { + if (obj == null) return "null"; + try { + return new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(obj); + } catch (com.fasterxml.jackson.core.JsonProcessingException e) { + // log appropriately (use your existing logger) + System.err.println("JSON conversion failed: " + e.getMessage()); + return "{}"; // or "N/A" depending on your needs + } + } + +} \ No newline at end of file