update code
This commit is contained in:
@@ -44,7 +44,7 @@ public class SecurityConfig {
|
||||
"/webjars/**",
|
||||
"/error")
|
||||
.permitAll()
|
||||
.requestMatchers("/payment/callback/startPayment")
|
||||
.requestMatchers("/payment/callback/startPayment","/checkTicketStatus/complaints/")
|
||||
.permitAll().requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.anyRequest().authenticated())
|
||||
.exceptionHandling(ex -> ex.authenticationEntryPoint(jwtAuthenticationEntryPoint))
|
||||
|
||||
@@ -6,75 +6,67 @@ import java.time.LocalDateTime;
|
||||
import jakarta.persistence.PrePersist;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
|
||||
/**
|
||||
* Generic JPA entity listener that populates common audit fields on entities.
|
||||
*
|
||||
* Behavior:
|
||||
* - On PrePersist: sets createdAt/creationDate/createdEpochDate if present (only when null),
|
||||
* and forces isDeleted/deleted to false if those fields exist.
|
||||
* - On PreUpdate: sets modifiedDate/modifiedEpochDate/updatedAt/updatedOn if present.
|
||||
*
|
||||
* This uses reflection so entities don't need to extend a specific base class.
|
||||
*/
|
||||
public class AuditListener {
|
||||
|
||||
@PrePersist
|
||||
public void prePersist(Object entity) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
setIfNull(entity, "createdAt", now);
|
||||
setIfNull(entity, "createdOn", now);
|
||||
setIfNull(entity, "creationDate", now == null ? null : now.toString());
|
||||
|
||||
// Creation fields
|
||||
setIfNull(entity, "createDateTime", now);
|
||||
setIfNull(entity, "createdBy", null); // handle manually in service if needed
|
||||
setIfNull(entity, "createdEpochDate", System.currentTimeMillis());
|
||||
|
||||
// Ensure isDeleted / deleted exists and is set to false on create
|
||||
// Set isDeleted = false on creation
|
||||
setAlways(entity, "isDeleted", Boolean.FALSE);
|
||||
}
|
||||
|
||||
/*@PreUpdate
|
||||
public void preUpdate(Object entity) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
setIfNull(entity, "modifiedDate", now == null ? null : now.toString());
|
||||
setIfNull(entity, "modifiedEpochDate", System.currentTimeMillis());
|
||||
setIfNull(entity, "updatedAt", now);
|
||||
setIfNull(entity, "updatedOn", now);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* @PreUpdate public void preUpdate(Object entity) { LocalDateTime now =
|
||||
* LocalDateTime.now();
|
||||
*
|
||||
* // Update fields setAlways(entity, "updatedDateTime", now); setIfNull(entity,
|
||||
* "updatedBy", null); // you can override manually in service setAlways(entity,
|
||||
* "modifiedEpochDate", System.currentTimeMillis()); }
|
||||
*/
|
||||
private void setIfNull(Object entity, String fieldName, Object value) {
|
||||
try {
|
||||
Field f = findField(entity.getClass(), fieldName);
|
||||
if (f == null) return;
|
||||
|
||||
boolean accessible = f.canAccess(entity);
|
||||
f.setAccessible(true);
|
||||
Object current = f.get(entity);
|
||||
if (current == null && value != null) {
|
||||
|
||||
Object currentValue = f.get(entity);
|
||||
if (currentValue == null) {
|
||||
f.set(entity, value);
|
||||
}
|
||||
|
||||
f.setAccessible(accessible);
|
||||
} catch (Exception e) {
|
||||
// ignore reflection failures
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
private void setAlways(Object entity, String fieldName, Object value) {
|
||||
try {
|
||||
Field f = findField(entity.getClass(), fieldName);
|
||||
if (f == null) return;
|
||||
|
||||
boolean accessible = f.canAccess(entity);
|
||||
f.setAccessible(true);
|
||||
|
||||
f.set(entity, value);
|
||||
|
||||
f.setAccessible(accessible);
|
||||
} catch (Exception e) {
|
||||
// ignore reflection failures
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
private Field findField(Class<?> cls, String name) {
|
||||
Class<?> cur = cls;
|
||||
while (cur != null && cur != Object.class) {
|
||||
Class<?> current = cls;
|
||||
while (current != null && current != Object.class) {
|
||||
try {
|
||||
return cur.getDeclaredField(name);
|
||||
return current.getDeclaredField(name);
|
||||
} catch (NoSuchFieldException e) {
|
||||
cur = cur.getSuperclass();
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -17,25 +17,25 @@ import lombok.Setter;
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Auditable {
|
||||
@Column(name = "create_date_time")
|
||||
private LocalDateTime createDateTime;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
@Column(name = "updated_date_time")
|
||||
private LocalDateTime updatedDateTime;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
@Column(name = "create_by")
|
||||
private LocalDateTime createdBy;
|
||||
|
||||
@Column(name = "created_on")
|
||||
private LocalDateTime createdOn;
|
||||
@Column(name = "updated_by")
|
||||
private LocalDateTime updatedBy;
|
||||
|
||||
@Column(name = "updated_on")
|
||||
private LocalDateTime updatedOn;
|
||||
@Column(name = "created_epoch_date")
|
||||
private Long createdEpochDate;
|
||||
|
||||
@Column(name = "created_epoch_date")
|
||||
private Long createdEpochDate;
|
||||
@Column(name = "modified_epoch_date")
|
||||
private Long modifiedEpochDate;
|
||||
|
||||
@Column(name = "modified_epoch_date")
|
||||
private Long modifiedEpochDate;
|
||||
|
||||
@Column(name = "is_deleted")
|
||||
private Boolean isDeleted = Boolean.FALSE;
|
||||
@Column(name = "is_deleted")
|
||||
private Boolean isDeleted = Boolean.FALSE;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.billpaymentservice.bbps.entites;
|
||||
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.billpaymentservice.bbps.exception;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -12,6 +14,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
|
||||
import com.billpaymentservice.bbps.dto.ResponseModel;
|
||||
|
||||
@@ -90,16 +93,13 @@ public class GlobalExceptionHandler {
|
||||
|
||||
logger.warn("Invalid JSON received for endpoint {}: {}", endpoint, shortMsg);
|
||||
|
||||
Map<String, Object> data = Map.of(
|
||||
"exception", ex.getClass().getName(),
|
||||
"message", shortMsg
|
||||
);
|
||||
|
||||
|
||||
ResponseModel<?> resp = new ResponseModel<>(
|
||||
"[" + endpoint + "] Invalid JSON received",
|
||||
"Invalid JSON received",
|
||||
"FAILED",
|
||||
HttpStatus.BAD_REQUEST.value(),
|
||||
data
|
||||
null
|
||||
);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
|
||||
@@ -164,6 +164,79 @@ public class GlobalExceptionHandler {
|
||||
return ResponseEntity.status(httpStatus).body(resp);
|
||||
}
|
||||
|
||||
// ------------------------- RESOURCE ACCESS / TIMEOUT / CONNECT ------------------------
|
||||
@ExceptionHandler(ResourceAccessException.class)
|
||||
public ResponseEntity<ResponseModel<?>> handleResourceAccess(
|
||||
ResourceAccessException ex,
|
||||
HttpServletRequest request,
|
||||
HandlerMethod handlerMethod) {
|
||||
|
||||
String context = buildErrorContext(ex, request, handlerMethod);
|
||||
logger.error("ResourceAccessException → {}", context, ex);
|
||||
|
||||
Throwable cause = ex.getCause();
|
||||
String message;
|
||||
HttpStatus status;
|
||||
|
||||
if (cause instanceof SocketTimeoutException) {
|
||||
message = "Server timeout - server may be down";
|
||||
status = HttpStatus.GATEWAY_TIMEOUT; // 504
|
||||
} else if (cause instanceof ConnectException) {
|
||||
message = "Server unavailable - connection refused";
|
||||
status = HttpStatus.SERVICE_UNAVAILABLE; // 503
|
||||
} else {
|
||||
message = "Server unreachable: " + ex.getMessage();
|
||||
status = HttpStatus.SERVICE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
ResponseModel<?> resp = new ResponseModel<>(
|
||||
message,
|
||||
"FAILED",
|
||||
status.value(),
|
||||
null
|
||||
);
|
||||
|
||||
return ResponseEntity.status(status).body(resp);
|
||||
}
|
||||
|
||||
@ExceptionHandler(SocketTimeoutException.class)
|
||||
public ResponseEntity<ResponseModel<?>> handleSocketTimeout(
|
||||
SocketTimeoutException ex,
|
||||
HttpServletRequest request,
|
||||
HandlerMethod handlerMethod) {
|
||||
|
||||
String context = buildErrorContext(ex, request, handlerMethod);
|
||||
logger.error("SocketTimeoutException → {}", context, ex);
|
||||
|
||||
ResponseModel<?> resp = new ResponseModel<>(
|
||||
"Server timeout - server is down",
|
||||
"FAILED",
|
||||
HttpStatus.GATEWAY_TIMEOUT.value(),
|
||||
null
|
||||
);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.GATEWAY_TIMEOUT).body(resp);
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConnectException.class)
|
||||
public ResponseEntity<ResponseModel<?>> handleConnectException(
|
||||
ConnectException ex,
|
||||
HttpServletRequest request,
|
||||
HandlerMethod handlerMethod) {
|
||||
|
||||
String context = buildErrorContext(ex, request, handlerMethod);
|
||||
logger.error("ConnectException → {}", context, ex);
|
||||
|
||||
ResponseModel<?> resp = new ResponseModel<>(
|
||||
"Server unavailable - connection refused",
|
||||
"FAILED",
|
||||
HttpStatus.SERVICE_UNAVAILABLE.value(),
|
||||
null
|
||||
);
|
||||
|
||||
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body(resp);
|
||||
}
|
||||
|
||||
// ------------------------- GENERIC EXCEPTION ------------------------
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<ResponseModel<?>> handleAll(
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.billpaymentservice.bbps.serviceImpl;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.net.ConnectException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.HttpServerErrorException;
|
||||
import org.springframework.web.client.RestClient;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@@ -24,6 +26,15 @@ public class HttpService {
|
||||
private final RestClient restClient;
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
// Helper to produce server-down/timeout style responses
|
||||
private HashMap<String, String> buildServerDownResponse(String code, String message, Exception e) {
|
||||
HashMap<String, String> response = new HashMap<>();
|
||||
response.put("respCode", code);
|
||||
response.put("data", message);
|
||||
log.error("❌ {} - {}", code, message, e);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public HashMap<String, String> postRequest(String url, String payload, HttpHeaders customHeaders) {
|
||||
@@ -60,6 +71,15 @@ public class HttpService {
|
||||
response.put("respCode", "403");
|
||||
response.put("data", "FORBIDDEN - Check credentials in HttpService");
|
||||
|
||||
} catch (ResourceAccessException e) {
|
||||
// This often wraps timeouts or connection refused
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof ConnectException) {
|
||||
return buildServerDownResponse("503", "Server unavailable - connection refused", e);
|
||||
} else {
|
||||
return buildServerDownResponse("503", "Server unreachable: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("❌ HttpService Exception: {}", e.getMessage());
|
||||
response.put("respCode", "500");
|
||||
@@ -97,6 +117,13 @@ public class HttpService {
|
||||
log.error("❌ HTTP Error: {}", httpException.getMessage(), httpException);
|
||||
response.put("respCode", String.valueOf(httpException.getStatusCode().value()));
|
||||
response.put("data", httpException.getResponseBodyAsString());
|
||||
} catch (ResourceAccessException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof ConnectException) {
|
||||
return buildServerDownResponse("503", "Server unavailable - connection refused", e);
|
||||
} else {
|
||||
return buildServerDownResponse("503", "Server unreachable: " + e.getMessage(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("❌ Exception during GET call: {}", e.getMessage(), e);
|
||||
response.put("respCode", "500");
|
||||
@@ -133,6 +160,13 @@ public class HttpService {
|
||||
log.error("❌ HTTP Error: {}", httpException.getMessage(), httpException);
|
||||
response.put("respCode", String.valueOf(httpException.getStatusCode().value()));
|
||||
response.put("data", httpException.getResponseBodyAsString());
|
||||
} catch (ResourceAccessException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof ConnectException) {
|
||||
return buildServerDownResponse("503", "Server unavailable - connection refused", e);
|
||||
} else {
|
||||
return buildServerDownResponse("503", "Server unreachable: " + e.getMessage(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("❌ Exception during GET call: {}", e.getMessage(), e);
|
||||
response.put("respCode", "500");
|
||||
@@ -171,6 +205,13 @@ public class HttpService {
|
||||
response.put("respCode", String.valueOf(e.getStatusCode().value()));
|
||||
response.put("data", e.getResponseBodyAsString()); // still HTML or error string
|
||||
|
||||
} catch (ResourceAccessException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof ConnectException) {
|
||||
return buildServerDownResponse("503", "Server unavailable - connection refused", e);
|
||||
} else {
|
||||
return buildServerDownResponse("503", "Server unreachable: " + e.getMessage(), e);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("❌ FORM POST Exception: {}", e.getMessage(), e);
|
||||
|
||||
@@ -181,7 +222,4 @@ public class HttpService {
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -192,7 +192,6 @@ public class PaymentServiceImpl implements PaymentService {
|
||||
String apiName = BBPSConstant.API_CHECK_TRANSACTION_STATUS;
|
||||
String txnId = helper.generateTxnId(15);
|
||||
String requestId = transactionStatusRequest.getReqId();
|
||||
|
||||
// START log for internal transaction status check
|
||||
LOGGER.info("[{}] START (internal) | checkTxnId={} | reqId={} | bankTxnId={}", apiName, txnId, requestId,
|
||||
transactionStatusRequest.getTxnId());
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.billpaymentservice.bbps.util;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class BBPSConstant {
|
||||
public class BBPSConstant extends BBPS_RESPONSE_COD_CONSTANT {
|
||||
|
||||
// Jwt Token Expiration Time
|
||||
public static final long JWT_EXPIRATION_MS = 1000 * 60 * 60 * 24; // 24 hours
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.billpaymentservice.bbps.util;
|
||||
|
||||
public class BBPS_RESPONSE_COD_CONSTANT {
|
||||
|
||||
}
|
||||
@@ -720,11 +720,8 @@ public class BillerMapperHelper {
|
||||
parent.setUserId(responseWrapper.getUserId());
|
||||
// Map incoming DTO date strings into Auditable LocalDateTime fields
|
||||
LocalDateTime parentCreatedOn = parseToLocalDateTime(responseWrapper.getCreationDate());
|
||||
if (parentCreatedOn != null)
|
||||
parent.setCreatedOn(parentCreatedOn);
|
||||
|
||||
LocalDateTime parentUpdatedOn = parseToLocalDateTime(responseWrapper.getModifiedDate());
|
||||
if (parentUpdatedOn != null)
|
||||
parent.setUpdatedOn(parentUpdatedOn);
|
||||
parent.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
|
||||
parent.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
|
||||
parent.setReqId(reqId);
|
||||
@@ -967,12 +964,10 @@ public class BillerMapperHelper {
|
||||
// DATES
|
||||
// Map incoming DTO date strings into Auditable LocalDateTime fields
|
||||
LocalDateTime bmCreatedOn = parseToLocalDateTime(responseWrapper.getCreationDate());
|
||||
if (bmCreatedOn != null) {
|
||||
billMaster.setCreatedOn(bmCreatedOn);
|
||||
}
|
||||
|
||||
LocalDateTime bmUpdatedOn = parseToLocalDateTime(responseWrapper.getModifiedDate());
|
||||
if (bmUpdatedOn != null) {
|
||||
billMaster.setUpdatedOn(bmUpdatedOn);
|
||||
billMaster.setUpdatedDateTime(bmUpdatedOn);
|
||||
}
|
||||
billMaster.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
|
||||
billMaster.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
|
||||
@@ -1107,16 +1102,12 @@ public class BillerMapperHelper {
|
||||
record.setQrString(Optional.ofNullable(apiResponse.getResponseData().getQrString()).orElse("NO_QR"));
|
||||
// parse createdOn string into LocalDateTime and set on Auditable
|
||||
LocalDateTime createdOn = parseToLocalDateTime(apiResponse.getResponseData().getCreatedOn());
|
||||
if (createdOn == null)
|
||||
createdOn = LocalDateTime.now();
|
||||
record.setCreatedOn(createdOn);
|
||||
// default status pending
|
||||
|
||||
record.setTxnStatus("PENDING");
|
||||
} else {
|
||||
record.setAmount("0.00");
|
||||
record.setMid(request.getMid());
|
||||
record.setTxnStatus("PENDING");
|
||||
record.setCreatedOn(LocalDateTime.now());
|
||||
}
|
||||
|
||||
// store the original request body and raw response
|
||||
|
||||
@@ -184,8 +184,6 @@ public class Helper {
|
||||
user.setName(request.getName());
|
||||
user.setEmail(request.getEmail());
|
||||
user.setMid(request.getMid());
|
||||
// set audit createdOn timestamp
|
||||
user.setCreatedOn(LocalDateTime.now());
|
||||
// Generate a unique userId (UUID)
|
||||
String uniqueUserId = generateUniqueUserId();
|
||||
user.setUserId(uniqueUserId);
|
||||
|
||||
@@ -18,11 +18,14 @@ swagger.server.description=Local Development Server
|
||||
|
||||
|
||||
# DataSource
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/devdbuat
|
||||
spring.datasource.username=postgres
|
||||
spring.datasource.password=UAT@DB_2025
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/bbps_new_updated
|
||||
|
||||
#spring.datasource.password=himanshu@123
|
||||
#spring.datasource.url=jdbc:postgresql://localhost:5432/bbps_enhanced
|
||||
>>>>>>> Stashed changes
|
||||
spring.datasource.username=postgres
|
||||
#spring.datasource.password=UAT@DB_2025
|
||||
|
||||
spring.datasource.password=himanshu@123
|
||||
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ spring.profiles.active=local
|
||||
|
||||
|
||||
# DataSource
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/BBPS_Enhanced
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/devdbuat
|
||||
spring.datasource.username=postgres
|
||||
#spring.datasource.password=UAT@DB_2025
|
||||
|
||||
|
||||
Reference in New Issue
Block a user