Skip to content

Commit

Permalink
Feat : 휴대폰 인증 요청/확인 API (application.properties 미적용)
Browse files Browse the repository at this point in the history
  • Loading branch information
Suhun0331 committed Jul 28, 2024
1 parent c9f24f6 commit a78d304
Show file tree
Hide file tree
Showing 10 changed files with 382 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package umc.kkijuk.server.member.controller.response;

import lombok.Data;

@Data
public class CreateMemberResponse {
private Long id;
private String message;

public CreateMemberResponse(String message) {
this.message = message;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package umc.kkijuk.server.member.controller.response;

import lombok.Data;

import java.util.List;

@Data
public class MemberFieldResponse{
private List<String> field;

public MemberFieldResponse(List<String> field) {
this.field = field;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package umc.kkijuk.server.member.controller.response;

import lombok.Data;

import java.time.LocalDate;

@Data
public class MemberInfoResponse {
private String email;
private String name;
private String phoneNumber;
private LocalDate birthDate;

public MemberInfoResponse() {
}

public MemberInfoResponse(String email, String name, String phoneNumber, LocalDate birthDate) {
this.email = email;
this.name = name;
this.phoneNumber = phoneNumber;
this.birthDate = birthDate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package umc.kkijuk.server.member.controller.response;

import lombok.Data;

@Data
public class ResultResponse{
private String message;

public ResultResponse(){

}

public ResultResponse(String message) {
this.message = message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package umc.kkijuk.server.member.dto;

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class MemberPhoneNumberDto {
private String phoneNumber;

@Builder
public MemberPhoneNumberDto(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
112 changes: 112 additions & 0 deletions src/main/java/umc/kkijuk/server/member/phoneauth/MessageService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package umc.kkijuk.server.member.phoneauth;

import lombok.RequiredArgsConstructor;
import net.nurigo.sdk.NurigoApp;
import net.nurigo.sdk.message.model.Message;
import net.nurigo.sdk.message.request.SingleMessageSendingRequest;
import net.nurigo.sdk.message.response.SingleMessageSentResponse;
import net.nurigo.sdk.message.service.DefaultMessageService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;


import java.util.HashMap;
import java.util.Random;

@Service
public class MessageService {
private final SmsCertification smsCertification;
private final DefaultMessageService messageService;

// @Value("${coolsms.apikey}")
// private String apiKey;
//
// @Value("${coolsms.apisecret}")
// private String apiSecret;

@Value("$01033236326")
private String fromNumber;

public MessageService(SmsCertification smsCertification, @Value("${coolsms.api.key}") String apiKey,
@Value("${coolsms.api.secret}") String apiSecret ) {
this.smsCertification = smsCertification;
// 반드시 계정 내 등록된 유효한 API 키, API Secret Key를 입력해주셔야 합니다!
this.messageService = NurigoApp.INSTANCE.initialize(apiKey, apiSecret, "https://api.coolsms.co.kr");
}



private String createRandomNumber() {
Random rand = new Random();
String randomNum = "";
for (int i = 0; i < 4; i++) {
String random = Integer.toString(rand.nextInt(10));
randomNum += random;
}

return randomNum;
}

private HashMap<String, String> makeParams(String to, String randomNum) {
HashMap<String, String> params = new HashMap<>();
params.put("from", fromNumber);
params.put("type", "SMS");
params.put("app_version", "test app 1.2");
params.put("to", to);
params.put("text", randomNum);
return params;
}


// 인증번호 전송하기
public SingleMessageSentResponse sendSMS(String phoneNumber) {
Message coolsms = new Message();
coolsms.setFrom(fromNumber);
coolsms.setTo(phoneNumber);
// 랜덤한 인증 번호 생성
String randomNum = createRandomNumber();
System.out.println(randomNum);
coolsms.setText("인증번호: "+randomNum);


// 발신 정보 설정
HashMap<String, String> params = makeParams(phoneNumber, randomNum);

// try {
// JSONObject obj = (JSONObject) coolsms.send(params);
// System.out.println(obj.toString());
// } catch (Exception e) {
// System.out.println(e.getMessage());
// System.out.println(e.getCode());
// }

SingleMessageSentResponse response = this.messageService.sendOne(new SingleMessageSendingRequest(coolsms));
System.out.println(response);


// DB에 발송한 인증번호 저장
smsCertification.createSmsCertification(phoneNumber,randomNum);


return response;


// return "문자 전송이 완료되었습니다.";
}

// 인증 번호 검증
public String verifySms(SmsCertificationDto requestDto) {
if (isVerify(requestDto)) {
throw new IllegalArgumentException("인증번호가 일치하지 않습니다.");
}
smsCertification.deleteSmsCertification(requestDto.getPhoneNumber());

return "인증 완료되었습니다.";
}

private boolean isVerify(SmsCertificationDto requestDto) {
return !(smsCertification.hasKey(requestDto.getPhoneNumber()) &&
smsCertification.getSmsCertification(requestDto.getPhoneNumber())
.equals(requestDto.getRandomNumber()));
}
}
33 changes: 33 additions & 0 deletions src/main/java/umc/kkijuk/server/member/phoneauth/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package umc.kkijuk.server.member.phoneauth;

import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@RequiredArgsConstructor
@EnableRedisRepositories
public class RedisConfig {
private final RedisProperties redisProperties;

// lettuce
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
}

@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package umc.kkijuk.server.member.phoneauth;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import java.time.Duration;

@RequiredArgsConstructor
@Repository
public class SmsCertification {
private final String PREFIX = "sms:"; // key값이 중복되지 않도록 상수 선언
private final int LIMIT_TIME = 3 * 60; // 인증번호 유효 시간

private final StringRedisTemplate stringRedisTemplate;

// Redis에 저장
public void createSmsCertification(String phone, String certificationNumber) {
stringRedisTemplate.opsForValue()
.set(PREFIX + phone, certificationNumber, Duration.ofSeconds(LIMIT_TIME));
}

// 휴대전화 번호에 해당하는 인증번호 불러오기
public String getSmsCertification(String phone) {
return stringRedisTemplate.opsForValue().get(PREFIX + phone);
}

// 인증 완료 시, 인증번호 Redis에서 삭제
public void deleteSmsCertification(String phone) {
stringRedisTemplate.delete(PREFIX + phone);
}

// Redis에 해당 휴대번호로 저장된 인증번호가 존재하는지 확인
public boolean hasKey(String phone) {
return stringRedisTemplate.hasKey(PREFIX + phone);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package umc.kkijuk.server.member.phoneauth;

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class SmsCertificationDto {
private String phoneNumber;
private String randomNumber;

@Builder
public SmsCertificationDto(String phoneNumber, String randomNumber) {
this.phoneNumber = phoneNumber;
this.randomNumber = randomNumber;
}
}
99 changes: 99 additions & 0 deletions src/test/java/umc/kkijuk/server/member/service/MemberInfoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package umc.kkijuk.server.member.service;

import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import umc.kkijuk.server.member.controller.response.MemberInfoResponse;
import umc.kkijuk.server.member.controller.response.ResultResponse;
import umc.kkijuk.server.member.domain.MarketingAgree;
import umc.kkijuk.server.member.domain.Member;
import umc.kkijuk.server.member.domain.State;
import umc.kkijuk.server.member.dto.MemberInfoChangeDto;
import umc.kkijuk.server.member.repository.MemberJpaRepository;
import umc.kkijuk.server.common.LoginUser;

import java.time.LocalDate;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MemberInfoTest {


@Autowired
private TestRestTemplate restTemplate;

@Autowired
private MemberJpaRepository memberJpaRepository;

@BeforeEach
public void setup() {
memberJpaRepository.deleteAll();
}

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
public void 내정보_조회() {
// Given
Member member1 = new Member("[email protected]", "홍길동", "010-1234-5678",
LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE);
memberJpaRepository.save(member1);
System.out.println("test1");
// When
ResponseEntity<MemberInfoResponse> response = restTemplate.getForEntity("/member/myPage/info", MemberInfoResponse.class);

// Then
assertEquals(HttpStatus.OK, response.getStatusCode());

MemberInfoResponse body = response.getBody();
assertNotNull(body);
assertEquals("[email protected]", body.getEmail());
assertEquals("홍길동", body.getName());
assertEquals("010-1234-5678", body.getPhoneNumber());
assertEquals(LocalDate.parse("1999-03-31"), body.getBirthDate());
}

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.AFTER_METHOD)
public void 내정보_수정() {
// Given
Member member1 = new Member("[email protected]", "홍길동", "010-1234-5678",
LocalDate.parse("1999-03-31"), "passwordTest", MarketingAgree.BOTH, State.ACTIVATE);
memberJpaRepository.save(member1);
System.out.println("test2");


MemberInfoChangeDto changeDto = MemberInfoChangeDto.builder()
.phoneNumber("010-5678-1234")
.birthDate(LocalDate.parse("2000-01-01"))
.marketingAgree(MarketingAgree.EMAIL)
.build();

HttpEntity<MemberInfoChangeDto> requestEntity = new HttpEntity<>(changeDto);

// When
ResponseEntity<ResultResponse> response = restTemplate.exchange("/member/myPage/info", HttpMethod.PUT, requestEntity, ResultResponse.class);

// Then
assertEquals(HttpStatus.OK, response.getStatusCode());
ResultResponse body = response.getBody();
assertNotNull(body);
assertEquals("information update success", body.getMessage());

// Verify changes
Member updatedMember = memberJpaRepository.findById(member1.getId()).orElse(null);
assertNotNull(updatedMember);
assertEquals("010-5678-1234", updatedMember.getPhoneNumber());
assertEquals(LocalDate.parse("2000-01-01"), updatedMember.getBirthDate());
assertEquals(MarketingAgree.EMAIL, updatedMember.getMarketingAgree());
}

}

0 comments on commit a78d304

Please sign in to comment.