From 362b6b60d4902d8256fb35f37e53627b739fd03d Mon Sep 17 00:00:00 2001 From: kyy Date: Tue, 6 Jan 2026 15:02:44 +0900 Subject: [PATCH] =?UTF-8?q?SMS=20=EA=B8=B0=EB=8A=A5=20=EC=97=B0=EB=8F=99?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.sample | 6 +++ docker-compose.yaml | 2 + test/test_sms.py | 110 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 test/test_sms.py diff --git a/.env.sample b/.env.sample index ce5855f6..f6f7af07 100644 --- a/.env.sample +++ b/.env.sample @@ -25,3 +25,9 @@ COOKIE_SECRET=super-secret-key-must-be-32-bytes! # --- Frontend Configuration --- # Descope Project ID (Required for Auth) DESCOPE_PROJECT_ID=P2t...your_descope_project_id + +# --- Naver Cloud Services --- +NAVER_CLOUD_ACCESS_KEY=ncp_iam_... +NAVER_CLOUD_SECRET_KEY=ncp_iam_... +NAVER_CLOUD_SERVICE_ID=ncp:sms:kr:...:... +NAVER_SENDER_PHONE_NUMBER=... diff --git a/docker-compose.yaml b/docker-compose.yaml index c086d936..2ad152a8 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -6,6 +6,8 @@ services: context: ./backend dockerfile: Dockerfile container_name: baron_backend + env_file: + - .env environment: - APP_ENV=${APP_ENV:-development} - COOKIE_SECRET=${COOKIE_SECRET} diff --git a/test/test_sms.py b/test/test_sms.py new file mode 100644 index 00000000..3ce0c0bb --- /dev/null +++ b/test/test_sms.py @@ -0,0 +1,110 @@ +# python3 test/test_sms.py 01027774695 +import os +import requests +import time +import hmac +import hashlib +import base64 +import json +import sys +from dotenv import load_dotenv + +def get_env_variable(key, env_file): + """Reads an environment variable from a given .env file.""" + with open(env_file, 'r') as f: + for line in f: + line = line.strip() + if line and not line.startswith('#'): + k, v = line.split('=', 1) + if k == key: + return v.strip() + return None + +def main(): + if len(sys.argv) < 2: + print("Usage: python test/test_sms.py ") + sys.exit(1) + + recipient_phone = sys.argv[1] + + # Load environment variables from .env or .env.sample + env_path = os.path.join(os.getcwd(), '.env') + if not os.path.exists(env_path): + print("Info: .env file not found. Using .env.sample as a fallback.") + env_path = os.path.join(os.getcwd(), '.env.sample') + + if not os.path.exists(env_path): + print("Error: No configuration file found (.env or .env.sample).") + sys.exit(1) + + access_key = get_env_variable("NAVER_CLOUD_ACCESS_KEY", env_path) + secret_key = get_env_variable("NAVER_CLOUD_SECRET_KEY", env_path) + service_id = get_env_variable("NAVER_CLOUD_SERVICE_ID", env_path) + sender_phone = get_env_variable("NAVER_SENDER_PHONE_NUMBER", env_path) + + if not all([access_key, secret_key, service_id, sender_phone]): + print(f"Error: One or more required environment variables are missing in {env_path}.") + sys.exit(1) + + timestamp = str(int(time.time() * 1000)) + api_path = f"/sms/v2/services/{service_id}/messages" + api_url = f"https://sens.apigw.ntruss.com{api_path}" + + # Create the signature for the API request + message = f"POST {api_path}\n{timestamp}\n{access_key}" + h = hmac.new(bytes(secret_key, 'UTF-8'), bytes(message, 'UTF-8'), hashlib.sha256) + signature = base64.b64encode(h.digest()).decode('UTF-8') + + # Construct the JSON request body + json_body = { + "type": "SMS", + "contentType": "COMM", + "countryCode": "82", + "from": sender_phone, + "content": "[Baron SSO] Test message from Python script.", + "messages": [ + { + "to": recipient_phone + } + ] + } + + 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": signature + } + + print("========================================") + print(" Attempting to send SMS via SENS API (Python)") + print("========================================") + print(f" Recipient: {recipient_phone}") + print(f" Timestamp: {timestamp}") + print(f" Service ID: {service_id}") + print("========================================") + print() + + try: + response = requests.post(api_url, headers=headers, json=json_body) + response.raise_for_status() # Raise an exception for HTTP errors + print("API Response:") + print(json.dumps(response.json(), indent=2, ensure_ascii=False)) + except requests.exceptions.RequestException as e: + print(f"Request failed: {e}") + if hasattr(e, 'response') and e.response is not None: + print("API Error Response:") + try: + print(json.dumps(e.response.json(), indent=2, ensure_ascii=False)) + except json.JSONDecodeError: + print(e.response.text) + except Exception as e: + print(f"An unexpected error occurred: {e}") + + print() + print("========================================") + print(" Request complete.") + print("========================================") + +if __name__ == "__main__": + main()