callbacktoSMS/README.md
2026-07-07 14:28:24 +08:00

5.0 KiB
Raw Blame History

回调告警转短信服务

本项目是一个 Python 后端服务,用于接收 AI 视频分析平台的 HTTP 回调,并将关键告警信息转为阿里云短信发送给手机号列表。

启动指令

pip install -r requirements.txt py -m uvicorn app.main:app --host 0.0.0.0 --port 2336

核心目标:

  1. 接收并解析上游回调 JSON。
  2. 生成短信模板变量 ACTION。
  3. 查询 SQLite 中已启用手机号并群发。
  4. 记录可追踪日志,返回标准化接口结果。

1. 功能概览

服务提供两个接口:

  1. GET /healthz健康检查。
  2. POST /callback接收告警回调并触发短信逻辑。

POST /callback 的处理流程:

  1. 解析 JSON支持常见编码容错
  2. 提取事件标识 event_id优先 snowflake_id其次 analysis_job_id
  3. 脱敏写日志(图片 base64、密钥等敏感字段不落盘
  4. 生成短信预览文本:发现有${ACTION}行为,请去摄像头查看。
  5. 查询 SQLite 中 is_enabled=1 的手机号。
  6. 根据 LOG_ONLY_NO_SMS 决定仅预览还是实际调用阿里云接口。
  7. 返回统一结构code、message、data。

2. 环境准备

在项目根目录执行:

pip install -r requirements.txt

推荐 Python 3.11+。

3. 配置说明

项目默认通过 .env 读取配置,主要参数如下:

  1. ALIBABA_CLOUD_ACCESS_KEY_ID阿里云 AK。
  2. ALIBABA_CLOUD_ACCESS_KEY_SECRET阿里云 SK。
  3. ALIBABA_CLOUD_REGION_ID区域默认 cn-hangzhou。
  4. ALIYUN_SMS_SIGN_NAME已审核通过的短信签名。
  5. ALIYUN_SMS_TEMPLATE_CODE短信模板编码。
  6. SMS_DB_PATHSQLite 数据库路径,默认 data/sms_receivers.db。
  7. SMS_DB_TABLE手机号表名默认 sms_receivers。
  8. LOG_ONLY_NO_SMS是否仅预览不实发。

LOG_ONLY_NO_SMS 取值建议:

  1. true联调阶段使用不调用阿里云发送。
  2. false生产或实发测试使用会真实发送短信。

4. 手机号来源与优先级

服务启动时会自动创建手机号表(如果不存在):

CREATE TABLE IF NOT EXISTS sms_receivers (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  phone_number TEXT NOT NULL UNIQUE,
  is_enabled INTEGER NOT NULL DEFAULT 1,
  updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);

接收方选择规则:

  1. 仅使用 SQLite 中 is_enabled=1 的手机号。

这意味着你在服务运行期间修改数据库,下一次 callback 会立即生效,无需重启。

常用维护 SQL

INSERT INTO sms_receivers (phone_number, is_enabled) VALUES ('17394641215', 1);
UPDATE sms_receivers SET is_enabled = 0, updated_at = CURRENT_TIMESTAMP WHERE phone_number = '17394641215';
DELETE FROM sms_receivers WHERE phone_number = '17394641215';

5. 启动服务

在项目根目录执行:

py -m uvicorn app.main:app --host 0.0.0.0 --port 2336

启动成功后会看到:

  1. sms_db_ready
  2. Uvicorn running on http://0.0.0.0:2336

6. 如何测试

6.1 健康检查

curl http://127.0.0.1:2336/healthz

6.2 回调测试

方式一:使用示例文件 test_callback_payload.json。

curl -X POST "http://127.0.0.1:2336/callback" \
  -H "Content-Type: application/json; charset=utf-8" \
  --data-binary "@test_callback_payload.json"

方式二:直接发最小 JSON。

curl -X POST "http://127.0.0.1:2336/callback" \
  -H "Content-Type: application/json" \
  -d "{\"algorithm_name\":\"行人闯入\",\"snowflake_id\":\"demo-001\"}"

7. 返回结构说明

接口始终返回统一结构:

{
  "code": 0,
  "message": "ok",
  "data": {
    "event_id": "1768287987212271616",
    "sms_preview": "发现有行人闯入行为,请去摄像头查看。",
    "sms_ok": true,
    "sms_skipped": false,
    "receiver_count": 1,
    "sms": {
      "code": "OK",
      "message": "OK",
      "request_id": "...",
      "biz_id": "..."
    },
    "sms_error": ""
  }
}

字段含义:

  1. sms_preview短信文本语义预览。
  2. sms_skipped是否因为 LOG_ONLY_NO_SMS=true 而跳过实发。
  3. sms_ok阿里云返回码是否为 OK。
  4. sms阿里云网关返回详情。
  5. sms_error发送失败时的错误信息。

8. 日志与排障

日志位置logs/callback.log。

常见日志事件:

  1. callback_received收到回调。
  2. sms_preview短信预览与模板参数。
  3. sms_receivers_loaded当前收件人数。
  4. sms_sent已调用阿里云并返回结果。
  5. sms_skipped当前为仅预览模式。
  6. sms_config_missing缺少必要配置。

常见问题:

  1. 看见中文乱码:多数是终端显示编码问题,先以接口 JSON 返回为准。
  2. 未发送短信:检查 LOG_ONLY_NO_SMS 是否为 true。
  3. receiver_count 为 0检查 SQLite 是否有 is_enabled=1 的号码。
  4. 阿里云报模板错误:确认签名、模板编码、模板变量 ACTION 与控制台一致。

9. 安全建议

  1. 不要把 AK/SK 提交到版本库。
  2. 生产环境建议通过系统环境变量注入密钥。
  3. 定期轮换 AK/SK并限制 RAM 权限最小化。