海外软件试用转正、会员涨价、年度续费,多数人是在扣款短信到了以后才想起来。这篇用 MPChat Bot API 和 Python 标准库写一个订阅到期提醒机器人:私聊里发 /add 记下日期,到期前 3 天、前 1 天各推送一次,并按事件类型附上处理建议(取消试用、关闭自动续费、重新评估涨价)。文末附本地 Mock 测试,模拟 9 天的日期推进,验证提醒时点、去重和 429 重试。

你会用到的点:getUpdates 长轮询、sendMessage 推送、429 指数退避、状态持久化防重复提醒、注入 today_fn 做时间相关测试。

一、为什么把提醒放进聊天机器人

日历也能提醒,用起来有两处不顺:添加时要切出当前对话,提醒弹出来也只有一行标题,接下来该做什么还得自己想。放进每天都会打开的聊天工具里,一条 /add 就能记下,到点时提醒和处理建议在同一条消息里,扫一眼就能做决定。

MPChat Bot API 有一条限制直接决定了交互设计:机器人不能主动发起会话。用户先给机器人发过消息,机器人才能往这个聊天里推送。这种被动触发的机制,对提醒类机器人来说正好把骚扰挡在外面。

二、接口规则速览

以下来自 MPChat 帮助中心 Bot 开发文档:

项规则
请求地址https://call.mp.net/bot/bot{TOKEN}/{methodName},token 在路径里
拉消息getUpdates 长轮询,timeout 最大 50,limit 最大 100
发消息sendMessage,必填 chat_id、text
频率每个 token 默认每秒 30 次,超出返回 429
重试429、500 用有上限的指数退避;400、401、403 不重试
IDchat_id 可能超出 32 位,按字符串或 BIGINT 存

三、数据模型

每个聊天对应一组记录。每条记录有四个业务字段,外加一个“哪些时点已经提醒过”:

{  "offset": 15,  "chats": {    "778899001122": [      {"name": "修图App", "date": "2026-11-03", "kind": "试用",       "amount": "9.99", "sent": [3]}    ]  }}

kind 只有三种:试用、续费、涨价。三种事件的容错成本不同,要做的决定也不同,提醒文案分开写。sent 记下已经发过的提前天数,同一个时点只提醒一次,机器人重启后也不会重发。

四、核心逻辑:每天检查一次,只在固定时点提醒

REMIND_DAYS = (3, 1)
def due_reminders(state, today):    out = []    for chat_id, items in state["chats"].items():        for it in items:            left = (date.fromisoformat(it["date"]) - today).days
            if left in REMIND_DAYS and left not in it["sent"]:                it["sent"].append(left)                out.append((chat_id, it, left))    return out

选前 3 天和前 1 天,是因为很多服务取消自动续费后仍能用到本期结束。前 3 天是决策窗口,前 1 天用来最后确认。按类型给出的处理建议:

ACTION = {    "试用": "不打算付费的话,今天就去服务方账户里取消试用。",    "续费": "还在用就留着;不常用的,去账户设置里关掉自动续费,一般能用到本期结束。",    "涨价": "先看看上个月用了几次,再决定继续、降档还是取消。",}

主循环把“增量消息处理”和“每日时点检查”解耦,每日检查按日期去重:

def run(bot, today_fn=date.today, max_loops=None):    state = load_state()    last_check = None    while ...:        today = today_fn()        for upd in bot.call("getUpdates", offset=state["offset"], timeout=30,                            limit=50, allowed_updates=["message"]) or []:            state["offset"] = upd["update_id"] + 1            if "message" in upd:                handle(bot, state, upd["message"], today)            save_state(state)        if last_check != today:            send_reminders(bot, state, today)            last_check = today
            save_state(state)

today_fn 做成可注入参数,测试时可以直接模拟日期推进。

五、请求封装与 token 安全

def call(self, method, **params):    ...
    if data.get("ok"):        return data.get("result")    code = data.get("error_code")    if code in RETRYABLE and attempt < self.max_retries:        self.sleep(delay)        delay = min(delay * 2, self.max_delay)        continue    raise MPBotError(code, data.get("description", ""))

帮助中心对 token 有几条要求:不进前端代码,日志脱敏,.env 加入 .gitignore,不贴进工单或 AI 对话,泄露后立刻在 BotFather 吊销并更换。本文代码里 token 只拼进 URL,日志只打印方法名和错误码。

六、本地 Mock 测试:不用干等,把 9 天压缩成几秒

test_with_mock.py 起一个本地 HTTP 服务模拟接口。用户先添加三条记录,另发一条格式错误的命令,然后把日期从 10/31 推进到 11/08,每天跑一轮。第一次 sendMessage 故意返回 429,用来验证退避重试。实际输出(节选):

[retry] sendMessage 返回 429,1s 后重试
[10-31] 已记下:修图App,2026-11-03 免费试用到期,之后自动转为付费。
[10-31] 格式:/add 名称 YYYY-MM-DD 试用|续费|涨价 [金额]
[10-31] 1. 修图App|试用|2026-11-03(还有 3 天) 9.99 美元
        2. 云盘|续费|2026-11-05(还有 5 天) 2.99 美元
        3. 音乐会员|涨价|2026-11-07(还有 7 天) 12.99 美元
[10-31] ⏰ 修图App:3 天后(2026-11-03)免费试用到期,之后自动转为付费,金额 9.99 美元。
        不打算付费的话,今天就去服务方账户里取消试用。
[11-02] ⏰ 修图App:1 天后(2026-11-03)……
[11-02] ⏰ 云盘:3 天后(2026-11-05)自动续费扣款,金额 2.99 美元。
[11-04] ⏰ 云盘:1 天后……
[11-04] ⏰ 音乐会员:3 天后(2026-11-07)新价格生效……
[11-06] ⏰ 音乐会员:1 天后……
全部断言通过

断言覆盖四件事:3 条记录共触发 6 次提醒;提醒日期正好落在前 3 天和前 1 天;格式错误会返回提示;过期两天以上的记录自动清理。示例里的软件名和金额为构造数据。

七、几个常见问题

机器人重启后会不会重复提醒? 不会。每条记录的 sent 字段持久化在状态文件里,重启后读回来,已发过的时点会被跳过。

chat_id 为什么存成字符串? 文档说明 chat_id 可能超出 32 位整数范围,用字符串或 BIGINT 存最省心,在 JSON 里直接当 key 用也方便。

为什么不用系统 cron 定时发?getUpdates 长轮询本身就在常驻循环里,顺手按日期做一次检查,少维护一个进程,状态也只在一处读写。

八、可以继续扩展的方向

  • 按钮代替命令:提醒消息下挂“已取消”“继续用”的 inline_keyboard 按钮,收到 callback_query 后在 300 秒内调用 answerCallbackQuery,再把记录归档。

  • 自动顺延:续费类记录到期后按月顺延到下一次日期。

  • 团队群共用:把机器人放进研发团队群,盯住公用 SaaS 账号的续费节点,比如 CI/CD 服务、设计协作工具,谁都能看到哪个账号快到期了。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐