fixed the biller Id Saving problem added 404 not found url

This commit is contained in:
Lincpay Tech
2025-11-12 10:24:52 +05:30
parent d9973ac69a
commit 50b26af952
14 changed files with 374 additions and 16 deletions
@@ -0,0 +1,42 @@
package com.billpaymentservice.bbps.controller;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.BillPaymentRequest;
import com.billpaymentservice.bbps.dto.request.ComplaintRequestDTO;
import com.billpaymentservice.bbps.service.ComplainService;
import com.billpaymentservice.bbps.service.PaymentService;
@RestController
@RequestMapping("/complain")
@CrossOrigin(origins = "*")
public class ComplainController {
private final ComplainService complainService;
public ComplainController(ComplainService complainService) {
this.complainService=complainService;
}
@PostMapping(
value = "/addComplain",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<ResponseModel> addComplain(
@Validated @RequestBody ComplaintRequestDTO complainRequestDTO) {
ResponseModel response = complainService.addComplain(complainRequestDTO);
return ResponseEntity.ok(response);
}
}
@@ -0,0 +1,32 @@
package com.billpaymentservice.bbps.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class ComplaintDetailsDTO {
private String complaintId; // UUID
private String complaintDescr; // Complaint description
private String complaintDispos; // Complaint disposition
private String complaintType;
// Complaint type
@JsonProperty("txnId")
private String bankTxnId; // Transaction ID
private String txnNpciId; // Transaction NPCI ID
private String assignedTo; // Assigned person
private String complaintNpciId; // Complaint NPCI ID
private String complaintRaisedFrom; // Who raised the complaint
private String userId; // User ID
private String status; // Complaint status
private String refId; // Reference ID
private String estimated_TAT; // Estimated Turnaround Time
private String creationDate; // ISO timestamp
private String modifiedDate; // ISO timestamp
private Long createdEpochDate; // Epoch creation time
private Long modifiedEpochDate; // Epoch modified time
}
@@ -1,6 +1,7 @@
package com.billpaymentservice.bbps.dto.request;
import com.billpaymentservice.bbps.dto.DeviceDetail;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
@@ -15,37 +16,53 @@ import lombok.ToString;
@AllArgsConstructor
@NoArgsConstructor
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class BaseClass {
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@NotBlank(message = "MID cannot be null or blank")
private String mid;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@NotBlank(message = "Secret key cannot be null or blank")
private String secretKey;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@NotBlank(message = "Request ID cannot be null or blank")
private String reqId;
@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;
}
@@ -0,0 +1,15 @@
package com.billpaymentservice.bbps.dto.request;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ComplaintRequestDTO extends BaseClass {
private String complaintDescription; // Complaint description that the user enters
private String complaintDisposition; // Complaint disposition
private String complaintType; // Type of complaint
private String txnId; // Transaction ID (optional)
private String clientReqId; // Client Req ID (optional)
}
@@ -0,0 +1,16 @@
package com.billpaymentservice.bbps.dto.response;
import java.util.List;
import com.billpaymentservice.bbps.dto.ComplaintDetailsDTO;
import com.billpaymentservice.bbps.dto.GeneralResp;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ComplaintResponse {
private ComplaintDetailsDTO complaints; // multiple complaints
private GeneralResp generalResp;
}
@@ -0,0 +1,71 @@
package com.billpaymentservice.bbps.entites;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Entity
@Table(name = "complaint_details")
@Getter
@Setter
@ToString
public class ComplaintDetails {
@Id
@Column(name = "complaint_id", nullable = false, unique = true)
private String complaintId; // Primary key (UUID from BBPS API)
@Column(name = "req_id")
private String reqId;
@Column(name = "txn_id")
private String txnId;
@Column(name = "complaint_descr")
private String complaintDescr;
@Column(name = "complaint_dispos")
private String complaintDispos;
@Column(name = "complaint_type")
private String complaintType;
@Column(name = "bank_txn_id")
private String bankTxnId;
@Column(name = "txn_npci_id")
private String txnNpciId;
@Column(name = "assigned_to")
private String assignedTo;
@Column(name = "complaint_npci_id")
private String complaintNpciId;
@Column(name = "complaint_raised_from")
private String complaintRaisedFrom;
@Column(name = "user_id")
private String userId;
@Column(name = "status")
private String status;
@Column(name = "ref_id")
private String refId;
@Column(name = "estimated_tat")
private String estimated_TAT;
@Column(name = "creation_date")
private String creationDate;
@Column(name = "modified_date")
private String modifiedDate;
@Column(name = "created_epoch_date")
private Long createdEpochDate;
@Column(name = "modified_epoch_date")
private Long modifiedEpochDate;
}
@@ -2,10 +2,13 @@ package com.billpaymentservice.bbps.entites;
import java.util.List;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.CascadeType;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
@@ -36,10 +39,11 @@ public class Group {
@Column(name = "input")
private String input;
// Example: "Admission No/Application No/GR No" → stored as multiple params
@ElementCollection
@CollectionTable(name = "group_params", joinColumns = @JoinColumn(name = "group_id"))
@Column(name = "param_name")
@CollectionTable(
name = "group_params",
joinColumns = @JoinColumn(name = "group_id"),
foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT)
)
private List<String> params;
// 🔗 Parent group relationship (for nested groups)
@@ -9,6 +9,7 @@ import org.springframework.http.*;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.NoHandlerFoundException;
import com.billpaymentservice.bbps.dto.ResponseModel;
@@ -36,6 +37,18 @@ public class GlobalExceptionHandler {
resp.setData(fieldErrors);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
}
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<ResponseModel<?>> handleNotFound(NoHandlerFoundException ex) {
logger.warn("Endpoint not found: {}", ex.getRequestURL());
ResponseModel<?> resp = new ResponseModel<>(
"Endpoint not found: " + ex.getRequestURL(),
"FAILED",
HttpStatus.NOT_FOUND.value(),
null
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
}
@ExceptionHandler(AppException.class)
public ResponseEntity<ResponseModel<?>> handleAppException(AppException ex) {
@@ -0,0 +1,9 @@
package com.billpaymentservice.bbps.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.billpaymentservice.bbps.entites.ComplaintDetails;
public interface ComplainRepository extends JpaRepository<ComplaintDetails, String> {
}
@@ -0,0 +1,10 @@
package com.billpaymentservice.bbps.service;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.ComplaintRequestDTO;
public interface ComplainService {
public ResponseModel addComplain(ComplaintRequestDTO complainRequestDTO);
}
@@ -162,7 +162,7 @@ public class AgentServiceImpl implements AgentService {
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";
String fullUrl = agentDtaUrl + BBPSConstant.BILL_FETCH_BY_ID + billFetchByBillIdRequest.getBillId();
helper.validateMerchant(billFetchByBillIdRequest.getMid());
@@ -347,7 +347,7 @@ public class AgentServiceImpl implements AgentService {
billFetchByBillIdRequest.setReqId(reqId);
LOGGER.info("Waiting for 2 seconds before fetching bill by ID...");
try {
Thread.sleep(2000);
Thread.sleep(12000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOGGER.warn("Thread interrupted during delay: {}", e.getMessage());
@@ -370,7 +370,7 @@ public class AgentServiceImpl implements AgentService {
String txnId = helper.generateTxnId(15);
String reqId = billRequest.getReqId();
String billId = billRequest.getBillId();
String fullUrl = agentDtaUrl + BBPSConstant.BILL_VALIDATE_ID_URL+ "c9670952-ebd7-487a-b6ea-49f2b4d4a718";
String fullUrl = agentDtaUrl + BBPSConstant.BILL_VALIDATE_ID_URL+ billRequest.getBillId(); ;
helper.validateMerchant(billRequest.getMid());
@@ -0,0 +1,118 @@
package com.billpaymentservice.bbps.serviceImpl;
import java.util.Map;
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.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import com.billpaymentservice.bbps.dto.GeneralResp;
import com.billpaymentservice.bbps.dto.ResponseModel;
import com.billpaymentservice.bbps.dto.request.ComplaintRequestDTO;
import com.billpaymentservice.bbps.dto.response.BillerDataResponse;
import com.billpaymentservice.bbps.dto.response.ComplaintResponse;
import com.billpaymentservice.bbps.entites.BharatConnectMaster;
import com.billpaymentservice.bbps.entites.BillPayment;
import com.billpaymentservice.bbps.entites.BillerDetails;
import com.billpaymentservice.bbps.entites.ComplaintDetails;
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.ComplainRepository;
import com.billpaymentservice.bbps.service.ComplainService;
import com.billpaymentservice.bbps.util.BBPSConstant;
import com.billpaymentservice.bbps.util.EntityRelationshipUtil;
import com.billpaymentservice.bbps.util.Helper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class ComplainServiceImpl implements ComplainService {
@Value("${complaint.data.url}")
private String complainDataUrl;
public static final Logger LOGGER = LoggerFactory.getLogger(ComplainServiceImpl.class);
private final Helper helper;
private final ObjectMapper objectMapper = new ObjectMapper();
private final BharatConnectMasterRepository beneficiaryDetailsRepository;
private final HttpService httpService;
private final ComplainRepository complainRepository;
public ComplainServiceImpl(Helper helper
,HttpService httpService,
BharatConnectMasterRepository beneficiaryDetailsRepository,
ComplainRepository complainRepository) {
this.helper=helper;
this.httpService=httpService;
this.beneficiaryDetailsRepository=beneficiaryDetailsRepository;
this.complainRepository=complainRepository;
}
@Override
public ResponseModel addComplain(ComplaintRequestDTO complainRequestDTO) {
LOGGER.info("Initiating addComplain for request ID: {} and MID", complainRequestDTO.getReqId(),
complainRequestDTO.getMid());
String apiName = "ADDCOMPLAIN";
String txnId = helper.generateTxnId(15);
String requestId = complainRequestDTO.getReqId();
String fullUrl = complainDataUrl + BBPSConstant.ADD_COMPLAIN_ENDPOINT;
String requestJson = helper.convertObjectToJson(complainRequestDTO);
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);
InboundTraceLog inboundLog = helper.createInboundLog(requestId, txnId, apiName, complainRequestDTO.getMid(),
"POST", requestJson);
OutboundTraceLog outboundLog = helper.createOutboundLog(txnId, requestId, apiName, fullUrl, "POST", null);
LOGGER.info("Calling external API: {}", fullUrl);
LOGGER.info("Request payload: {}", requestJson);
Map<String, String> responseMap = httpService.postRequest(fullUrl, requestJson, headers);
String responseData = responseMap.get("data");
LOGGER.info("fetched data from api is :{}", responseData);
helper.updateOutboundLogResponse(outboundLog, responseData);
try {
Map<String, Object> dataMap = objectMapper.readValue(responseData,
new TypeReference<Map<String, Object>>() {
});
LOGGER.info("Parsed response data: {}", dataMap);
if (!dataMap.containsKey("generalResp")) {
helper.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")));
}
ComplaintResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintResponse.class);
GeneralResp generalResp = responseWrapper.getGeneralResp();
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
ComplaintDetails entity = mapper.map(responseWrapper.getComplaints(), ComplaintDetails.class);
entity.setReqId(complainRequestDTO.getReqId());
entity.setTxnId(txnId);
complainRepository.save(entity);
ResponseModel responseModel = new ResponseModel(generalResp.getMessage(), generalResp.getStatus(),
Integer.parseInt(generalResp.getStatusCode()), responseWrapper);
helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus());
return responseModel;
} catch (JsonProcessingException e) {
LOGGER.error("Error parsing responseData JSON: {}", e.getMessage());
helper.updateInboundLogFailure(inboundLog, e.getMessage(), "JSON_ERROR");
throw new CustomException("Invalid JSON received from API");
}
}
}
@@ -44,5 +44,6 @@ public class BBPSConstant {
public static final String DISPOSTION_URL = "/disposition";
public static final String PLANS_URL = "/plans";
public static final String ADD_COMPLAIN_ENDPOINT = "/couapp/complaints";
}
+10
View File
@@ -42,6 +42,16 @@ logging.level.io.github.resilience4j.retry=DEBUG
master.data.url = https://bbps-staging.digiledge.in/agent/cou-master/masters
agent.data.url=https://bbps-staging.digiledge.in/agent/bill-payment-new
payment.data.url=https://bbps-staging.digiledge.in/couapp
complaint.data.url=https://bbps-staging.digiledge.in
# throw NoHandlerFoundException for 404s
spring.mvc.throw-exception-if-no-handler-found=true
# disable white-label error page
spring.web.resources.add-mappings=false
# (optional) to avoid path match issues on Spring Boot 2.6+
spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
# Resilience4j Retry