commit create and verify tranpin
parent
a3d69d66eb
commit
6f95055761
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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…
Reference in New Issue