## 部署步骤
1. 把整个 `plugin-qurk-subscription/` 目录复制(或重命名)为 `wp-content/plugins/qurk-subscription/`:
目标路径:`wp-content/plugins/qurk-subscription/`
2. 进入 WP 后台 → **插件**,启用「Qurk Subscription」。激活时会:
– 自动创建数据表 `{$prefix}qurk_subscriptions`
– 自动创建一个名为「会员订阅」的页面(内容为 `[qurk_subscription]` 短代码)
– 注册每日到期检查定时任务
3. 进入 **订阅管理 → 订阅设置**,填写:
– 微信支付 AppID / MCHID / API Key(V2 32 位密钥)
– 月/季度/年价格(默认 19 / 49 / 168 元)
– 选择订阅页面
4. 在微信商户平台 → 产品中心 → 开发配置,回调地址无需手动配置(统一下单时通过 `notify_url` 字段动态传递),但要确保你的站点在「**支付授权域名**」白名单中,并且站点允许外网访问(异步通知必须可访问)。
## 主要功能
### 用户侧
– 在订阅页面(默认 `/会员订阅/`)展示三档套餐
– 点击「立即订阅」弹窗显示二维码,使用微信扫码完成支付
– 前端每 2 秒轮询订单状态,支付成功自动刷新页面解锁会员标识
– 已订阅用户在页面顶部显示「VIP 当前会员 + 到期时间」
### 后台侧
– **订阅管理 → 订单列表**:所有订单(按状态过滤),含订单号、用户、套餐、金额、微信交易号、订阅区间
– **订阅管理 → 订阅设置**:微信支付参数、套餐价格、订阅页面
– **用户列表**:新增「订阅状态」列,显示当前套餐与到期时间
– **用户编辑页**:显示订阅摘要、最近 10 条订单、可手动「赠送一份」订阅
### 开发者
– 全局函数:`qurk_is_active_subscriber( $user_id = 0 )` 判断当前/指定用户是否为有效订阅会员
– 钩子:
– `do_action( ‘qurk_sub_paid’, $user_id, $plan_key, $order_no, $expire_ts )` 支付成功
– `do_action( ‘qurk_sub_expired’, $user_id )` 会员到期
– 用户 meta:
– `qurk_sub_expire_at` 到期时间戳
– `qurk_sub_current_plan` 当前套餐 key(month/quarter/year)
– `qurk_sub_status` active / expired
### 在主题中限制内容(示例)
“`php
if ( qurk_is_active_subscriber() ) {
// 显示付费内容
} else {
echo ‘<p>本内容仅向订阅会员开放,<a href=”/会员订阅/”>立即开通</a>。</p>’;
}
“`
## 数据表结构
插件激活/升级时会自动创建以下三张表(DB 版本:`1.1.0`)。
### 1. `{$prefix}qurk_subscriptions`(订单表,每次下单一条)
| 字段 | 说明 |
| ————– | ——————————— |
| id | 主键 |
| user_id | WordPress 用户 ID |
| order_no | 平台订单号(唯一索引) |
| plan | month / quarter / year |
| amount | 实付金额(元) |
| status | pending / active / cancelled / expired |
| transaction_id | 微信支付交易号 |
| pay_method | wechat |
| start_at | 本次订阅生效时间 |
| expire_at | 本次订阅到期时间 |
| paid_at | 支付完成时间 |
| created_at | 订单创建时间 |
| updated_at | 更新时间 |
### 2. `{$prefix}qurk_subscribers`(订阅会员表,user_id 唯一)
| 字段 | 说明 |
| ————– | ——————————— |
| id | 主键 |
| user_id | WordPress 用户 ID(唯一) |
| plan | 当前套餐 |
| status | active / expired / none |
| start_at | 订阅起始时间 |
| expire_at | 当前到期时间 |
| last_order_no | 最近一笔订单 |
| total_paid | 累计实付金额 |
| total_orders | 累计成功订单数 |
| created_at | 首次订阅时间 |
| updated_at | 更新时间 |
### 3. `{$prefix}qurk_subscription_logs`(事件日志表)
记录订阅生命周期内的关键事件:`order_created` / `order_paid` / `order_cancelled` / `subscription_expired` 等。
| 字段 | 说明 |
| ———- | ———————————– |
| id | 主键 |
| user_id | 用户 ID |
| order_no | 关联订单号(可空) |
| event | 事件类型(如 order_paid) |
| message | 事件说明 |
| data | JSON 扩展数据 |
| ip | 请求来源 IP |
| created_at | 事件时间 |
## REST API(基于 JWT 鉴权)
依赖插件:`jwt-authentication-for-wp-rest-api`(需在 `wp-config.php` 中定义 `JWT_AUTH_SECRET_KEY`)。
### 1. 获取 Token
“`http
POST /wp-json/jwt-auth/v1/token
Content-Type: application/json
{ “username”: “admin”, “password”: “your-password” }
“`
返回的 `token` 字段用于后续请求头:
“`
Authorization: Bearer <token>
“`
### 2. 订阅相关接口(命名空间 `qurk-sub/v1`)
| 方法 | 路径 | 说明 | 鉴权 |
| —— | ——————————————— | ——————————————– | —- |
| GET | `/wp-json/qurk-sub/v1/plans` | 套餐列表 | 公开 |
| GET | `/wp-json/qurk-sub/v1/me` | 当前用户订阅摘要 + 会员表数据 | JWT |
| GET | `/wp-json/qurk-sub/v1/orders?limit=20` | 当前用户订单列表 | JWT |
| POST | `/wp-json/qurk-sub/v1/orders` | 创建待支付订单(body:`{“plan”:”month”}`) | JWT |
| GET | `/wp-json/qurk-sub/v1/orders/{order_no}` | 订单详情 | JWT |
| POST | `/wp-json/qurk-sub/v1/orders/{order_no}/wechat-pay` | 微信统一下单,返回 `code_url` | JWT |
| POST | `/wp-json/qurk-sub/v1/orders/{order_no}/cancel` | 取消未支付订单 | JWT |
| GET | `/wp-json/qurk-sub/v1/logs?limit=50` | 当前用户订阅事件日志 | JWT |
### 3. 调用示例
“`bash
# 1) 获取 token
curl -X POST https://example.com/wp-json/jwt-auth/v1/token \
-H “Content-Type: application/json” \
-d ‘{“username”:”admin”,”password”:”xxx”}’
# 2) 创建订单
curl -X POST https://example.com/wp-json/qurk-sub/v1/orders \
-H “Authorization: Bearer <token>” \
-H “Content-Type: application/json” \
-d ‘{“plan”:”month”}’
# 3) 唤起微信支付(拿到 code_url 由前端渲染二维码)
curl -X POST https://example.com/wp-json/qurk-sub/v1/orders/QRK20260530xxx/wechat-pay \
-H “Authorization: Bearer <token>”
# 4) 查看订阅状态
curl https://example.com/wp-json/qurk-sub/v1/me \
-H “Authorization: Bearer <token>”
“`
## 续期逻辑
– 用户支付成功时:
– 若当前 `expire_at > now`:在原有到期时间上叠加套餐月数(不浪费已购时间)
– 否则:从「当前时间」起算 + 套餐月数
## 安全
– 所有 AJAX 接口使用 nonce 校验
– 微信回调使用 V2 MD5 签名校验,并校验金额
– 后台仅 `manage_options` 角色可访问
## 注意事项
– 插件默认引用 jsdelivr 的 `qrcodejs` 渲染二维码;如内网/无法访问 CDN,请将 `https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js` 下载到 `assets/js/qrcode.min.js` 并在 `class-qurk-frontend.php::register_assets()` 中改为本地引用
– 微信支付 V2 接口需要商户号 + API Key(32 位)。若只有 V3 证书,可后续扩展 `class-qurk-wechat-pay.php`
– 若开启了 OPcache,请在调整设置后清缓存
—
## 付费场景使用指南(Paywall)
插件内置了多种付费内容控制场景,通过短代码、Meta Box、CSS 类即可启用,无需写任何代码。
### 场景 1:整篇文章付费阅读
在文章/页面编辑器侧边栏找到「订阅付费配置」面板:
1. 勾选 **整篇付费**
2. 设置 **免费试读字数**(如 200),0 = 全部隐藏
效果:非会员只能看到前 N 个字(渐变淡出)+ 「订阅解锁」卡片;会员看到完整正文。
### 场景 2:付费资源解锁(下载链接 / 视频 / 附件)
在正文中插入短代码:
“`
[qurk_paid_resource url=”https://example.com/secret.zip” type=”download” text=”立即下载”]这是付费资源说明[/qurk_paid_resource]
“`
参数说明:
– `url`:资源真实地址(非会员 HTML 中**不会出现**此 URL)
– `type`:`download` | `video` | `link`
– `text`:按钮文字
### 场景 3:任意链接/按钮点击需订阅
**方式 A:CSS 类标记**(适合主题开发者):
“`html
<a class=”qurk-paid” href=”/secret-page”>查看秘密内容</a>
<button class=”qurk-paid” data-qurk-paid=”1″>解锁功能</button>
“`
**方式 B:短代码**(适合编辑器用户):
“`
[qurk_paid_button href=”/secret-page” text=”立即查看”]
“`
效果:未订阅用户点击时,当前页面弹出套餐选择 + 微信扫码支付弹层;支付成功后自动刷新页面解锁。
### 场景 4:独立页面专属付费内容
每篇文章/页面可配置「本页专属付费内容」(在侧边栏 Meta Box 中编辑),然后在正文合适位置插入:
“`
[qurk_premium]
“`
也可跨页引用其它文章的付费内容:
“`
[qurk_premium id=”123″]
“`
### 后台配置
进入 **订阅管理 → Paywall 设置**:
– 修改解锁卡片的标题 / 描述 / 按钮文字
– 设置全局默认免费试读字数
– 启用/禁用全站 `.qurk-paid` 拦截 JS
### 新增 REST API
| 方法 | 路径 | 说明 | 鉴权 |
| —- | —- | —- | —- |
| GET | `/wp-json/qurk-sub/v1/post/{id}/premium` | 文章专属付费内容 | 会员 |
| GET | `/wp-json/qurk-sub/v1/resource?url=…&token=…` | 资源中转(302 跳转) | 会员 |