diff --git a/src/main/java/com/billpaymentservice/bbps/config/SecurityConfig.java b/src/main/java/com/billpaymentservice/bbps/config/SecurityConfig.java index 891013d..5270cb6 100644 --- a/src/main/java/com/billpaymentservice/bbps/config/SecurityConfig.java +++ b/src/main/java/com/billpaymentservice/bbps/config/SecurityConfig.java @@ -31,7 +31,7 @@ public class SecurityConfig { http.csrf(csrf -> csrf.disable()).cors(cors -> cors.configurationSource(corsConfigurationSource())) .authorizeHttpRequests(auth -> auth - .requestMatchers("/masterData/**", + .requestMatchers("/auth/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", diff --git a/src/main/java/com/billpaymentservice/bbps/controller/AuthController.java b/src/main/java/com/billpaymentservice/bbps/controller/AuthController.java new file mode 100644 index 0000000..fcbe602 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/controller/AuthController.java @@ -0,0 +1,64 @@ +package com.billpaymentservice.bbps.controller; + +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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.auth.AuthResponse; +import com.billpaymentservice.bbps.dto.response.AuthResponses; +import com.billpaymentservice.bbps.dto.auth.LoginRequest; +import com.billpaymentservice.bbps.dto.auth.OtpSendResponse; +import com.billpaymentservice.bbps.dto.auth.RegisterRequest; +import com.billpaymentservice.bbps.dto.auth.VerifyOtpRequest; +import com.billpaymentservice.bbps.service.AuthService; + +import lombok.extern.slf4j.Slf4j; + +@RestController +@RequestMapping("/auth") +@CrossOrigin(origins = "*") +@Slf4j +public class AuthController { + + private final AuthService authService; + + public AuthController(AuthService authService) { + this.authService = authService; + } + + @PostMapping(value = "/sendOtp", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity sendOtp(@Validated @RequestBody LoginRequest request) { + log.info("Received sendOtp request for mobile: {}", request.getMobile()); + OtpSendResponse resp = authService.sendOtp(request); + return ResponseEntity.ok(resp); + } + + @PostMapping(value = "/verifyOtp", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity verifyOtp(@Validated @RequestBody VerifyOtpRequest request) { + AuthResponses resp = authService.verifyOtp(request); + return ResponseEntity.ok(resp); + } + + @PostMapping(value = "/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity register(@Validated @RequestBody RegisterRequest request) { + AuthResponse resp = authService.registerUser(request); + return ResponseEntity.ok(resp); + } + + @PostMapping("/loginWithoutDecryption") + public ResponseEntity login(@RequestBody LoginRequest loginRequest) { + try { + AuthResponses authResponse = authService.authenticateUser(loginRequest); + return ResponseEntity.ok(authResponse); + } catch (Exception e) { + return ResponseEntity.status(500).body(AuthResponses.builder().status("Unauthorized") + .message("An unexpected error occurred").statusCode(500).build()); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java index 0d011eb..7520b33 100644 --- a/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java +++ b/src/main/java/com/billpaymentservice/bbps/controller/MasterDataController.java @@ -20,7 +20,7 @@ import com.billpaymentservice.bbps.dto.request.LoginRequest; import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.dto.request.PlanRequest; -import com.billpaymentservice.bbps.dto.response.AuthResponse; +import com.billpaymentservice.bbps.dto.response.AuthResponses; import com.billpaymentservice.bbps.service.MasterDataService; import jakarta.validation.Valid; @@ -148,14 +148,4 @@ public class MasterDataController { return ResponseEntity.ok(masterDataService.fetchPlanByCategories(requestModel)); } - @PostMapping("/loginWithoutDecryption") - public ResponseEntity login(@RequestBody LoginRequest loginRequest) { - try { - AuthResponse authResponse = masterDataService.authenticateUser(loginRequest); - return ResponseEntity.ok(authResponse); - } catch (Exception e) { - return ResponseEntity.status(500).body(AuthResponse.builder().status("Unauthorized") - .message("An unexpected error occurred").statusCode(500).build()); - } - } } diff --git a/src/main/java/com/billpaymentservice/bbps/controller/PaymentController.java b/src/main/java/com/billpaymentservice/bbps/controller/PaymentController.java index decc81c..fdfaf84 100644 --- a/src/main/java/com/billpaymentservice/bbps/controller/PaymentController.java +++ b/src/main/java/com/billpaymentservice/bbps/controller/PaymentController.java @@ -54,11 +54,13 @@ public class PaymentController { return ResponseEntity.ok(response); } + @PostMapping(value="/callback/paymentIntiate", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity handleBillValidateCallback(@RequestBody TransactionStatusResponse transactionStatusResponse) { ResponseModel genralResp=paymentService.handlePaymentIntiateCallback(transactionStatusResponse); // Return a response indicating successful receipt return ResponseEntity.ok(genralResp); } + } diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/AuthResponse.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/AuthResponse.java new file mode 100644 index 0000000..a88d366 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/AuthResponse.java @@ -0,0 +1,51 @@ +package com.billpaymentservice.bbps.dto.auth; + +import com.billpaymentservice.bbps.dto.auth.UserDto; + +public class AuthResponse { + private boolean success; + private String message; + private boolean userExists; + private UserDto user; + + public AuthResponse() {} + + public AuthResponse(boolean success, String message, boolean userExists, UserDto user) { + this.success = success; + this.message = message; + this.userExists = userExists; + this.user = user; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isUserExists() { + return userExists; + } + + public void setUserExists(boolean userExists) { + this.userExists = userExists; + } + + public UserDto getUser() { + return user; + } + + public void setUser(UserDto user) { + this.user = user; + } +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/LoginRequest.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/LoginRequest.java new file mode 100644 index 0000000..8d8a65a --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/LoginRequest.java @@ -0,0 +1,19 @@ +package com.billpaymentservice.bbps.dto.auth; + +public class LoginRequest { + private String mobile; + + public LoginRequest() {} + + public LoginRequest(String mobile) { + this.mobile = mobile; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/OtpSendResponse.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/OtpSendResponse.java new file mode 100644 index 0000000..67dc6ff --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/OtpSendResponse.java @@ -0,0 +1,29 @@ +package com.billpaymentservice.bbps.dto.auth; + +public class OtpSendResponse { + private boolean success; + private String message; + + public OtpSendResponse() {} + + public OtpSendResponse(boolean success, String message) { + this.success = success; + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/RegisterRequest.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/RegisterRequest.java new file mode 100644 index 0000000..ee156a1 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/RegisterRequest.java @@ -0,0 +1,14 @@ +package com.billpaymentservice.bbps.dto.auth; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class RegisterRequest { + private String mobile; + private String name; + private String email; + private int age; + +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/UserDto.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/UserDto.java new file mode 100644 index 0000000..1c35570 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/UserDto.java @@ -0,0 +1,20 @@ +package com.billpaymentservice.bbps.dto.auth; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class UserDto { + private Long id; + private String mobile; + private String name; + private String email; + private int age; + + +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/dto/auth/VerifyOtpRequest.java b/src/main/java/com/billpaymentservice/bbps/dto/auth/VerifyOtpRequest.java new file mode 100644 index 0000000..a52c072 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/auth/VerifyOtpRequest.java @@ -0,0 +1,30 @@ +package com.billpaymentservice.bbps.dto.auth; + +public class VerifyOtpRequest { + private String mobile; + private String otp; + + public VerifyOtpRequest() { + } + + public VerifyOtpRequest(String mobile, String otp) { + this.mobile = mobile; + this.otp = otp; + } + + public String getMobile() { + return mobile; + } + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getOtp() { + return otp; + } + + public void setOtp(String otp) { + this.otp = otp; + } +} diff --git a/src/main/java/com/billpaymentservice/bbps/dto/request/TransactionHistory.java b/src/main/java/com/billpaymentservice/bbps/dto/request/TransactionHistory.java new file mode 100644 index 0000000..a879f88 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/dto/request/TransactionHistory.java @@ -0,0 +1,5 @@ +package com.billpaymentservice.bbps.dto.request; + +public class TransactionHistory { + +} diff --git a/src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponse.java b/src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponses.java similarity index 74% rename from src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponse.java rename to src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponses.java index f508f46..bf5c6b5 100644 --- a/src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponse.java +++ b/src/main/java/com/billpaymentservice/bbps/dto/response/AuthResponses.java @@ -9,7 +9,7 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor @Builder -public class AuthResponse { +public class AuthResponses { private String token; @@ -24,7 +24,7 @@ public class AuthResponse { private String anotherData; // Constructor - public AuthResponse(String status, String message, int statusCode, String token) { + public AuthResponses(String status, String message, int statusCode, String token) { this.status = status; this.message = message; @@ -32,7 +32,7 @@ public class AuthResponse { this.token = token; } - public AuthResponse(String token, String status, String message, int statusCode, Object data) { + public AuthResponses(String token, String status, String message, int statusCode, Object data) { this.token = token; this.status = status; this.message = message; diff --git a/src/main/java/com/billpaymentservice/bbps/entites/UserEntity.java b/src/main/java/com/billpaymentservice/bbps/entites/UserEntity.java new file mode 100644 index 0000000..ab454eb --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/entites/UserEntity.java @@ -0,0 +1,42 @@ +package com.billpaymentservice.bbps.entites; + +import com.billpaymentservice.bbps.audit.Auditable; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Table(name = "users") +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class UserEntity extends Auditable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "mobile", nullable = false, unique = true, length = 20) + private String mobile; + + @Column(name = "name", length = 150) + private String name; + + @Column(name = "email", length = 150) + private String email; + + @Column(name = "age") + private int age; + + + +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/repository/UserRepository.java b/src/main/java/com/billpaymentservice/bbps/repository/UserRepository.java new file mode 100644 index 0000000..54c7362 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/repository/UserRepository.java @@ -0,0 +1,13 @@ +package com.billpaymentservice.bbps.repository; + +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.billpaymentservice.bbps.entites.UserEntity; + +@Repository +public interface UserRepository extends JpaRepository { + Optional findByMobile(String mobile); +} diff --git a/src/main/java/com/billpaymentservice/bbps/service/AuthService.java b/src/main/java/com/billpaymentservice/bbps/service/AuthService.java new file mode 100644 index 0000000..5698c80 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/service/AuthService.java @@ -0,0 +1,21 @@ +package com.billpaymentservice.bbps.service; + +import com.billpaymentservice.bbps.dto.auth.AuthResponse; +import com.billpaymentservice.bbps.dto.auth.LoginRequest; +import com.billpaymentservice.bbps.dto.auth.OtpSendResponse; +import com.billpaymentservice.bbps.dto.auth.RegisterRequest; +import com.billpaymentservice.bbps.dto.auth.VerifyOtpRequest; +import com.billpaymentservice.bbps.dto.response.AuthResponses; +import com.billpaymentservice.bbps.entites.UserEntity; + +public interface AuthService { + OtpSendResponse sendOtp(LoginRequest request); + + AuthResponses verifyOtp(VerifyOtpRequest request); + + AuthResponse registerUser(RegisterRequest request); + + UserEntity findByMobile(String mobile); + + AuthResponses authenticateUser(LoginRequest loginRequest); +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java b/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java index 74660e7..f8f4cbe 100644 --- a/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java +++ b/src/main/java/com/billpaymentservice/bbps/service/MasterDataService.java @@ -9,7 +9,7 @@ import com.billpaymentservice.bbps.dto.request.LoginRequest; import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.dto.request.PlanRequest; -import com.billpaymentservice.bbps.dto.response.AuthResponse; +import com.billpaymentservice.bbps.dto.response.AuthResponses; public interface MasterDataService { @@ -37,6 +37,4 @@ public interface MasterDataService { public ResponseModel getTicketDispositions(DispositionRequest dispositionDetailRequest); - public AuthResponse authenticateUser(LoginRequest loginRequest); - } diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java index 271bf91..a22994f 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AgentServiceImpl.java @@ -270,7 +270,7 @@ public class AgentServiceImpl implements AgentService { String apiName = BBPSConstant.API_INITIATE_BILL_VALIDATE; String reqId = fetchBillValidateRequest.getReqId(); String mid = fetchBillValidateRequest.getMid(); - LOGGER.info("[{}] START | reqId={} | mid={} | billerId={}", apiName, fetchBillValidateRequest, mid, + LOGGER.info("[{}] START | reqId={} | mid={} | billerId={}", apiName, fetchBillValidateRequest.getReqId(), mid, fetchBillValidateRequest.getBillerId()); String txnId = helper.generateTxnId(15); String fullUrl = agentDtaUrl + BBPSConstant.BILLER_VALIDATE_URL; @@ -395,8 +395,6 @@ public class AgentServiceImpl implements AgentService { helper.updateInboundLogSuccess(inboundLog, responseData, generalResp.getStatus()); System.out.println("responseWrapper:" + responseWrapper); mapperHelper.saveBillValidation(responseWrapper, billRequest); - LOGGER.info("Bill data saved successfully for billId: {}", billId); - return new ResponseModel(generalResp.getMessage(), generalResp.getStatus(), Integer.parseInt(generalResp.getStatusCode()), responseWrapper); } catch (JsonProcessingException e) { diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/AuthServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AuthServiceImpl.java new file mode 100644 index 0000000..2d962c9 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/AuthServiceImpl.java @@ -0,0 +1,168 @@ +package com.billpaymentservice.bbps.serviceImpl; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.billpaymentservice.bbps.config.JwtUtil; +import com.billpaymentservice.bbps.dto.UserDetailsDTO; +import com.billpaymentservice.bbps.dto.auth.AuthResponse; +import com.billpaymentservice.bbps.dto.auth.LoginRequest; +import com.billpaymentservice.bbps.dto.auth.OtpSendResponse; +import com.billpaymentservice.bbps.dto.auth.RegisterRequest; +import com.billpaymentservice.bbps.dto.auth.UserDto; +import com.billpaymentservice.bbps.dto.auth.VerifyOtpRequest; +import com.billpaymentservice.bbps.dto.response.AuthResponses; +import com.billpaymentservice.bbps.entites.UserEntity; +import com.billpaymentservice.bbps.entites.UsersDetails; +import com.billpaymentservice.bbps.repository.UserRepository; +import com.billpaymentservice.bbps.repository.UsersDetailsRepository; +import com.billpaymentservice.bbps.service.AuthService; +import com.billpaymentservice.bbps.util.Helper; +import com.billpaymentservice.bbps.util.OtpClient; + +import java.util.Optional; + +@Service +public class AuthServiceImpl implements AuthService { + + private static final Logger LOGGER = LoggerFactory.getLogger(AuthServiceImpl.class); + + private final UserRepository userRepository; + private final OtpClient otpClient; + private final Helper helper; + private final UsersDetailsRepository userRepo; + + private final JwtUtil jwtUtil; + + @Autowired + public AuthServiceImpl(UserRepository userRepository, OtpClient otpClient, Helper helper, + UsersDetailsRepository userRepo, JwtUtil jwtUtil) { + this.userRepository = userRepository; + this.otpClient = otpClient; + this.helper = helper; + this.userRepo=userRepo; + this.jwtUtil=jwtUtil; + } + + @Override + public OtpSendResponse sendOtp(LoginRequest request) { + Optional existing = userRepository.findByMobile(request.getMobile()); + + if (existing.isPresent()) { + UserEntity u = existing.get(); + UserDto dto = new UserDto(u.getId(), u.getMobile(), u.getName(), u.getEmail(), u.getAge()); + return null; + } + // delegate to external OTP provider + return otpClient.sendOtp(request.getMobile()); + } + + @Override + public AuthResponses verifyOtp(VerifyOtpRequest request) { + boolean ok = otpClient.verifyOtp(request.getMobile(), request.getOtp()); + LOGGER.info("OTP STATUS"+ ok); + if (ok) { + return new AuthResponses("","Invalid OTP","Failed", 401, null); + } + String mobileNo = request.getMobile(); + try { + + + Optional byAdminEmail = userRepo.findByUserMobNo(mobileNo); + + if (byAdminEmail.isPresent()) { + UsersDetails user = byAdminEmail.get(); + String token = jwtUtil.generateToken(user.getUserMobNo()); + + LOGGER.info("Generated JWT token for mobileNo: " + mobileNo); + + Object userDetailsDTO = null; + + if (user != null) { + userDetailsDTO = UserDetailsDTO.builder().id(user.getId()).userEmailId(user.getUserEmailId()) + .userMobNo(user.getUserMobNo()).userName(user.getUserName()).userAge(user.getUserAge()) + .build(); + } + return new AuthResponses(token, "Success", "Login Done", 200, userDetailsDTO); + } else { + return new AuthResponses("", "User Not Found", "Authentication failed", 401, null); + } + + } catch (Exception ex) { + System.out.println("Error occurred during login for mobile no: " + mobileNo + + " Exception: " + ex.getMessage()); + + return AuthResponses.builder().status("Unauthorized").message("Authentication failed: " + ex.getMessage()) + .statusCode(401).build(); + } + +// Optional userOpt = userRepository.findByMobile(request.getMobile()); +// if (userOpt.isPresent()) { +// UserEntity user = userOpt.get(); +// UserDto dto = new UserDto(user.getId(), user.getMobile(), user.getName(), user.getEmail(), user.getAge()); +// return new AuthResponse(true, "Login successful", true, dto); +// } else { +// return new AuthResponse(true, "OTP verified; user not found - proceed to registration", false, null); +// } + } + + @Override + @Transactional + public AuthResponse registerUser(RegisterRequest request) { + Optional existing = userRepository.findByMobile(request.getMobile()); + if (existing.isPresent()) { + UserEntity u = existing.get(); + UserDto dto = new UserDto(u.getId(), u.getMobile(), u.getName(), u.getEmail(), u.getAge()); + return new AuthResponse(false, "User already exists", true, dto); + } + + UserEntity user = helper.createNewUser(request); + user = userRepository.save(user); + UserDto dto = new UserDto(user.getId(), user.getMobile(), user.getName(), user.getEmail(), user.getAge()); + return new AuthResponse(true, "Registration successful", true, dto); + } + + @Override + public UserEntity findByMobile(String mobile) { + return userRepository.findByMobile(mobile).orElse(null); + } + + @Override + public AuthResponses authenticateUser(LoginRequest loginRequest) { + LOGGER.info("Processing login for Request: " + loginRequest); + + try { + String mobileNo = loginRequest.getMobile(); + + Optional byAdminEmail = userRepo.findByUserMobNo(mobileNo); + + if (byAdminEmail.isPresent()) { + UsersDetails user = byAdminEmail.get(); + String token = jwtUtil.generateToken(user.getUserMobNo()); + + LOGGER.info("Generated JWT token for mobileNo: " + mobileNo); + + Object userDetailsDTO = null; + + if (user != null) { + userDetailsDTO = UserDetailsDTO.builder().id(user.getId()).userEmailId(user.getUserEmailId()) + .userMobNo(user.getUserMobNo()).userName(user.getUserName()).userAge(user.getUserAge()) + .build(); + } + return new AuthResponses(token, "Success", "Login Done", 200, userDetailsDTO); + } else { + return new AuthResponses("", "User Not Found", "Authentication failed", 401, null); + } + + } catch (Exception ex) { + System.out.println("Error occurred during login for mobile no: " + loginRequest.getMobile() + + " Exception: " + ex.getMessage()); + + return AuthResponses.builder().status("Unauthorized").message("Authentication failed: " + ex.getMessage()) + .statusCode(401).build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java index 0804cb6..f8397a1 100644 --- a/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java +++ b/src/main/java/com/billpaymentservice/bbps/serviceImpl/MasterDataServiceImpl.java @@ -30,7 +30,7 @@ import com.billpaymentservice.bbps.dto.request.MasterCategoryRequest; import com.billpaymentservice.bbps.dto.request.MasterRequest; import com.billpaymentservice.bbps.dto.request.PlanRequest; import com.billpaymentservice.bbps.dto.response.AmountOptionsResponse; -import com.billpaymentservice.bbps.dto.response.AuthResponse; +import com.billpaymentservice.bbps.dto.response.AuthResponses; import com.billpaymentservice.bbps.dto.response.BillerDataResponse; import com.billpaymentservice.bbps.dto.response.BillerResponse; import com.billpaymentservice.bbps.dto.response.ChannelsListResponse; @@ -89,11 +89,6 @@ public class MasterDataServiceImpl implements MasterDataService { private final InboundTraceLogRepository inboundTraceLogRepository; private final OutboundTraceLogRepository outboundTraceLogRepository; private final CustomParamRepository customParamReposiotory; - @Autowired - private UsersDetailsRepository userRepo; - - @Autowired - private JwtUtil jwtUtil; public MasterDataServiceImpl(MerchantRepository merchantRegisterRepo, HttpService httpService, HttpClientApi httpClientApi, Helper helper, BillerDataRepository billerDataRespository, @@ -882,40 +877,4 @@ public class MasterDataServiceImpl implements MasterDataService { } } - @Override - public AuthResponse authenticateUser(LoginRequest loginRequest) { - LOGGER.info("Processing login for Request: " + loginRequest); - - try { - String mobileNo = loginRequest.getMobileNumber(); - - Optional byAdminEmail = userRepo.findByUserMobNo(mobileNo); - - if (byAdminEmail.isPresent()) { - UsersDetails user = byAdminEmail.get(); - String token = jwtUtil.generateToken(user.getUserMobNo()); - - LOGGER.info("Generated JWT token for mobileNo: " + mobileNo); - - Object userDetailsDTO = null; - - if (user != null) { - userDetailsDTO = UserDetailsDTO.builder().id(user.getId()).userEmailId(user.getUserEmailId()) - .userMobNo(user.getUserMobNo()).userName(user.getUserName()).userAge(user.getUserAge()) - .build(); - } - return new AuthResponse(token, "Success", "Login Done", 200, userDetailsDTO); - } else { - return new AuthResponse("", "User Not Found", "Authentication failed", 401, null); - } - - } catch (Exception ex) { - System.out.println("Error occurred during login for mobile no: " + loginRequest.getMobileNumber() - + " Exception: " + ex.getMessage()); - - return AuthResponse.builder().status("Unauthorized").message("Authentication failed: " + ex.getMessage()) - .statusCode(401).build(); - } - } - } \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/util/Helper.java b/src/main/java/com/billpaymentservice/bbps/util/Helper.java index 9949670..74a4d3f 100644 --- a/src/main/java/com/billpaymentservice/bbps/util/Helper.java +++ b/src/main/java/com/billpaymentservice/bbps/util/Helper.java @@ -8,9 +8,11 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +import com.billpaymentservice.bbps.dto.auth.RegisterRequest; import com.billpaymentservice.bbps.entites.BBPSMastersData; import com.billpaymentservice.bbps.entites.InboundTraceLog; import com.billpaymentservice.bbps.entites.OutboundTraceLog; +import com.billpaymentservice.bbps.entites.UserEntity; import com.billpaymentservice.bbps.entites.BharatConnectMaster; import com.billpaymentservice.bbps.exception.CustomException; import com.billpaymentservice.bbps.repository.BBPSMasterDataRepo; @@ -166,4 +168,14 @@ public class Helper { return headers; } + public UserEntity createNewUser(RegisterRequest request) { + UserEntity user = new UserEntity(); + + user.setMobile(request.getMobile()); + user.setName(request.getName()); + user.setEmail(request.getEmail()); + user.setAge(request.getAge()); + return user; + } + } \ No newline at end of file diff --git a/src/main/java/com/billpaymentservice/bbps/util/OtpClient.java b/src/main/java/com/billpaymentservice/bbps/util/OtpClient.java new file mode 100644 index 0000000..758ced5 --- /dev/null +++ b/src/main/java/com/billpaymentservice/bbps/util/OtpClient.java @@ -0,0 +1,186 @@ +package com.billpaymentservice.bbps.util; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import com.billpaymentservice.bbps.dto.auth.OtpSendResponse; + +import java.util.HashMap; +import java.util.Map; +import java.util.Collections; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Component +public class OtpClient { + + private static final Logger logger = LoggerFactory.getLogger(OtpClient.class); + + private final RestTemplate restTemplate = new RestTemplate(); + + @Value("${ekyc.mobile}") + private String sendUrl; + + @Value("${ekyc.mobile.verify.otp}") + private String verifyUrl; + + // New config properties for eKYC-style OTP API + @Value("${ekyc.mobile}") + private String ekycMobileUrl; + + @Value("${ekyc.apikey}") + private String apiKey; + + @Value("${ekyc.secreteKey}") + private String secretKey; + + + /** + * Calls external API to send OTP. The implementation assumes a POST with JSON {"mobile":"..."} + * Modify headers/body as per your external API. Updated to support eKYC OTP generation logic. + */ + public OtpSendResponse sendOtp(String mobile) { + try { + logger.info("Initiating OTP send process for mobile: {}", mobile); + + logger.info("eKYC Mobile URL: {}", ekycMobileUrl); + logger.info("API Key: {}", apiKey != null && !apiKey.isEmpty()); + logger.info("Secret Key: {}", secretKey != null && !secretKey.isEmpty()); + logger.info("Send URL: {}", sendUrl); + logger.info("Verify URL: {}", verifyUrl); + logger.info("Mobile Number: {}", mobile); + + // If explicit eKYC config present, use that flow + if (ekycMobileUrl != null && !ekycMobileUrl.isEmpty()) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + // Build JSON body string as in user's snippet + String jsonBody = "{\"mobileNumber\":\"" + mobile + "\", \"apiKey\":\"" + apiKey + + "\", \"secretKey\":\"" + secretKey + "\"}"; + + HttpEntity request = new HttpEntity<>(jsonBody, headers); + + try { + ResponseEntity response = restTemplate.exchange(ekycMobileUrl, HttpMethod.POST, request, + String.class); + logger.info("eKYC OTP generation API response status: {}", response.getStatusCode()); + + if (response.getStatusCode() == HttpStatus.OK) { + logger.info("OTP generated successfully for mobile: {}", mobile); + return new OtpSendResponse(true, "OTP generated successfully"); + + } else { + logger.error("Failed to call eKYC OTP generation API: {}", response.getStatusCode()); + return new OtpSendResponse(false, "Failed to call OTP generation service"); + } + } catch (Exception e) { + logger.error("Error calling eKYC OTP generation API: {}", e.getMessage(), e); + return new OtpSendResponse(false, "Error while generating OTP: " + e.getMessage()); + } + } + + // Fallback to previously configured generic sendUrl behavior + if (sendUrl == null || sendUrl.isEmpty()) { + return new OtpSendResponse(true, "(stub) OTP sent to " + mobile); + } + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + Map body = new HashMap<>(); + body.put("mobile", mobile); + HttpEntity> req = new HttpEntity<>(body, headers); + // expecting external API returns {"success":true,"message":"..."} + Map resp = restTemplate.postForObject(sendUrl, req, Map.class); + boolean success = resp != null && Boolean.TRUE.equals(resp.get("success")); + String message = resp == null ? "no response" : String.valueOf(resp.get("message")); + return new OtpSendResponse(success, message); + } catch (Exception e) { + logger.error("Unexpected error in sendOtp: {}", e.getMessage(), e); + return new OtpSendResponse(false, "Failed to call OTP send: " + e.getMessage()); + } + } + + /** + * Calls external API to verify OTP. Returns true if OTP valid. + */ + public boolean verifyOtp(String mobile, String otp) { + try { + // basic input validation + if (mobile == null || mobile.isEmpty() || otp == null || otp.isEmpty()) { + logger.debug("verifyOtp called with empty mobile or otp"); + return false; + } + + logger.info("Verifying Mobile OTP for mobile: {}", mobile); + + // If an eKYC verify endpoint is configured, use it + if (verifyUrl != null && !verifyUrl.isEmpty()) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + Map requestBody = new HashMap<>(); + requestBody.put("mobileNumber", mobile); + requestBody.put("apiKey", apiKey); + requestBody.put("secretKey", secretKey); + requestBody.put("otp", otp); + + HttpEntity> requestEntity = new HttpEntity<>(requestBody, headers); + try { + ResponseEntity response = restTemplate.exchange(verifyUrl, HttpMethod.POST, + requestEntity, String.class); + + logger.info("Mobile OTP verification API response: status={}, body={}", response.getStatusCode(), + response.getBody()); + + if (response.getStatusCode() == HttpStatus.OK) { + String respBody = response.getBody(); + if (respBody != null) { + // try to parse JSON and look for common verification keys + ObjectMapper mapper = new ObjectMapper(); + try { + Map respMap = mapper.readValue(respBody, Map.class); + if (respMap.containsKey("verified")) { + return Boolean.TRUE.equals(respMap.get("verified")); + } + if (respMap.containsKey("success")) { + return Boolean.TRUE.equals(respMap.get("success")); + } + if (respMap.containsKey("status") && "OK".equalsIgnoreCase(String.valueOf(respMap.get("status")))) { + return true; + } + } catch (Exception e) { + logger.debug("Unable to parse verification response body to JSON: {}", e.getMessage()); + // fall through to treat 200 as success + } + } + // fallback: treat HTTP 200 as successful verification + return true; + } else { + logger.warn("OTP verification endpoint returned non-OK status: {}", response.getStatusCode()); + return false; + } + } catch (Exception e) { + logger.error("Error calling eKYC OTP verify API: {}", e.getMessage(), e); + return false; + } + } + + // stub behaviour when no verify URL configured: accept OTP "123456" + return false; + } catch (Exception e) { + logger.error("Unexpected error in verifyOtp: {}", e.getMessage(), e); + return false; + } + } +} diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties index 17c421e..4eaafbc 100644 --- a/src/main/resources/application-local.properties +++ b/src/main/resources/application-local.properties @@ -20,12 +20,20 @@ swagger.server.description=Local Development Server # DataSource spring.datasource.url=jdbc:postgresql://localhost:5432/BBPS spring.datasource.username=postgres -spring.datasource.password=UAT@DB_2025 +#spring.datasource.password=UAT@DB_2025 -#spring.datasource.password=himanshu@123 +spring.datasource.password=himanshu@123 spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.type=com.zaxxer.hikari.HikariDataSource +ekyc.apikey=key_live_823fb2b5ba984ea293b6695331f83788 +ekyc.secreteKey= secret_live_b2acae6e1fd54d6faa148b08af8ae098 +ekyc.mobile=https://ekyc.lincpay.in/EKYC/ekyc/mobile/generate-otp +ekyc.mobile.verify.otp=https://ekyc.lincpay.in/EKYC/ekyc/verify-mobile-otp + + + +enc.key=lincpay # HikariCP settings spring.datasource.hikari.connection-timeout=10000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d32e5c2..d72e0a0 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -48,6 +48,12 @@ payment.data.url=https://bbps-staging.digiledge.in/couapp complaint.data.url=https://bbps-staging.digiledge.in/agent/bill-payment-new + +ekyc.apikey=key_live_823fb2b5ba984ea293b6695331f83788 +ekyc.secreteKey= secret_live_b2acae6e1fd54d6faa148b08af8ae098 +ekyc.mobile=https://ekyc.lincpay.in/EKYC/ekyc/mobile/generate-otp +ekyc.mobile.verify.otp=https://ekyc.lincpay.in/EKYC/ekyc/verify-mobile-otp + # throw NoHandlerFoundException for 404s spring.mvc.throw-exception-if-no-handler-found=true