技术派付费阅读方案设计(👍强烈推荐)
有一段时间没有更新“技术派”的相关文章了,最近偷偷的上线了一个有趣的功能:“文章的付费解锁阅读”,不知道有没有小伙伴注意到;接下来我将介绍一下这个付费阅读的设计思路与实现方式
付费阅读方案设计
按照惯例,编码之前,先捋一下我准备怎么做,我的技术方案是什么,影响范围有多大,改动点有多少
接下来我们顺一下,要实现付费阅读,整个任务应该如何进行拆解
1. 需求拆分与整体方案设计
基于需求本身要点进行方案设计
1.1 任务拆分
文章支持付费阅读,从需求描述,我们可以抓到两个重点:
- 付费之后才可以阅读,需要记录用户与文章之间的付费关系
- 需要有一个完整的付费流程
1.2 概要设计
1.2.1 用户与文章的付费关系
A. 新增文章阅读类型
用户只有付费之后才能阅读文章,与之对应的没有付费就不能阅读全文,基于此,文章本身需要一个阅读的权限控制,由原有的所有人都可以阅读,扩展为付费阅读模式
因此,一个很容易想到的变更就是在文章主表上,新增一个字段来控制阅读类型
alter table `article` add column `read_type` tinyint not null default '0' comment '文章阅读类型 0-直接阅读 1-登录阅读 2-限时阅读 3-星球用户专享 4-付费阅读';
说明:由于专栏文章也有一个阅读类型的控制,因此我们直接在它的基础上进行扩展,新增一个付费阅读类型
B. 记录付费关系
接下来我们需要维护用户与文章的付费关系,以此来判断用户是否可以阅读全文,因此我们考虑建立一个关系表,其中核心的字段为:
- 付费用户
- 文章id
- 付费状态
其中 付费用户 + 文章id 两者要求唯一性约束(避免出现一个用户对同一个文章的重复支付情况)
付费关系的维护逻辑:
初始关系维护的触发时机:
- 方案一:登录用户,首次访问付费文章时
- 优点:准备支付时,无需额外打一个接口,可以直接唤起支付窗口
- 缺点:有很多不准备付费的用户,也建立了映射关系,存在数据冗余的情况
- 方案二:用户准备付费时
- 优点:按需写入数据,较方案一少很多无效数据
- 缺点:唤起支付时,需要向后端打一个接口,用于写入用户与文章的关系
支付中状态:未支付 + 支付中 + 支付成功 + 支付失败
为什么要支付中状态?
- 对于支付而言,通常是不完全信任用户交互行为,用户完成了支付之后,是以接收到微信/支付宝的支付结果回调通知,来更新对应的状态为支付成功/支付失败的
- 如果没有支付中,那么对于用户而言,支付成功了,但是刷新页面,若此时微信/支付宝的回调还没有到你的服务器,此时依然是未支付状态,对于用户就会产生干扰(我都付钱了,为啥还告诉我没有支付?),有可能出现重复支付的问题
何时更新为支付中状态?
- 用户完成支付之后,打一个接口给后端,将支付状态设置为支付中
何时更新为支付成功 or 支付失败 状态?
- 基于三方支付的回调来判断支付成功还是失败
1.2.2 文章付费流程
付费解锁,那么就需要有一个完整的支付渠道;当前国内最常见的个人支付是基于微信/支付宝来实现的,下面以微信支付的流程进行说明
A. 微信支付流程
借助微信支付来实现文章的付费功能,首先我们看一下微信的支付流程

微信H5支付业务流程图
基于微信的支付流程,从技术上,微信H5-支付对接,我们最小实现是只需要关注两点,即后台的改造如下:
- 用户请求支付时,后台服务向微信下单,获取用于支付的中间页地址
- 后台提供一个回调接口,用于微信回传支付结果
使用微信或者支付宝的支付,技术上一般都不是什么难点,麻烦的在于技术之外的账号上
- 不支持个人主体申请支付
- 申请支付的前置准备

B.基于个人收款码的支付方式
对于个人而言,想走微信/支付宝支付的成本还是较高的,相信大部分小伙伴都没有这个条件;因此我们考虑做一个妥协,基于我们日常使用的微信/支付宝的收款码方式,来打通这个付费流程
核心流程如下:
- 用户阅读付费文章, 点击去支付
- 展示作者的收款码
- 用户扫描收款码,进行转账
- 作者收到转账,手动标记用于已完成付费

上面这个方案,优点比较明显,不需要去注册商家号,申请开通各种支付功能,所有的用户都可以直接体验
当然缺点也同样很突出,首先是需要维护每个作者的收款码,其次就是是否支付成功完全靠作者来人肉判断,而且这种转账方式,无法设置具体的付费金额,这也是一个缺陷
对于这个方案,我们需要做的相应改造点如下:
- 每个作者维护自己的收款码
- 新增回调接口,供作者刷新用户是否付费成功
小结:
上面介绍的付费流程,很明显对于正规一点的玩法,毫无疑问选择第一个微信/支付宝的支付方案;对于没有支付条件的小伙伴,那就选择第二种收款码方式
对于技术派而言,我们选择第二种方式来实现
2. 详细方案设计
在前面的需求拆分与概要设计中,我们敲定了整体的实现方案,接下来我们在详细设计中,将具体的方案进行落地,以指导我们后续的研发工作
2.1 新增文章阅读权限
由于存在付费阅读类型的文章,我们将新增一个字段read_type用于控制文章的阅读权限,在作者发布文章时,进行维护这个字段;
考虑到当前存在较多的历史文章数据,都是可以直接阅读的,因此新增这个字段时,考虑一下历史数据的兼容
alter table `article` add column `read_type` tinyint not null default '0' comment '文章阅读类型 0-直接阅读 1-登录阅读 2-限时阅读 3-星球用户专享 4-付费阅读';
同样的,定义一个枚举与上面的字段进行映射
@Getter
public enum ArticleReadTypeEnum {
NORMAL(0, "直接阅读"),
LOGIN(1, "登录阅读"),
TIME_READ(2, "限时阅读"),
STAR_READ(3, "星球阅读"),
PAY_READ(4, "付费阅读"),
;
private Integer type;
private String desc;
ArticleReadTypeEnum(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
}
重点关注一下付费阅读这种类型,其他的几种是从专栏文章中扩展而来,不在本文的重点,因此不详细进行说明
当文章维护上面的字段之后,用户在进行阅读文章时,我们就需要通过这个字段进行权限的管控,需要一个统一的方法,判断用户的阅读权限
public boolean hasReadPermisson(Article article, User currentUser) {
if (currentUser == null) {
// 没有登录
if (article.readType == 0) {
// 未登录时,只有 NORMAL 阅读方式的文章才有权限进行阅读
return true;
}
return false;
}
// 如果是作者阅读自己的文章,可以直接看
if (currentUser.userId.equals(article.author)) {
return true;
}
if (article.readType == 1) {
// 登录之后才能阅读
return true;
} else if (article.readType == 2) {
// 限时阅读,普通文章不支持这种场景,直接返回true
return true;
} else if (article.readType == 3) {
// 星球用户专享
return currentUser.isStartUser();
} else if (article.readType == 4) {
// 判断用户是否付费成功
return payService.hasPaied(article.id, currentUser.userId);
}
}
2.2 用户文章付费关系
在上面判断用户是否可以阅读付费文章时,就需要使用到这个付费关系来辅佐判断,那么这个关系表,应该包含哪些字段呢?
- 文章id: article_id
- 支付用户: pay_user_id
- 收款用户: receive_user_id
- 支付状态: pay_status
- 备注信息:notes 用于记录用户打赏的文案
除了上面的基本字段之外,为了简化作者的回调难度,我们希望在用户完成支付之后,将支付状态设置为支付中时,系统主动给作者发送一个通知,其中包含两个操作按钮(已支付 + 未支付),这样作者在根据实际的到账情况,点击对应的按钮之后,就可以将对应的支付状态更新为 支付成功/支付失败
基于上面的策略,我们额外新增下面几个字段
- 校验码:verify_code 用于校验回调合法的随机code
- 通知次数:notify_cnt 记录通知作者的次数
- 通知时间:notify_time 记录通知作者的时间戳
对应的DDL如下
CREATE TABLE `article_pay_record` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`article_id` bigint unsigned NOT NULL DEFAULT '0' COMMENT '文章ID',
`pay_user_id` bigint unsigned NOT NULL DEFAULT '0' CO...未能定位到原文的划线
企业级Agent工作流编排项目PaiFlow
Vibe Coding版本的PaiAgent
派聪明RAG AI知识库Java版本+Go版本
微服务 PmHub、技术派、MYDB
求职派JobClaw(OpenClaw/Hermes架构
PaiCLI(类似Claude Code的Agent
派简历(代码已完成)
等实战项目。
1. 微信扫右侧的优惠券加入知识星球
2. 解锁星球的实战项目教程和源码: 项目源码+教程获取
真诚点赞 诚不我欺
回复