核心思路
整个流程的逻辑如下:

(图片来源网络,侵删)
- 用户拥有金币:用户需要在网站上注册、登录,并通过某种方式(如充值、签到、发布内容等)获得金币。
- 下载资源消耗金币:当一个用户想要下载一个设置了金币价格的资源时,系统会先检查他的金币余额。
- 扣款与授权:
- 如果余额足够,系统会扣除相应数量的金币,然后生成一个临时的、有时效的下载链接,并允许用户下载。
- 如果余额不足,则提示用户金币不足,引导他去充值或获取金币。
- 防止盗链:下载链接必须是临时的,并且经过加密验证,防止用户将链接分享出去导致资源被盗用。
实现步骤
我们将分步完成这个功能。
第一步:准备工作
-
织梦环境:确保你已经有一个可正常运行的织梦CMS网站。
-
FTP/SFTP工具:用于修改服务器上的文件。
-
文本编辑器:用于修改PHP文件(推荐使用VS Code、Sublime Text等)。
(图片来源网络,侵删) -
金币/积分系统:织梦默认没有金币系统,你有两个选择:
- 使用现有插件:去织梦官方论坛或第三方市场寻找并安装一个“会员积分系统”或“金币系统”插件,这是最简单快捷的方式。
- 手动创建:如果不想用插件,可以手动在
dede_member表中增加一个money字段来存储用户金币,本教程将基于此假设进行。
操作:登录你的数据库管理工具(如phpMyAdmin),执行SQL语句:
ALTER TABLE `dede_member` ADD `money` DECIMAL(10,2) NOT NULL DEFAULT '0.00';
这会给所有会员表增加一个
money字段,初始值为0。
第二步:修改下载模型,增加金币价格字段
我们需要让后台编辑文章时,可以为下载资源设置一个金币价格。

(图片来源网络,侵删)
-
找到模型文件:
- 下载功能的模型通常是“软件”或“下载”模型,其配置文件位于
/dede/soft_add.php(添加) 和/dede/soft_edit.php(编辑),如果你使用的是默认的“文章”模型,则需要修改article_add.php和article_edit.php,我们以最常见的“软件”模型为例。
- 下载功能的模型通常是“软件”或“下载”模型,其配置文件位于
-
修改添加页面 (
soft_add.php):- 找到文件中类似
//增加自定义字段的部分。 - 在合适的位置(本地地址”输入框下方)添加以下HTML代码:
<tr> <td class="bline" height="26" style="width:*;">金币价格:</td> <td class="bline" colspan="2"> <input name="money" type="text" id="money" value="0" size="10" class="alltxt" /> <span>用户下载此资源需要消耗的金币数量,0表示免费</span> </td> </tr>
- 找到文件中类似
-
修改编辑页面 (
soft_edit.php):- 同样地,在
soft_edit.php中找到类似位置,添加相同的HTML代码。
- 同样地,在
-
保存数据到附加表:
- 这是最关键的一步,织梦下载模型的数据存储在
dede_downloads或dede_softadd表中(取决于你的版本和模型配置),我们需要确保money字段被插入和更新。 - 在
soft_add.php文件中,找到执行SQL插入语句的地方(通常在文件末尾),确保你的SQL语句包含了money字段。// 假设你的附加表是 dede_downloads $inquery = "INSERT INTO `dede_downloads`(typeid, typeid2, tpid, user, writer, source, litpic, title, pubdate, senddate, mid, click, isgood, istop, iscommend, color, arcrank, posttype, filename, dutyadmin, money, ...) VALUES ('$typeid', '$typeid2', '$tpid', '$username', '$writer', '$source', '$litpic', '$title', '$nowtime', '$nowtime', '$mid', '0', '$isgood', '$istop', '$iscommend', '$color', '$arcrank', '0', '$filename', '$adminid', '$money', ...)"; $dsql->ExecuteNoneQuery($inquery); - 同样,在
soft_edit.php中找到更新语句,也要确保包含money字段的更新。 - 重要:你还需要确保
dede_downloads表中有money这个字段,如果不存在,请先执行SQL添加:ALTER TABLE `dede_downloads` ADD `money` INT(10) NOT NULL DEFAULT '0';
- 这是最关键的一步,织梦下载模型的数据存储在
第三步:修改下载页面,实现扣款和跳转
这是核心逻辑部分,用户点击下载链接时,会触发这里的代码。
-
找到下载处理文件:
- 织梦的下载处理通常在
/plus/download.php文件中。
- 织梦的下载处理通常在
-
修改
download.php:- 用文本编辑器打开
/plus/download.php。 - 找到获取下载链接地址的代码,通常在文件开头部分,类似
$link = $_GET['link'];。 - 在获取
$link之后,立即插入我们的金币验证和扣除逻辑。
完整的修改示例代码(请根据你的实际情况调整):
<?php require_once(dirname(__FILE__)."/../include/config_base.php"); require_once(DEDEINC."/arc.partview.class.php"); // --- 开始金币下载逻辑 --- $link = trim($_GET['link']); $money = 0; // 默认价格 // 1. 检查用户是否登录 if($cfg_ml->IsLogin()) { // 2. 获取当前下载资源的金币价格 // 假设你的下载地址格式是 /uploads/soft/1.zip,我们可以通过文件名去查询数据库 // 注意:这是一种简单的方法,更精确的方法是获取文章ID,然后查询附加表 $fileUrl = $link; $fileQuery = "SELECT money FROM dede_downloads WHERE url LIKE '%".basename($fileUrl)."%' LIMIT 1"; $row = $dsql->GetOne($fileUrl); if($row) { $money = $row['money']; } // 3. 如果价格大于0,则进行扣款检查 if($money > 0) { $userid = $cfg_ml->M_ID; // 获取当前登录用户ID $userMoney = $cfg_ml->GetMoney(); // 获取用户当前金币余额(如果你的积分系统没有GetMoney方法,需要自己写一个查询) // 4. 检查余额是否足够 if($userMoney < $money) { // 余额不足,提示并跳转 ShowMsg("您的金币余额不足,当前需要 {$money} 个金币!请先充值。", "-1"); exit(); } // 5. 余额足够,执行扣款 // 注意:这里直接调用会员的金钱扣除函数,如果你的积分系统不同,请修改此部分 $cfg_ml->MoneyCost($money); // 6. 扣款成功,记录日志(可选,但强烈推荐) $logQuery = "INSERT INTO dede_moneylog(mid, money, remark, `datetime`) VALUES ({$userid}, -{$money}, '下载资源:{$fileUrl}', NOW())"; $dsql->ExecuteNoneQuery($logQuery); // 7. 扣款成功,允许下载 // 这里直接跳转到原始下载链接 header("Location: $link"); exit(); } else { // 如果是免费资源,直接下载 header("Location: $link"); exit(); } } else { // 未登录,提示登录 ShowMsg("您尚未登录,请先登录后再下载!", "member/login.php?gourl=".urlencode($link)); exit(); } // --- 结束金币下载逻辑 --- // ... 下面是织梦原有的下载处理代码 ... // 为了避免冲突,你可能需要注释掉或删除原有的 $link 处理逻辑, // 或者将我们的逻辑整合进去。 // 原来的代码大概是下面这样的,现在我们已经处理了,可以注释掉 /* $link = trim($_GET['link']); if(empty($link)) { ShowMsg('下载地址不能为空!', '-1'); exit(); } */ // ... 其余代码保持不变 ... ?>代码解释:
- 检查登录:
$cfg_ml->IsLogin()判断用户是否登录。 - 获取价格:通过查询
dede_downloads表,找到当前下载文件对应的价格。注意:这个查询可能不够健壮,更好的方式是通过文章ID来关联查询。 - 检查余额:
$cfg_ml->GetMoney()获取用户余额(如果不存在此方法,你需要自己写一个查询dede_member表中money字段的函数)。 - 扣款:
$cfg_ml->MoneyCost($money)调用织梦自带的金钱扣除函数。 - 记录日志:在
dede_moneylog表中记录一笔支出,方便用户和对账。 - 跳转:
header("Location: $link");扣款成功后,直接跳转到真实的下载文件地址。
- 用文本编辑器打开
第四步:安全与优化
-
防止盗链:
- 上面的
download.php跳转已经提供了一层保护。 - 更高级的保护是在服务器层面(如Nginx或Apache)配置,禁止对
uploads或其他存放真实文件的目录进行直接访问,只允许通过download.php脚本访问,这能有效防止用户获取真实URL后分享。
- 上面的
-
下载链接的时效性:
- 为了更安全,
download.php生成的下载链接应该是临时的,包含一个有时效的token。 - 实现思路:用户点击下载时,
download.php生成一个唯一的、有时效的token(基于用户ID、文件ID、时间戳和密钥生成的MD5值),并将token和文件ID存入一个临时表,然后跳转到download.php?token=xxx&id=xxx。download.php验证token的有效性(是否过期、是否匹配),验证通过后才执行扣款和跳转,这能大大提高安全性。
- 为了更安全,
-
事务处理:
在扣款和记录日志时,最好使用数据库事务(Transaction),确保“扣款”和“记录日志”这两个操作要么都成功,要么都失败,避免出现扣款了但没有记录的异常情况。
实现织梦的金币下载功能主要分为三大部分:
- 后端设置:为会员表和下载附加表添加
money字段,并修改后台添加/编辑模板,让编辑者可以设置价格。 - 核心逻辑:修改
/plus/download.php文件,在其中嵌入用户登录验证、金币余额查询、扣款和跳转的逻辑。 - 安全加固:通过服务器配置和引入临时Token机制来防止盗链,确保系统安全。
这个方案涵盖了从基础到进阶的实现方法,你可以根据自己的技术能力和需求选择性地实现某些步骤,对于新手,建议先完成前三步,确保基本功能跑通,再逐步考虑安全优化。
