-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat : 휴대폰 인증 요청/확인 API (application.properties 미적용)
- Loading branch information
Showing
10 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
src/main/java/umc/kkijuk/server/member/controller/response/CreateMemberResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/umc/kkijuk/server/member/controller/response/MemberFieldResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/umc/kkijuk/server/member/controller/response/MemberInfoResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/umc/kkijuk/server/member/controller/response/ResultResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/main/java/umc/kkijuk/server/member/dto/MemberPhoneNumberDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
112
src/main/java/umc/kkijuk/server/member/phoneauth/MessageService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
33
src/main/java/umc/kkijuk/server/member/phoneauth/RedisConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/umc/kkijuk/server/member/phoneauth/SmsCertification.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/umc/kkijuk/server/member/phoneauth/SmsCertificationDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
99
src/test/java/umc/kkijuk/server/member/service/MemberInfoTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | ||
} | ||
|
||
} |