NAVER CLOUD PlATFORM[SENS API] - 네이버 문자 인증
프로젝트를 진행하면서 휴대폰 인증 기능이 추가되어 과정을 기록할 겸 적어보겠다.
이용한 api는 네이버 클라우드에서 제공해주는 한 달에 50건 무료인 api를 사용했다.
네이버 클라우드에 우선 가입을 해주고 콘솔에서 빨간 박스로 들어가 줍니다.
들어간 후 api 가이드에 따라 진행하면 수월하다.
친절하게 설명이 되어 있는데 설명에 따라 우선 프로젝트를 생성해 줍니다.
그 후 SMS를 눌러줍니다.
발신번호 등록을 해주고 간편하게 SMS 인증을 선택해 줍니다.
발신 번호 등록이 완료되면 위에 처럼 나옵니다! 이후 다시 작업하던 대로(Project-SMS-message) 돌아가 줍니다.
이제 Open API 가이드를 보고 따라 만들면 됩니다!
*accessKey, secretKey 발급받기
인증키 관리 -> 신규 API 인증키 생성-> 끝
누르자마자 바로 생성되는데 여기서 AccessKeyId를 발급받습니다.
accessKey, secretKey, serviceId 필요한 정보를 다 얻었으니 이제 api 로직을 작성해 보겠습니다.
API 명세서
https://api.ncloud-docs.com/docs/ko/ai-application-service-sens-smsv2
명세서가 잘 나와있어서 내용만 잘 기입하면 쉽게 구현할 수 있다. 참고로 secretKey가 project와 마이페이지에 총 2개 있어서 헷갈릴 수 있는데 명세서를 잘 읽어보면
마이페이지의 secretKey를 이용하면 된다.
MessageDto
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class MessagesDto {
private String to;
private String content;
}
SmsRequest
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class SmsRequest {
private String type;
private String contentType;
private String countryCode;
private String from;
private String content;
private List<MessagesDto> messages;
}
SmsResponse
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Getter
public class SmsResponse {
private String requestId;
private LocalDateTime requestTime;
private String statusCode;
private String statusName;
}
SmsService
@Service
@Transactional
public class SmsService {
@Value("${sms.serviceId}")
private String serviceId;
@Value("${sms.accessKey}")
private String accessKey;
@Value("${sms.secretKey}")
private String secretKey;
public SmsResponse sendSms(String recipientPhoneNumber, String content) throws JsonProcessingException, UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException, URISyntaxException {
Long time = System.currentTimeMillis();
List<MessagesDto> messages = new ArrayList<>();
messages.add(new MessagesDto(recipientPhoneNumber, content));
SmsRequest smsRequest = new SmsRequest("SMS", "COMM", "82", "발신자 전화번호", "내용", messages);
ObjectMapper objectMapper = new ObjectMapper();
String jsonBody = objectMapper.writeValueAsString(smsRequest);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("x-ncp-apigw-timestamp", time.toString());
headers.set("x-ncp-iam-access-key", this.accessKey);
String sig = makeSignature(time); //암호화
headers.set("x-ncp-apigw-signature-v2", sig);
HttpEntity<String> body = new HttpEntity<>(jsonBody,headers);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
SmsResponse smsResponse = restTemplate.postForObject(new URI("https://sens.apigw.ntruss.com/sms/v2/services/"+this.serviceId+"/messages"), body, SmsResponse.class);
return smsResponse;
}
public String makeSignature(Long time) throws UnsupportedEncodingException, NoSuchAlgorithmException, 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;
}
}
SmsController
@RestController
@RequiredArgsConstructor
public class SmsController {
private final SmsService smsService;
@PostMapping("/user/sms")
public ResponseEntity<SmsResponse> test(@RequestBody Request request) throws NoSuchAlgorithmException, URISyntaxException, UnsupportedEncodingException, InvalidKeyException, JsonProcessingException {
SmsResponse data = smsService.sendSms(request.getRecipientPhoneNumber(), request.getContent());
return ResponseEntity.ok().body(data);
}
}
Request
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
public class Request {
private String recipientPhoneNumber;
private String title;
private String content;
}
네이버 클라우드 API 호출 방식
https://api.ncloud-docs.com/docs/common-ncpapi
여기에 JAVA코드로 친절하게 다 나와있다.
포스트맨을 통한 확인
성공이다!
참고로 api 명세에 Optional로 subject가 있어서 적용해봤는데 아무런 변화가 없었다. 그냥 내용만 적어주면 될 듯하다.
이유는 아무리 찾아봐도 안나와서 나중에 더 공부하면 찾아와서 적겠다 😂