跳到主要内容

案例 - 蚁阅会员付费的实现

蚁阅是一个网页版RSS阅读器应用,使用艺爪付费轻松实现了会员付费功能。

蚁阅会员付费界面

效果如上图所示,可以用测试账号直接体验会员付费功能:

  1. 浏览器打开蚁阅 https://rss.anyant.com/
  2. 输入账号 testvip@anyant.com 密码 test123456 登录。
  3. 点击右上角菜单 - 账号设置,点击「蚁阅会员」进入付费界面。

准备接入

以下步骤参考官方文档 艺爪付费 - 快速开始

1. 创建艺爪付费项目

首先进入 艺爪付费后台,点击首页右上角,创建项目。

项目名称填写「蚁阅」,点击保存,结果如下图所示,项目ID和API密钥后续会用到。

项目详情

通知渠道和通知URL可以先不填,填写了就会在用户付费后发消息通知我们。参考配置项目通知

2. 配置价格表

在艺爪付费后台,进入价格表页面。蚁阅会员有 5 元和 30 元两个价格,所以要添加两个价格等级。

价格表

3. 配置支付渠道

在艺爪付费后台,进入支付渠道页面。先创建一个简易的微信收款码支付渠道。

收款码图片可以在手机微信「收付款 -> 二维码收款」中生成。未设置金额的即为不定额收款码,用户支付时可以支付任意金额。设置了金额的为定额收款码,用户扫码后支付指定的金额。

支付渠道-微信收款

也可以创建标准支付渠道,例如标准支付宝和微信支付。我使用的是 虎皮椒支付,它是微信和支付宝服务商,给个人小微商户提供支付渠道,申请成功之后在虎皮椒后台查看对接信息。

虎皮椒后台对接信息

然后在艺爪付费支付渠道页面,创建一个虎皮椒-微信支付的支付渠道。

支付渠道-微信支付

填写完对接信息后,点击「检查配置」按钮,会提示「配置正确,可正常使用」,然后点击保存按钮,支付渠道就准备就绪了。

4. 创建权益和商品

在艺爪付费后台,进入权益页面,点击添加权益。

蚁阅会员是订阅模式,新用户可以试用30天,所以模式选择「订阅/永久」,初始余额填写「30d」。别名填写 equity_vip,后续会用到。

会员权益

然后回到商品页面,点击添加商品。蚁阅有一年会员和单月会员两个商品,商品权益是相应的会员时长。

商品-一年会员 商品-单月会员

5. 配置付费界面

在艺爪付费后台,进入商品页面,点击添加付费界面。

付��费界面详情

别名填写 paywall_vip,后续会用到。可以配置展示哪些商品,使用哪些支付方式。

介绍字段会展示在付费界面上,可以填写Markdown或者HTML文本。蚁阅的介绍文案如下:

<table>
<tr>
<th></th>
<th>会员版</th>
<th>免费版</th>
</tr>
<tr>
<td>订阅数量</td>
<td style="color:#66bb6a;">不限</td>
<td>不限</td>
</tr>
<tr>
<td>全部功能</td>
<td style="color:#66bb6a;">支持</td>
<td>试用30天</td>
</tr>
<tr>
<td>技术支持</td>
<td style="color:#66bb6a;">优先</td>
<td>常规</td>
</tr>
</table>
<div style="font-weight:bold;">原价 5 元每月,现在年付半价购买</div>

配置好之后,商品列表如下图所示,点击付费界面预览按钮能查看实际效果。

商品列表

API集成

1. 添加后端接口

蚁阅后端使用 Python 语言,将文档中的 参考代码 - Python 复制到项目里面,安装好相关依赖。

然后实现一个获取用户信息的接口,逻辑是获取请求中的用户参数,调用艺爪付费并返回结果。

@EzrevenueView.post('ezrevenue/customer.info')
def ezrevenue_customer_info(
request,
include_balance: T.bool.default(True),
) -> T.dict:
# 如果未配置艺爪付费,返回错误码(蚁阅开源版未配置会员功能)
if not EZREVENUE_CLIENT:
return Response(status=501)
user: AbstractUser = request.user
params = dict(
paywall_alias='paywall_vip',
customer=dict(
external_id=user.id,
nickname=user.username,
external_dt_created=user.date_joined.isoformat(),
),
include_balance=include_balance,
)
return EZREVENUE_CLIENT.call('customer.info', params)

2. 前端界面交互

蚁阅前端用的 Javascript 和 Vue 框架,主要逻辑代码如下:

首先是在用户登录之后,请求后端接口获取会员信息。

async login({ account, password } = {}) {
let user = await API.user.login({ account, password })
// .....请求接口获取会员信息
this.syncVipCustomer()
})
}

格式化会员到期时间,注意接口返回的时间单位是 而 Javascript 需要 毫秒

get balanceText() {
const item = this.balance
if (_.isNil(item)) {
return '####-##-##'
}
if (item.is_balance_infinite) {
return '9999-12-31'
}
return formatDate(item.balance * 1000)
}

然后在账号设置页面,显示会员到期时间信息。

<div class="action-row" @click="goVip">
<span class="action-label">蚁阅会员</span>
<span>
<span class="vip-balance">{{ customerBalance }} 到期</span>
<fa-icon class="action-icon" icon="chevron-right" />
</span>
</div>

当用户点击会员按钮时,打开对话框窗口,显示会员界面。这里用 window.open 接口开启对话框,加载会员界面链接。通过参数控制对话框大小,并显示在页面中间。

窗口打开之后,通过轮训的方式等待窗口关闭,定时每秒检查一下窗口 closed 状态。等窗口关闭后,获取最新会员信息。

  async openVipHomeLink() {
// 高度设置为当前页面内容区域
const padTop = window.outerHeight - window.innerHeight
const height = window.innerHeight - padTop
const top = window.screenTop + padTop + 8
// 宽度设置为当前页面内容区域居中
let width = window.innerWidth - 16
if (width > 800) {
width = 800
}
const padLeft = Math.round((window.innerWidth - width) / 2)
const left = window.screenLeft + padLeft
const popupConfig = `popup,width=${width},height=${height},left=${left},top=${top}`
// 打开对话框窗口,轮训等待窗口关闭
const popup = window.open(url, '', popupConfig)
await new Promise(resolve => {
const popupTick = setInterval(() => {
if (popup.closed) {
clearInterval(popupTick)
resolve(true)
}
}, 1000)
})
// 窗口关闭后,获取最新会员信息
await this.syncVipCustomer()
}

由于 Iframe 页面无法拉起支付宝和微信支付,所以要用对话框窗口加载付费界面,不能用 Iframe 标签。

导入会员数据

因为蚁阅之前有一套会员系统,需要把会员数据迁移到艺爪付费,用 导入会员数据 功能实现。

首先从旧的会员系统数据库导出用户数据,生成一个CSV文件,导出的文件要带表头。

select
id as customer_external_id,
GREATEST(balance - unix_timestamp(), 0) as amount,
nickname as customer_nickname
from customer;

然后在艺爪付费后台界面,创建数据导入任务。可以创建一个测试项目导入数据并测试,没问题了再操作导入数据到正式项目中。

导入会员数据

执行导入,等待完成后,用户权益余额就会和旧系统一致。

用户权益余额

最后选一个用户访问较少的时间段,将旧系统会员充值暂停,然后上线新代码,蚁阅会员付费功能就完成了。