关于 digital-products
digital-products 是指导开发者和店铺运营者配置数字商品交付的技能,涵盖平台原生功能、第三方应用及自定义安全下载方案。
主要功能
- 01比较各平台的数字商品交付方式
- 02配置下载次数与有效期
- 03提供许可证密钥交付建议
- 04说明订阅内容访问控制
- 05介绍 S3 预签名链接
适用场景
- 01为购买者配置文件下载与交付邮件
- 02向软件购买者分配许可证密钥
- 03为订阅内容设置访问和撤销规则
- 04为无原生功能的店铺设计安全下载
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill digital-products安装后在 Claude Code 中输入/digital-products确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/license-key-pool-management-and-inventor/criteria.jsontask.mdevals/post-purchase-access-provisioning-and-de/criteria.jsontask.mdevals/secure-presigned-download-urls/criteria.jsontask.md详细介绍
数字产品
概述
销售数字产品——电子书、软件许可证、模板、音乐、课程——需要在付款后安全交付,设置下载次数限制以防止未经授权的分享,并提供会过期的访问链接。每个主流平台要么内置了此功能(WooCommerce),要么有成熟的应用可处理此事(Shopify、BigCommerce)。优先使用平台的原生解决方案;只有当你的使用场景(复杂的许可证密钥管理、订阅门控的内容库)超出应用的能力时,才构建自定义交付基础设施。
何时使用此技能
- 为现有商店添加可下载产品(PDF、软件、音频、模板)时
- 为软件产品实现许可证密钥交付系统时
- 构建通过订阅控制数字内容库访问权限的功能时
- 将可公开访问的下载 URL 替换为安全、会过期的签名 URL 时
核心说明
步骤 1:确定平台并选择合适的工具
| 平台 | 推荐工具 | 原因 |
|---|---|---|
| Shopify | Sky Pilot 或 Fileflare | Sky Pilot 支持文件、许可证密钥、流媒体视频和下载次数限制;Fileflare 更简单,适用于基本文件下载 |
| WooCommerce | WooCommerce 可下载产品(内置) | WooCommerce 原生支持数字产品,包括下载次数限制、有效期和安全令牌 URL |
| BigCommerce | 可下载数字产品(内置)或 Fileflare | BigCommerce 原生支持文件附件和下载交付 |
| 自定义 / 无头架构 | 使用 S3 预签名 URL 构建交付功能 | 当平台不支持原生数字产品时必需 |
步骤 2:平台专属设置
Shopify
Shopify 不原生支持数字产品,因此你需要安装应用。Sky Pilot 是功能最全面的选项。
设置 Sky Pilot:
- 从 Shopify 应用商店安装 Sky Pilot
- 前往 Sky Pilot → Files → Upload 上传你的数字文件(PDF、ZIP 等)
- 前往 Sky Pilot → Products,将已上传的文件关联到特定产品或变体
- 配置交付设置:
- 下载次数限制:标准产品设为 3–5 次,订阅产品设为不限次数
- 链接有效期:通常为 48–72 小时;客户可以从自己的账户申请新链接
- 自动交付:默认启用——客户付款后会立即收到下载邮件
- 在 Sky Pilot → Settings → Email template 中自定义交付邮件
许可证密钥产品:
- 在 Sky Pilot 中,前往 License Keys → Import,上传包含许可证密钥的 CSV 文件
- 将许可证密钥池关联到产品
- Sky Pilot 会自动为每笔购买分配一个密钥,并将其包含在交付邮件中
订阅门控内容(Sky Pilot + Recharge):
- Sky Pilot 与 Recharge 集成——拥有有效订阅的客户会自动获得访问权限;订阅取消时,访问权限会被撤销
WooCommerce
WooCommerce 内置数字产品交付功能,基本使用无需额外安装插件。
设置可下载产品:
- 前往 WooCommerce → Products → Add Product
- 勾选 Downloadable(还可选中 Virtual,以跳过配送)
- 在 Product Data → Downloadable Files 下:
- 点击 Add File 并上传文件或输入 URL
- 文件名:显示在客户账户中的名称
- 配置访问设置:
- Download limit:输入次数(例如
5),或留空表示不限制 - Download expiry:购买后的天数(例如
365),或留空表示永不过期
- Download limit:输入次数(例如
- WooCommerce 会自动为每笔购买生成安全的基于令牌的下载 URL
强制客户登录账户才能下载:
- 前往 WooCommerce → Settings → Accounts & Privacy
- 启用 Grant access to downloadable products after payment 和 Require login to download
对于许可证密钥产品:
- 安装 License Manager for WooCommerce(免费插件)
- 前往 License Manager → Add License Keys,批量导入密钥
- 将许可证密钥池关联到产品
- 插件会通过订单确认邮件和客户账户页面交付密钥
BigCommerce
设置数字产品交付(内置功能):
- 前往 Products → Add Product
- 在 Files 下上传数字文件(BigCommerce 支持最大 512 MB 的文件)
- 设置 Max downloads,以限制每笔订单的文件下载次数
- 付款后,BigCommerce 会自动发送包含安全链接的下载邮件
更高级的交付方式:
- 从 BigCommerce App Marketplace 安装 SendOwl 或 Fileflare
- 这些应用可添加许可证密钥管理、下载分析和流媒体视频交付功能
自定义 / 无头架构
对于无头商店,可使用 S3 预签名 URL 实现安全文件交付 — 切勿暴露原始 S3 密钥:
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const s3 = new S3Client({ region: process.env.AWS_REGION });
// Generate a short-lived presigned URL for each download attempt
export async function generateDownloadUrl(orderId: string, digitalProductId: string) {
const access = await db.orderDigitalAccess.findUnique({
where: { orderId_digitalProductId: { orderId, digitalProductId } },
include: { digitalProduct: true },
});
if (!access) throw new Error('No access record found');
if (access.expiresAt && access.expiresAt < new Date()) throw new Error('Download access has expired');
if (access.maxDownloads && access.downloadCount >= access.maxDownloads) throw new Error('Download limit reached');
// Atomically increment download count
await db.orderDigitalAccess.update({ where: { id: access.id }, data: { downloadCount: { increment: 1 } } });
// 60-second presigned URL — short enough to prevent sharing, long enough for the redirect
const command = new GetObjectCommand({
Bucket: process.env.DIGITAL_PRODUCTS_BUCKET,
Key: access.digitalProduct.fileStorageKey,
ResponseContentDisposition: `attachment; filename="${access.digitalProduct.fileName}"`,
});
return getSignedUrl(s3, command, { expiresIn: 60 });
}
// Provision access after payment — call this from your payment webhook
export async function provisionDigitalAccess(orderId: string) {
const order = await db.orders.findUnique({
where: { id: orderId },
include: { items: { include: { variant: { include: { digitalProduct: true } } } } },
});
for (const item of order.items.filter(i => i.variant.digitalProduct)) {
const dp = item.variant.digitalProduct;
await db.orderDigitalAccess.upsert({
where: { orderId_digitalProductId: { orderId, digitalProductId: dp.id } },
create: {
orderId, digitalProductId: dp.id, downloadCount: 0,
maxDownloads: dp.downloadLimit,
expiresAt: dp.accessDurationDays ? new Date(Date.now() + dp.accessDurationDays * 86400000) : null,
},
update: {}, // Idempotent — webhooks can fire multiple times
});
}
}
// License key pool management
export async function assignLicenseKey(orderId: string, productId: string) {
return db.$transaction(async tx => {
const license = await tx.digitalProductLicenses.findFirst({
where: { productId, status: 'available' },
});
if (!license) throw new Error(`No available license keys for product ${productId}`);
await tx.digitalProductLicenses.update({
where: { id: license.id },
data: { status: 'sold', orderId, soldAt: new Date() },
});
return license.licenseKey;
});
}
步骤 3:配置购买后交付邮件
所有平台都会自动发送交付邮件 — 请将其自定义得清晰、专业:
应包含的内容:
- 订单确认编号
- 产品名称和描述
- 下载链接(或醒目显示的许可证密钥)
- 适用时注明下载次数限制和过期日期
- 产品访问或安装说明
- 客户遇到问题时的支持联系方式
Shopify(Sky Pilot): 在 Sky Pilot → Settings → Email Template 下自定义
WooCommerce: 在 WooCommerce → Settings → Emails → Customer Processing Order 下自定义(会自动包含下载链接)
BigCommerce: 在 Marketing → Transactional Emails → Order Status Notification 下自定义
步骤 4:监控许可证密钥库存
对于许可证密钥产品,请在密钥用完前设置提醒:
- Sky Pilot:前往 License Keys → [Product] — 查看剩余密钥数量;当库存低于你配置的阈值时,Sky Pilot 会发送邮件提醒
- License Manager for WooCommerce:仪表板会显示每款产品的剩余密钥数量,并通过颜色标记发出警告
- 自定义:每天检查一次,并在可用密钥少于 10 个时发出提醒
最佳实践
- 确认付款后再交付数字产品——通过付款确认 Webhook 触发交付,而不是通过订单创建事件;订单创建后仍可能发生银行卡拒付
- **使用短时有效的下载链接(60 秒)**用于无头实现——每次下载页面加载时重新生成 URL,而不是在页面渲染时生成
- 为大多数产品设置下载次数限制——3–5 次是常见设置;订阅访问可设为不限次数;限制可防止随意共享文件
- 将文件存储在私有存储桶中——切勿将 S3/GCS 存储桶设为公开;所有访问都必须通过签名 URL 生成来实现
- 监控许可证密钥库存——密钥耗尽会导致支持请求和拒付;当库存低于初始数量的 20% 时设置提醒
- 单独发送专门的交付邮件——不要将许可证密钥附在通用订单确认邮件中;内容专一的交付邮件更便于客户查找和查看
常见问题
| 问题 | 解决方案 |
|---|---|
| 下载链接在客户点击前过期 | 对于无头构建,在每次页面加载时生成新的预签名 URL,而不是在发送邮件时生成 |
| 付款失败后仍交付了数字产品 | 仅通过付款成功 Webhook(Stripe 中的 payment_intent.succeeded)触发交付,切勿通过订单创建触发 |
| 许可证密钥被重复分配 | 使用数据库事务分配密钥,并进行原子状态检查——切勿分两步先查询再更新 |
| 账户删除后客户失去访问权限 | 将下载权限关联到 order_id + email,而不只是用户账户 ID;允许通过订单号恢复访问权限 |
| 大文件下载超时 | 使用 S3 预签名 URL,将文件直接从 S3 发送到客户的浏览器——切勿通过服务器代理 |
相关技能
- @inventory-tracking
- @low-stock-alerts
- @product-data-modeling