commit create and verify tranpin

Nabeel-DG-BS
Raja Nabeel 2 years ago
parent a3d69d66eb
commit 6f95055761

@ -22,6 +22,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>

@ -8,4 +8,6 @@ public interface UCOURI {
String GET_TRANSACTION_PIN = "/transactionPin";
String SUBMIT_TRANSACTION = "/submitTransaction";
String GENERATE_TRANSACTIONS_REPORT = "/generateReport";
String CREATE_TRAN_PIN = "/createTransactionPin";
String VERIFY_TRAN_PIN = "/verifyTransactionPin";
}

@ -0,0 +1,18 @@
package com.mfsys.uco.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientconfiguration {
@LoadBalanced
@Bean
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}

@ -6,7 +6,10 @@ import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.mfsys.uco.UCOURI;
import com.mfsys.uco.dto.*;
import com.mfsys.uco.service.TransactionPinService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.io.ByteArrayOutputStream;
@ -18,6 +21,9 @@ import java.util.List;
@RestController
@RequiredArgsConstructor
public class UserController {
private final TransactionPinService transactionPinService;
@PostMapping(UCOURI.VIEW_BALANCE)
public ViewBalanceResponseModel viewBalance(@RequestBody ViewBalanceRequestModel viewBalanceRequestModel) {
ViewBalanceResponseModel viewBalanceResponseModel = new ViewBalanceResponseModel();
@ -107,6 +113,27 @@ public class UserController {
return "Error generating report";
}
}
@PostMapping(UCOURI.CREATE_TRAN_PIN)
public ResponseEntity<HttpStatus> createTransactionPin(@RequestBody CreateTransactionPinRequest request) {
try {
transactionPinService.createTransactionPin(request);
return ResponseEntity.ok(HttpStatus.OK);
} catch (Exception e) {
return ResponseEntity.ok(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping(UCOURI.VERIFY_TRAN_PIN)
public ResponseEntity<?> verifyPin(@RequestBody VerifyPinRequest request) {
try {
boolean isVerified = transactionPinService.verifyOTPAndSavePin(request);
if (isVerified) {
return ResponseEntity.ok("PIN verified successfully.");
} else {
return ResponseEntity.badRequest().body("PIN verification failed.");
}
} catch (Exception e) {
return ResponseEntity.status(500).body("Error during PIN verification: " + e.getMessage());
}
}
}

@ -0,0 +1,21 @@
package com.mfsys.uco.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CreateTransactionPinRequest {
private String newTransPincode;
private String channelCode;
private String pctCstycode;
private String porOrgacode;
private String cmpCustcode;
private boolean isOtpRequired;
}

@ -0,0 +1,21 @@
package com.mfsys.uco.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OTPRequest {
private boolean isOtpRequired;
private String email;
private String phone;
private String channelCode;
private String porOrgacode;
private String username;
private String pinType;
private String subject;
}

@ -0,0 +1,22 @@
package com.mfsys.uco.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class VerifyPinRequest {
String channelCode;
String pctCstycode;
String porOrgacode;
String cmpCustcode;
String email;
String obpPincode;
String pinType;
}

@ -1,10 +1,7 @@
package com.mfsys.uco.model;
import com.mfsys.comm.util.FieldNameLength;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -16,6 +13,7 @@ import java.time.LocalDate;
@Table(name = "BN_CS_MP_CUSTOMERPROFILE")
@Data
@Builder
@IdClass(CustomerProfileId.class)
@AllArgsConstructor
@NoArgsConstructor
public class CustomerProfile {
@ -30,6 +28,7 @@ public class CustomerProfile {
@Column(name = "PIT_IDENVALUE", nullable = true, columnDefinition = FieldNameLength.CODE_20)
protected String pitIdenvalue;
@Column(name = "PIT_IDENCODE", nullable = true, columnDefinition = FieldNameLength.CODE_20)
protected String pitIdencode;
@ -39,10 +38,21 @@ public class CustomerProfile {
@Column(name = "KYC_RENEWAL_DATE", nullable = true, columnDefinition = FieldNameLength.DATE)
protected LocalDate kycRenewalDate;
@Column(name = "CMP_EMAIL", nullable = true, columnDefinition = FieldNameLength.CODE_50)
private String cmpEmail;
@Column(name = "CMP_NAME", nullable = true, columnDefinition = FieldNameLength.CODE_50)
private String cmpName;
@Column(name = "CMP_USERNAME", nullable = true, columnDefinition = FieldNameLength.CODE_50)
private String cmpUserName;
@Column(name = "CMP_ISKYC_VERIFIED", nullable=false, columnDefinition=FieldNameLength.BOOLEAN_BIT)
protected boolean cmpIsKycVerified = false;
@Column(name = "CMP_TRAN_PIN", nullable=false, columnDefinition=FieldNameLength.PIN_VALUE)
protected String cmpTranpin;
@Column(name = "CMP_TRAN_PIN_VERIFIED", nullable=false, columnDefinition=FieldNameLength.BOOLEAN_BIT)
protected boolean cmpTranpinVerfied = false;
}

@ -0,0 +1,66 @@
package com.mfsys.uco.model;
import java.io.Serializable;
public class CustomerProfileId implements Serializable {
private static final long serialVersionUID = 1L;
private String porOrgacode;
private String cmpCustcode;
public String getPorOrgacode() {
return porOrgacode;
}
public void setPorOrgacode(String porOrgacode) {
this.porOrgacode = porOrgacode;
}
public String getCmpCustcode() {
return cmpCustcode;
}
public void setCmpCustcode(String cmpCustcode) {
this.cmpCustcode = cmpCustcode;
}
public CustomerProfileId() {
}
public CustomerProfileId(String porOrgacode, String cmpCustcode) {
this.porOrgacode = porOrgacode;
this.cmpCustcode = cmpCustcode;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cmpCustcode == null) ? 0 : cmpCustcode.hashCode());
result = prime * result + ((porOrgacode == null) ? 0 : porOrgacode.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CustomerProfileId other = (CustomerProfileId) obj;
if (cmpCustcode == null) {
if (other.cmpCustcode != null)
return false;
} else if (!cmpCustcode.equals(other.cmpCustcode))
return false;
if (porOrgacode == null) {
if (other.porOrgacode != null)
return false;
} else if (!porOrgacode.equals(other.porOrgacode))
return false;
return true;
}
}

@ -0,0 +1,64 @@
package com.mfsys.uco.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.mfsys.comm.util.FieldNameLength;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import java.time.LocalDateTime;
@Entity(name = "DG_PN_PIN")
@Table(name = "DG_PN_PIN")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Pin {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "PINSERIAL", nullable = false, updatable = false, columnDefinition = FieldNameLength.BIGINT)
private Long pinserial;
@Column(name = "POR_ORGACODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.POR_ORGACODE)
private String porOrgacode;
@Column(name = "username", nullable = false, updatable = false, columnDefinition = FieldNameLength.USER_NAME)
private String userName;
@Column(name = "CHANNEL_CODE", nullable = false, updatable = false, columnDefinition = FieldNameLength.CHANNEL_CODE)
private String channelCode;
@Column(name = "PINTYPE", nullable = false, updatable = false, columnDefinition = FieldNameLength.CODE_10)
private String pintype;
@Column(name = "PINLENGTH", nullable = false, updatable = false, columnDefinition = FieldNameLength.PIN_LENGTH)
private int pinlength;
@Column(name = "PINCODE", nullable = false, updatable = true, columnDefinition = FieldNameLength.PIN_VALUE)
private String pincode;
@Column(name = "PIN_CREATEDATE", nullable = false, updatable = true, columnDefinition = FieldNameLength.DATETIME)
private LocalDateTime pinCreatedate;
@Column(name = "PIN_EXPIRYDATE", nullable = false, updatable = true, columnDefinition = FieldNameLength.DATETIME)
private LocalDateTime pinExpirydate;
@Column(name = "PINSTATUS", nullable = false, updatable = true, columnDefinition = FieldNameLength.CODE_20)
private String pinstatus;
@Column(name = "PIN_VALIDATIONDATE", nullable = true, updatable = true, columnDefinition = FieldNameLength.DATETIME)
private LocalDateTime pinValidationdate;
@JsonIgnore
@Column(name = "Version", nullable = false, updatable = true, columnDefinition = FieldNameLength.INT)
@Version
private int version;
}

@ -0,0 +1,10 @@
package com.mfsys.uco.repository;
import com.mfsys.uco.model.CustomerProfile;
import com.mfsys.uco.model.CustomerProfileId;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CustomerProfileRepository extends JpaRepository<CustomerProfile, CustomerProfileId> {
}

@ -0,0 +1,15 @@
package com.mfsys.uco.repository;
import com.mfsys.uco.model.Pin;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface PinRepository extends JpaRepository<Pin, Long> {
@Query("SELECT p FROM DG_PN_PIN p WHERE p.userName = :username AND p.pinstatus = 'Unverified' AND p.pinExpirydate > CURRENT_TIMESTAMP ORDER BY p.pinserial DESC LIMIT 1")
Optional<Pin> findLatestActiveOtpByUserName(String username);
}

@ -0,0 +1,63 @@
package com.mfsys.uco.service;
import com.mfsys.comm.commonservices.OtpService;
import com.mfsys.comm.constant.EurekaRegisteredMicroServicesURI;
import com.mfsys.comm.exception.InvalidOTPException;
import com.mfsys.uco.dto.OTPRequest;
import com.mfsys.uco.model.Pin;
import com.mfsys.uco.repository.PinRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Optional;
@Component
public class NotificationService {
@LoadBalanced
private final WebClient webClient;
private final OtpService otpService;
private final PinRepository pinRepository;
public NotificationService(WebClient.Builder webClientBuilder, OtpService otpService, PinRepository pinRepository) {
this.webClient = webClientBuilder.baseUrl(EurekaRegisteredMicroServicesURI.NOTIFICATION_SERVICE_LB).build();
this.otpService = otpService;
this.pinRepository = pinRepository;
}
public Mono<String> sendOtp(OTPRequest otpRequest) {
String otp = otpRequest.isOtpRequired() ? otpService.generateOtp() : "123456";
Pin pin = new Pin();
final LocalDateTime createDate = LocalDateTime.now();
final LocalDateTime expiryDate = LocalDateTime.now().plusMinutes(5);
pin.setPinCreatedate(createDate);
pin.setPinExpirydate(expiryDate);
pin.setChannelCode(otpRequest.getChannelCode());
pin.setPintype(otpRequest.getPinType());
pin.setPincode(otp);
pin.setPorOrgacode(otpRequest.getPorOrgacode());
pin.setVersion(1);
pin.setPinlength(6);
pin.setPinstatus("Unverified");
pin.setUserName(otpRequest.getEmail());
pinRepository.save(pin);
webClient.post().uri("/notification/otp/email").bodyValue(Map.of("email", otpRequest.getEmail(), "subject", otpRequest.getSubject(), "otp", otp, "userName", otpRequest.getUsername())).retrieve()
.onStatus(status -> status.is4xxClientError() || status.is5xxServerError(), clientResponse
-> Mono.error(new RuntimeException("Response has error status."))).bodyToMono(String.class).block();
return null;
}
public void verifyOtp(String porOrgacode, String email, String obpPincode) {
Optional<Pin> pin = pinRepository.findLatestActiveOtpByUserName(email);
if (pin.isPresent() && pin.get().getPincode().equals(obpPincode) && pin.get().getPorOrgacode().equals(porOrgacode)) {
pin.get().setPinstatus("VERIFIED");
pinRepository.save(pin.get());
return;
}
throw new InvalidOTPException(porOrgacode);
}
}

@ -0,0 +1,53 @@
package com.mfsys.uco.service;
import com.mfsys.uco.dto.CreateTransactionPinRequest;
import com.mfsys.uco.dto.OTPRequest;
import com.mfsys.uco.dto.VerifyPinRequest;
import com.mfsys.uco.model.CustomerProfile;
import com.mfsys.uco.model.CustomerProfileId;
import com.mfsys.uco.repository.CustomerProfileRepository;
import com.mfsys.uco.repository.PinRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class TransactionPinService {
private final CustomerProfileRepository customerProfileRepository;
private final NotificationService notificationService;
public void createTransactionPin(CreateTransactionPinRequest request) {
CustomerProfile profile = fetchCustomer(request.getPorOrgacode(), request.getCmpCustcode());
OTPRequest otpRequest = OTPRequest.builder()
.porOrgacode(request.getPorOrgacode())
.channelCode(request.getChannelCode())
.pinType("C_PIN")
.email(profile.getCmpEmail())
.phone(profile.getPadAdrsmobphone())
.isOtpRequired(request.isOtpRequired())
.username(profile.getCmpUserName())
.subject("Create Transaction Pin Verification OTP")
.build();
notificationService.sendOtp(otpRequest);
customerProfileRepository.save(profile);
}
public boolean verifyOTPAndSavePin(VerifyPinRequest request) {
notificationService.verifyOtp(request.getPorOrgacode(), request.getEmail(), request.getObpPincode());
CustomerProfile profile = fetchCustomer(request.getPorOrgacode(), request.getCmpCustcode());
profile.setCmpTranpinVerfied(true);
customerProfileRepository.save(profile);
return true;
}
public CustomerProfile fetchCustomer(String porOrgacode, String cmpCustcode){
CustomerProfileId profileId = new CustomerProfileId(porOrgacode,cmpCustcode);
return customerProfileRepository.findById(profileId)
.orElseThrow(() -> new IllegalArgumentException("Customer profile not found for ID: " + profileId));
}
}
Loading…
Cancel
Save