本文约 5,159 字,预计阅读 13 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:半夜三点的人工发货,撑不过第一个爆款
做 WordPress 主题或插件变现的独立开发者,最初的套路几乎都一样:PayPal 收款后手动打包发送。前几十单还能撑住,一旦内容被推到首页或被某个社群传播,半夜里订单蜂拥而至,你还得爬起来回邮件。更糟的是下载链接发出去就等于公开——网络上两天后就出现”破解版”。数字商品站真正需要的是三件事:付款即自动发货、下载链接有时间与次数限制、软件本身能校验用户是否真的买过。
原理分析:两条成熟路线的取舍
路线一是在 WooCommerce 里把商品勾选 Virtual(虚拟)+ Downloadable(可下载),WooCommerce 自带 Download limit 与 Download expiry 字段,权限记录在下载权限表里并与订单绑定,发货逻辑由订单状态驱动:支付完成 → 授予下载权限 → 触发邮件。
路线二是用 Easy Digital Downloads(EDD),它天生为虚拟商品设计,有 download_history、file delivery method、以及官方扩展 Software Licensing 来做激活与校验。缺点是模板与支付网关生态要重新熟悉。
| 维度 | WooCommerce 虚拟商品 | Easy Digital Downloads |
|---|---|---|
| 上手成本 | 低,已有 Woo 直接改 | 中,需另行搭建商品页 |
| 授权功能 | 需第三方商业扩展 | 官方有收费扩展 Software Licensing |
| 与博客共存 | 天然兼容 | 需处理两套 URL 结构 |
| 适合人群 | 以内容为主、顺带卖书 | 以数字产品为主业 |
下载保护层面,Nginx 下可以用内部重定向(X-Accel-Redirect)让真实文件不暴露路径:location 设为 internal;,PHP 侧返回 X-Accel-Redirect 响应头即可让 Nginx 接管发送。
保姆级实操
步骤 1:建立商品。 WooCommerce → 商品 → 新建,在「商品数据」下拉中选择 Virtual + Downloadable,上传文件到 Downloads 标签页,填入 Download limit(留空表示不限次数)与 Download expiry(过期天数,留空表示永不过期)。
步骤 2:开启自动完成。 WooCommerce → 设置 → 商品 → Virtual → 勾上 “Virtual” 商品订单在付款后自动转为 Completed,权限即刻生效,邮件自动带走下载链接。
步骤 3:锁住上传目录,仅允许经脚本取文件:
# 真实文件不允许直接 URL 访问,由 PHP 验权后通过内部重定向输出
location /wp-content/uploads/protected/ {
internal;
alias /var/www/html/wp-content/uploads/protected/;
}
步骤 4:自建 REST 接口做授权校验。 下面是一个真实可用的注册端点和校验逻辑:
add_action( 'rest_api_init', function () {
register_rest_route( 'mimangfei/v1', '/license/activate', [
'methods' => 'POST',
'permission_callback' => '__return_true',
'callback' => function ( WP_REST_Request $req ) {
$license = sanitize_text_field( $req->get_param( 'license_key' ) );
$domain = sanitize_text_field( $req->get_param( 'domain' ) );
global $wpdb;
$row = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}mf_licenses WHERE license_key = %s",
$license
) );
if ( ! $row ) {
return new WP_REST_Response( [ 'valid' => false, 'code' => 'LICENSE_NOT_FOUND' ], 404 );
}
if ( time() > strtotime( $row->expires_at ) ) {
return new WP_REST_Response( [ 'valid' => false, 'code' => 'LICENSE_EXPIRED' ], 403 );
}
$sites = array_filter( explode( ',', $row->activated_domains ) );
if ( count( $sites ) >= (int) $row->limit && ! in_array( $domain, $sites, true ) ) {
return new WP_REST_Response( [ 'valid' => false, 'code' => 'LICENSE_LIMIT_EXCEEDED' ], 409 );
}
$sites[] = $domain;
$wpdb->update(
"{$wpdb->prefix}mf_licenses",
[ 'activated_domains' => implode( ',', array_unique( $sites ) ) ],
[ 'license_key' => $license ]
);
return new WP_REST_Response( [ 'valid' => true, 'expires_at' => $row->expires_at ], 200 );
},
] );
} );
// 付款成功时生成授权码并写表(演示:真实项目请改用更安全的随机源)
add_action( 'woocommerce_order_status_completed', function ( $order_id ) {
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item ) {
if ( ! wc_get_product( $item->get_product_id() )->is_virtual() ) {
continue;
}
$key = strtoupper( wp_generate_password( 16, false, false ) );
global $wpdb;
$wpdb->insert(
"{$wpdb->prefix}mf_licenses",
[
'license_key' => implode( '-', str_split( $key, 4 ) ),
'order_id' => $order_id,
'limit' => 3,
'expires_at' => gmdate( 'Y-m-d H:i:s', time() + YEAR_IN_SECONDS ),
'activated_domains' => '',
]
);
}
} );
步骤 5:配套一张表。 插件启用时用 dbDelta 建表,注意字段之间必须两个空格:
register_activation_hook( __FILE__, function () {
global $wpdb;
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$wpdb->prefix}mf_licenses (
id bigint(20) NOT NULL AUTO_INCREMENT,
license_key varchar(64) NOT NULL,
order_id bigint(20) NOT NULL,
limit int(11) DEFAULT 3,
activated_domains text,
expires_at datetime NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY license_key (license_key)
) $charset;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
} );
步骤 6:把授权码写进邮件。 使用 woocommerce_email_order_meta 输出刚才生成的 key,用户下单后无需人工介入。
常见踩坑
- 只勾了 Virtual 忘了 Downloadable,商品页不出现 Downloads 标签,压根没有下载权限。
- 案例: 某开发者把下载文件放在公共 uploads 目录,也没有任何限制,搜索引擎第三方爬虫抓取了 PDF,一个月后盗版文档在盗盘论坛传播,退款率激增。
dbDelta()的 SQL 字段间只有一个空格,表结构更新被静默忽略。- Nginx
alias路径末尾少了斜杠,Nginx 报403 Forbidden,但 WooCommerce 侧只表现为”点了下载没反应”。 - 开了 CDN 且未排除下载路径,CDN 节点缓存了带鉴权的响应,非付费用户也能撞缓存下载。
- 授权校验接口没做频率限制,被脚本轮询爆破——至少加个 Transients 限流。WordPress 权限管理与安全加固
- 未设置产品退款政策,数码商品被滥用退款。WooCommerce 退款与售后流程
总结
数字商品站的判断标准是:发货是否全自动、文件是否无法被直接列举、授权是否可校验。行动清单:确定 WooCommerce 还是 EDD → 打通付款到 Completed 的自动转换 → 把上传目录设为内部访问 → 自建或用商业 License 扩展做校验 → 邮件注入授权信息。别急着商业化的细节,先保证”付费即交付”这一环绝对可靠。
