搜索全站
安装部署 11 分钟阅读

用 WordPress 搭建付费会员社区:等级、权限与内容保护完整方案

会员站最难的不是收钱,是把"谁能看什么"管住。本文用 Paid Memberships Pro 讲清等级设计、内容保护粒度、文件防盗链三条主线,附权限判断代码。

U
UFO_PF 2016-05-17 · 阅读 11 分钟
用 安装部署
阅读提示
本文约 4,338 字,预计阅读 11 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:权限一旦设计反了,改起来要动全站

一个付费社区通常有三种内容:完全公开的引流内容、登录可见的社区内容、按等级开放的付费内容。很多站长一开始只做了”公开 / 付费”两档,等要加”年度会员专属”时,才发现模板里到处是硬编码的 is_user_logged_in() 判断,改一处漏三处。等级的划分应该在建站第一天就按”内容粒度”倒推:你打算保护到文章级、分类级,还是某一段文字级?粒度决定了插件选型和后续维护成本。

原理分析:权限判断的三个层次

层次 粒度 实现位置 典型钩子
页面级 整页重定向 template_redirect template_redirect
内容级 单篇文章/分类 the_content、pre_get_posts pre_get_posts
片段级 段落/短代码 短代码回调 add_shortcode

主流插件里,Paid Memberships Pro(PMPro)免费版自带无限等级、内容保护与签到流程;MemberPress 规则引擎更强但为纯商业插件;Restrict Content Pro 轻量、代码干净,适合开发者。中文社区场景下,PMPro 加免费扩展是最实际的组合。

PMPro 的核心函数有三个:pmpro_hasMembershipLevel() 判断当前用户是否拥有某等级,pmpro_getMembershipLevelForUser() 取用户的等级对象,pmpro_getLevel() 取等级配置。二次开发基本围绕这三个函数展开。

保姆级实操

步骤 1:先定等级矩阵,再建等级。 把等级写成一张表:免费注册(看社区)、月度会员(看专栏)、年度会员(看专栏 + 资料库 + 答疑)。等级不要超过 4 个,等级越多用户决策成本越高。

步骤 2:安装并配置 PMPro。 在”Memberships → Settings”里设置”Membership Levels”页面、”Levels”页面与”Account”页面,插件安装向导会自动生成。支付网关先配测试模式跑通再切生产。

步骤 3:用短代码做片段级保护。 PMPro 自带 [membership level="1"]...[/membership] 短代码,适合保护文章中间的一段下载链接或答案。

// 自定义一个更贴合中文场景的片段保护短代码
add_shortcode( 'member_only', 'mimangfei_member_only_shortcode' );
function mimangfei_member_only_shortcode( $atts, $content = null ) {
    $atts = shortcode_atts( array( 'level' => '1' ), $atts, 'member_only' );
    $levels = array_filter( array_map( 'intval', explode( ',', $atts['level'] ) ) );

    if ( ! is_user_logged_in() ) {
        return '<div class="locked">该内容登录后可见,<a href="' . esc_url( wp_login_url( get_permalink() ) ) . '">点此登录</a></div>';
    }
    if ( function_exists( 'pmpro_hasMembershipLevel' ) && ! pmpro_hasMembershipLevel( $levels ) ) {
        return '<div class="locked">该内容需升级会员后可见,<a href="' . esc_url( home_url( '/pricing/' ) ) . '">查看方案</a></div>';
    }
    return do_shortcode( $content );
}

步骤 4:做页面级保护。 在 template_redirect 阶段拦截,比在模板里判断更早、更省资源,也能避免正文被节选提前输出。

add_action( 'template_redirect', 'mimangfei_protect_single' );
function mimangfei_protect_single() {
    if ( ! is_singular( array( 'post', 'page' ) ) ) {
        return;
    }
    $required = (array) get_post_meta( get_queried_object_id(), '_required_level', true );
    $required = array_filter( array_map( 'intval', (array) $required ) );
    if ( empty( $required ) ) {
        return;
    }
    if ( ! is_user_logged_in() || ! pmpro_hasMembershipLevel( $required ) ) {
        wp_safe_redirect( home_url( '/pricing/?from=' . get_queried_object_id() ) );
        exit;
    }
}

步骤 5:把受保护内容从列表里剔除。 否则首页摘要会泄露付费内容的第一段。用 pre_get_posts 加 meta_query 排除带 _required_level 的文章。

add_action( 'pre_get_posts', 'mimangfei_hide_member_posts' );
function mimangfei_hide_member_posts( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) {
        return;
    }
    if ( $query->is_home() || $query->is_archive() || $query->is_search() ) {
        if ( ! is_user_logged_in() || ! pmpro_hasMembershipLevel( array( 1, 2, 3 ) ) ) {
            $query->set( 'meta_query', array(
                array(
                    'key'     => '_required_level',
                    'compare' => 'NOT EXISTS',
                ),
            ) );
        }
    }
}

步骤 6:保护上传文件。 这是最容易被忽略的一环:文章拦住了,PDF 直链还在公网上。用 Nginx 给 wp-content/uploads/protected/ 加 internal 规则,由 PHP 鉴权后通过 X-Accel-Redirect 返回。

location ^~ /wp-content/uploads/protected/ {
    internal;
    alias /var/www/html/wp-content/uploads/protected/;
}
// 鉴权通过后由 Nginx 内部重定向输出文件,直链无法直接访问
function mimangfei_send_protected_file( $file_rel_path ) {
    if ( ! pmpro_hasMembershipLevel( array( 2, 3 ) ) ) {
        wp_die( '无权访问该文件' );
    }
    header( 'X-Accel-Redirect: /wp-content/uploads/protected/' . ltrim( $file_rel_path, '/' ) );
    header( 'Content-Type: application/pdf' );
    exit;
}

步骤 7:配置到期与续费提醒。 在 PMPro 的”Settings → Email”里开启到期前提醒,并接入 SMTP 保证送达。

常见踩坑

  1. 等级变更后缓存未刷新。 用户刚付款 upgrade,页面仍显示旧权限,需在等级变更钩子里清缓存。
  2. 首页摘要泄露付费内容。 只做了 the_content 判断,没处理 pre_get_posts。
  3. PDF 直链外泄。 上传目录没有做鉴权,搜索引擎甚至能索引到内部资料。
  4. 案例: 某会员站在模板里用 is_user_logged_in() 判断权限,结果所有注册用户(包括免费注册)都能看到年度会员专区,持续两个月才发现。根因是”登录”与”付费”被混为一谈,必须判断等级而不是登录态。
  5. 未登录跳转导致收录问题。 给爬虫返回 200 的正常内容,只对真人用户跳转。
  6. 短代码嵌套没用 do_shortcode()。 会员内容里的其他短代码不解析。
  7. 测试网关切生产时忘了换密钥。 支付一直走沙箱,订单不生效。

总结

会员站的三条主线是等级、权限、文件。判断方案是否合格的三个标准:未付费用户在服务端就拿不到正文、列表页不泄露付费摘要、上传目录的直链被 Web 服务器拦住。等级控制在 4 个以内,权限判断集中在钩子里而不是散落模板。会员到期后怎么自动降级,见会员续费与权限回收;社区互动部分怎么接,见WordPress 论坛社区搭建。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。