diff --git a/src/main/java/com/backend/config/SecurityConfig.java b/src/main/java/com/backend/config/SecurityConfig.java index b1f925e..d249ed9 100644 --- a/src/main/java/com/backend/config/SecurityConfig.java +++ b/src/main/java/com/backend/config/SecurityConfig.java @@ -62,6 +62,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers(mvcMatcherBuilder.pattern("/api/**")).permitAll() .requestMatchers(mvcMatcherBuilder.pattern("/mail/**")).permitAll() .requestMatchers(mvcMatcherBuilder.pattern("/s3/create")).permitAll() + .requestMatchers(mvcMatcherBuilder.pattern("/sms")).permitAll() .anyRequest().authenticated()) .exceptionHandling() .authenticationEntryPoint(entryPoint); diff --git a/src/main/java/com/backend/domain/mail/controller/MailController.java b/src/main/java/com/backend/domain/mail/controller/MailController.java index dbd7dae..5ec9015 100644 --- a/src/main/java/com/backend/domain/mail/controller/MailController.java +++ b/src/main/java/com/backend/domain/mail/controller/MailController.java @@ -1,14 +1,16 @@ package com.backend.domain.mail.controller; import com.backend.domain.mail.dto.request.MailRequest; +import com.backend.domain.mail.dto.request.SmsRequest; import com.backend.domain.mail.service.MailService; +import com.backend.error.ErrorCode; +import com.backend.error.exception.custom.BusinessException; +import io.github.resilience4j.ratelimiter.annotation.RateLimiter; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; -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.bind.annotation.*; @RestController @RequiredArgsConstructor @@ -21,4 +23,17 @@ public class MailController { public ResponseEntity sendCode(@Valid @RequestBody MailRequest emailRequest) { return ResponseEntity.ok(mailService.sendAuthenticationCode(emailRequest)); } + + @RateLimiter(name = "jedero", fallbackMethod = "rateLimiterFallback") + @GetMapping("/sms") + public ResponseEntity sendSMS(@Valid @RequestBody SmsRequest smsRequest) { + int result = mailService.sendSMS(smsRequest); + return ResponseEntity.ok(result); + } + + public ResponseEntity rateLimiterFallback(Throwable t) { +// HttpHeaders responseHeaders = new HttpHeaders(); +// responseHeaders.set("Retry-After", "10s"); + throw new BusinessException(ErrorCode.TOO_MANY_SMS); + } } \ No newline at end of file diff --git a/src/main/java/com/backend/domain/mail/dto/request/SmsRequest.java b/src/main/java/com/backend/domain/mail/dto/request/SmsRequest.java new file mode 100644 index 0000000..09e3768 --- /dev/null +++ b/src/main/java/com/backend/domain/mail/dto/request/SmsRequest.java @@ -0,0 +1,6 @@ +package com.backend.domain.mail.dto.request; + +import jakarta.validation.constraints.NotEmpty; + +public record SmsRequest(@NotEmpty String toNumber) { +} \ No newline at end of file diff --git a/src/main/java/com/backend/domain/mail/service/MailService.java b/src/main/java/com/backend/domain/mail/service/MailService.java index c178b3c..8a52347 100644 --- a/src/main/java/com/backend/domain/mail/service/MailService.java +++ b/src/main/java/com/backend/domain/mail/service/MailService.java @@ -1,21 +1,45 @@ package com.backend.domain.mail.service; import com.backend.domain.mail.dto.request.MailRequest; +import com.backend.domain.mail.dto.request.SmsRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +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.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.stereotype.Service; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + @Service @RequiredArgsConstructor @Slf4j public class MailService { + private final JavaMailSender javaMailSender; - @Value("{mail.mail.username}") + + private DefaultMessageService messageService; + + @Value("${spring.mail.username}") private String username; + @Value("${coolsms.api.key}") + private String apiKey; + + @Value("${coolsms.api.secret}") + private String apiSecret; + + @Value("${coolsms.api.fromNumber}") + private String fromNumber; + + public int sendAuthenticationCode(MailRequest mailRequest) { int code = (int) (Math.random() * 900000) + 100000; @@ -31,4 +55,23 @@ public int sendAuthenticationCode(MailRequest mailRequest) { return code; } -} + + public int sendSMS(SmsRequest smsRequest) { + Message message = new Message(); + this.messageService = NurigoApp.INSTANCE.initialize(apiKey, apiSecret, "https://api.coolsms.co.kr"); + + Random rand = new Random(); + String code = IntStream.range(0, 4) + .mapToObj(i -> Integer.toString(rand.nextInt(10))) + .collect(Collectors.joining()); + + message.setFrom(fromNumber); + message.setTo(smsRequest.toNumber()); + message.setText("[제대로] 인증번호를 입력해주세요.\n인증번호: " + code); + + SingleMessageSentResponse response = messageService.sendOne(new SingleMessageSendingRequest(message)); + log.info("SMS 메세지 결과 = {}", response); + + return Integer.parseInt(code); + } +} \ No newline at end of file diff --git a/src/main/java/com/backend/error/ErrorCode.java b/src/main/java/com/backend/error/ErrorCode.java index 5ee15b5..eaf3642 100644 --- a/src/main/java/com/backend/error/ErrorCode.java +++ b/src/main/java/com/backend/error/ErrorCode.java @@ -17,7 +17,8 @@ public enum ErrorCode { INVALID_GROUP_TYPE(BAD_REQUEST, "잘못된 그룹 종류입니다."), INVALID_PASSWORD(BAD_REQUEST, "잘못된 비밀번호입니다."), IMAGE_UPLOAD_FAIL(BAD_REQUEST, "이미지 업로드에 실패했습니다."), - INVALID_FILE(BAD_REQUEST, "잘못된 파일 형식입니다."); + INVALID_FILE(BAD_REQUEST, "잘못된 파일 형식입니다."), + TOO_MANY_SMS(TOO_MANY_REQUESTS, "짧은 시간에 너무 많은 요청을 보냈습니다. 1분 후에 재시도하세요."); private final int code; private final String message;