mcpField
D
digital-products

digital-products

github.com/finsilabs其他60142 次安装5 天前更新
代码仓库

关于 digital-products

digital-products 是指导开发者和店铺运营者配置数字商品交付的技能,涵盖平台原生功能、第三方应用及自定义安全下载方案。

主要功能

  1. 01比较各平台的数字商品交付方式
  2. 02配置下载次数与有效期
  3. 03提供许可证密钥交付建议
  4. 04说明订阅内容访问控制
  5. 05介绍 S3 预签名链接

适用场景

  1. 01为购买者配置文件下载与交付邮件
  2. 02向软件购买者分配许可证密钥
  3. 03为订阅内容设置访问和撤销规则
  4. 04为无原生功能的店铺设计安全下载

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill digital-products

安装后在 Claude Code 中输入/digital-products确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

tile.json
evals/license-key-pool-management-and-inventor/
criteria.json
task.md
evals/post-purchase-access-provisioning-and-de/
criteria.json
task.md
evals/secure-presigned-download-urls/
criteria.json
task.md

详细介绍

数字产品

概述

销售数字产品——电子书、软件许可证、模板、音乐、课程——需要在付款后安全交付,设置下载次数限制以防止未经授权的分享,并提供会过期的访问链接。每个主流平台要么内置了此功能(WooCommerce),要么有成熟的应用可处理此事(Shopify、BigCommerce)。优先使用平台的原生解决方案;只有当你的使用场景(复杂的许可证密钥管理、订阅门控的内容库)超出应用的能力时,才构建自定义交付基础设施。

何时使用此技能

  • 为现有商店添加可下载产品(PDF、软件、音频、模板)时
  • 为软件产品实现许可证密钥交付系统时
  • 构建通过订阅控制数字内容库访问权限的功能时
  • 将可公开访问的下载 URL 替换为安全、会过期的签名 URL 时

核心说明

步骤 1:确定平台并选择合适的工具
平台推荐工具原因
ShopifySky Pilot 或 FileflareSky Pilot 支持文件、许可证密钥、流媒体视频和下载次数限制;Fileflare 更简单,适用于基本文件下载
WooCommerceWooCommerce 可下载产品(内置)WooCommerce 原生支持数字产品,包括下载次数限制、有效期和安全令牌 URL
BigCommerce可下载数字产品(内置)或 FileflareBigCommerce 原生支持文件附件和下载交付
自定义 / 无头架构使用 S3 预签名 URL 构建交付功能当平台不支持原生数字产品时必需

步骤 2:平台专属设置

Shopify

Shopify 不原生支持数字产品,因此你需要安装应用。Sky Pilot 是功能最全面的选项。

设置 Sky Pilot:

  1. 从 Shopify 应用商店安装 Sky Pilot
  2. 前往 Sky Pilot → Files → Upload 上传你的数字文件(PDF、ZIP 等)
  3. 前往 Sky Pilot → Products,将已上传的文件关联到特定产品或变体
  4. 配置交付设置:
    • 下载次数限制:标准产品设为 3–5 次,订阅产品设为不限次数
    • 链接有效期:通常为 48–72 小时;客户可以从自己的账户申请新链接
    • 自动交付:默认启用——客户付款后会立即收到下载邮件
  5. 在 Sky Pilot → Settings → Email template 中自定义交付邮件

许可证密钥产品:

  1. 在 Sky Pilot 中,前往 License Keys → Import,上传包含许可证密钥的 CSV 文件
  2. 将许可证密钥池关联到产品
  3. Sky Pilot 会自动为每笔购买分配一个密钥,并将其包含在交付邮件中

订阅门控内容(Sky Pilot + Recharge):

  • Sky Pilot 与 Recharge 集成——拥有有效订阅的客户会自动获得访问权限;订阅取消时,访问权限会被撤销

WooCommerce

WooCommerce 内置数字产品交付功能,基本使用无需额外安装插件。

设置可下载产品:

  1. 前往 WooCommerce → Products → Add Product
  2. 勾选 Downloadable(还可选中 Virtual,以跳过配送)
  3. 在 Product Data → Downloadable Files 下:
    • 点击 Add File 并上传文件或输入 URL
    • 文件名:显示在客户账户中的名称
  4. 配置访问设置:
    • Download limit:输入次数(例如 5),或留空表示不限制
    • Download expiry:购买后的天数(例如 365),或留空表示永不过期
  5. 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

设置数字产品交付(内置功能):

  1. 前往 Products → Add Product
  2. 在 Files 下上传数字文件(BigCommerce 支持最大 512 MB 的文件)
  3. 设置 Max downloads,以限制每笔订单的文件下载次数
  4. 付款后,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

评论

支持 Markdown