pharmacy-pos-qr-system/backend/services/nhn_alimtalk.py
thug0bin e7c529c22c feat: 알림톡 MILEAGE_CLAIM_V3 템플릿 대응 + 구매품목 요약
- nhn_alimtalk.py: build_item_summary() 추가 ("타이레놀 외 3건" 형식)
- send_mileage_claim_alimtalk()에 items 파라미터 추가, V3 우선 시도
- app.py: kiosk_current_session 클리어 전 items 캡처 버그 수정
- NHN API에 MILEAGE_CLAIM_V3 템플릿 등록 (발송 근거 문구 포함)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 17:09:39 +09:00

128 lines
3.9 KiB
Python

"""
NHN Cloud 알림톡 발송 서비스
마일리지 적립 완료 등 알림톡 발송
"""
import os
import logging
from datetime import datetime, timezone, timedelta
import requests
logger = logging.getLogger(__name__)
# NHN Cloud 알림톡 설정
APPKEY = os.getenv('NHN_ALIMTALK_APPKEY', 'u0TLUaXXY9bfQFkY')
SECRET_KEY = os.getenv('NHN_ALIMTALK_SECRET', 'naraGEUJfpkRu1fgirKewJtwADqWQ5gY')
SENDER_KEY = os.getenv('NHN_ALIMTALK_SENDER', '341352077bce225195ccc2697fb449f723e70982')
API_BASE = f'https://api-alimtalk.cloud.toast.com/alimtalk/v2.3/appkeys/{APPKEY}'
# KST 타임존
KST = timezone(timedelta(hours=9))
def _send_alimtalk(template_code, recipient_no, template_params):
"""
알림톡 발송 공통 함수
Args:
template_code: 템플릿 코드
recipient_no: 수신 번호 (01012345678)
template_params: 템플릿 변수 딕셔너리
Returns:
tuple: (성공 여부, 메시지)
"""
url = f'{API_BASE}/messages'
headers = {
'Content-Type': 'application/json;charset=UTF-8',
'X-Secret-Key': SECRET_KEY
}
data = {
'senderKey': SENDER_KEY,
'templateCode': template_code,
'recipientList': [
{
'recipientNo': recipient_no,
'templateParameter': template_params
}
]
}
try:
resp = requests.post(url, headers=headers, json=data, timeout=10)
result = resp.json()
if resp.status_code == 200 and result.get('header', {}).get('isSuccessful'):
logger.info(f"알림톡 발송 성공: {template_code}{recipient_no}")
return (True, "발송 성공")
else:
error_msg = result.get('header', {}).get('resultMessage', str(result))
logger.warning(f"알림톡 발송 실패: {template_code}{recipient_no}: {error_msg}")
return (False, error_msg)
except requests.exceptions.Timeout:
logger.warning(f"알림톡 발송 타임아웃: {template_code}{recipient_no}")
return (False, "타임아웃")
except Exception as e:
logger.warning(f"알림톡 발송 오류: {template_code}{recipient_no}: {e}")
return (False, str(e))
def build_item_summary(items):
"""구매 품목 요약 문자열 생성 (예: '타이레놀 외 3건')"""
if not items:
return "약국 구매"
first = items[0]['name']
if len(first) > 20:
first = first[:18] + '..'
if len(items) == 1:
return first
return f"{first}{len(items) - 1}"
def send_mileage_claim_alimtalk(phone, name, points, balance, items=None):
"""
마일리지 적립 완료 알림톡 발송
Args:
phone: 수신 전화번호 (01012345678)
name: 고객명
points: 적립 포인트
balance: 적립 후 총 잔액
items: 구매 품목 리스트 [{'name': ..., 'qty': ..., 'total': ...}, ...]
Returns:
tuple: (성공 여부, 메시지)
"""
now_kst = datetime.now(KST).strftime('%Y-%m-%d %H:%M')
item_summary = build_item_summary(items)
# MILEAGE_CLAIM_V3 (발송 근거 + 구매품목 포함) 우선 시도
template_code = 'MILEAGE_CLAIM_V3'
params = {
'고객명': name,
'구매품목': item_summary,
'적립포인트': f'{points:,}',
'총잔액': f'{balance:,}',
'적립일시': now_kst,
'전화번호': phone
}
success, msg = _send_alimtalk(template_code, phone, params)
if not success:
# V3 실패 시 V2 폴백 (구매품목 변수 없는 버전)
template_code = 'MILEAGE_CLAIM_V2'
params_v2 = {
'고객명': name,
'적립포인트': f'{points:,}',
'총잔액': f'{balance:,}',
'적립일시': now_kst,
'전화번호': phone
}
success, msg = _send_alimtalk(template_code, phone, params_v2)
return (success, msg)