테니스장 회원 관리 시스템 개발 중,
비밀번호 재설정 기능 구현에 필요한 본인인증 코드 전송에 SMS 전송 기능을 사용하기로 했다.
비밀번호 재설정을 위해서만이라면, 이메일 전송을 사용하는 편이 더 쉬운 선택지였다.
과금될 걱정도 없고 이전에 사용해 본 방법이라 더 쉽게 느껴지기도 했다.
하지만 지금 문자 전송 기능을 구현해두면,
회원들의 수강 횟수가 다 소진된 후 재결제 문자 알림을 보내는 기능
을 이후에 추가할 때
구현해 둔 기능을 활용할 수 있을 것 같아 SMS 전송을 이용하는 방식을 선택했다.
네이버 클라우드 플랫폼의 Simple & Easy Notification Service를 사용하기로 했다.
네이버 클라우드 플랫폼 회원가입 후 아래 링크에서 서비스 이용 신청하기
🔗 www.ncloud.com/product/applicationService/sens
우측 상단 마이페이지
> 계정 관리
비밀번호 입력 후 인증키 관리
탭 진입 > 신규 API 인증키 생성
> key Access Key ID 와 Secret Key 복사해두기
콘솔 > Simple & Easy Notification Service
> SMS 메뉴
에서 프로젝트 생성하기
생성된 프로젝트의 서비스 ID 복사해두기
Simple & Easy Notification Service
> SMS
> Calling Number 메뉴
에서 발송할 때 사용할 번호 등록
번호 등록 방법에는 서류 등록과 본인인증 등록 2가지 방법이 있다.
일단 테스트를 위해 사용중인 개인 번호로 설정해두었다.
사전 작업 과정에서 따로 적어둔
Access Key ID
Secret Key
서비스 ID
를 이용해 코드를 작성해보았다.
서버 쪽 환경변수로 Access Key ID
Secret Key
서비스 ID
기록 및 사용 가능하도록 세팅
server/.env
server/config/config.js
const dotenv = require("dotenv");
dotenv.config();
function required(key, defaultValue = undefined) {
const value = process.env[key] || defaultValue;
if (value == null) {
throw new Error(`Key ${key} is undefined`);
}
return value;
}
module.exports = {
// ...
sens: {
accessKey: required("NCP_SENS_ACCESS"),
secretKey: required("NCP_SENS_SECRET"),
serviceId: required("NCP_SENS_ID"),
callNumber: required("NCP_SENS_NUMBER"),
},
};
server/controllers/.../util.js
const { sens } = require("../config");
module.exports = {
sendVerificationSMS: async (req, res) => {
// 환경 변수
const sens_service_id = sens.serviceId;
const sens_access_key = sens.accessKey;
const sens_secret_key = sens.secretKey;
const sens_call_number = sens.callNumber;
// ...
},
};
$ npm install crypto-js
server/controllers/.../util.js
const CryptoJS = require("crypto-js");
// ...
server/controllers/.../util.js
const { createRandomNumber } = require("./functions/utility");
const { sens } = require("../config");
const CryptoJS = require("crypto-js");
const axios = require("axios");
module.exports = {
sendVerificationSMS: async (req, res) => {
try {
const { tel } = req.body;
const user_phone_number = tel.split("-").join(""); // SMS를 수신할 전화번호
const verificationCode = createRandomNumber(6); // 인증 코드 (6자리 숫자)
const date = Date.now().toString(); // 날짜 string
// 환경 변수
const sens_service_id = sens.serviceId;
const sens_access_key = sens.accessKey;
const sens_secret_key = sens.secretKey;
const sens_call_number = sens.callNumber;
// url 관련 변수 선언
const method = "POST";
const space = " ";
const newLine = "\n";
const url = `https://sens.apigw.ntruss.com/sms/v2/services/${sens_service_id}/messages`;
const url2 = `/sms/v2/services/${sens_service_id}/messages`;
// signature 작성 : crypto-js 모듈을 이용하여 암호화
console.log(1);
const hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, sens_secret_key);
console.log(2);
hmac.update(method);
hmac.update(space);
hmac.update(url2);
hmac.update(newLine);
hmac.update(date);
hmac.update(newLine);
console.log(sens_access_key);
hmac.update(sens_access_key);
const hash = hmac.finalize();
console.log(4);
const signature = hash.toString(CryptoJS.enc.Base64);
console.log(5);
// sens 서버로 요청 전송
const smsRes = await axios({
method: method,
url: url,
headers: {
"Contenc-type": "application/json; charset=utf-8",
"x-ncp-iam-access-key": sens_access_key,
"x-ncp-apigw-timestamp": date
,
"x-ncp-apigw-signature-v2": signature,
},
data: {
type: "SMS",
countryCode: "82",
from: sens_call_number,
content: `인증번호는 [${verificationCode}] 입니다.`,
messages: [{ to: `${user_phone_number}` }],
},
});
console.log("response", smsRes.data);
return res.status(200).json({ message: "SMS sent" });
} catch (err) {
console.log(err);
return res.status(404).json({ message: "SMS not sent" });
}
},
};
server/router/util.js
const express = require("express");
const router = express.Router();
const { isAuth } = require("../middlewares");
const { sendVerificationSMS } = require("../controllers/util");
router.get("/message/code", isAuth, sendVerificationSMS);
module.exports = router;
request body의 tel 프로퍼티에 수신할 전화번호를 담아,
설정한 라우터의 엔드포인트로 POST 요청을 보냈더니 문자가 잘 수신되는 것을 확인할 수 있었다.
참고한 글
[Node.js] NCP SENS 문자 발송 API
[Node.js] 네이버 문자 전송 API 사용하기(feat. axios)