make some changes

This commit is contained in:
Lincpay Tech
2025-12-09 15:12:26 +05:30
parent 2c4855d59a
commit fb3c5d2e96
9 changed files with 118 additions and 60 deletions
@@ -36,7 +36,7 @@ public class PaymentController {
@PostMapping(value = "/intiatePayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseModel> requestBillFetch(
@Validated @RequestBody BillPaymentRequest billPaymentRequest) {
@RequestBody BillPaymentRequest billPaymentRequest) {
ResponseModel response = paymentService.initiatePayment(billPaymentRequest);
return ResponseEntity.ok(response);
@@ -11,43 +11,33 @@ import lombok.Setter;
@Setter
public class BillPaymentRequest extends BaseClass {
@NotBlank(message = "ref id cannot be null or empty")
private String refId;
@NotBlank(message = "bill id cannot be null or empty")
private String billId;
// Change the field to Boolean (wrapper) type to allow @NotNull validation
@NotNull(message = "Amount options cannot be null.")
private boolean amountOptions; // Changed to Boolean (wrapper type)
@NotBlank(message = "payment mode cannot be null or empty")
private String paymentMode;
@NotBlank(message = "payment information cannot be null or empty")
private String paymentInformation;
@NotBlank(message = "biller id cannot be null or empty")
private String billerId;
@NotBlank(message = "biller name cannot be null or empty")
private String billerName;
@NotBlank(message = "biller category cannot be null or empty")
private String billerCategory;
private String macAdress;
private String customerMobNo;
@NotNull(message = "Transaction amount cannot be null.")
private Integer txnAmount; // Changed to @NotNull as it's an Integer (non-nullable)
private String txnAmount; // Changed to @NotNull as it's an Integer (non-nullable)
private String paymentRefId;
private String clientReqId;
@NotBlank(message = "payment channel cannot be null or empty")
private String paymentChannel;
private List<DeviceBlockTagRequest> deviceBlockTags;
@@ -29,7 +29,7 @@ public class BillPaymentForwardRequest {
private String billerCategory;
private String macAdress;
private String customerMobNo;
private Integer txnAmount;
private String txnAmount;
private String paymentRefId;
private String clientReqId;
private String paymentChannel;
@@ -28,7 +28,6 @@ public class AuditListener {
// Ensure isDeleted / deleted exists and is set to false on create
setAlways(entity, "isDeleted", Boolean.FALSE);
setAlways(entity, "deleted", Boolean.FALSE);
}
@PreUpdate
@@ -8,7 +8,6 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@@ -17,8 +16,8 @@ import lombok.ToString;
@Setter
@Entity
@ToString
@Table(name = "payment_channel")
public class PaymentChannel extends Auditable {
@Table(name = "bbps_payment_channel")
public class PaymentChannel {
@Id
@Column(name = "payment_channel_limit_id")
@@ -42,4 +41,4 @@ public class PaymentChannel extends Auditable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "biller_id")
private BillerDetails biller;
}
}
@@ -9,76 +9,145 @@ 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.method.HandlerMethod;
import org.springframework.web.servlet.NoHandlerFoundException;
import com.billpaymentservice.bbps.dto.ResponseModel;
import jakarta.servlet.http.HttpServletRequest;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ResponseModel<?>> handleValidation(MethodArgumentNotValidException ex) {
List<Map<String, String>> fieldErrors = ex.getBindingResult().getFieldErrors()
.stream()
.map(fe -> Map.of("field", fe.getField(), "message", fe.getDefaultMessage()))
.collect(Collectors.toList());
logger.warn("Validation failed: {}", fieldErrors);
ResponseModel<List<Map<String, String>>> resp = new ResponseModel<>(
"Validation failed for request",
"FAILED",
HttpStatus.BAD_REQUEST.value(),
null
/**
* 🔥 Common logger formatter for all exceptions
*/
private String buildErrorContext(Exception ex, HttpServletRequest request, HandlerMethod handlerMethod) {
// API endpoint
String endpoint = (request != null)
? request.getMethod() + " " + request.getRequestURI()
: "unknown";
// Controller method
String controllerMethod = (handlerMethod != null)
? handlerMethod.getBeanType().getSimpleName() + "." + handlerMethod.getMethod().getName()
: "NoControllerMethodMatched";
// Root cause (actual throw point)
StackTraceElement root = ex.getStackTrace()[0];
String rootCause = root.getClassName() + "." + root.getMethodName() + "():" + root.getLineNumber();
return String.format(
"API: %s | Controller: %s | Thrown From: %s | Exception: %s",
endpoint,
controllerMethod,
rootCause,
ex.getClass().getSimpleName()
);
// put validation errors into data or duplicate field in ResponseModel as required
resp.setData(fieldErrors);
}
// ------------------------- VALIDATION EXCEPTION ------------------------
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ResponseModel<?>> handleValidation(
MethodArgumentNotValidException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
String context = buildErrorContext(ex, request, handlerMethod);
logger.warn("ValidationException → {}", context);
List<Map<String, String>> fieldErrors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(fe -> Map.of("field", fe.getField(), "message", fe.getDefaultMessage()))
.collect(Collectors.toList());
ResponseModel<List<Map<String, String>>> resp = new ResponseModel<>(
"Validation failed",
"FAILED",
HttpStatus.BAD_REQUEST.value(),
fieldErrors
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
}
// ------------------------- NO HANDLER (404 NOT FOUND) ------------------------
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<ResponseModel<?>> handleNotFound(NoHandlerFoundException ex) {
logger.warn("Endpoint not found: {}", ex.getRequestURL());
logger.warn("404 Not Found → {}", ex.getRequestURL());
ResponseModel<?> resp = new ResponseModel<>(
"Endpoint not found: " + ex.getRequestURL(),
"FAILED",
HttpStatus.NOT_FOUND.value(),
null
"Endpoint not found: " + ex.getRequestURL(),
"FAILED",
HttpStatus.NOT_FOUND.value(),
null
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
}
// ------------------------- CUSTOM APP EXCEPTION ------------------------
@ExceptionHandler(AppException.class)
public ResponseEntity<ResponseModel<?>> handleAppException(AppException ex) {
logger.warn("AppException: status={}, message={}", ex.getStatus(), ex.getMessage());
ResponseModel<?> resp = new ResponseModel<>(ex.getMessage(), ex.getStatus(), ex.getStatusCode(), ex.getData());
public ResponseEntity<ResponseModel<?>> handleAppException(
AppException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
String context = buildErrorContext(ex, request, handlerMethod);
logger.warn("AppException → {}", context);
ResponseModel<?> resp = new ResponseModel<>(
ex.getMessage(),
ex.getStatus(),
ex.getStatusCode(),
ex.getData()
);
return ResponseEntity.status(HttpStatus.valueOf(ex.getStatusCode())).body(resp);
}
// ------------------------- CUSTOMException ------------------------
@ExceptionHandler(CustomException.class)
public ResponseEntity<ResponseModel<?>> handleCustomException(CustomException ex) {
logger.warn("CustomException: {}", ex.getMessage());
public ResponseEntity<ResponseModel<?>> handleCustomException(
CustomException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
String context = buildErrorContext(ex, request, handlerMethod);
logger.warn("CustomException → {}", context);
ResponseModel<?> resp = new ResponseModel<>(
ex.getMessage(),
"FAILED",
HttpStatus.BAD_REQUEST.value(),
null
ex.getMessage(),
"FAILED",
HttpStatus.BAD_REQUEST.value(),
null
);
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
}
// ------------------------- GENERIC EXCEPTION ------------------------
@ExceptionHandler(Exception.class)
public ResponseEntity<ResponseModel<?>> handleAll(Exception ex) {
logger.error("Unhandled exception", ex);
public ResponseEntity<ResponseModel<?>> handleAll(
Exception ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
String context = buildErrorContext(ex, request, handlerMethod);
logger.error("UnhandledException → {}", context, ex);
ResponseModel<?> response = new ResponseModel<>(
"Service temporarily unavailable. Please try again later.",
"FAILED",
HttpStatus.INTERNAL_SERVER_ERROR.value(),
null
"Internal Server Error",
"FAILED",
HttpStatus.INTERNAL_SERVER_ERROR.value(),
null
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
@@ -113,7 +113,6 @@ public class MasterDataServiceImpl implements MasterDataService {
@Override
public ResponseModel getMasterData(MasterRequest masterRequest) {
String apiName = BBPSConstant.API_GET_MASTER_DATA;
String requestId = masterRequest.getReqId();
String mid = masterRequest.getMid();
@@ -888,7 +887,7 @@ public class MasterDataServiceImpl implements MasterDataService {
LOGGER.info("[{}] END | reqId={} | status={}", apiName, requestId, generalResp.getStatus());
return responseModel;
} catch (JsonProcessingException e) {
LOGGER.error("Error parsing responseData JSON: {}", e.getMessage());
LOGGER.error("Error parsing responseData JSON: {} :: class :: method ", e.getMessage());
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
throw new CustomException("Invalid JSON received from API");
}
@@ -90,11 +90,14 @@ public class PaymentServiceImpl implements PaymentService {
@Override
public ResponseModel initiatePayment(BillPaymentRequest billPaymentRequest) {
String apiName = BBPSConstant.API_INITIATE_PAYMENT;
LOGGER.info("[{}] START | reqId={} | mid={}", apiName, billPaymentRequest.getReqId(),
billPaymentRequest.getMid());
String txnId = helper.generateTxnId(15);
String requestId = billPaymentRequest.getReqId();
String userId = billPaymentRequest.getClientReqId();
String url = paymentUrl + BBPSConstant.PAYMENT_URL;
billPaymentRequest.setClientReqId(txnId);
LOGGER.info("Initiating payment for reqId={} and txnId={} and userId={}", requestId, txnId, userId);
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
@@ -92,7 +92,6 @@ public class Helper {
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));