make some changes
This commit is contained in:
@@ -36,7 +36,7 @@ public class PaymentController {
|
|||||||
|
|
||||||
@PostMapping(value = "/intiatePayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
@PostMapping(value = "/intiatePayment", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResponseEntity<ResponseModel> requestBillFetch(
|
public ResponseEntity<ResponseModel> requestBillFetch(
|
||||||
@Validated @RequestBody BillPaymentRequest billPaymentRequest) {
|
@RequestBody BillPaymentRequest billPaymentRequest) {
|
||||||
|
|
||||||
ResponseModel response = paymentService.initiatePayment(billPaymentRequest);
|
ResponseModel response = paymentService.initiatePayment(billPaymentRequest);
|
||||||
return ResponseEntity.ok(response);
|
return ResponseEntity.ok(response);
|
||||||
|
|||||||
@@ -11,43 +11,33 @@ import lombok.Setter;
|
|||||||
@Setter
|
@Setter
|
||||||
public class BillPaymentRequest extends BaseClass {
|
public class BillPaymentRequest extends BaseClass {
|
||||||
|
|
||||||
@NotBlank(message = "ref id cannot be null or empty")
|
|
||||||
private String refId;
|
private String refId;
|
||||||
|
|
||||||
@NotBlank(message = "bill id cannot be null or empty")
|
|
||||||
private String billId;
|
private String billId;
|
||||||
|
|
||||||
// Change the field to Boolean (wrapper) type to allow @NotNull validation
|
// 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)
|
private boolean amountOptions; // Changed to Boolean (wrapper type)
|
||||||
|
|
||||||
@NotBlank(message = "payment mode cannot be null or empty")
|
|
||||||
private String paymentMode;
|
private String paymentMode;
|
||||||
|
|
||||||
@NotBlank(message = "payment information cannot be null or empty")
|
|
||||||
private String paymentInformation;
|
private String paymentInformation;
|
||||||
|
|
||||||
@NotBlank(message = "biller id cannot be null or empty")
|
|
||||||
private String billerId;
|
private String billerId;
|
||||||
|
|
||||||
@NotBlank(message = "biller name cannot be null or empty")
|
|
||||||
private String billerName;
|
private String billerName;
|
||||||
|
|
||||||
@NotBlank(message = "biller category cannot be null or empty")
|
|
||||||
private String billerCategory;
|
private String billerCategory;
|
||||||
|
|
||||||
private String macAdress;
|
private String macAdress;
|
||||||
|
|
||||||
private String customerMobNo;
|
private String customerMobNo;
|
||||||
|
|
||||||
@NotNull(message = "Transaction amount cannot be null.")
|
private String txnAmount; // Changed to @NotNull as it's an Integer (non-nullable)
|
||||||
private Integer txnAmount; // Changed to @NotNull as it's an Integer (non-nullable)
|
|
||||||
|
|
||||||
private String paymentRefId;
|
private String paymentRefId;
|
||||||
|
|
||||||
private String clientReqId;
|
private String clientReqId;
|
||||||
|
|
||||||
@NotBlank(message = "payment channel cannot be null or empty")
|
|
||||||
private String paymentChannel;
|
private String paymentChannel;
|
||||||
|
|
||||||
private List<DeviceBlockTagRequest> deviceBlockTags;
|
private List<DeviceBlockTagRequest> deviceBlockTags;
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ public class BillPaymentForwardRequest {
|
|||||||
private String billerCategory;
|
private String billerCategory;
|
||||||
private String macAdress;
|
private String macAdress;
|
||||||
private String customerMobNo;
|
private String customerMobNo;
|
||||||
private Integer txnAmount;
|
private String txnAmount;
|
||||||
private String paymentRefId;
|
private String paymentRefId;
|
||||||
private String clientReqId;
|
private String clientReqId;
|
||||||
private String paymentChannel;
|
private String paymentChannel;
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ public class AuditListener {
|
|||||||
|
|
||||||
// Ensure isDeleted / deleted exists and is set to false on create
|
// Ensure isDeleted / deleted exists and is set to false on create
|
||||||
setAlways(entity, "isDeleted", Boolean.FALSE);
|
setAlways(entity, "isDeleted", Boolean.FALSE);
|
||||||
setAlways(entity, "deleted", Boolean.FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreUpdate
|
@PreUpdate
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import jakarta.persistence.JoinColumn;
|
|||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import jakarta.validation.constraints.Min;
|
import jakarta.validation.constraints.Min;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -17,8 +16,8 @@ import lombok.ToString;
|
|||||||
@Setter
|
@Setter
|
||||||
@Entity
|
@Entity
|
||||||
@ToString
|
@ToString
|
||||||
@Table(name = "payment_channel")
|
@Table(name = "bbps_payment_channel")
|
||||||
public class PaymentChannel extends Auditable {
|
public class PaymentChannel {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "payment_channel_limit_id")
|
@Column(name = "payment_channel_limit_id")
|
||||||
@@ -42,4 +41,4 @@ public class PaymentChannel extends Auditable {
|
|||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "biller_id")
|
@JoinColumn(name = "biller_id")
|
||||||
private BillerDetails biller;
|
private BillerDetails biller;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,76 +9,145 @@ import org.springframework.http.*;
|
|||||||
import org.springframework.validation.FieldError;
|
import org.springframework.validation.FieldError;
|
||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||||
|
|
||||||
import com.billpaymentservice.bbps.dto.ResponseModel;
|
import com.billpaymentservice.bbps.dto.ResponseModel;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
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<>(
|
* 🔥 Common logger formatter for all exceptions
|
||||||
"Validation failed for request",
|
*/
|
||||||
"FAILED",
|
private String buildErrorContext(Exception ex, HttpServletRequest request, HandlerMethod handlerMethod) {
|
||||||
HttpStatus.BAD_REQUEST.value(),
|
|
||||||
null
|
// 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);
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------- NO HANDLER (404 NOT FOUND) ------------------------
|
||||||
@ExceptionHandler(NoHandlerFoundException.class)
|
@ExceptionHandler(NoHandlerFoundException.class)
|
||||||
public ResponseEntity<ResponseModel<?>> handleNotFound(NoHandlerFoundException ex) {
|
public ResponseEntity<ResponseModel<?>> handleNotFound(NoHandlerFoundException ex) {
|
||||||
logger.warn("Endpoint not found: {}", ex.getRequestURL());
|
|
||||||
|
logger.warn("404 Not Found → {}", ex.getRequestURL());
|
||||||
|
|
||||||
ResponseModel<?> resp = new ResponseModel<>(
|
ResponseModel<?> resp = new ResponseModel<>(
|
||||||
"Endpoint not found: " + ex.getRequestURL(),
|
"Endpoint not found: " + ex.getRequestURL(),
|
||||||
"FAILED",
|
"FAILED",
|
||||||
HttpStatus.NOT_FOUND.value(),
|
HttpStatus.NOT_FOUND.value(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------- CUSTOM APP EXCEPTION ------------------------
|
||||||
@ExceptionHandler(AppException.class)
|
@ExceptionHandler(AppException.class)
|
||||||
public ResponseEntity<ResponseModel<?>> handleAppException(AppException ex) {
|
public ResponseEntity<ResponseModel<?>> handleAppException(
|
||||||
logger.warn("AppException: status={}, message={}", ex.getStatus(), ex.getMessage());
|
AppException ex,
|
||||||
ResponseModel<?> resp = new ResponseModel<>(ex.getMessage(), ex.getStatus(), ex.getStatusCode(), ex.getData());
|
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);
|
return ResponseEntity.status(HttpStatus.valueOf(ex.getStatusCode())).body(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------- CUSTOMException ------------------------
|
||||||
@ExceptionHandler(CustomException.class)
|
@ExceptionHandler(CustomException.class)
|
||||||
public ResponseEntity<ResponseModel<?>> handleCustomException(CustomException ex) {
|
public ResponseEntity<ResponseModel<?>> handleCustomException(
|
||||||
logger.warn("CustomException: {}", ex.getMessage());
|
CustomException ex,
|
||||||
|
HttpServletRequest request,
|
||||||
|
HandlerMethod handlerMethod) {
|
||||||
|
|
||||||
|
String context = buildErrorContext(ex, request, handlerMethod);
|
||||||
|
logger.warn("CustomException → {}", context);
|
||||||
|
|
||||||
ResponseModel<?> resp = new ResponseModel<>(
|
ResponseModel<?> resp = new ResponseModel<>(
|
||||||
ex.getMessage(),
|
ex.getMessage(),
|
||||||
"FAILED",
|
"FAILED",
|
||||||
HttpStatus.BAD_REQUEST.value(),
|
HttpStatus.BAD_REQUEST.value(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
|
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------- GENERIC EXCEPTION ------------------------
|
||||||
@ExceptionHandler(Exception.class)
|
@ExceptionHandler(Exception.class)
|
||||||
public ResponseEntity<ResponseModel<?>> handleAll(Exception ex) {
|
public ResponseEntity<ResponseModel<?>> handleAll(
|
||||||
logger.error("Unhandled exception", ex);
|
Exception ex,
|
||||||
|
HttpServletRequest request,
|
||||||
|
HandlerMethod handlerMethod) {
|
||||||
|
|
||||||
|
String context = buildErrorContext(ex, request, handlerMethod);
|
||||||
|
logger.error("UnhandledException → {}", context, ex);
|
||||||
|
|
||||||
ResponseModel<?> response = new ResponseModel<>(
|
ResponseModel<?> response = new ResponseModel<>(
|
||||||
"Service temporarily unavailable. Please try again later.",
|
"Internal Server Error",
|
||||||
"FAILED",
|
"FAILED",
|
||||||
HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
HttpStatus.INTERNAL_SERVER_ERROR.value(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ public class MasterDataServiceImpl implements MasterDataService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseModel getMasterData(MasterRequest masterRequest) {
|
public ResponseModel getMasterData(MasterRequest masterRequest) {
|
||||||
|
|
||||||
String apiName = BBPSConstant.API_GET_MASTER_DATA;
|
String apiName = BBPSConstant.API_GET_MASTER_DATA;
|
||||||
String requestId = masterRequest.getReqId();
|
String requestId = masterRequest.getReqId();
|
||||||
String mid = masterRequest.getMid();
|
String mid = masterRequest.getMid();
|
||||||
@@ -888,7 +887,7 @@ public class MasterDataServiceImpl implements MasterDataService {
|
|||||||
LOGGER.info("[{}] END | reqId={} | status={}", apiName, requestId, generalResp.getStatus());
|
LOGGER.info("[{}] END | reqId={} | status={}", apiName, requestId, generalResp.getStatus());
|
||||||
return responseModel;
|
return responseModel;
|
||||||
} catch (JsonProcessingException e) {
|
} 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);
|
helper.updateInboundLogFailure(inboundLog, e.getMessage(), BBPSConstant.JSON_ERROR);
|
||||||
throw new CustomException("Invalid JSON received from API");
|
throw new CustomException("Invalid JSON received from API");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,11 +90,14 @@ public class PaymentServiceImpl implements PaymentService {
|
|||||||
@Override
|
@Override
|
||||||
public ResponseModel initiatePayment(BillPaymentRequest billPaymentRequest) {
|
public ResponseModel initiatePayment(BillPaymentRequest billPaymentRequest) {
|
||||||
String apiName = BBPSConstant.API_INITIATE_PAYMENT;
|
String apiName = BBPSConstant.API_INITIATE_PAYMENT;
|
||||||
|
LOGGER.info("[{}] START | reqId={} | mid={}", apiName, billPaymentRequest.getReqId(),
|
||||||
|
billPaymentRequest.getMid());
|
||||||
String txnId = helper.generateTxnId(15);
|
String txnId = helper.generateTxnId(15);
|
||||||
String requestId = billPaymentRequest.getReqId();
|
String requestId = billPaymentRequest.getReqId();
|
||||||
String userId = billPaymentRequest.getClientReqId();
|
String userId = billPaymentRequest.getClientReqId();
|
||||||
String url = paymentUrl + BBPSConstant.PAYMENT_URL;
|
String url = paymentUrl + BBPSConstant.PAYMENT_URL;
|
||||||
billPaymentRequest.setClientReqId(txnId);
|
billPaymentRequest.setClientReqId(txnId);
|
||||||
|
|
||||||
LOGGER.info("Initiating payment for reqId={} and txnId={} and userId={}", requestId, txnId, userId);
|
LOGGER.info("Initiating payment for reqId={} and txnId={} and userId={}", requestId, txnId, userId);
|
||||||
|
|
||||||
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
|
BharatConnectMaster headersData = beneficiaryDetailsRepository.findByOrgId(BBPSConstant.ORG_ID);
|
||||||
|
|||||||
@@ -92,7 +92,6 @@ public class Helper {
|
|||||||
|
|
||||||
public static String generateTxnId(int n) {
|
public static String generateTxnId(int n) {
|
||||||
StringBuilder sb = new StringBuilder(n);
|
StringBuilder sb = new StringBuilder(n);
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int index = secureRandom.nextInt(CHARACTERS.length());
|
int index = secureRandom.nextInt(CHARACTERS.length());
|
||||||
sb.append(CHARACTERS.charAt(index));
|
sb.append(CHARACTERS.charAt(index));
|
||||||
|
|||||||
Reference in New Issue
Block a user