跳转至

跨项目集成指南:赞助版 / 许可证验证(可复制到任意 Web 项目)

本文是“可移植的实施手册”。你可以把这份文档连同你的项目上下文发给我,我能据此快速落地集成。文档覆盖了:架构、远程接口契约、机器码算法、DB 结构、后端与前端对接、宽限与容错、安全策略、测试与运维。


0. 集成目标与范围

  • 为任意 Web 项目(Node/Express、NestJS、Django、Flask、SpringBoot、Go 等)集成“许可证验证 + 动态额度 + 宽限容错”的赞助版能力。
  • 支持本地缓存 + 远程校验的“双层验证”,保证在远程服务抖动时不影响正常使用。
  • 支持“设备绑定与切换”,阻止简单的“拔网线绕过”。
  • 前端提供管理界面:激活、状态展示、手动刷新、设备切换、错误提示。

1. 总体架构

  • 远程验证服务:https://license.zhoujie218.top/
  • POST /api/license/verify:许可证校验
  • POST /api/license/switch-device:设备切换
  • 本地后端(你的项目):
  • 暴露:POST /api/sponsor/activateGET /api/sponsor/statusPOST /api/sponsor/heartbeatPOST /api/sponsor/clearPOST /api/sponsor/device-switch-requestGET /api/sponsor/machine-id
  • 每日 3-5 点随机心跳一次
  • 本地 DB 缓存:许可证、状态、错误日志、额度、上次校验时间
  • 前端管理页:
  • 激活表单(输入许可证) + “获取许可证”引导链接
  • 状态卡片(版本、许可证、状态徽标、宽限提示、最近反馈)
  • 远程详情区(许可证字段展示)
  • 设备切换表单

2. 远程接口契约(固定,不要更改)

2.1 Verify(验证许可证)

  • 方法:POST https://license.zhoujie218.top/api/license/verify
  • 请求:
    {
      "licenseKey": "{string}",
      "machineId": "{string}",
      "deviceInfo": "{string}"  // 可填 "sponsor-activation:{machineId}"
    }
    
  • 响应(成功示例):
    {
      "success": true,
      "message": "密钥验证成功",
      "license": {
        "licenseKey": "my-...",
        "applicationName": "密钥管理系统",
        "licenseTypeName": "终生赞助版",
        "licenseTypeDisplayName": "终生赞助版",
        "status": "active",
        "maxUses": 999999,
        "currentUses": 8,
        "maxDevices": 1,
        "currentDevices": 2,
        "customField1": "500",   // 动态总额
        "customField2": "100",   // 动态批量
        "customField3": "10",
        "expiresAt": "2125-07-16T08:29:19Z",
        "activatedAt": "2025-08-09 08:29:19",
        "timezone": "UTC",
        "clientIP": "1.2.3.4"
      },
      "token": "optional-jwt-or-session"
    }
    
  • 响应(失败示例):

    {
      "success": false,
      "message": "密钥已被暂停",
      "details": "..."
    }
    
    {
      "success": false,
      "message": "密钥不存在",
      "details": "..."
    }
    

  • 失败时 HTTP 可能返回 4xx/5xx,需要把状态码与消息一并透传到前端。

2.2 Switch Device(设备切换)

  • 方法:POST https://license.zhoujie218.top/api/license/switch-device
  • 请求:
    {
      "licenseKey": "{string}",
      "oldMachineId": "{string}",
      "newMachineId": "{string}",
      "reason": "{string?}"
    }
    
  • 响应:与 Verify 一致的成功/失败结构(success 布尔 + 消息 + 可选的 license/token)。

3. 机器码生成(跨语言可实现)

  • 设计目标:同一台宿主/容器内稳定、升级/重启不变;迁移机器需显式切换,保证在同一台机器上,不同的容器也能机器码不变
  • 建议特征:
  • OS 平台(os.platform()/uname
  • CPU 核数与型号(cpus.length、第一颗 CPU model)
  • 总内存(totalmem
  • OS 版本信息(release/version)
  • 架构(x64/arm64
  • 主机名(hostname)
  • 容器/虚拟化标识(cgroup、/proc、环境变量)
  • 网络接口签名(接口名+MAC 聚合并排序)
  • 实现:将以上键值排序后 JSON 序列化,计算 SHA-256 哈希,前缀 server_,保留前 16 字符。

4. 本地数据模型(建议表)

表名自定,以下为建议字段(与现有实现对齐,便于迁移): - license_key(唯一,TEXT) - machine_id(TEXT) - verification_token(TEXT) - status(TEXT:active/grace/grace_limited/expired/pending/switching) - remote_verified_atlocal_verified_at(DATETIME) - last_remote_error_messagelast_remote_error_http_statuslast_remote_error_time(记录失败) - last_license_type_name(TEXT) - limit_total_licenses(INTEGER,远程 customField1) - limit_batch_count(INTEGER,远程 customField2) - consecutive_failures(INTEGER) - device_switch_requested_atold_machine_id(DATETIME/TEXT)

可用任意 DB(SQLite/MySQL/Postgres)。重要的是:字段含义与流程一致,便于状态机计算与 UI 展示。


5. 本地状态机与宽限策略

  • 信任期 trustDays(默认 7 天):最近成功后一定时间内完全信任。
  • 宽限期 graceDays(默认 15 天):远程失败但曾成功激活时,进入宽限提示(所有功能不受限);倒计时以“最后一次失败时间”为起点,超期后回退为社区版。
  • grace_limited 可选:若需要在宽限末期局部限流,可在业务层加入(例如批量生成上限=20)。

6. 动态额度与社区兜底

  • 赞助版激活:
  • 总量上限 = customField1(整数,空或无表示无限)
  • 批量上限 = customField2(整数,空或无表示无限)
  • 社区版兜底:
  • 总量上限 200,批量上限 20
  • 实施点:在实际“生成密钥/创建资源”的后端入口处统一检查额度(读取本地状态与缓存额度)。

7. 后端集成步骤(通用)

  1. 引入 HTTP 客户端与 DB 层(如 axios + ORM/原生驱动)。
  2. 实现机器码生成器。
  3. 创建赞助表(见 §4)。
  4. 实现“远程校验包装”:
  5. 成功:落库状态、额度、last_license_type_name,清空错误;
  6. 失败:记录 last_remote_error_*,累加 consecutive_failures,返回结构化 remoteError{httpStatus,data,message}
  7. 实现接口:
  8. POST /api/sponsor/activate(入参 licenseKey → 远程 verify)
  9. GET /api/sponsor/status(仅读本地,不触发远程)
  10. POST /api/sponsor/heartbeat(凭本地 license_key 远程 verify)
  11. POST /api/sponsor/device-switch-request(可选)
  12. POST /api/sponsor/clear(删除本地记录,回退社区版)
  13. GET /api/sponsor/machine-id
  14. 管理业务限额点:把“动态额度 / 社区兜底”并入总量与批量检查函数中。
  15. 定时任务:每日 3-5 点随机执行一次 heartbeat()(或业务合适时间窗口)。

8. 前端集成要点

  • 页面模块:
  • 状态卡:机器码、当前版本名(last_license_type_name 或社区版)、当前许可证、赞助状态、宽限提示(验证失败才显示)、最近一次刷新反馈(含 HTTP 码与时间)。
  • 激活表单:提交后调用 /api/sponsor/activate,成功前置渲染远程详情,再调用 GET /api/sponsor/status 刷新状态。
  • 设备切换:输入新机器码 + 原因,调用 /api/sponsor/device-switch-request
  • 手动刷新:调用 /api/sponsor/heartbeat
  • 交互准则:状态接口不触发远程;防止“刚展示的远程详情被刷新覆盖”。
  • 提示文案:
  • 未激活:显示“未激活”。
  • 已激活但失败:显示“当前验证失败,请稍后刷新。已进入宽限期,还剩 N 天,期间所有功能不受影响,过后将回退到社区版。”

9. 安全策略与反绕过

  • 绑定稳定机器码 + 设备切换流程,防止简单复制迁移。
  • 宽限倒计时 + 每日自动心跳 → 防止“断网长期绕过”。
  • 服务端强校验额度,前端仅展示;所有异常要记录到日志并落库。
  • 接口均需鉴权(如 JWT + 管理员角色)。

10. 错误处理与可观测

  • 远程调用错误统一结构化:remoteError{httpStatus,data,message},并写入 DB。
  • 前端展示“最近一次刷新反馈”。
  • 关键日志:激活成功/失败、心跳成功/失败、额度超限被拒绝。

11. 配置建议

  • SPONSOR_GRACE_TRUST_DAYS(默认 7)
  • SPONSOR_GRACE_MAX_DAYS(默认 15)
  • SPONSOR_MAX_CONSECUTIVE_FAILURES(默认 10)
  • SPONSOR_DEVICE_SWITCH_WINDOW_HOURS(默认 24)
  • SPONSOR_ALLOW_OFFLINE_TRUST(默认 true)

    远程 URL 建议硬编码(降低运维复杂性),如需多环境可在构建期切换。


12. 测试清单(可直接执行)

  1. 激活成功:展示远程详情;状态为“已激活”。
  2. 激活失败:提示远程失败原因;状态回落到最近本地评估;记录错误。
  3. 手动刷新成功/失败路径各一次,前端“最近一次刷新反馈”正确显示。
  4. 动态额度:当 customField1/2 返回后,总量/批量检查生效;当为空时放开。
  5. 社区兜底:无许可证时总量=300,批量=20。
  6. 断网 1 天:仍可使用;显示宽限倒计时减少。
  7. 宽限到期:自动回退社区版;前端提示变化。
  8. 设备切换:旧→新机器码走通,旧机器受限。
  9. 清除许可证:回退社区版;状态与 UI 更新。

13. 交付与运维

  • 日志:后端日志 + DB 中最近错误字段。
  • 定时任务可靠性:心跳失败不抛死,记录警告并重排到次日。
  • 备份:定期备份包含 sponsor_verification 的 DB 文件。

14. 落地步骤(摘要)

  • 第 1 步:落库(新增表或新增列)
  • 第 2 步:接入机器码算法
  • 第 3 步:实现远程校验包装
  • 第 4 步:实现后端接口(activate/status/heartbeat/...)
  • 第 5 步:在“生成关键资源”的入口合并额度检查
  • 第 6 步:前端页面(状态卡、激活、刷新、切换)
  • 第 7 步:部署定时心跳
  • 第 8 步:联调与验收(按 §12 清单)

15. 附:可复用的接口返回结构(建议)

  • 激活/心跳成功:
    {
      "success": true,
      "status": "active",
      "license": { "...远程license对象..." },
      "graceDays": 15,
      "trustDays": 7
    }
    
  • 激活/心跳失败:
    {
      "success": false,
      "status": "grace",
      "message": "...",
      "remoteError": {"httpStatus":403, "data": {"message":"密钥暂停"}, "message":"密钥暂停"},
      "fallback": {"isSponsored": true, "status": "grace"},
      "graceDays": 15,
      "trustDays": 7
    }
    

16. 我需要你提供的最小信息(便于我快速集成)

  • 项目类型与语言(Node/Nest/Django/Flask/Spring/Go 等)
  • 鉴权方式(JWT/Session)与管理端路由
  • 你希望的额度策略(若需区别不同类型的赞助版)
  • 现有数据库类型(SQLite/MySQL/Postgres)与迁移方式
  • 需要覆盖的页面位置与样式偏好
  • 部署环境(容器/物理机)、是否允许计划任务

准备好这些信息,把本指南与项目仓库/示例接口一并发给我,我即可在最短时间完成集成。