"""알림톡 대행사 계약은 여기 한 곳에만 둔다. 승인 URL·전화번호·응답 원문을 로깅하지 않는다.""" import hashlib import hmac from config import social_config as config import secrets from datetime import datetime, timezone def is_configured(): return all( config.get(k) for k in ( "ALIMTALK_API_KEY", "ALIMTALK_API_SECRET", "ALIMTALK_PROFILE_ID", "ALIMTALK_SENDER", "ALIMTALK_TEMPLATE_CODE", ) ) async def send(to, template_code, variables, *, client): date = datetime.now(timezone.utc).isoformat() salt = secrets.token_hex(16) signature = hmac.new( config.required("ALIMTALK_API_SECRET").encode(), (date + salt).encode(), hashlib.sha256, ).hexdigest() res = await client.post( "https://api.solapi.com/messages/v4/send-many/detail", headers={ "Authorization": f"HMAC-SHA256 apiKey={config.required('ALIMTALK_API_KEY')}, date={date}, salt={salt}, signature={signature}" }, json={ "messages": [ { "to": to, "from": config.required("ALIMTALK_SENDER"), "type": "ATA", "kakaoOptions": { "pfId": config.required("ALIMTALK_PROFILE_ID"), "templateId": template_code, "variables": variables, "disableSms": True, }, } ], "allowDuplicates": False, }, ) if res.status_code not in (200, 201): raise RuntimeError("ALIMTALK_SEND_FAILED") data = res.json() if data.get("failedMessageList") or not data.get("groupInfo"): raise RuntimeError("ALIMTALK_SEND_FAILED")