본문 바로가기

& 프로그래밍/& API

SMS Api를 활용하여 웹에서 SMS 발신하기_2탄

자, 이전 시간에 네이버클라우드 플랫폼을 이용하여 계정과 프로젝트를 생성하였고, API를 사용하기 위한 사전 작업들을 모두 마쳤다

 

이번에는 실제 API 소스코드를 가져와서 반영해보도록 하자

내가 직접 작성한 코드가 아니라, 이미 네이버에서 공개해놓은 API 가이드라인을 참고해서 작성한거라는 점

그러니 더 정확한 정보가 필요한 사람은 이곳을 참고하시길

 

참고로 나는 VScode와 Python, Flask를 활용하였다

Config.ini파일 생성

사실 Config.ini파일은 필수는 아니지만 Access Key, Secret Key등이 소스코드에 바로 노출되는 부분을 방지하기 위해 별도에 파일로 관리한다고 생각하면 된다

[server]
server_ip = 0.0.0.0 #로컬호스트에서 실행하기 위해 0.0.0.0으로 설정
server_port = 9000 # 포트번호
[sms]
sms_url = https://sens.apigw.ntruss.com 
sms_access_key = 발급받은 Access Key
sms_secret_key = 발급받은 Secret Key
sms_uri = /sms/v2/services/서비스ID/messages
sms_type = SMS # 발신타입 sms, lms가 있다
sms_from_countryCode = 82 # 국가번호(옵션)
sms_from_number = 발신번호
sms_to_number = 수신번호

간단하게 살펴보자면,

(필수)sms_url : Api 접속 주소를 입력하면 된다. 이미 가이드라인에 나와있기에 그대로 넣으면 된다

(필수)sms_access_key = 이전 포스팅에서 API 인증키를 발급받은적이 있다. 해당 값을 넣으면 된다

(필수)sms_secret_key = access key와 마찬가지로 해당 값을 복붙하면 된다

(필수)sms_uri = 콘솔에서 프로젝트를 생성하고 우측에 서비스ID가 있었다. 해당 값을 넣으면 된다

(필수)sms_type = 메세지 타입으로 단문sms, 장문lms, 미디어mms를 지원한다

(옵션)sms_from_countryCode = 국가번호를 입력하면 된다. 우리나라는 82

(필수)sms_from_number = 네이버 플랫폼에 등록된 발신번호를 입력한다.(미등록시 발신 불가)

(필수)sms_to_number = 수신자 번호를 입력한다. 사실 이벤트 발생때마다 수신자가 변경되니 여기서 굳이 작성하지 않아도 된다

 

main 소스코드 작성

Config파일이 구성이 완료 되었으니 메인 소스코드를 작성해보도록 하자

 

1. 먼저 Flask와 소스코드 구성에 필요한 객체들을 import 해준다

# main.py

from flask import Flask, request
from flask_restx import Api, Resource
import time, requests, hmac, socket, configparser, base64, hashlib, json

2. Config파일 연동시켜주기

소스코드에 앞서 작성한 config 정보들을 전역변수로 지정해주는 작업을 한다.

수시로 사용되는 정보이면서 인증키, 암호 등 민감한 정보들이 들어있기에 별도로 보관하되, 쉽게 사용할 수 있도록 한거다

# main.py 

config = configparser.ConfigParser()
config.read('config.ini')

sms_url = config['sms']['sms_url']
sms_access_key = config['sms']['sms_access_key']
sms_secret_key = config['sms']['sms_secret_key']
sms_uri = config['sms']['sms_uri']
sms_type = config['sms']['sms_type']
sms_from_countryCode = config['sms']['sms_from_countryCode']
sms_from_number = config['sms']['sms_from_number']
sms_to_number = config['sms']['sms_to_number']

timestamp = str(int(time.time() * 1000))

3. Api를 인증하는 함수 만들기

Api를 접속하려면 정해진 규정에 맞춰 인증정보를 발신해야 한다.

내가 발신하려는 sms 정보에 인증정보를 담아서 날려야 하기에 함수로 구성해서 작성해준다

def make_signature():
  secret_key = bytes(sms_secret_key, 'UTF-8')
  method = "POST"
  message = method + " " + sms_uri + "\n" + timestamp + "\n" + sms_access_key
  message = bytes(message, 'UTF-8')
  signingKey = base64.b64encode(hmac.new(secret_key, message, digestmod=hashlib.sha256).digest())
  return signingKey

참고로 위 함수 내용 또한 api 가이드라인에 맞춰서 작성한 것이므로 구성요소가 변하면 안된다.

 

4. 실제 sms 발신을 위한 함수 만들기

지금까지 작성한 소스코드는 이제 작성할 코드를 뒷받침 해주는 초석과 같은 녀석들이었다.

지금 작성하는 이녀석이 실제 발신에 필요한 핵심 정보들이 담겨있는 부분이다.

def send_sms():
  api_url = sms_url + sms_uri
  access_key = sms_access_key
  phone_num = "메세지 받을사람 전화번호"  
  
  headers = {
    'Content-Type': 'application/json; charset=UTF-8',
    'x-ncp-apigw-timestamp': timestamp,
    'x-ncp-iam-access-key': access_key,
    'x-ncp-apigw-signature-v2': make_signature()
  }
  
  body = {
    "type" : "SMS",
    "from" : sms_from_number,
    "content" : "테스트 메세지 입니다.",
    "messages" : [{"to" : phone_num}]
  }
  
  body = json.dumps(body)
  
  response = requests.post(api_url, headers=headers, data=body)
  response.raise_for_status()

자, 모든 소스코드가 작성되었고 이제 테스트만 하면 된다.

 

그.전.에!!!!

가장 중요한 정보!!!!

 

본인의 통신사 어플에 들어가서 '번호도용문자차단'서비스가 가입되어 있는지 확인하자

만약 가입이 되어있다면 반드시 해지해야만 APi에서 발신이 가능하다

실제로 나는 모든 api 소스코드를 정상적으로 작성했고, 콘솔에서는 정상적으로 api가 작동되었다고 나오는데 발신처리 부분에서 지속적으로 오류가 발생하였다

statusCode : '3018', statusName : 'fail', statusMessage : '기타오류'

이 오류 원인은 간단했다. 웹에서 내 번호를 통해 sms가 발신될 때, 번호가 도용된다라고 판단하고 통신사에서 무조건으로 차단을 해버리는 것이다. 따라서 해당 부가서비스를 해지하고 24시간 뒤에 재시도를 해보니 성공!

api를 통해 sms발신이 성공하면 네이버 콘솔에서도 위와 같이 내역을 조회할 수 있다

 

이로써 sms Api 기능 구현 성공!