微信小程序,帮用户记录各类订阅/会员服务,在到期前自动推送提醒,避免忘记续费或错过取消免费试用。
技术栈:微信小程序原生框架(WXML/WXSS/JS)+ 微信云开发(云函数 + 云数据库 + 定时触发器),无需自建服务器、无需域名备案。
小程序只能在微信内打开,为了方便没有微信环境的招聘方/访客直接在浏览器里预览界面,配了一个只读静态演示页,见下方「网页演示版」一节。
├── app.js / app.json / app.wxss # 小程序入口配置
├── pages/
│ ├── index/ # 订阅列表页(首页)
│ ├── edit/ # 添加/编辑订阅页
│ └── household/ # 共享组管理页(创建/加入/邀请)
├── cloudfunctions/
│ ├── addSubscription/ # 新增一条订阅
│ ├── getSubscriptions/ # 获取当前用户的订阅列表(含我参与的共享组订阅)
│ ├── updateSubscription/ # 编辑一条订阅
│ ├── deleteSubscription/ # 软删除一条订阅
│ ├── scanExpiring/ # 每日定时扫描,命中到期规则就推送提醒(共享订阅通知全部成员)
│ ├── createHousehold/ # 创建一个共享组,生成邀请码
│ ├── joinHousehold/ # 凭邀请码加入一个共享组
│ └── getHouseholds/ # 获取当前用户所在的共享组列表
└── web-demo/
└── index.html # 只读静态网页演示版,写死示例数据,不连真实数据库
-
用微信开发者工具打开本项目文件夹:菜单选"导入项目",目录选这个文件夹,AppID 填你在 mp.weixin.qq.com 后台"开发管理 -> 开发设置"里看到的那个。
-
开通云开发环境:工具栏点"云开发",首次会引导你创建一个环境(有免费额度)。记下环境ID,填到
app.js里wx.cloud.init的env字段。 -
建数据库集合:云开发控制台 -> 数据库 -> 新建集合,需要建两个:
subscriptions和households(代码里写死了这两个名字)。权限都选"仅创建者可读写"(共享组的可见性完全由云函数里的权限校验控制,不依赖数据库的默认读写规则)。 -
上传并部署云函数:在开发者工具左侧
cloudfunctions目录下,右键每一个函数文件夹(addSubscription / getSubscriptions / updateSubscription / deleteSubscription / scanExpiring / createHousehold / joinHousehold / getHouseholds),选择"上传并部署:云端安装依赖"。八个都要传一遍。 -
申请订阅消息模板:mp.weixin.qq.com -> 基础功能 -> 订阅消息 -> 公共模板库,搜"到期提醒"或"续费提醒"相关的模板,选用后拿到模板ID,分别填到:
pages/edit/edit.js里的TEMPLATE_IDcloudfunctions/scanExpiring/index.js里的TEMPLATE_ID(两处要填同一个ID)
-
确认定时触发器生效:
cloudfunctions/scanExpiring/config.json里配置了每天 9:00 自动跑一次(cron:0 0 9 * * * *)。部署完云函数后,去云开发控制台 -> 云函数 -> scanExpiring -> 触发管理,确认触发器已启用;开发调试阶段也可以在控制台手动点"测试"直接触发一次。
| 字段 | 类型 | 说明 |
|---|---|---|
_openid |
String | 云开发自动注入,天然按用户隔离数据;共享订阅的创建者也存在这个字段里,只有创建者能编辑/删除 |
name |
String | 订阅名称 |
amount |
Number | 金额(共享订阅是总金额,不是人均金额) |
currency |
String | 币种,默认 CNY |
cycleType |
String | monthly / yearly / custom |
cycleDays |
Number | 自定义周期天数 |
nextBillingDate |
String | 'YYYY-MM-DD' |
remindDaysBefore |
Number | 提前几天提醒,默认 3 |
isActive |
Boolean | 软删除标记 |
lastRemindedAt |
String | 最近一次提醒日期,防止同一天重复推送 |
groupId |
String | null | 共享给哪个 households 集合的组,不共享则为 null |
isShared |
Boolean | 是否共享订阅,等价于 groupId 是否非空,冗余存一份方便前端查询判断 |
| 字段 | 类型 | 说明 |
|---|---|---|
name |
String | 组名,如"家庭账单" |
ownerOpenid |
String | 创建者 |
members |
Array<String> | 成员 _openid 列表,创建者也在里面 |
inviteCode |
String | 6 位邀请码,用于加入这个组 |
createdAt |
Date | 创建时间 |
设计取舍:共享关系没有直接把 members 数组塞进每一条 subscriptions 文档,而是单独建了 households 集合,用 groupId 关联。原因是一个共享组通常对应多条订阅(比如一家人共享 Netflix + Disney+ + 一份云存储),组成员变动时只需要改 households 一条记录,不用批量改所有关联的订阅;邀请码、组名这些也是"组"的属性而不是"某一条订阅"的属性,放在订阅文档上不合适。代价是查询订阅列表、扫描到期提醒时都要多一次 households 查询做人数/成员名单的关联,但这个项目量级下(个人/家庭用户,几条到几十条订阅)这点开销可以忽略,换来的是数据一致性更好维护。
- 打开"我的订阅"首页 -> 右上角"管理共享组" -> 创建一个组(比如"家庭账单"),拿到 6 位邀请码。
- 把邀请码告诉家人,或者点"分享邀请"通过微信直接转发小程序卡片(卡片链接里带了邀请码,对方点开后邀请码会自动填好)。
- 对方在"管理共享组"页输入邀请码 -> 加入,双方现在都在同一个
households.members里。 - 添加/编辑一条订阅时,"共享给"选择器里选这个组,保存后这条订阅的
groupId就指向这个组。 - 组内所有成员打开首页都能看到这条订阅,金额按当前组人数自动平均分摊,摊到自己头上的部分单独在首页统计卡片和列表条目里显示。
- 到期提醒触发时(
scanExpiring),会给组内每一个成员分别发送订阅消息,不再只发给创建者。
微信小程序只能在微信客户端内打开,招聘方/访客大概率没有微信环境去实际体验。为了解决这个问题,web-demo/index.html 是一个只读的静态演示页,用浏览器直接打开这一个文件就能看,不需要装任何依赖、不需要起服务、不连接真实云数据库:
- 页面顶部有明显的"演示模式 / Demo Preview"标注,避免被误认为生产环境。
- 界面完整复刻小程序首页:统计卡片(订阅数 / 我自己的订阅 / 共享分摊)、按到期时间排序的订阅列表、共享订阅的分摊标签、skeleton loading 骨架屏 -> 数据这个真实加载过程、按紧急程度分级的左侧颜色条(红/橙/绿)。
- 数据是几条写死在
<script>里的示例订阅(RAW_DATA),到期日期用相对"今天"的偏移天数生成,所以不管什么时候打开都会显示"最近到期",不会像固定日期一样过一阵子就变得不合理。 - 点击订阅条目/"管理共享组"/右下角"+"这些交互,会弹出提示说明这是演示模式、完整功能需要在小程序内体验,而不是静默失败。
- 目前只做了静态版本,没有接入云开发的 HTTP 触发云函数做真实只读数据源(那样需要额外设计一层免鉴权只读接口和跨域配置),优先保证这一版能直接打开就用,是后续如果需要"看真实数据"时可以再加的方向。
打开方式:直接双击 web-demo/index.html 用浏览器打开,或者 cd web-demo && python3 -m http.server 8080 起个本地静态服务器后访问 http://localhost:8080。
pages/edit/edit.js的loadExisting目前是从上一页缓存的列表里找数据回显,正式做法应该是单独写一个getSubscriptionDetail云函数按_id查询。- 订阅消息是"一次性"授权机制,
scanExpiring在用户没有最近重新授权的情况下会发送失败,这是微信平台限制导致的预期行为,不是 bug(详见项目开发计划书第 7 节)。 - 月度支出统计(
index.js里的 own/shared 两个 total)目前对custom周期类型做了简化处理,没有按cycleDays精确折算成月度等价支出。 - 共享订阅目前只有创建者能编辑/删除,其他成员只能查看和被通知,避免多人同时编辑冲突;退出共享组、把成员踢出组这些管理功能还没做,目前只能通过邀请码加入,没有对应的退出/移除入口。
- 邀请码没有做唯一性校验(6 位随机码理论上有极低概率重复),个人项目量级下影响可以忽略,真要严谨的话应该在生成时查重。
- 微信支付账单自动识别:设想是通过微信支付的账单/交易流水查询接口,自动识别用户新产生的订阅类扣费,免去手动添加这一步,甚至能在续费金额变化时自动提醒。目前没有实现、也没有写任何对接代码——这类接口面向的是已接入微信支付、有真实收单场景的商户/服务商,需要商户号资质,个人主体 + "工具"类目的小程序申请不到,是平台资质门槛问题,不是技术难度问题。评估后主动排除,只作为路线图记录。
配套的完整开发计划书(需求范围、系统架构、8周开发排期、简历表述示例等)见:订阅到期提醒管理器_开发计划书.md