uap_message_service.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. """
  2. 统一登录平台 (UAP) 消息推送服务
  3. 用于向运维人员发送设备自检等通知消息
  4. """
  5. import hmac
  6. import hashlib
  7. import time
  8. from typing import List
  9. import requests
  10. from utils.logger_config import logger
  11. # 复用 auth 中的 SSO 配置
  12. from api.auth import SSO_APP_ID, SSO_APP_SECRET
  13. UAP_MESSAGES_URL = 'https://api.hnyunzhu.com/api/v1/messages/'
  14. # 运维人员账号列表(统一登录平台 app_user_id)
  15. OPS_USER_IDS: List[str] = ['liuq', 'longb']
  16. # 自检页面链接(生产环境需配置为实际域名)
  17. SELF_CHECK_BASE_URL = 'http://api.ygtxfj.com:8169'
  18. def _generate_signature(secret: str, params: dict) -> str:
  19. """生成 HMAC-SHA256 签名(与 auth 中规则一致)"""
  20. data = {k: v for k, v in params.items() if k != "sign" and v is not None}
  21. sorted_keys = sorted(data.keys())
  22. query_string = "&".join([f"{k}={data[k]}" for k in sorted_keys])
  23. return hmac.new(
  24. secret.encode('utf-8'),
  25. query_string.encode('utf-8'),
  26. hashlib.sha256
  27. ).hexdigest()
  28. def send_self_check_notification(content: str, target_url: str = None) -> None:
  29. """
  30. 向运维人员发送自检通知消息
  31. :param content: 消息内容(如:总设备数 X,在线 Y,离线 Z)
  32. :param target_url: 点击跳转地址,默认 /self_check
  33. """
  34. if target_url is None:
  35. target_url = f"{SELF_CHECK_BASE_URL}/self_check"
  36. timestamp = int(time.time())
  37. params = {"app_id": SSO_APP_ID, "timestamp": timestamp}
  38. sign = _generate_signature(SSO_APP_SECRET, params)
  39. headers = {
  40. "Content-Type": "application/json",
  41. "X-App-Id": SSO_APP_ID,
  42. "X-Timestamp": str(timestamp),
  43. "X-Sign": sign,
  44. }
  45. payload = {
  46. "app_id": SSO_APP_ID,
  47. "type": "NOTIFICATION",
  48. "content_type": "TEXT",
  49. "title": "韫珠展厅设备每日自检信息",
  50. "content": content,
  51. "auto_sso": True,
  52. "target_url": target_url,
  53. "action_text": "前往查看",
  54. }
  55. for app_user_id in OPS_USER_IDS:
  56. try:
  57. body = {**payload, "app_user_id": app_user_id}
  58. resp = requests.post(UAP_MESSAGES_URL, json=body, headers=headers, timeout=10)
  59. if resp.ok:
  60. logger.info(f"[UAP] 自检通知已发送至 {app_user_id}")
  61. else:
  62. logger.warning(f"[UAP] 发送通知失败 {app_user_id}: status={resp.status_code}, body={resp.text}")
  63. except Exception as e:
  64. logger.error(f"[UAP] 发送通知异常 {app_user_id}: {e}")