updated code
This commit is contained in:
@@ -1,116 +0,0 @@
|
|||||||
package com.billpaymentservice.bbps.config;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import jakarta.servlet.FilterChain;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
|
||||||
import com.billpaymentservice.bbps.util.BBPSConstant;
|
|
||||||
import com.billpaymentservice.bbps.dto.ResponseModel;
|
|
||||||
|
|
||||||
import io.github.resilience4j.ratelimiter.RateLimiter;
|
|
||||||
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Order(1)
|
|
||||||
public class RateLimitingFilter extends OncePerRequestFilter {
|
|
||||||
|
|
||||||
private final RateLimiterRegistry rateLimiterRegistry;
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitingFilter.class);
|
|
||||||
|
|
||||||
// Har MID ke liye alag limiter
|
|
||||||
private final Map<String, RateLimiter> limiterCache = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
|
||||||
|
|
||||||
public RateLimitingFilter(RateLimiterRegistry rateLimiterRegistry) {
|
|
||||||
this.rateLimiterRegistry = rateLimiterRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doFilterInternal(HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
FilterChain filterChain)
|
|
||||||
throws ServletException, IOException {
|
|
||||||
String mid = request.getHeader("mid");
|
|
||||||
if(mid == null) {
|
|
||||||
mid = "GLOBAL";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate MID
|
|
||||||
if (mid == null || mid.isBlank()) {
|
|
||||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
|
|
||||||
ResponseModel<Object> apiResponse = new ResponseModel<>("mid cannot be null or blank", "FAILURE", HttpServletResponse.SC_BAD_REQUEST, null);
|
|
||||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
RateLimiter rateLimiter = limiterCache.computeIfAbsent(
|
|
||||||
mid,
|
|
||||||
key -> rateLimiterRegistry.rateLimiter("default")
|
|
||||||
);
|
|
||||||
|
|
||||||
// Rate limit check
|
|
||||||
if (!rateLimiter.acquirePermission()) {
|
|
||||||
|
|
||||||
// Prefer existing constant if it maps to 429, otherwise fallback to literal 429
|
|
||||||
int tooManyRequestsStatus =429;
|
|
||||||
|
|
||||||
response.setStatus(tooManyRequestsStatus);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
|
|
||||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Rate limit exceeded for MID: " + mid, "FAILURE", tooManyRequestsStatus, null);
|
|
||||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proceed with the chain and catch downstream exceptions to return consistent model
|
|
||||||
try {
|
|
||||||
filterChain.doFilter(request, response);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
LOGGER.error("Unhandled exception in filter chain for MID: {}", mid, ex);
|
|
||||||
if (!response.isCommitted()) {
|
|
||||||
response.reset();
|
|
||||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Internal server error", "FAILURE", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
|
|
||||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("Error while rate limiting request", e);
|
|
||||||
if (!response.isCommitted()) {
|
|
||||||
response.reset();
|
|
||||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Internal server error", "FAILURE", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
|
|
||||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
|
||||||
|
|
||||||
String path = request.getRequestURI();
|
|
||||||
|
|
||||||
return path.startsWith("/swagger")
|
|
||||||
|| path.startsWith("/v3/api-docs")
|
|
||||||
|| path.startsWith("/actuator");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.billpaymentservice.bbps.entites;
|
package com.billpaymentservice.bbps.entites;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.EntityListeners;
|
import jakarta.persistence.EntityListeners;
|
||||||
@@ -9,33 +10,34 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base mapped superclass for audit fields. All JPA entities should extend this to
|
* Base mapped superclass for audit fields. All JPA entities should extend this
|
||||||
* get automatic population of createdAt/updatedAt/isDeleted via AuditListener.
|
* to get automatic population of createdAt/updatedAt/isDeleted via
|
||||||
|
* AuditListener.
|
||||||
*/
|
*/
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
@EntityListeners(AuditListener.class)
|
@EntityListeners(AuditListener.class)
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
public abstract class Auditable {
|
public abstract class Auditable implements Serializable {
|
||||||
@Column(name = "create_date_time")
|
@Column(name = "create_date_time")
|
||||||
private LocalDateTime createDateTime;
|
private Date createDateTime;
|
||||||
|
|
||||||
@Column(name = "updated_date_time")
|
@Column(name = "updated_date_time")
|
||||||
private LocalDateTime updatedDateTime;
|
private Date updatedDateTime;
|
||||||
|
|
||||||
@Column(name = "create_by")
|
@Column(name = "create_by")
|
||||||
private LocalDateTime createdBy;
|
private String createdBy;
|
||||||
|
|
||||||
@Column(name = "updated_by")
|
@Column(name = "updated_by")
|
||||||
private LocalDateTime updatedBy;
|
private String updatedBy;
|
||||||
|
|
||||||
@Column(name = "created_epoch_date")
|
@Column(name = "created_epoch_date")
|
||||||
private Long createdEpochDate;
|
private Long createdEpochDate;
|
||||||
|
|
||||||
@Column(name = "modified_epoch_date")
|
@Column(name = "modified_epoch_date")
|
||||||
private Long modifiedEpochDate;
|
private Long modifiedEpochDate;
|
||||||
|
|
||||||
@Column(name = "is_deleted")
|
@Column(name = "is_deleted")
|
||||||
private Boolean isDeleted = Boolean.FALSE;
|
private Boolean isDeleted = Boolean.FALSE;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -77,6 +77,9 @@ public class ComplaintResponseEntity extends Auditable {
|
|||||||
@Column(name = "user_id")
|
@Column(name = "user_id")
|
||||||
private String userId;
|
private String userId;
|
||||||
|
|
||||||
|
@Column(name = "mid")
|
||||||
|
private String mid;
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY)
|
@OneToMany(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "ticket_id", referencedColumnName = "ticket_id", insertable = false, updatable = false)
|
@JoinColumn(name = "ticket_id", referencedColumnName = "ticket_id", insertable = false, updatable = false)
|
||||||
private Set<ComplainStatus> complaintStatusList = new HashSet<>();
|
private Set<ComplainStatus> complaintStatusList = new HashSet<>();
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ public class ComplainServiceImpl implements ComplainService {
|
|||||||
ComplaintResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintResponse.class);
|
ComplaintResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintResponse.class);
|
||||||
|
|
||||||
String saveComplaintResponseEntity = mapperHelper.saveComplaintResponseEntity(responseWrapper, requestId,
|
String saveComplaintResponseEntity = mapperHelper.saveComplaintResponseEntity(responseWrapper, requestId,
|
||||||
txnId, userId, requestTxnId);
|
txnId, userId, requestTxnId, mid);
|
||||||
LOGGER.info("Save Complaint Response Count" + saveComplaintResponseEntity);
|
LOGGER.info("Save Complaint Response Count" + saveComplaintResponseEntity);
|
||||||
ResponseModel responseModel = new ResponseModel(responseWrapper.getMessage(), responseWrapper.getStatus(),
|
ResponseModel responseModel = new ResponseModel(responseWrapper.getMessage(), responseWrapper.getStatus(),
|
||||||
Integer.parseInt(responseWrapper.getStatusCode()), responseWrapper);
|
Integer.parseInt(responseWrapper.getStatusCode()), responseWrapper);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.time.format.DateTimeFormatter;
|
|||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -528,6 +529,7 @@ public class BillerMapperHelper {
|
|||||||
entity.setNpciTicketStatus(dto.getNpciTicketStatus());
|
entity.setNpciTicketStatus(dto.getNpciTicketStatus());
|
||||||
entity.setCreatedTime(dto.getCreatedTime());
|
entity.setCreatedTime(dto.getCreatedTime());
|
||||||
entity.setUserId(userId);
|
entity.setUserId(userId);
|
||||||
|
entity.setCreateDateTime(new Date());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ComplainStatus saved = complaintStatusRepository.save(entity);
|
ComplainStatus saved = complaintStatusRepository.save(entity);
|
||||||
@@ -558,7 +560,7 @@ public class BillerMapperHelper {
|
|||||||
entity.setReqId(reqId);
|
entity.setReqId(reqId);
|
||||||
entity.setTxnId(txnId);
|
entity.setTxnId(txnId);
|
||||||
entity.setUserId(userId);
|
entity.setUserId(userId);
|
||||||
|
entity.setCreateDateTime(new Date());
|
||||||
complaintHistoryRepository.save(entity);
|
complaintHistoryRepository.save(entity);
|
||||||
savedCount++;
|
savedCount++;
|
||||||
}
|
}
|
||||||
@@ -673,6 +675,7 @@ public class BillerMapperHelper {
|
|||||||
entity.setPage(String.valueOf(responseWrapper.getPage()));
|
entity.setPage(String.valueOf(responseWrapper.getPage()));
|
||||||
entity.setPageSize(String.valueOf(responseWrapper.getPageSize()));
|
entity.setPageSize(String.valueOf(responseWrapper.getPageSize()));
|
||||||
entity.setUserId(userId);
|
entity.setUserId(userId);
|
||||||
|
entity.setCreateDateTime(new Date());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,6 +855,7 @@ public class BillerMapperHelper {
|
|||||||
entity.setTotalPages(String.valueOf(responseWrapper.getTotalPages()));
|
entity.setTotalPages(String.valueOf(responseWrapper.getTotalPages()));
|
||||||
entity.setTotalElements(String.valueOf(responseWrapper.getTotalElements()));
|
entity.setTotalElements(String.valueOf(responseWrapper.getTotalElements()));
|
||||||
entity.setUserId(userId);
|
entity.setUserId(userId);
|
||||||
|
entity.setCreateDateTime(new Date());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -962,9 +966,9 @@ public class BillerMapperHelper {
|
|||||||
LocalDateTime bmCreatedOn = parseToLocalDateTime(responseWrapper.getCreationDate());
|
LocalDateTime bmCreatedOn = parseToLocalDateTime(responseWrapper.getCreationDate());
|
||||||
|
|
||||||
LocalDateTime bmUpdatedOn = parseToLocalDateTime(responseWrapper.getModifiedDate());
|
LocalDateTime bmUpdatedOn = parseToLocalDateTime(responseWrapper.getModifiedDate());
|
||||||
if (bmUpdatedOn != null) {
|
// if (bmUpdatedOn != null) {
|
||||||
billMaster.setUpdatedDateTime(bmUpdatedOn);
|
// billMaster.setUpdatedDateTime(bmUpdatedOn);
|
||||||
}
|
// }
|
||||||
billMaster.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
|
billMaster.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
|
||||||
billMaster.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
|
billMaster.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
|
||||||
|
|
||||||
@@ -1091,20 +1095,26 @@ public class BillerMapperHelper {
|
|||||||
record.setClientUserId(request.getClientUserId());
|
record.setClientUserId(request.getClientUserId());
|
||||||
record.setInternalTxnId(txnId);
|
record.setInternalTxnId(txnId);
|
||||||
|
|
||||||
if (apiResponse != null &&
|
if (apiResponse != null && apiResponse.getResponseData() != null) {
|
||||||
apiResponse.getResponseData() != null) {
|
record.setAmount(Optional.ofNullable(apiResponse.getResponseData().getAmount()).orElse("0.00"));
|
||||||
record.setAmount(Optional.ofNullable(apiResponse.getResponseData().getAmount(
|
|
||||||
)).orElse("0.00"));
|
|
||||||
|
|
||||||
record.setTxnId(Optional.ofNullable(apiResponse.getResponseData().getTxnId())
|
record.setTxnId(Optional.ofNullable(apiResponse.getResponseData().getTxnId()).orElse("DUMMY_TXN"));
|
||||||
.orElse("DUMMY_TXN"));
|
record.setQrString(Optional.ofNullable(apiResponse.getResponseData().getQrString()).orElse("NO_QR")); // parse
|
||||||
record.setQrString(Optional.ofNullable(apiResponse.getResponseData().
|
// createdOn
|
||||||
getQrString()).orElse("NO_QR")); // parse createdOn string into LocalDateTime and set on Auditable
|
// string
|
||||||
LocalDateTime createdOn =parseToLocalDateTime(apiResponse.getResponseData().getCreatedOn());
|
// into
|
||||||
|
// LocalDateTime
|
||||||
record.setTxnStatus("PENDING"); } else { record.setAmount("0.00");
|
// and
|
||||||
record.setTxnStatus("PENDING"); }
|
// set
|
||||||
|
// on
|
||||||
|
// Auditable
|
||||||
|
LocalDateTime createdOn = parseToLocalDateTime(apiResponse.getResponseData().getCreatedOn());
|
||||||
|
|
||||||
|
record.setTxnStatus("PENDING");
|
||||||
|
} else {
|
||||||
|
record.setAmount("0.00");
|
||||||
|
record.setTxnStatus("PENDING");
|
||||||
|
}
|
||||||
|
|
||||||
// store the original request body and raw response
|
// store the original request body and raw response
|
||||||
record.setRequestBody(requestJson);
|
record.setRequestBody(requestJson);
|
||||||
@@ -1151,7 +1161,7 @@ public class BillerMapperHelper {
|
|||||||
|
|
||||||
// Persist complaint response entity
|
// Persist complaint response entity
|
||||||
public String saveComplaintResponseEntity(ComplaintResponse responseWrapper, String requestId, String txnId,
|
public String saveComplaintResponseEntity(ComplaintResponse responseWrapper, String requestId, String txnId,
|
||||||
String userId, String requestTxnId) {
|
String userId, String requestTxnId, String mid) {
|
||||||
if (responseWrapper == null || responseWrapper.getTicketDetails() == null) {
|
if (responseWrapper == null || responseWrapper.getTicketDetails() == null) {
|
||||||
return "No data";
|
return "No data";
|
||||||
}
|
}
|
||||||
@@ -1164,6 +1174,8 @@ public class BillerMapperHelper {
|
|||||||
complaintResponseEntity.setTicketDesp(responseWrapper.getTicketDetails().getTicketDesp());
|
complaintResponseEntity.setTicketDesp(responseWrapper.getTicketDetails().getTicketDesp());
|
||||||
complaintResponseEntity.setTicketDesr(responseWrapper.getTicketDetails().getTicketDesr());
|
complaintResponseEntity.setTicketDesr(responseWrapper.getTicketDetails().getTicketDesr());
|
||||||
complaintResponseEntity.setRequestTxnId(requestTxnId);
|
complaintResponseEntity.setRequestTxnId(requestTxnId);
|
||||||
|
complaintResponseEntity.setMid(mid);
|
||||||
|
complaintResponseEntity.setCreateDateTime(new Date());
|
||||||
|
|
||||||
complaintResponseEntity.setMessage(responseWrapper.getMessage());
|
complaintResponseEntity.setMessage(responseWrapper.getMessage());
|
||||||
complaintResponseEntity.setRemarks(responseWrapper.getRemarks());
|
complaintResponseEntity.setRemarks(responseWrapper.getRemarks());
|
||||||
@@ -1273,7 +1285,7 @@ public class BillerMapperHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComplaintResponseDto toDto(ComplaintResponseEntity e) {
|
public ComplaintResponseDto toDto(ComplaintResponseEntity e) {
|
||||||
|
|
||||||
ComplaintResponseDto dto = new ComplaintResponseDto();
|
ComplaintResponseDto dto = new ComplaintResponseDto();
|
||||||
dto.setTicketId(e.getTicketId());
|
dto.setTicketId(e.getTicketId());
|
||||||
|
|||||||
Reference in New Issue
Block a user