네이버 sens API

이경택·2023년 6월 20일

백엔드

목록 보기
2/5

sens api 문자 메시지를 통한 휴대폰 번호 검증

회원 가입 시 핸드폰 번호 검증을 위해 네이버의 sens api (문자 보내주는 api)를 사용하기로 했다.

한 달 50건 까지 무료라 문자 테스트 하기에는 딱 좋았다.

개요 사진

사용 방법

  1. 시그니처 생성

    시그니처란?

    • Body를 Access Key ID와 맵핑되는 Secret Key로 암호화한 서명값
    • HMAC 암호화 알고리즘은 HmacSHA256 사용
  • 시그니처 생성 방법
    export class AuthService {
      constructor() {}
    
    	private makeSignature(): string {
    	    const space = ' ';
    	    const newLine = '\n';
    	    const method = 'POST';
    	    const timeStamp = Date.now().toString();
    			// url은 https://sens.apigw.ntruss.com 뺀 뒤 부분 
    	    const url = this.configService.get('NCP_URL');
    			// 시크릿 키는 계정 관리의 인증키 관리의 secret 키
    	    const secret = this.configService.get('NCP_SECRET_KEY');
    	
    	    const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, secret);
    	
    	    hmac.update(method);
    	    hmac.update(space);
    	    hmac.update(url);
    	    hmac.update(newLine);
    	    hmac.update(timeStamp);
    	    hmac.update(newLine);
    			// 액세스 키는 정 관리의 인증키 관리의 access key id
    	    hmac.update(this.configService.get('NCP_ACCESS_KEY'));
    	    const hash = hmac.finalize();
    	    return hash.toString(CryptoJS.enc.Base64);
    	  }
    // WTPItrmMIfLUk/UyUIyoQbA/z5hq9o3G8eQMolUzTEa= 이런 암호화된 값이 나옴
  1. api header, body를 채워서 url 로 요청하기
    • API Header
      headers: {
              'Content-Type': 'application/json; charset=utf-8',
              'x-ncp-iam-access-key': this.configService.get('NCP_ACCESS_KEY'),
              'x-ncp-apigw-timestamp': Date.now().toString(),
      				// 시그니처 만든 함수 호출로 string화 된 시그니처 주입
              'x-ncp-apigw-signature-v2': this.makeSignature(),
            },
    • Body
      const body = {
            type: 'SMS',
      			// 일반 문자는 'COMM', 광고성 문자는 'AD'
            contentType: 'COMM',
      			// 보낼 전화번호 (네이버 sens api 등록할 때 번호여야 함.)
            from: this.configService.get('HOST_PHONE_NUMBER'),
      			// 보낼 문자 메시지
            content: `인증번호 [${verifyCode}]를 입력 해주세요.`,
            messages: [
              {
                to: phoneNumber,
              },
            ],
          };
      
      // 인증번호를 만들기 위해 for문 및 랜덤 숫자 생성
      let verifyCode = '';
      for (let i = 1; i < 7; i++) {
        verifyCode += Number(Math.random() * 10).toFixed(0);
      }
  2. 요청
try {
      const res = await axios.post(
        this.configService.get('NCP_URI'),
        body,
        options,
      );
    } catch (error) {
      throw new InternalServerErrorException('서버 에러');
    }
  1. 보낸 인증번호 캐시 저장 후 유저가 입력하는 인증번호와 비교 로직

위의 요청 후 await this.cacheManager.set(phoneNumber, verifyCode, 180000); 로 nest가 제공하는 인메모리 캐시에 저장

async checkSMS({ phoneNumber, verifyCode }) {
    const cacheVerifyNum = await this.cacheManager.get(phoneNumber);
    if (!cacheVerifyNum) {
      throw new Error('인증 번호가 만료되었습니다');
    } else if (cacheVerifyNum === verifyCode) {
      return true;
    } else {
      throw new UnauthorizedException('인증 번호가 일치하지 않습니다');
    }
  }

cacheManager 를 사용하기 위해 constructor 및 module 파일에 등록해 줘야 한다.

// auth.service.ts
@Injectable()
@UseInterceptors(CacheInterceptor)
export class AuthService {
  constructor(
    private userRepository: UserRepository,
    private jwtService: JwtService,
    private configService: ConfigService,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
  ) {}

// auth.module.ts
CacheModule.register({ ttl: 만료시간(milliseconds), max: 캐시에 저장할 아이템 개수(number)}),
profile
한 줄로 소개 할 수 없는 개발자

0개의 댓글