예전에 친구 부탁으로 한 번 사용한 적이 있는 데 이번에 회사에 적용하게 되면서 다시 정리한다
- 일단 NAVER CLOUD에서 계정 생성을 한다.
- 계정을 생성했으면 나중에 API 사용에 필요한 인증키를 확인해야 하는 데 나는 여기서 가장 헤맸다 왜냐하면 나는 아무리 찾아도 마이페이지에 계정관리 밑에 인증키 관리 메뉴가 보이지 않았기 때문이다. 무조건 마이페이지 -> 결제관리 -> 결제수단 관리 메뉴에서 결제수단 등록을 해야한다. 그렇지 않으면 콘솔에 이동했을때도 안보이는 서비스가 많다. 이게 당연할 수도 있지만 아무도 말해주지 않아서 난 정말 몇시간을 헤맸다...
- 결제수단 등록 후 다시 마이페이지 -> 계정관리 -> 인증키 관리 메뉴로 이동해서 신규 API 인증키 생성 버튼을 눌러 키를 발급 받는다.
- 키를 발급 후 페이지 오른쪽 상단에 콘솔로 이동해 service메뉴에서 Application Service에 속해있는 Simple&Easy Notification Service로 이동한다.
- 이동 후 좌측상단 프로젝트 생성하기를 눌러 프로젝트를 용도에 맞게 생성한다.
- 프로젝트를 생성했다면 SMS 메뉴로 이동 후 메세지 발송시 사용할 발신번호를 등록한다.
- 이제 API를 사용하기 전 준비는 끝났다. Message 메뉴로 이동해 미리 발송이 잘 되는지 테스트를 해봐도 좋고 바로 API를 사용하고자 한다면 상단의 OPEN API 가이드 버튼을 눌러준다 OPEN API LINK
- 문서로 이동했다면 API Header부분이 나올텐데 여기서 가장 처음에 어려운 것이 signature부분이다 Signature 생성 관련 공식문서 여기로 이동하면 언어별 signature 생성 코드가 친절하게 나와있는데 직접 이해해 보길 바란다. 여기서 사용되는 SecretKey는 처음 메인 페이지에서 인증키 관리에서 발급한 SecretKey를 사용한다.
- 이제 공식문서를 천천히 읽어보며 자신에 맞게 작성하면 된다. signature 부분을 제외한다면 그렇게 크게 어렵지는 않은 API니 직접 한 번 구현 해보시길 바란다.
나의 코드
import { BadRequestException, Injectable } from "@nestjs/common";
import * as crypto from "crypto";
import axios from "axios";
import { CreateSmsBodyDto } from "./dto/createSmsBody.dto";
import { CreateSmsDto } from "./dto/createSms.dto";
import { LoggerService } from "src/global/log/logger";
@Injectable()
export class SmsService {
secretKey: string = process.env.SECRET_KEY;
accessKey: string = process.env.ACCESS_KEY;
// 아까 발신번호 등록한 번호를 넣어야 한다.
phoneNumber: string = process.env.PHONE_NUMBER;
serviceId: string = process.env.SERVICE_ID;
// 헤더에 적용할 timestamp 값 생성
timestamp = Date.now().toString();
constructor(private readonly logger: LoggerService) {}
// 헤더에 적용할 signature 값 생성
// 스타일에 따라 사용하는 방식이 달라 다른 방식으로도 작성가능
makeSignature = (): string => {
const hmac = crypto
.createHmac("sha256", this.secretKey)
.update(`POST /sms/v2/services/${this.serviceId}/messages\n`)
.update(`${this.timestamp}\n`)
.update(`${this.accessKey}`);
return hmac.digest("base64").toString();
};
// 문자 발송시 보낼 암호생성 코드
makeRanNum = (): number => {
const randNum = Math.floor(Math.random() * 1000000);
return randNum;
};
// 실제 문자를 발송하는 로직
async create(createSmsDto: CreateSmsDto) {
const { to } = createSmsDto;
const checkNumber: string = this.makeRanNum()
.toString()
.substring(4, 0);
const doneSignature: string = this.makeSignature();
const body: CreateSmsBodyDto = {
type: "SMS",
contentType: "COMM",
countryCode: "82",
from: this.phoneNumber,
content: `[코딩보따리] 인증번호 [${checkNumber}]입니다.`,
messages: [
{
to: to
}
]
};
const headers = {
"Content-Type": "application/json; charset=utf-8",
"x-ncp-apigw-timestamp": this.timestamp,
"x-ncp-iam-access-key": this.accessKey,
"x-ncp-apigw-signature-v2": doneSignature
};
const url: string = `https://sens.apigw.ntruss.com/sms/v2/services/${this.serviceId}/messages`;
await axios
.post(url, body, { headers })
.then((res) => {
console.log("succeed");
})
.catch((e) => {
this.logger.customLog(e.response.data);
throw new BadRequestException("문자요청이 실패했습니다.");
});
return { message: "succeed", checkNum: checkNumber };
}
}
처음 SMS 서비스를 도입하는 분들에게 많은 도움을 되길 바라며 DTO에 들어갈 값이나 코드를 보며 무슨 값인지 모르겠는것들은 OPEN API LINK에 충분히 설명되어 있을테니 확인해보시길 바라며 직접 본인 스타일에 맞게 구현도 한 번 해보길 추천한다!!
'개발 > NestJS' 카테고리의 다른 글
[NestJS] CORS 설정과 주의할 점(preflight) (0) | 2022.11.26 |
---|---|
[NestJs] 순환 종속성(Circular Dependency) 에러 (0) | 2022.10.23 |
TypeError: Class extends value undefined is not a constructor or null (0) | 2022.09.27 |
npm install vs npm ci (0) | 2022.09.21 |
[NestJs] Serialization! (0) | 2022.07.16 |
댓글