From a1ef31e18cf1f7e1ddb2e834114f0bfd38c1dd7f Mon Sep 17 00:00:00 2001 From: HyoBin Yang <50162252+HyoBN@users.noreply.github.com> Date: Sun, 27 Aug 2023 17:23:48 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8[FEAT]=20SMS=20=EC=9D=B8=EC=A6=9D=20AP?= =?UTF-8?q?I=20=EA=B0=9C=EB=B0=9C=20(#74)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: SMS 인증 API 개발 * :bug: SMS API 토큰 검증 제외 * :memo: Docs: SMS API 스웨거 명세 작성 --- .../FeignClient/KakaoFeignConfiguration.java | 7 +- .../FeignClient/NaverFeignConfiguration.java | 38 +++++ .../FeignClient/NaverSmsFeignClient.java | 17 ++ .../FeignClientExceptionErrorDecoder.java | 14 +- .../server/auth/config/SecurityConfig.java | 3 +- src/main/java/zipdabang/server/base/Code.java | 8 + .../handler/AuthNumberException.java | 10 ++ .../server/domain/etc/AuthNumber.java | 2 - .../repository/AuthNumberRepository.java | 11 ++ .../memberRepositories/MemberRepository.java | 2 + .../server/service/MemberService.java | 2 + .../serviceImpl/MemberServiceImpl.java | 8 + .../zipdabang/server/sms/dto/MessageDto.java | 13 ++ .../server/sms/dto/PhoneAuthDto.java | 14 ++ .../server/sms/dto/SmsRequestDto.java | 18 ++ .../server/sms/service/SmsService.java | 18 ++ .../service/serviceImpl/SmsServiceImpl.java | 158 ++++++++++++++++++ .../web/controller/MemberRestController.java | 33 +++- src/main/resources/application.yml | 18 +- 19 files changed, 373 insertions(+), 21 deletions(-) create mode 100644 src/main/java/zipdabang/server/FeignClient/NaverFeignConfiguration.java create mode 100644 src/main/java/zipdabang/server/FeignClient/NaverSmsFeignClient.java create mode 100644 src/main/java/zipdabang/server/base/exception/handler/AuthNumberException.java create mode 100644 src/main/java/zipdabang/server/repository/AuthNumberRepository.java create mode 100644 src/main/java/zipdabang/server/sms/dto/MessageDto.java create mode 100644 src/main/java/zipdabang/server/sms/dto/PhoneAuthDto.java create mode 100644 src/main/java/zipdabang/server/sms/dto/SmsRequestDto.java create mode 100644 src/main/java/zipdabang/server/sms/service/SmsService.java create mode 100644 src/main/java/zipdabang/server/sms/service/serviceImpl/SmsServiceImpl.java diff --git a/src/main/java/zipdabang/server/FeignClient/KakaoFeignConfiguration.java b/src/main/java/zipdabang/server/FeignClient/KakaoFeignConfiguration.java index 41d3c42..7951acb 100644 --- a/src/main/java/zipdabang/server/FeignClient/KakaoFeignConfiguration.java +++ b/src/main/java/zipdabang/server/FeignClient/KakaoFeignConfiguration.java @@ -8,10 +8,9 @@ public class KakaoFeignConfiguration { - @Bean - public RequestInterceptor requestInterceptor(){ - return template -> template.header("Content-Type", "application/x-www-form-urlencoded"); - } +// @Bean +// public RequestInterceptor requestInterceptor(){ return null; +// } @Bean public ErrorDecoder errorDecoder() { diff --git a/src/main/java/zipdabang/server/FeignClient/NaverFeignConfiguration.java b/src/main/java/zipdabang/server/FeignClient/NaverFeignConfiguration.java new file mode 100644 index 0000000..13de4a2 --- /dev/null +++ b/src/main/java/zipdabang/server/FeignClient/NaverFeignConfiguration.java @@ -0,0 +1,38 @@ +package zipdabang.server.FeignClient; + +import feign.Logger; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.codec.ErrorDecoder; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import zipdabang.server.FeignClient.exception.FeignClientExceptionErrorDecoder; + +@RequiredArgsConstructor +public class NaverFeignConfiguration { + + @Bean + public RequestInterceptor basicAuthRequestInterceptor() { + return new ColonInterceptor(); + } + public static class ColonInterceptor implements RequestInterceptor { + @Override + public void apply(RequestTemplate template) { + template.uri(template.path().replaceAll("%3A", ":")); + } + } + + @Bean + public ErrorDecoder errorDecoder() { + return new FeignClientExceptionErrorDecoder(); + } + + @Bean + Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + + + + +} diff --git a/src/main/java/zipdabang/server/FeignClient/NaverSmsFeignClient.java b/src/main/java/zipdabang/server/FeignClient/NaverSmsFeignClient.java new file mode 100644 index 0000000..689a8ca --- /dev/null +++ b/src/main/java/zipdabang/server/FeignClient/NaverSmsFeignClient.java @@ -0,0 +1,17 @@ +package zipdabang.server.FeignClient; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.*; +import zipdabang.server.sms.dto.SmsRequestDto; + + +@FeignClient(name = "feign", url = "https://sens.apigw.ntruss.com/sms/v2/services", configuration = NaverFeignConfiguration.class) +public interface NaverSmsFeignClient { + + @PostMapping(value = "/{serviceId}/messages") + void sendSms(@PathVariable(value = "serviceId") String serviceId, + @RequestHeader HttpHeaders headers, + @RequestBody SmsRequestDto request); +} diff --git a/src/main/java/zipdabang/server/FeignClient/exception/FeignClientExceptionErrorDecoder.java b/src/main/java/zipdabang/server/FeignClient/exception/FeignClientExceptionErrorDecoder.java index 4fc494a..e0fb9e0 100644 --- a/src/main/java/zipdabang/server/FeignClient/exception/FeignClientExceptionErrorDecoder.java +++ b/src/main/java/zipdabang/server/FeignClient/exception/FeignClientExceptionErrorDecoder.java @@ -7,17 +7,21 @@ import zipdabang.server.base.Code; import zipdabang.server.base.exception.handler.CustomFeignClientException; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + public class FeignClientExceptionErrorDecoder implements ErrorDecoder { Logger logger = LoggerFactory.getLogger(FeignClientExceptionErrorDecoder.class); + @Override public Exception decode(String methodKey, Response response) { - if (response.status() >= 400 && response.status() <= 499){ - logger.error("카카오 소셜 로그인 400번대 에러 발생 : {}", response.reason()); + if (response.status() >= 400 && response.status() <= 499) { + logger.error("{}번 에러 발생 : {}", response.status(), response.reason()); return new CustomFeignClientException(Code.FEIGN_CLIENT_ERROR_400); - } - else{ - logger.error("카카오 소셜 로그인 500번대 에러 발생 : {}", response.reason()); + } else { + logger.error("500번대 에러 발생 : {}", response.reason()); return new CustomFeignClientException(Code.FEIGN_CLIENT_ERROR_500); } } diff --git a/src/main/java/zipdabang/server/auth/config/SecurityConfig.java b/src/main/java/zipdabang/server/auth/config/SecurityConfig.java index ef7fdc6..3345002 100644 --- a/src/main/java/zipdabang/server/auth/config/SecurityConfig.java +++ b/src/main/java/zipdabang/server/auth/config/SecurityConfig.java @@ -39,7 +39,8 @@ public WebSecurityCustomizer webSecurityCustomizer(){ "/v3/api-docs", "/v3/api-docs/**", "/swagger-ui/**", - "/docs/**","/members/oauth", "/members/oauth/info","/members/new-token","/members/terms","/categories","/members/exist-nickname" + "/docs/**","/members/oauth", "/members/oauth/info","/members/new-token","/members/terms","/categories","/members/exist-nickname", + "/members/phone/sms","/members/phone/auth" ); } diff --git a/src/main/java/zipdabang/server/base/Code.java b/src/main/java/zipdabang/server/base/Code.java index df04852..69b1b67 100644 --- a/src/main/java/zipdabang/server/base/Code.java +++ b/src/main/java/zipdabang/server/base/Code.java @@ -18,6 +18,7 @@ public enum Code { OAUTH_JOIN(HttpStatus.OK,2011,"회원가입 입니다."), NICKNAME_EXIST(HttpStatus.OK,2010, "닉네임이 이미 존재합니다."), NICKNAME_OK(HttpStatus.OK,2011, "사용 가능한 닉네임 입니다."), + PHONE_NUMBER_EXIST(HttpStatus.OK, 2020, "이미 인증된 전화번호입니다."), @@ -61,9 +62,16 @@ public enum Code { NO_RECIPE_EXIST(HttpStatus.BAD_REQUEST, 4101, "해당 레시피가 존재하지 않습니다."), BLOCKED_USER_RECIPE(HttpStatus.BAD_REQUEST, 4102, "차단한 사용자의 레시피입니다."), + // SMS error + PHONE_AUTH_NOT_FOUND(HttpStatus.BAD_REQUEST, 4200, "인증 번호 요청이 필요합니다."), + PHONE_AUTH_ERROR(HttpStatus.BAD_REQUEST, 4201, "잘못된 인증 번호 입니다."), + PHONE_AUTH_TIMEOUT(HttpStatus.BAD_REQUEST, 4202, "인증 시간이 초과되었습니다."), INTERNAL_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 5000, "Internal server Error"), FEIGN_CLIENT_ERROR_500(HttpStatus.INTERNAL_SERVER_ERROR, 5001, "Inter server Error in feign client"); + + + private final HttpStatus httpStatus; private final Integer code; private final String message; diff --git a/src/main/java/zipdabang/server/base/exception/handler/AuthNumberException.java b/src/main/java/zipdabang/server/base/exception/handler/AuthNumberException.java new file mode 100644 index 0000000..7d60867 --- /dev/null +++ b/src/main/java/zipdabang/server/base/exception/handler/AuthNumberException.java @@ -0,0 +1,10 @@ +package zipdabang.server.base.exception.handler; + +import zipdabang.server.base.Code; +import zipdabang.server.base.exception.GeneralException; + +public class AuthNumberException extends GeneralException { + public AuthNumberException(Code errorCode){ + super(errorCode); + } +} diff --git a/src/main/java/zipdabang/server/domain/etc/AuthNumber.java b/src/main/java/zipdabang/server/domain/etc/AuthNumber.java index 257a509..93b0d8e 100644 --- a/src/main/java/zipdabang/server/domain/etc/AuthNumber.java +++ b/src/main/java/zipdabang/server/domain/etc/AuthNumber.java @@ -19,10 +19,8 @@ public class AuthNumber { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(length = 18) private String phoneNum; - private LocalDateTime authNumTime; private Integer authNum; } diff --git a/src/main/java/zipdabang/server/repository/AuthNumberRepository.java b/src/main/java/zipdabang/server/repository/AuthNumberRepository.java new file mode 100644 index 0000000..91ab6da --- /dev/null +++ b/src/main/java/zipdabang/server/repository/AuthNumberRepository.java @@ -0,0 +1,11 @@ +package zipdabang.server.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import zipdabang.server.domain.etc.AuthNumber; + +import java.util.Optional; + +public interface AuthNumberRepository extends JpaRepository { + Optional findByPhoneNum(String phoneNum); + void deleteByPhoneNum(String phoneNum); +} diff --git a/src/main/java/zipdabang/server/repository/memberRepositories/MemberRepository.java b/src/main/java/zipdabang/server/repository/memberRepositories/MemberRepository.java index 2781c6c..769d2d0 100644 --- a/src/main/java/zipdabang/server/repository/memberRepositories/MemberRepository.java +++ b/src/main/java/zipdabang/server/repository/memberRepositories/MemberRepository.java @@ -9,4 +9,6 @@ public interface MemberRepository extends JpaRepository { Optional findByEmail(String email); Optional findByNickname(String nickname); + + boolean existsByPhoneNum(String phoneNum); } diff --git a/src/main/java/zipdabang/server/service/MemberService.java b/src/main/java/zipdabang/server/service/MemberService.java index 0d2f30c..27cc098 100644 --- a/src/main/java/zipdabang/server/service/MemberService.java +++ b/src/main/java/zipdabang/server/service/MemberService.java @@ -15,6 +15,8 @@ public interface MemberService { OAuthResult.OAuthResultDto SocialLogin(MemberRequestDto.OAuthRequestDto request, String type); Optional checkExistNickname(String nickname); + + public void existByPhoneNumber(String phoneNum); OAuthJoin.OAuthJoinDto joinInfoComplete(MemberRequestDto.MemberInfoDto request, String type); diff --git a/src/main/java/zipdabang/server/service/serviceImpl/MemberServiceImpl.java b/src/main/java/zipdabang/server/service/serviceImpl/MemberServiceImpl.java index 8d7d4b9..af3b660 100644 --- a/src/main/java/zipdabang/server/service/serviceImpl/MemberServiceImpl.java +++ b/src/main/java/zipdabang/server/service/serviceImpl/MemberServiceImpl.java @@ -6,6 +6,7 @@ import org.springframework.transaction.annotation.Transactional; import zipdabang.server.auth.provider.TokenProvider; import zipdabang.server.base.Code; +import zipdabang.server.base.exception.handler.AuthNumberException; import zipdabang.server.base.exception.handler.MemberException; import zipdabang.server.converter.MemberConverter; import zipdabang.server.domain.Category; @@ -95,6 +96,13 @@ public Optional checkExistNickname(String nickname){ return memberRepository.findByNickname(nickname); } + @Override + public void existByPhoneNumber(String phoneNum) { + if (memberRepository.existsByPhoneNum(phoneNum)) { + throw new AuthNumberException(Code.PHONE_NUMBER_EXIST); + } + } + @Override public List getCategoryList(){ return categoryRepository.findAll(); diff --git a/src/main/java/zipdabang/server/sms/dto/MessageDto.java b/src/main/java/zipdabang/server/sms/dto/MessageDto.java new file mode 100644 index 0000000..c6e0527 --- /dev/null +++ b/src/main/java/zipdabang/server/sms/dto/MessageDto.java @@ -0,0 +1,13 @@ +package zipdabang.server.sms.dto; + +import lombok.*; + +@Builder +@Getter +@Setter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class MessageDto { + String to; + String content; +} \ No newline at end of file diff --git a/src/main/java/zipdabang/server/sms/dto/PhoneAuthDto.java b/src/main/java/zipdabang/server/sms/dto/PhoneAuthDto.java new file mode 100644 index 0000000..b253e57 --- /dev/null +++ b/src/main/java/zipdabang/server/sms/dto/PhoneAuthDto.java @@ -0,0 +1,14 @@ +package zipdabang.server.sms.dto; +import lombok.*; + +import java.time.LocalDateTime; + +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class PhoneAuthDto{ + String phoneNum; + LocalDateTime sendTime; + Integer authNum; +} \ No newline at end of file diff --git a/src/main/java/zipdabang/server/sms/dto/SmsRequestDto.java b/src/main/java/zipdabang/server/sms/dto/SmsRequestDto.java new file mode 100644 index 0000000..e69a328 --- /dev/null +++ b/src/main/java/zipdabang/server/sms/dto/SmsRequestDto.java @@ -0,0 +1,18 @@ +package zipdabang.server.sms.dto; + +import lombok.*; + +import java.util.List; + +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class SmsRequestDto { + String type; + String contentType; + String countryCode; + String from; + String content; + List messages; +} \ No newline at end of file diff --git a/src/main/java/zipdabang/server/sms/service/SmsService.java b/src/main/java/zipdabang/server/sms/service/SmsService.java new file mode 100644 index 0000000..070aa86 --- /dev/null +++ b/src/main/java/zipdabang/server/sms/service/SmsService.java @@ -0,0 +1,18 @@ +package zipdabang.server.sms.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestClientException; +import zipdabang.server.sms.dto.SmsResponseDto; + +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +public interface SmsService { + public String makeSignature(Long time) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException; + public SmsResponseDto.AuthNumResultDto authNumber(Integer authNum, String phoneNum); + public String sendSms(String targetNumber) throws JsonProcessingException, RestClientException, URISyntaxException, InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException; + public String getRandomNumber(); +} diff --git a/src/main/java/zipdabang/server/sms/service/serviceImpl/SmsServiceImpl.java b/src/main/java/zipdabang/server/sms/service/serviceImpl/SmsServiceImpl.java new file mode 100644 index 0000000..7afa49f --- /dev/null +++ b/src/main/java/zipdabang/server/sms/service/serviceImpl/SmsServiceImpl.java @@ -0,0 +1,158 @@ +package zipdabang.server.sms.service.serviceImpl; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestTemplate; +import zipdabang.server.FeignClient.NaverSmsFeignClient; +import zipdabang.server.base.Code; +import lombok.RequiredArgsConstructor; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import zipdabang.server.base.exception.handler.AuthNumberException; +import zipdabang.server.domain.etc.AuthNumber; +import zipdabang.server.repository.AuthNumberRepository; +import zipdabang.server.sms.dto.MessageDto; +import zipdabang.server.sms.dto.SmsRequestDto; +import zipdabang.server.sms.dto.SmsResponseDto; +import zipdabang.server.sms.service.SmsService; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.*; + +@Service +@RequiredArgsConstructor +public class SmsServiceImpl implements SmsService { + private final AuthNumberRepository authNumberRepository; + private final NaverSmsFeignClient naverSmsFeignClient; + + @Value("${naver-sms.accessKey}") + private String accessKey; + + @Value("${naver-sms.secretKey}") + private String secretKey; + + @Value("${naver-sms.serviceId}") + private String serviceId; + + @Value("${naver-sms.senderPhone}") + private String phone; + + @Override + public String makeSignature(Long time) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { + String space = " "; + String newLine = "\n"; + String method = "POST"; + String url = "/sms/v2/services/"+ this.serviceId+"/messages"; + String timestamp = time.toString(); + String accessKey = this.accessKey; + String secretKey = this.secretKey; + + String message = new StringBuilder() + .append(method) + .append(space) + .append(url) + .append(newLine) + .append(timestamp) + .append(newLine) + .append(accessKey) + .toString(); + + SecretKeySpec signingKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), "HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(signingKey); + byte[] rawHmac = mac.doFinal(message.getBytes("UTF-8")); + String encodeBase64String = Base64.encodeBase64String(rawHmac); + return encodeBase64String; + } + + @Override + @Transactional + public SmsResponseDto.AuthNumResultDto authNumber(Integer authNum, String phoneNum) { + AuthNumber authNumber = authNumberRepository.findByPhoneNum(phoneNum).orElseThrow(() -> new AuthNumberException(Code.PHONE_AUTH_NOT_FOUND)); + + if (!authNumber.getAuthNum().equals(authNum)) + throw new AuthNumberException(Code.PHONE_AUTH_ERROR); + else{ + LocalDateTime nowTime = LocalDateTime.now(); + + long timeCheck = ChronoUnit.MINUTES.between(authNumber.getAuthNumTime(), nowTime); + if (timeCheck >= 5) + throw new AuthNumberException(Code.PHONE_AUTH_TIMEOUT); + } + + System.out.println(authNumber.getPhoneNum()); + authNumberRepository.deleteByPhoneNum(authNumber.getPhoneNum()); + + return SmsResponseDto.AuthNumResultDto.builder() + .responseCode(Code.OK) + .build(); + } + + @Override + @Transactional + public String sendSms(String targetNumber) throws JsonProcessingException, RestClientException, URISyntaxException, InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { + Long time = System.currentTimeMillis(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.set("x-ncp-apigw-timestamp", time.toString()); + headers.set("x-ncp-iam-access-key", accessKey); + headers.set("x-ncp-apigw-signature-v2", makeSignature(time)); + + List messages = new ArrayList<>(); + String randomNumber = getRandomNumber(); + StringBuilder sb = new StringBuilder(); + sb.append("[집다방] 인증번호 : ["+randomNumber+"]를 입력해주세요"); + String content = String.valueOf(sb); + messages.add(MessageDto.builder() + .to(targetNumber) + .content(content) + .build()); + + SmsRequestDto request = SmsRequestDto.builder() + .type("SMS") + .contentType("COMM") + .countryCode("82") + .from(phone) + .content(content) + .messages(messages) + .build(); + + + + naverSmsFeignClient.sendSms(serviceId, headers,request); + + AuthNumber authNumber = AuthNumber.builder() + .phoneNum(targetNumber) + .authNumTime(LocalDateTime.now()) + .authNum(Integer.valueOf(randomNumber)) + .build(); + + authNumberRepository.deleteByPhoneNum(targetNumber); + authNumberRepository.save(authNumber); + + return randomNumber; + } + + @Override + public String getRandomNumber() { + return RandomStringUtils.randomNumeric(6); + } +} diff --git a/src/main/java/zipdabang/server/web/controller/MemberRestController.java b/src/main/java/zipdabang/server/web/controller/MemberRestController.java index 490d205..0190356 100644 --- a/src/main/java/zipdabang/server/web/controller/MemberRestController.java +++ b/src/main/java/zipdabang/server/web/controller/MemberRestController.java @@ -1,5 +1,6 @@ package zipdabang.server.web.controller; +import com.fasterxml.jackson.core.JsonProcessingException; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -16,6 +17,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.RestClientException; import zipdabang.server.FeignClient.service.KakaoOauthService; import zipdabang.server.auth.handler.annotation.AuthMember; import zipdabang.server.base.Code; @@ -26,6 +28,7 @@ import zipdabang.server.redis.domain.RefreshToken; import zipdabang.server.redis.service.RedisService; import zipdabang.server.service.MemberService; +import zipdabang.server.sms.service.SmsService; import zipdabang.server.utils.dto.OAuthJoin; import zipdabang.server.web.dto.requestDto.MemberRequestDto; import zipdabang.server.web.dto.responseDto.MemberResponseDto; @@ -34,6 +37,10 @@ import zipdabang.server.sms.dto.SmsResponseDto; import zipdabang.server.utils.dto.OAuthResult; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Optional; @@ -45,6 +52,7 @@ public class MemberRestController { private final MemberService memberService; + private final SmsService smsService; private final KakaoOauthService kakaoOauthService; @@ -122,14 +130,33 @@ public ResponseDto memberInfoForSignUp(@Request } //인증번호 요청 + @Operation(summary = "🎪figma[회원가입 까지 페이지 - 회원정보 입력] 인증번호 요청 API ✔️️", description = "인증번호 요청 API입니다. 대시(-) 제외 전화번호 입력하시면 됩니다. ex) 01012345678 ") + @ApiResponses({ + @ApiResponse(responseCode = "2000",description = "OK 성공 , 인증번호 전송 완료"), + @ApiResponse(responseCode = "2020",description = "OK 성공 , 이미 회원가입된 전화번호입니다."), + @ApiResponse(responseCode = "5000",description = "SERVER ERROR, 백앤드 개발자에게 알려주세요",content = @Content(schema = @Schema(implementation = ResponseDto.class))), + }) @PostMapping("/members/phone/sms") - public ResponseDto sendSms(@RequestBody MemberRequestDto.SmsRequestDto request) { - return null; + public ResponseDto sendSms(@RequestBody MemberRequestDto.SmsRequestDto request) throws JsonProcessingException, RestClientException, URISyntaxException, InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { + memberService.existByPhoneNumber(request.getTargetPhoneNum()); + smsService.sendSms(request.getTargetPhoneNum()); + return ResponseDto.empty(); } //인증번호 검증 + @Operation(summary = "🎪figma[회원가입 까지 페이지 - 회원정보 입력] 인증번호 검증 API ✔️️", description = "인증번호 검증 API입니다. 대시(-) 제외 전화번호와 인증번호 입력하시면 됩니다.") + @ApiResponses({ + @ApiResponse(responseCode = "2000",description = "OK 성공 , 인증 성공"), + @ApiResponse(responseCode = "4200",description = "BAD_REQUEST , 전화번호를 잘못 전달했거나, 인증요청을 하지않은 상태로 확인버튼을 누른 경우"), + @ApiResponse(responseCode = "4201",description = "BAD_REQUEST, 인증 번호가 옳지 않습니다."), + @ApiResponse(responseCode = "4202",description = "BAD_REQUEST, 인증 시간(5분)이 지난 경우"), + @ApiResponse(responseCode = "5000",description = "SERVER ERROR, 백앤드 개발자에게 알려주세요",content = @Content(schema = @Schema(implementation = ResponseDto.class))) + }) @PostMapping("/members/phone/auth") - public ResponseDto authPhoneNum(@RequestBody MemberRequestDto.PhoneNumAuthDto request) {return null;} + public ResponseDto authPhoneNum(@RequestBody MemberRequestDto.PhoneNumAuthDto request) { + SmsResponseDto.AuthNumResultDto authNumResultDto = smsService.authNumber(request.getAuthNum(), request.getPhoneNum()); + return ResponseDto.of(authNumResultDto); + } //프로필 수정 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 28224f3..0850dc2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -11,17 +11,17 @@ spring: ansi: enabled: always -## # local redis + # local redis # redis: # host:localhost redis: host: zipdabang-redis.osattk.ng.0001.apn2.cache.amazonaws.com - # batch: - # jdbc: - # initialize-schema: always - # job: - # names: myJob + batch: + jdbc: + initialize-schema: always + job: + names: myJob jpa: properties: hibernate: @@ -76,3 +76,9 @@ jwt: authorities-key: ${JWT_AUTHORITIES_KEY} access-token-validity-in-seconds: 1210000000 # 30 m refresh-token-validity-in-seconds: 1210000000 # 14 d + +naver-sms: + accessKey: ${NAVER_SMS_ACCESSKEY} + secretKey: ${NAVER_SMS_SECRET} + serviceId: ${NAVER_SMS_SERVICEID} + senderPhone: ${NAVER_SMS_PHONE} \ No newline at end of file