一个关于微信订阅消息功能的思考(一个关于微信订阅消息功能的思考与实践)

本文主要分享了如何设计一个发送微信订阅消息功能。

一、总结简述

1.封装微信订阅消息模板获取和发送代码

2.提供存储方案,表结构设计

3.提供真实生产项目代码案例,实现异步机制、定时发送、超时取消发送等功能

4.文末提供代码仓库,有兴趣的小伙伴可以fork代码

二、架构设计

开发订阅消息分2步:

1)记录用户授权

2)发送订阅消息

思考1:是否一定需要记录订阅消息模板的用户授权次数?

其实发送订阅消息跟发送短信一样,只不过多了个需要用户授权才能发送成功。像程序单次触发订阅消息,其实是不需要知道目标用户有没有授权的,我们只管无脑发,如果用户有授权就成功,没授权就失败。

思考2:那为什么要记录授权次数呢?

使用场景:按授权记录找到用户。比如需要筛选订阅了某个模板的用户,给这些用户发订阅消息。因为这里给所有用户无脑发就行不通了,因为你的用户量可能百万甚至千万级别的,无效发送会导致性能问题。

思考3:订阅消息有哪些触发时机呢?

1)用户完成了某个操作之后触发。比如拼团,团员参团后给团长发送1个订阅消息告知

2)定时任务触发。比如优惠券过期提醒,每天或每周扫描一下是否有即将过期的优惠券,有则发送

3)用户完成某个操作之后,针对这个操作预备一个未来发送的订阅消息。比如用户领取了1张优惠券,针对该优惠券在过期前n天给用户发送1个提醒消息

三、代码实现

1.数据库表结构设计

CREATE TABLE `subscribe_template` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `pri_tmpl_id` varchar(64) NOT NULL DEFAULT '' COMMENT '添加至账号下的模板 id,发送小程序订阅消息时所需',
  `title` varchar(32) NOT NULL DEFAULT '' COMMENT '模版标题',
  `content` varchar(255) NOT NULL DEFAULT '' COMMENT '模板内容',
  `example` varchar(255) NOT NULL DEFAULT '' COMMENT '模板内容示例',
  `type` int(11) NOT NULL DEFAULT '0' COMMENT '模版类型,2 为一次性订阅,3 为长期订阅',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uniq_pritmplid` (`pri_tmpl_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息模板';

CREATE TABLE `subscribe_type_template_config` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `type` varchar(32) NOT NULL DEFAULT '' COMMENT '业务类型',
  `param_index` varchar(32) NOT NULL DEFAULT '' COMMENT '参数索引(逗号分隔,空代表按顺序)',
  `template_code` varchar(64) NOT NULL DEFAULT '' COMMENT '模板编码(subscribe_template.pri_tmpl_id)',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uniq_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息业务-模板配置';

CREATE TABLE `subscribe_group_type` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `group` varchar(32) NOT NULL DEFAULT '' COMMENT '订阅组',
  `types` varchar(128) NOT NULL COMMENT '业务类型(多个英文逗号分隔,最多3个)',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uniq_group` (`group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息-订阅组';

CREATE TABLE `subscribe_template_grant` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `openid` varchar(32) NOT NULL COMMENT 'openid',
  `template_code` varchar(64) NOT NULL COMMENT '模板编码(subscribe_template.pri_tmpl_id)',
  `total_num` int(11) NOT NULL DEFAULT '0' COMMENT '授权总次数',
  `use_num` int(11) NOT NULL DEFAULT '0' COMMENT '已使用次数',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uniq_openid_templatecode` (`openid`,`template_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息-授权记录';

CREATE TABLE `subscribe_task` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `type` varchar(32) NOT NULL COMMENT '业务类型',
  `plan_send_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '计划发送时间',
  `over_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '超时取消发送时间',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息发送任务';

CREATE TABLE `subscribe_task_detail` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `task_id` int(11) unsigned NOT NULL COMMENT 'subscribe_task.id',
  `openid` varchar(32) NOT NULL COMMENT 'openid',
  `page` varchar(32) NOT NULL COMMENT '跳转页面',
  `template_param_json` varchar(255) DEFAULT NULL COMMENT '模板参数json',
  `plan_send_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '计划发送时间',
  `actual_send_time` datetime DEFAULT NULL COMMENT '实际发送时间',
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态(1:待发送,2:待定时发送,11:发送MQ成功,12:MQ消费成功,21:请求成功,22:请求失败,31:取消发送)',
  `template_code` varchar(64) NOT NULL DEFAULT '' COMMENT '模板编码(subscribe_template.pri_tmpl_id)',
  `content` varchar(255) DEFAULT NULL COMMENT '订阅消息内容',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_taskid` (`task_id`),
  KEY `idx_openid` (`openid`),
  KEY `idx_plansendtime_status` (`plan_send_time`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订阅消息发送任务明细';

表说明:

subscribe_template:直接同步微信的订阅消息模板,核心是模板ID和模板内容2个字段


subscribe_type_template_config:定于业务与模板ID的关系,一般某个业务会写死在代码中,利用这个表灵活配置某个业务发送的模板消息

subscribe_group_type:订阅消息1次最多订阅3个模板,前端根据group找到对应业务,从而找到需要订阅的模板组

subscribe_template_grant:用户每授权1次就记录,主要用于筛选订阅了某个模板的用户,给这些用户发消息的场景(不用到这种场景可不记录)

subscribe_task、subscribe_task_detail:订阅消息任务,可以理解为每次发送订阅消息都是1个订阅消息任务,每个订阅消息任务可以给多个用户发送订阅消息,营销信息常用,支持即时发送和定时发送

数据样例说明:

订阅消息模板

1)pri_teml_id即template_code,代码中根据pri_teml_id查询content,发送时解析传参

订阅消息业务-模板配置

1)代码中会写死type,跟据type查询到template_code,param_index用于代码中传递的参数数量与模板参数数量不匹配时用到,比如代码中写了传递4个参数,但是更换的模板只需要3个参数,默认情况下会取前3个参数填入,但如果不想要的参数是第2个,则填写0,2,3

订阅消息-订阅组

1)这里order_finish会写死到前端,通过值查询订阅的业务是3个,再通过type查询template_code返回给前端,进行订阅窗口的拉起

2.将subscribe_template、
subscribe_type_template_config、subscribe_group_type都做成后台配置功能,这里就不细讲了

3.核心代码展示

1)封装binarywang 微信SDK发送订阅消息代码

2)封装binarywang 微信SDK获取订阅消息模板代码(用于程序同步模板,无需手动添加)

3)生产者核心代码

4)消费者核心代码


怎么样?如果你觉得有用的话,还不快快收藏起来!!!

附:涉及的代码目录

github: https://github.com/897665787/springcloud-template

gitee:https://gitee.com/jq_di/springcloud-template

springcloud-template
└── template-tool
     └──controller
          └── SubscribeController -- 订阅消息相关API
     └── subscribe
          └── AsyncSubscribeSender -- 异步发送 订阅消息,MQ生产者逻辑
          └── SubscribeSenderConsumer -- 异步发送 订阅消息,MQ消费者逻辑
          └── SubscribeType -- 用于解决触发时机3的场景
└── sql
     └── tool
          └── 订阅消息设计相关表.sql
原文链接:,转发请注明来源!