백앤드 개발일지/웹, 백앤드

NAVER CLOUD PlATFORM[SENS API] - 네이버 문자 인증

giron 2021. 10. 17. 02:06
728x90

프로젝트를 진행하면서 휴대폰 인증 기능이 추가되어 과정을 기록할 겸 적어보겠다.

이용한 api는 네이버 클라우드에서 제공해주는 한 달에 50건 무료인 api를 사용했다. 

 https://www.ncloud.com

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

네이버 클라우드에 우선 가입을 해주고 콘솔에서 빨간 박스로 들어가 줍니다.

들어간 후 api 가이드에 따라 진행하면 수월하다.

친절하게 설명이 되어 있는데 설명에 따라 우선 프로젝트를 생성해 줍니다.

그 후 SMS를 눌러줍니다.

발신번호 등록을 해주고 간편하게 SMS 인증을 선택해 줍니다.

발신 번호 등록이 완료되면 위에 처럼 나옵니다! 이후 다시 작업하던 대로(Project-SMS-message) 돌아가 줍니다.

이제 Open API 가이드를 보고 따라 만들면 됩니다!

 

*accessKey, secretKey 발급받기

인증키 관리 -> 신규 API 인증키 생성-> 끝

x-ncp-iam-access-key

누르자마자 바로 생성되는데 여기서 AccessKeyId를 발급받습니다.

accessKey, secretKey, serviceId 필요한 정보를 다 얻었으니 이제 api 로직을 작성해 보겠습니다.

API 명세서

https://api.ncloud-docs.com/docs/ko/ai-application-service-sens-smsv2

 

SMS API - SENS

 

api.ncloud-docs.com

명세서가 잘 나와있어서 내용만 잘 기입하면 쉽게 구현할 수 있다. 참고로 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

 

NAVER Cloud Platform API - API 가이드

 

api.ncloud-docs.com

여기에 JAVA코드로 친절하게 다 나와있다. 

새벽 코딩..

포스트맨을 통한 확인

성공이다! 

참고로 api 명세에 Optional로 subject가 있어서 적용해봤는데 아무런 변화가 없었다. 그냥 내용만 적어주면 될 듯하다.

이유는 아무리 찾아봐도 안나와서 나중에 더 공부하면 찾아와서 적겠다 😂

728x90