资讯动态

帝国CMS新闻模型付费阅读:部分内容隐藏与会员免费查看完整实现

发布时间:2026/10/23 5:23:06 来源:尧图企业网站定制
简介帝国CMS新闻模型内容隐藏付费查看方案是一套面向网站管理员与开发者的轻量级付费阅读工具通过后台权限配置、多级会员等级判断以及SQL字段调整可实现部分正文仅对付费用户或指定等级会员开放。资源内整合了后台SQL执行脚本、输入表单替换HTML代码、Ecmsshop插件安装文档以及PHP、JS、CSS等前后端文件共20个文件压缩包仅120KB便于快速部署目前已有554人学习被用于新闻资讯、在线教育、知识付费等场景。借助这套方案运营者不必从零开发支付逻辑只需替换相应表单与接口参数即可搭建会员免费查看、付费解锁内容及支付对接的完整流程。同时支持设置特定会员免费查看让不同等级用户获得差异化体验。包内目录结构清晰SQL脚本与HTML片段可直接套用适合快速二次开发。1. “帝国CMS新闻模型部分内容隐藏付费查看”为什么成了内容站的刚需做行业资讯、报告解读、付费专栏这类站点的人大概率都碰到过同一个诉求文章前两段公开中间干货或者结论部分要付费才能看同时站里的 VIP 会员又能免费看。这个需求在帝国CMS上尤其常见因为帝国CMS的内容模型、会员系统已经相当完整但官方自带的收费功能更偏向“整篇收费”做不到“文章前两段免费、后半段付费”这种颗粒度。于是大家开始折腾“新闻模型部分内容隐藏付费查看(支持设置会员免费查看)”这套玩法本质上它就是把一篇文章拆成公开段和隐藏段根据当前访问者的登录状态、会员组、是否购买过这三个条件决定要不要把隐藏段吐出来。这篇文章我按自己做过这个功能的完整路径来讲从方案选型、后台字段设计、模板改造写到付费接口和常见翻车点。适合用帝国CMS做内容站、又想引入付费阅读或会员权益的开发者。你不需要懂很深的口语化玄学跟着步骤走就能在自己的站上复现只有几个地方容易踩坑我会在单独一章里全部讲透。2. 先选型三种“隐藏收费”方案的边界与代价2.1 模板PHP直判最直观但要分清动态与静态把“是否输出收费内容”的判断直接写进内容页模板是新手最容易想到的第一个方案。逻辑很直白在模板里取当前文章字段取当前会员组ID然后判断一次条件成立就输出 $navinfor[pay_content]不成立就输出一个“付费查看”的按钮和提示。这个方案适合内容更新频率低、访问量不大、并且你没有开启整站全静态生成的站点。因为在帝国CMS里内容页模板支持直接嵌入PHP代码只要后台开启了“模板中使用PHP代码”的选项代码会在每次访问时被解析并执行。但要注意如果你用的是生成静态页的模式这个判断只会在“生成静态页的那一刻”执行一次。默认游客访问静态页看到的都是生成时的那版HTML这就会导致“用户付费后页面还是锁着的”这种血泪场面。后面我会在避坑章节用完整案例说这件事。这个方案的最大优点是无需额外写接口和前端JS模板里几段代码就能跑通。缺点是只要开过静态化实时性就完蛋另外如果你不小心把收费内容字段直接输出了哪怕用CSS隐藏查看源代码照样能看到完整内容。2.2 前端隐藏JS解锁体验顺滑却挡不住“查看源代码”第二种做法是把完整内容输出到页面上但是用CSS或者注释块把收费部分隐藏起来然后等用户点击“付费查看”按钮时用JS把隐藏部分展开。这种方案体验非常好点击立即展开不需要刷新页面也不需要额外请求服务器因为内容本来就在当前HTML里。但是这里有一个非常致命的边界任何一个访问者打开这个页面按一下键盘上的“查看源代码”就能直接把付费内容复制走。哪怕你加了JS动态渲染只要首屏HTML里存在付费文本它就不具备“保护”属性。有些开发者误以为把隐藏内容塞进JS变量就安全了其实在浏览器开发者工具里照样一眼看穿。所以这个方案只适合图省事、内容价值不高的站点或者你根本不担心搬运只是想做一个“形式上的付费门槛”。另外它还有一个隐性问题SEO。搜索引擎的爬虫不会点击付费按钮它在页面上能抓到的还是完整内容这等于你把整篇文章免费送给了搜索引擎用户搜索时在摘要里就能看到大部分正文付费转化率会明显受影响。2.3 后端接口下放内容保证页面零泄露的正解第三种方案是把公开内容和收费内容彻底分开内容页模板只输出公开部分收费部分存放在后台字段里不在页面HTML中出现。用户想要看收费部分时必须触发一个动作比如点击按钮后通过AJAX请求接口接口会校验当前登录态、会员组、是否已购买通过后才把收费内容作为JSON返回值交给前端JS渲染到页面上。这个方案相对复杂一点但它同时解决了三个问题第一首屏HTML里完全没有收费内容查看源代码拿不到第二接口是实时校验的用户花钱购买后立刻生效不需要等静态页重新生成第三你可以把接口放在自己的后台目录下配合帝国CMS的登录态和会员组机制把免费查看的会员组判断也一起做进去。这是我最推荐的做法也是后面几章里主要展开的路径。实际的落地流程是后台加字段 → 模板改判断 → 写一个付费查看接口 → 前端AJAX联动 → 搭配会员组条件放行。往下走每一步都有可以照抄的代码。3. 落地核心新闻模型自定义字段与内容页模板改造3.1 后台加 pay_content 字段字段参数怎么定以最常见的新闻模型为例后台路径大致是“系统设置 → 数据表管理 → 新闻模型数据表 → 管理字段”不同帝国CMS版本菜单叫法略有差异。进入字段管理界面后点击“新增字段”。这里的字段名建议命名为 pay_content含义直白模板里引用也方便。字段类型这一项要慎重。如果你收费部分也包含图片、表格、段落格式建议选择“编辑器”类型这样在后台录新闻时可以直接用富文本排版和正文编辑体验一致。如果你只需要存放纯文本选“文本域”或者“大文本”就够了。新增字段的时候有几个参数需要注意后台“录入表单”选“显示”这样编辑新闻时才能看到输入框“前台列表显示”必须选“否”否则帝国CMS会在列表页自动把该字段值带出来这是一个非常隐蔽的泄露点后面避坑章会细说“前台搜索”选“不参与搜索”避免把收费内容被搜出来。第二步确认你的新闻模型前台的模板变量叫法。帝国CMS内容页模板里我们可以用全局数组 $navinfor 来取当前文章的字段值。新增字段之后$navinfor[pay_content] 就是收费内容。如果你用标签方式 [!--pay_content--] 也会生效但我们在模板里要写PHP判断所以我更习惯用 $navinfor 数组方式它方便做条件分支。3.2 内容页模板PHP逻辑示例脚本与参数说明在内容页模板的合适位置一般是正文输出结束之后插入下面这段PHP代码。先确认系统设置里已经开启“模板中使用PHP代码”代码生效的前提是当前访问用户信息已经在全局变量中存在。未登录用户和已登录用户的判断用 $userid帝国CMS的常规变量中未登录时它是空值或0。?php // 内容页模板部分内容隐藏付费查看 global $navinfor, $userid, $groupid; // 取出后台录入的收费内容 $payContent trim($navinfor[pay_content]); if(empty($payContent)) { // 没有设置收费内容直接输出全文 echo $navinfor[newstext]; } else { // 设置可免费查看的会员组ID例如数组中的 2 和 3 $freeGroups array(2, 3); $isFreeGroup in_array($groupid, $freeGroups); // 检查当前用户是否已经购买过这篇文章 $hasPaid check_article_paid($navinfor[id], $userid); if($isFreeGroup || $hasPaid) { // 会员免费查看或已购买输出完整内容 echo $navinfor[newstext] . div classpay-content . $payContent . /div; } else { // 游客或未购买输出公开部分 付费提示 echo $navinfor[newstext]; echo div classpay-tips p剩余内容为付费部分请登录后购买或开通会员免费查看。/p button classpay-btn>?php // 判断用户是否已购买指定文章 function check_article_paid($artid, $userid) { global $empire, $dbtbpre; if(empty($artid) || empty($userid)) { return false; } $artid intval($artid); $userid intval($userid); // 查询自建的购买记录表 ecms_pay_log $sql SELECT id FROM {$dbtbpre}ecms_pay_log WHERE artid$artid AND userid$userid LIMIT 1; $r $empire-fetch1($sql); return $r ? true : false; }这里涉及一张自建数据表 ecms_pay_log建议字段包括id自增主键、artid文章ID、userid购买用户ID、price支付金额、paytime购买时间。你可以在帝国CMS后台通过“系统设置 → 数据表管理 → 新建数据表”的方式创建也可以直接用SQL执行。无论哪种方式记得给 artid userid 这两个字段设一个唯一索引这能在程序逻辑出现极端并发时兜底防止同一用户对同一篇文章被重复扣费。购买记录表和会员免费组判断配合起来就实现了“部分文章对指定会员组免费其他用户必须付费”的完整逻辑。注意 $empire 和 $dbtbpre 是帝国CMS两个核心全局变量分别代表数据库查询对象和表前缀在函数内必须用 global 引入否则你会被“数据库查询失败”这类错误卡住。4.3 付费按钮和接口返回逻辑的联动模板里已经输出了“付费查看全文”按钮现在要让点击按钮之后真正完成付费或者解锁。完整的交付路径是前端AJAX请求 → 后端接口校验 → 扣费并写购买记录 → 返回完整收费内容 → 前端替换展示。接口文件可以命名为 pay_article.php放在 e/extend/ 目录下。代码必须引入帝国CMS的核心初始化文件然后从POST参数里取文章ID结合当前登录态做判断?php // e/extend/pay_article.php require_once(../class/connect.php); require_once(../class/db_sql.php); require_once(../class/member.php); $link db_connect(); $empire new dbquery(); header(Content-Type: application/json; charsetutf-8); // 取参数与当前登录用户 $artid intval($_POST[artid]); $userid intval($userid); if(empty($artid) || empty($userid)) { exit(json_encode(array(code0, msg请先登录))); } // 查文章信息和收费内容 $art $empire-fetch1(SELECT id, title, price, pay_content FROM {$dbtbpre}ecms_news WHERE id$artid LIMIT 1); if(empty($art[id])) { exit(json_encode(array(code0, msg文章不存在))); } // 检查是否已购买 if(check_article_paid($artid, $userid)) { exit(json_encode(array(code1, data$art[pay_content]))); } // 检查余额或点数这里假设会员扩展表里存了 money 字段 $member $empire-fetch1(SELECT money FROM {$dbtbpre}ecms_member WHERE userid$userid LIMIT 1); if($member[money] $art[price]) { exit(json_encode(array(code0, msg余额不足))); } // 扣费并写入购买记录 $newMoney $member[money] - $art[price]; $empire-query(UPDATE {$dbtbpre}ecms_member SET money$newMoney WHERE userid$userid); $empire-query(INSERT INTO {$dbtbpre}ecms_pay_log (artid, userid, price, paytime) VALUES ($artid, $userid, {$art[price]}, .time().)); exit(json_encode(array(code1, data$art[pay_content]))); ?这段接口代码里price 是你在新闻模型新加的收费价格字段金额单位可以是元也可以是站内点数但要和会员表的 money 字段口径保持一致。扣费和插入购买记录之间没有启用事务高并发下有极小概率造成重复扣款。解决思路有两个一是给 ecms_pay_log 加 artiduserid 唯一索引二是把扣款语句写成 UPDATE ... SET money money - 价格 WHERE userid 用户 AND money 价格这样当余额不足时受影响行数为0后续插入购买记录也不会执行。这里我保留了最简洁的写法方便你理解主流程生产环境记得把这两道保险加上。5. 上线最容易翻车的五个坑现象、原因与处理5.1 模板PHP直接不执行现象内容页模板里写了完整的PHP判断代码但打开页面后这部分代码被当作普通文本输出页面上出现大段 php 源码或者干脆被注释掉什么都不显示。原因最常见的是两个一是系统设置里的“模板是否支持PHP代码”没有开启二是模板的PHP代码块被帝国CMS自己的标签解析给篡改了。如果你把PHP代码写在模板的编辑界面里且代码包含了像 [!--...--] 这样的文本帝国CMS会在解析标签时先处理掉一部分代码。解决先去“系统设置 → 参数设置”确认模板PHP支持处于开启状态。代码块里尽量不要用帝国CMS的标签符PHP代码单独放在模板尾部的嵌入区域或者通过 include 引入外部PHP文件比如把整个判断逻辑都放进 pay_function.php模板里只写一行 。这样最干净也不会和模板标签机制打架。5.2 列表页和栏目页把收费内容带出来了现象首页、栏目页、搜索结果的摘要里出现了收费内容甚至文章的多数正文在列表页就完整露出用户体验变成“根本不需要付费”。原因帝国CMS的列表模板如果有调用新闻模型字段的地方或者后台新增字段时“前台列表显示”参数选择了“是”列表查询会把 pay_content 字段直接加载并输出到页面。解决立即在后台字段管理里把 pay_content 的“前台列表显示”改成“否”。另外检查一遍列表模板确认没有手写引用 pay_content 的地方。如果你用灵动标签或者SQL标签取列表也要在标签参数里排除这个字段。这个坑不显眼但一旦泄露付费率会直接归零。5.3 生成静态页后“交了钱看不到”现象用户已经支付成功接口也显示购买成功但刷新内容页后还是看不到收费内容页面始终是付费提示。原因你开启了帝国CMS整站生成静态页的功能。内容页模板里的PHP判断是在“生成HTML文件那一刻”执行的也就是生成静态页时你用什么身份访问生成出来的页面就以那个身份的判断结果为准。你以游客身份生成页面就是锁定状态就算用户购买后也不会自动重新生成一次针对他的页面。解决核心方案是避开静态页上做实时权限判断。内容页模板只输出一个固定的“加载区域”容器里面什么都不放用AJAX从接口读取当前用户是否有权看到收费内容如果有就显示完整内容。静态页本身不包含任何收费内容也不会因为生成时机不同而出错。如果你不想改造接口还有一个临时方案把所有涉及付费查看的文章设置成“动态访问”也就是在栏目设置里把内容页生成方式改为动态但这会牺牲一点访问性能流量大时不推荐。5.4 会员免费组配置了却不生效现象后台明明把某会员组设为免费但该组用户登录后访问文章仍然看到付费提示。原因大概率是 $groupid 没有正确取到当前登录用户的组ID。一种情况是模板中PHP代码在执行时作用域不对$groupid 没有被 global 声明拿到的是空值另一种情况是免费组ID写错了后台显示的组ID和数组里存的ID不一致。还有一个小概率用户的登录状态在帝国CMS中不是挂在 $groupid 上而是挂在别的全局变量里老版本CMS不同模板引擎下的变量名略有差异。解决先在模板PHP的入口处 var_dump($userid) 和 var_dump($groupid)确认登录用户访问页面后这两个值到底是什么。确认后再把免费组数组改成实际ID。代码里用 in_array 之前加一个空值保护$groupid intval($groupid)这样未登录时按0处理不会出现类型不匹配导致的判断失误。5.5 挖走内容的方式查看源代码与接口重放现象发布付费文章后第二天在其他平台看到完整内容的转载。原因查看页面源代码发现完整HTML里就包含了收费内容或者是接口返回的数据没有做任何时效性或身份校验别人可以直接用脚本请求接口批量拉全站收费内容。解决前端隐藏方案必须淘汰这是前提。接口方案要注意几点第一接口必须校验登录态和购买状态第二收费内容返回时不要一次性返回整篇全部内容配合全文输出即可但绝不能允许接口不带参数批量查询第三在接口里加上每用户每分钟的请求频次限制。如果站内文章价值很高可以进一步考虑接口返回的内容做一次简单加密前端拿到后动态解码渲染但这会明显增加开发量视内容价值决定要不要做。6. 再往前一步试读字数控制与“已购内容”聚合页6.1 用 mb_substr 控制试读长度收费文章并不一定非要遵循“正文部分全部公开”的逻辑。很多内容站希望公开区域只显示开头一两千字让用户对文章质量有感知但不至于看完关键内容。这个需求可以在模板里对公开部分做截取控制不需要额外处理字段。数组判断后如果进入未付费分支可以先把 $navinfor[newstext] 用 mb_substr 截断再接一个“继续阅读”的跳转锚点。注意如果公开部分包含HTML标签和图片直接截断会破坏标签结构。更稳的做法是配合 strip_tags 先去掉标签再截字最后加上省略号。代码示例如下?php // 按字符数截取公开部分作为试读 global $navinfor; $newsBody $navinfor[newstext]; $newsBodyPlain strip_tags($newsBody); $previewText mb_substr($newsBodyPlain, 0, 800, utf-8); echo div classpreview-text . htmlspecialchars($previewText) . .../div;这个技巧适合把高价值文章做成“标题开头一段付费”内容中段的精华不再免费露出。它将正文彻底降级为素材源真正对外展示的部分完全由代码控制。如果不想丢失富文本排版可以按HTML结构截取但那需要额外处理标签闭合做一个简易HTML截断函数这里不再展开。6.2 给登录用户一个“我的已购”聚合页付费功能上线以后用户最常问的一句话是“我买过的文章去哪里看”。帝国CMS默认的会员中心没有这个列表需要自己做一个简单页面。实现方式不复杂查询 ecms_pay_log 表关联新闻模型主表倒序输出已购文章标题和购买时间标题加上链接即可。接口或者会员页面里可以这样查询SELECT l.*, n.title, n.classid FROM {$dbtbpre}ecms_pay_log l LEFT JOIN {$dbtbpre}ecms_news n ON l.artid n.id WHERE l.userid 当前用户ID ORDER BY l.paytime DESC LIMIT 20这里用了一个两个表的联接把购买记录里只存的文章ID扩展成可直接点击的标题和栏目信息。给这个列表加上分页就能成为一个功能完整的“已购文章”页面。页面入口可以放在帝国CMS会员中心菜单里也可以在导航栏单独加一个链接。这样做的好处是用户对已购内容有确认感复购和信任度都会提升。我自己第一次做这个功能时也翻过车——当时只是在内容页上做了付费判断没有已购回看入口结果用户退款申诉率明显上升后来补上聚合页才算闭环。所以功能范围建议一次做全宁可前期多写一个查询页也不要让用户付费之后找不到内容入口。以上这套组合下来你得到的就是一个符合标题诉求的帝国CMS新闻模型付费阅读方案后台新增收费字段内容页区分公开和付费部分付费接口校验并扣费会员免费组直接放行再加一个已购列表做收尾。每个环节都用最简单直接的方式落地边界和坑在前面也都做了说明。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑