# 许可证管理系统使用指南

本指南详细说明如何使用 License Manager 进行软件授权管理，包括授权端（许可证生成方）和被授权端（许可证验证方）的配置和使用。

## 目录

- [系统概述](#系统概述)
- [授权端配置](#授权端配置)
  - [安装](#安装)
  - [密钥对生成](#密钥对生成)
  - [环境变量配置](#环境变量配置)
- [被授权端配置](#被授权端配置)
  - [安装](#安装)
  - [公钥配置](#公钥配置)
  - [中间件集成](#中间件集成)
- [许可证生成](#许可证生成)
  - [基础许可证生成](#基础许可证生成)
  - [自定义过期日期](#自定义过期日期)
  - [带宽限期许可证](#带宽限期许可证)
  - [批量生成许可证](#批量生成许可证)
  - [从 CSV 批量生成](#从-csv-批量生成)
- [许可证验证](#许可证验证)
  - [基础验证](#基础验证)
  - [严格模式](#严格模式)
  - [宽限期验证](#宽限期验证)
  - [域名绑定验证](#域名绑定验证)
  - [功能权限检查](#功能权限检查)
  - [使用量限制检查](#使用量限制检查)
- [API 接口说明](#api-接口说明)
- [常见问题](#常见问题)
- [最佳实践](#最佳实践)

---

## 系统概述

License Manager 是一个基于 RSA 非对称加密的软件授权系统：

- **授权端（Issuer）**：持有私钥，负责生成和签发许可证
- **被授权端（Verifier）**：持有公钥，负责验证许可证的有效性
- **安全性**：使用 RSA-2048 签名确保许可证不被篡改
- **灵活性**：支持多种许可证类型、功能授权、使用限制、宽限期等

### 许可证类型

| 类型 | 适用场景 | 功能特性 |
|------|----------|----------|
| **TRIAL** | 试用版本 | 基础功能，限制用户数 |
| **STANDARD** | 标准版 | 常用功能，中等限制 |
| **PROFESSIONAL** | 专业版 | 高级功能，较大限制 |
| **ENTERPRISE** | 企业版 | 全功能，宽松限制，白标 |
| **CUSTOM** | 自定义 | 完全自定义配置 |

---

## 授权端配置

授权端负责生成和签发许可证，需要持有私钥。

### 安装

```bash
# 在授权端项目中安装
npm install @your-scope/license-manager

# 或者从本地安装
npm install /path/to/license-manager
```

### 密钥对生成

首次使用需要生成 RSA 密钥对：

```bash
# 使用 License Manager 提供的工具
node -e "
const { Crypto } = require('@your-scope/license-manager');
const fs = require('fs');
const path = require('path');

const { publicKey, privateKey } = Crypto.generateKeyPair();

const keysDir = path.join(__dirname, 'keys');
if (!fs.existsSync(keysDir)) {
  fs.mkdirSync(keysDir, { recursive: true });
}

fs.writeFileSync(path.join(keysDir, 'private.key'), privateKey);
fs.writeFileSync(path.join(keysDir, 'public.key'), publicKey);

console.log('✅ 密钥对生成成功');
console.log('🔑 私钥: keys/private.key (请妥善保管，勿泄露)');
console.log('📜 公钥: keys/public.key (分发给被授权端');
"
```

### 环境变量配置

创建 `.env` 文件：

```bash
# 许可证私钥路径
LICENSE_PRIVATE_KEY_PATH=./keys/private.key

# 或者直接设置私钥内容（不推荐用于生产环境）
# LICENSE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n..."
```

---

## 被授权端配置

被授权端负责验证许可证，需要持有公钥。

### 安装

```bash
# 在被授权端项目中安装
npm install @your-scope/license-manager
```

### 公钥配置

**方式1：通过环境变量配置**

创建 `.env` 文件：

```bash
# 许可证公钥
LICENSE_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
-----END PUBLIC KEY-----"

# 许可证验证选项
LICENSE_CHECK_DOMAIN=true          # 是否检查域名绑定
LICENSE_ALLOW_GRACE_PERIOD=true    # 是否允许宽限期
LICENSE_STRICT_MODE=true           # 是否启用严格模式
```

**方式2：从文件加载公钥**

```javascript
const fs = require('fs');
const path = require('path');

const publicKeyPath = path.join(__dirname, 'keys/public.key');
const publicKey = fs.readFileSync(publicKeyPath, 'utf8');
```

### 中间件集成

在 Express.js 应用中集成许可证验证中间件：

```javascript
const express = require('express');
const {
  requireLicense,
  requireFeature,
  checkLimit,
  getLicenseInfo
} = require('./middleware/license');

const app = express();

// 方式1：全局许可证验证（所有API都需要许可证）
app.use('/api', requireLicense({
  strict: true,              // 严格模式：检查过期
  allowGracePeriod: true,    // 允许宽限期
  checkDomain: true,         // 检查域名绑定
  allowOverride: false,      // 生产环境禁用绕过
}));

// 方式2：特定路由验证
app.post('/api/users', [
  requireLicense({ strict: true }),
  requireFeature('apiAccess'),  // 检查是否有 API 访问权限
], createUserHandler);

// 方式3：检查使用限制
app.post('/api/users', [
  requireLicense(),
  checkLimit('maxUsers', async () => {
    const User = require('./models/User');
    return await User.countDocuments();
  })
], createUserHandler);

// 方式4：获取许可证信息端点
app.get('/api/license/info', requireLicense(), getLicenseInfo);

app.listen(3000);
```

---

## 许可证生成

### 基础许可证生成

```javascript
const { LicenseManager, LicenseType } = require('@your-scope/license-manager');
const fs = require('fs');

// 读取私钥
const privateKey = fs.readFileSync('./keys/private.key', 'utf8');

// 创建许可证管理器
const manager = new LicenseManager({ privateKey });

// 生成许可证
const license = manager.generate({
  // 基本信息
  licenseId: 'LIC-2024-001',           // 许可证唯一ID
  clientId: 'customer-001',            // 客户ID
  type: LicenseType.PROFESSIONAL,      // 许可证类型
  customerName: '北京科技有限公司',    // 客户名称
  customerEmail: 'contact@example.com', // 客户邮箱

  // 功能授权
  features: {
    aiAssistant: true,           // AI助手
    advancedAnalytics: true,     // 高级分析
    customReports: true,         // 自定义报表
    apiAccess: true,             // API访问
    whiteLabel: false,           // 白标功能
    multiTenant: false,          // 多租户
    customIntegration: false,    // 自定义集成
    premiumSupport: true,        // 高级支持
  },

  // 使用限制
  limits: {
    maxUsers: 200,              // 最大用户数
    maxRequests: 1000000,       // 最大API请求数/月
    maxStorage: 51200,          // 最大存储空间（MB）
    concurrentSessions: 50,     // 最大并发会话
  },

  // 绑定信息（可选）
  bindings: {
    domain: '*.example.com',    // 域名绑定（支持通配符）
    ipAddress: '192.168.1.100', // IP地址绑定
  },

  // 有效期（二选一）
  duration: 365,                // 有效期（天）
  // 或者指定具体过期日期
  // expiresAt: '2025-12-31T23:59:59.999Z',

  // 元数据（可选）
  metadata: {
    salesperson: '张三',
    contractId: 'CT-2024-001',
    notes: '年度采购合同',
  },
});

// 导出许可证（Base64格式，便于传输和存储）
const licenseKey = license.export('base64');

// 保存到文件
fs.writeFileSync('./licenses/customer-001.key', licenseKey);

console.log('✅ 许可证生成成功');
console.log('许可证ID:', license.data.licenseId);
console.log('过期日期:', license.data.expiresAt);
console.log('许可证密钥:', licenseKey);
```

### 自定义过期日期

```javascript
// 方式1：使用 duration 参数（相对时间）
const license1 = manager.generate({
  licenseId: 'lic-duration-001',
  clientId: 'customer-001',
  type: LicenseType.STANDARD,
  customerName: '示例客户',
  duration: 365,  // 365天后过期
});

// 方式2：使用 expiresAt 参数（绝对时间）
const license2 = manager.generate({
  licenseId: 'lic-expiry-001',
  clientId: 'customer-002',
  type: LicenseType.STANDARD,
  customerName: '示例客户2',
  expiresAt: '2025-12-31T23:59:59.999Z',  // 指定具体日期
});

// 方式3：计算特定日期（如财年、学年）
function getFiscalYearEnd() {
  const now = new Date();
  const year = now.getFullYear();
  // 财年到3月31日结束
  return new Date(year + 1, 2, 31, 23, 59, 59).toISOString();
}

const license3 = manager.generate({
  licenseId: 'lic-fiscal-001',
  clientId: 'customer-003',
  type: LicenseType.ENTERPRISE,
  customerName: '财年客户',
  expiresAt: getFiscalYearEnd(),
});
```

### 带宽限期许可证

宽限期允许许可证过期后继续使用一段时间，给客户续费缓冲期：

```javascript
// 生成带30天宽限期的1年许可证
const license = manager.generate({
  licenseId: 'lic-grace-001',
  clientId: 'customer-001',
  type: LicenseType.STANDARD,
  customerName: '带宽限期的客户',
  duration: 365,              // 1年有效期
  gracePeriodDays: 30,        // ⏰ 30天宽限期

  features: {
    aiAssistant: true,
    customReports: true,
    apiAccess: true,
  },
});

// 验证时允许宽限期
const verified = validator.verify(licenseKey, {
  strict: true,              // 启用严格模式
  allowGracePeriod: true,    // ✅ 允许宽限期
});

// 检查宽限期状态
console.log('是否过期:', verified.isExpired());           // true
console.log('是否在宽限期内:', verified.isInGracePeriod()); // true
console.log('宽限期剩余天数:', verified.getGracePeriodDaysRemaining()); // 25

// 时间线示例：
// 2024-01-01: 许可证生效
// 2025-01-01: 许可证过期（但仍可使用）
// 2025-01-31: 宽限期结束（完全不可用）
```

### 批量生成许可证

```javascript
// 从数据库或API获取客户列表
const customers = [
  {
    clientId: 'customer-001',
    customerName: '北京科技有限公司',
    customerEmail: 'beijing@example.com',
    type: LicenseType.PROFESSIONAL,
    duration: 365,
  },
  {
    clientId: 'customer-002',
    customerName: '上海网络技术公司',
    customerEmail: 'shanghai@example.com',
    type: LicenseType.STANDARD,
    duration: 180,
  },
  {
    clientId: 'customer-003',
    customerName: '深圳数据科技公司',
    customerEmail: 'shenzhen@example.com',
    type: LicenseType.ENTERPRISE,
    duration: 365 * 3,
    gracePeriodDays: 90,
  },
];

const generatedLicenses = [];

customers.forEach((customer) => {
  // 根据类型设置不同的功能和限制
  const features = {
    aiAssistant: customer.type === LicenseType.PROFESSIONAL || customer.type === LicenseType.ENTERPRISE,
    advancedAnalytics: customer.type === LicenseType.ENTERPRISE,
    customReports: true,
    apiAccess: true,
    whiteLabel: customer.type === LicenseType.ENTERPRISE,
    multiTenant: customer.type === LicenseType.ENTERPRISE,
    premiumSupport: customer.type === LicenseType.ENTERPRISE,
  };

  const limits = {
    maxUsers: customer.type === LicenseType.STANDARD ? 50 :
               customer.type === LicenseType.PROFESSIONAL ? 200 : 1000,
    maxRequests: customer.type === LicenseType.STANDARD ? 100000 : 1000000,
    maxStorage: customer.type === LicenseType.STANDARD ? 5120 : 51200,
  };

  const license = manager.generate({
    licenseId: `${customer.clientId}-${Date.now()}`,
    clientId: customer.clientId,
    type: customer.type,
    customerName: customer.customerName,
    customerEmail: customer.customerEmail,
    features,
    limits,
    duration: customer.duration,
    gracePeriodDays: customer.gracePeriodDays,
  });

  const licenseKey = license.export('base64');
  generatedLicenses.push({
    ...customer,
    licenseKey,
    issuedAt: license.data.issuedAt,
    expiresAt: license.data.expiresAt,
  });

  // 保存许可证文件
  fs.writeFileSync(
    `./licenses/${customer.clientId}.key`,
    licenseKey
  );

  console.log(`✅ ${customer.customerName}`);
});

// 保存清单
fs.writeFileSync(
  './licenses/manifest.json',
  JSON.stringify({
    generatedAt: new Date().toISOString(),
    total: generatedLicenses.length,
    licenses: generatedLicenses,
  }, null, 2)
);

console.log(`\n✅ 批量生成完成，总计 ${generatedLicenses.length} 个许可证`);
```

### 从 CSV 批量生成

```javascript
const fs = require('fs');

// 读取CSV文件
const csvData = fs.readFileSync('./customers.csv', 'utf8');

// 解析CSV
const rows = csvData.split('\n');
const headers = rows[0].split(',').map(h => h.trim());

const csvLicenses = [];

for (let i = 1; i < rows.length; i++) {
  const values = rows[i].split(',');
  const customer = {};

  headers.forEach((header, index) => {
    customer[header] = values[index]?.trim();
  });

  // 生成许可证
  const license = manager.generate({
    licenseId: `csv-${Date.now()}-${i}`,
    clientId: customer.clientId,
    type: customer.type.toUpperCase(),
    customerName: customer.customerName,
    customerEmail: customer.email,
    duration: parseInt(customer.duration),
    gracePeriodDays: parseInt(customer.gracePeriodDays) || 0,
  });

  csvLicenses.push({
    ...customer,
    licenseKey: license.export('base64'),
  });

  console.log(`✅ ${customer.customerName}`);
}

console.log(`\n总计: ${csvLicenses.length} 个许可证`);
```

---

## 许可证验证

### 基础验证

```javascript
const { LicenseValidator } = require('@your-scope/license-manager');
const fs = require('fs');

// 读取公钥
const publicKey = fs.readFileSync('./keys/public.key', 'utf8');

// 创建验证器
const validator = new LicenseValidator(publicKey);

// 从请求头获取许可证密钥
const licenseKey = req.headers['x-license-key'];

try {
  // 验证许可证（仅验证签名）
  const license = validator.verify(licenseKey);

  console.log('✅ 许可证有效');
  console.log('客户名称:', license.data.customerName);
  console.log('许可证类型:', license.data.type);
  console.log('过期日期:', license.data.expiresAt);

} catch (error) {
  console.error('❌ 许可证无效:', error.message);
}
```

### 严格模式

严格模式会检查许可证是否过期：

```javascript
try {
  const license = validator.verify(licenseKey, {
    strict: true,  // 启用严格模式，检查过期
  });

  console.log('✅ 许可证有效且未过期');

} catch (error) {
  if (error.message.includes('expired')) {
    console.error('❌ 许可证已过期');
  } else {
    console.error('❌ 许可证无效:', error.message);
  }
}
```

### 宽限期验证

允许许可证过期后在宽限期内继续使用：

```javascript
try {
  const license = validator.verify(licenseKey, {
    strict: true,              // 严格模式
    allowGracePeriod: true,    // 允许宽限期
  });

  if (license.isExpired()) {
    if (license.isInGracePeriod()) {
      const daysRemaining = license.getGracePeriodDaysRemaining();
      console.log(`⚠️ 许可证已过期，但在宽限期内（剩余 ${daysRemaining} 天）`);
      console.log('📢 请及时续费以避免服务中断');
    } else {
      console.error('❌ 许可证已过期且超过宽限期');
    }
  } else {
    console.log('✅ 许可证有效');
  }

} catch (error) {
  console.error('❌ 许可证验证失败:', error.message);
}
```

### 域名绑定验证

验证许可证是否绑定到指定域名：

```javascript
try {
  const license = validator.verify(licenseKey, {
    strict: true,
    checkBindings: {
      domain: req.hostname,  // 检查当前请求的域名
    },
  });

  console.log('✅ 域名绑定验证通过');

} catch (error) {
  if (error.message.includes('binding')) {
    console.error('❌ 域名绑定不匹配');
    console.error('当前域名:', req.hostname);
  } else {
    console.error('❌ 许可证验证失败:', error.message);
  }
}
```

### 功能权限检查

检查许可证是否包含特定功能：

```javascript
// 假设已经验证的许可证
const license = req.license;

// 检查AI助手功能
if (license.hasFeature('aiAssistant')) {
  console.log('✅ 有AI助手功能权限');
  // 提供AI助手功能
} else {
  console.log('❌ 无AI助手功能权限');
  // 提示升级许可证
}

// 检查高级分析功能
if (license.hasFeature('advancedAnalytics')) {
  // 显示高级分析面板
} else {
  // 显示基础分析或升级提示
}
```

### 使用量限制检查

检查当前使用量是否超过许可证限制：

```javascript
const license = req.license;

// 检查用户数限制
const currentUsers = await User.countDocuments();
if (!license.isWithinLimit('maxUsers', currentUsers)) {
  return res.status(429).json({
    success: false,
    error: 'LIMIT_EXCEEDED',
    message: '用户数已达上限',
    current: currentUsers,
    max: license.data.limits.maxUsers,
  });
}

// 检查API请求数限制（月度）
const monthlyRequests = await getMonthlyRequestCount();
if (!license.isWithinLimit('maxRequests', monthlyRequests)) {
  return res.status(429).json({
    success: false,
    error: 'RATE_LIMIT_EXCEEDED',
    message: '本月API请求数已达上限',
    current: monthlyRequests,
    max: license.data.limits.maxRequests,
  });
}

// 检查存储空间限制
const storageUsed = await getStorageUsed();
if (!license.isWithinLimit('maxStorage', storageUsed)) {
  return res.status(429).json({
    success: false,
    error: 'STORAGE_LIMIT_EXCEEDED',
    message: '存储空间已达上限',
    current: storageUsed,
    max: license.data.limits.maxStorage,
  });
}
```

---

## API 接口说明

### 许可证信息端点

**获取许可证信息**

```http
GET /api/license/info
Headers:
  X-License-Key: <许可证密钥>
```

**响应示例**：

```json
{
  "success": true,
  "data": {
    "licenseId": "LIC-2024-001",
    "customerName": "北京科技有限公司",
    "customerEmail": "contact@example.com",
    "type": "professional",
    "issuedAt": "2024-01-01T00:00:00.000Z",
    "expiresAt": "2025-01-01T00:00:00.000Z",
    "isExpired": false,
    "features": {
      "aiAssistant": true,
      "advancedAnalytics": true,
      "customReports": true,
      "apiAccess": true,
      "whiteLabel": false,
      "multiTenant": false
    },
    "limits": {
      "maxUsers": 200,
      "maxRequests": 1000000,
      "maxStorage": 51200
    },
    "bindings": {
      "domain": "*.example.com"
    }
  }
}
```

### 功能权限检查端点

**检查特定功能权限**

```http
GET /api/license/check-feature?feature=aiAssistant
Headers:
  X-License-Key: <许可证密钥>
```

**响应示例**：

```json
{
  "success": true,
  "data": {
    "feature": "aiAssistant",
    "enabled": true
  }
}
```

### 使用量检查端点

**检查使用量限制**

```http
GET /api/license/usage
Headers:
  X-License-Key: <许可证密钥>
```

**响应示例**：

```json
{
  "success": true,
  "data": {
    "users": {
      "current": 150,
      "max": 200,
      "remaining": 50,
      "percentage": 75
    },
    "requests": {
      "current": 450000,
      "max": 1000000,
      "remaining": 550000,
      "percentage": 45
    },
    "storage": {
      "current": 25600,
      "max": 51200,
      "remaining": 25600,
      "percentage": 50,
      "unit": "MB"
    }
  }
}
```

---

## 常见问题

### 1. 如何保护私钥安全？

**授权端私钥保护最佳实践**：

```javascript
// ❌ 错误：将私钥硬编码在代码中
const privateKey = '-----BEGIN PRIVATE KEY-----\nMIIBIjANBg...';

// ❌ 错误：将私钥提交到代码仓库
// .gitignore 应包含：
// keys/
// .env

// ✅ 正确：从环境变量读取
const privateKey = process.env.LICENSE_PRIVATE_KEY;

// ✅ 正确：从安全的密钥管理服务读取
const AWS = require('aws-sdk');
const ssm = new AWS.SSM();
const privateKey = await ssm.getParameter({
  Name: '/license/private-key',
  WithDecryption: true
}).promise();
```

### 2. 如何处理许可证过期通知？

```javascript
// 定期检查许可证过期情况
const cron = require('node-cron');

// 每天检查一次
cron.schedule('0 9 * * *', async () => {
  const customers = await Customer.find({});

  customers.forEach(async (customer) => {
    const license = validator.verify(customer.licenseKey);
    const expiresAt = new Date(license.data.expiresAt);
    const now = new Date();
    const daysUntilExpiry = Math.floor((expiresAt - now) / (1000 * 60 * 60 * 24));

    // 30天前提醒
    if (daysUntilExpiry === 30) {
      await sendEmail(customer.email, '您的许可证将在30天后过期', {
        customerName: customer.name,
        expiresAt: expiresAt.toLocaleDateString(),
        renewalLink: 'https://example.com/renew',
      });
    }

    // 7天前再次提醒
    if (daysUntilExpiry === 7) {
      await sendEmail(customer.email, '⚠️ 许可证即将过期：7天后', {
        customerName: customer.name,
        expiresAt: expiresAt.toLocaleDateString(),
      });
    }

    // 过期当天提醒
    if (daysUntilExpiry === 0) {
      await sendEmail(customer.email, '❌ 许可证已过期', {
        customerName: customer.name,
        gracePeriodDays: license.data.gracePeriodDays || 0,
        gracePeriodEnd: license.getGracePeriodDaysRemaining(),
      });
    }
  });
});
```

### 3. 如何在开发环境绕过许可证验证？

```javascript
// 开发环境配置
if (process.env.NODE_ENV === 'development') {
  app.use('/api', requireLicense({
    allowOverride: true,  // 允许通过环境变量绕过
  }));

  // 设置环境变量
  // BYPASS_LICENSE=true
}

// 生产环境配置
if (process.env.NODE_ENV === 'production') {
  app.use('/api', requireLicense({
    allowOverride: false,  // 禁止绕过
    strict: true,
    allowGracePeriod: true,
  }));
}
```

### 4. 如何处理许可证迁移？

```javascript
// 迁移许可证到新服务器
function migrateLicense(oldLicenseKey, newBindings) {
  // 1. 验证原许可证
  const oldLicense = validator.verify(oldLicenseKey);

  // 2. 生成新许可证（更新绑定信息）
  const newLicense = manager.generate({
    ...oldLicense.data,
    bindings: newBindings,  // 新的域名/IP绑定
    licenseId: `${oldLicense.data.licenseId}-migrated`,
    metadata: {
      ...oldLicense.data.metadata,
      migratedFrom: oldLicense.data.licenseId,
      migratedAt: new Date().toISOString(),
    },
  });

  // 3. 返回新许可证
  return {
    newLicenseKey: newLicense.export('base64'),
    oldLicenseId: oldLicense.data.licenseId,
    newLicenseId: newLicense.data.licenseId,
  };
}

// 使用示例
const result = migrateLicense(oldKey, {
  domain: '*.new-server.com',
});
console.log('新许可证:', result.newLicenseKey);
```

### 5. 如何撤销许可证？

由于许可证使用 RSA 签名，无法直接撤销。建议使用许可证黑名单：

```javascript
// 许可证黑名单（存储在数据库）
const LicenseBlacklist = require('./models/LicenseBlacklist');

// 撤销许可证
async function revokeLicense(licenseId, reason) {
  await LicenseBlacklist.create({
    licenseId,
    reason,
    revokedAt: new Date(),
    revokedBy: 'admin@example.com',
  });

  console.log(`✅ 许可证 ${licenseId} 已撤销`);
}

// 验证时检查黑名单
async function verifyLicenseWithBlacklist(licenseKey) {
  const license = validator.verify(licenseKey);

  // 检查黑名单
  const blacklisted = await LicenseBlacklist.findOne({
    licenseId: license.data.licenseId,
  });

  if (blacklisted) {
    throw new Error(`许可证已被撤销: ${blacklisted.reason}`);
  }

  return license;
}
```

---

## 最佳实践

### 1. 许可证ID命名规范

```javascript
// 推荐：使用有意义的命名模式
const license = manager.generate({
  licenseId: `${customerType}-${year}-${sequence}`,  // 如: ENT-2024-001
  // 或
  licenseId: `${customerCode}-${Date.now()}`,       // 如: ABC-1706123456789
  // 或
  licenseId: `v4_${uuidv4()}`,                      // 如: v4_a1b2c3d4-e5f6-7890
});
```

### 2. 错误处理

```javascript
// 完善的错误处理
function verifyLicenseWithErrorHandling(licenseKey) {
  try {
    const license = validator.verify(licenseKey, {
      strict: true,
      allowGracePeriod: true,
    });

    return {
      success: true,
      license,
      warnings: getWarnings(license),  // 获取警告信息
    };

  } catch (error) {
    // 分类错误
    if (error.message.includes('signature')) {
      return {
        success: false,
        error: 'INVALID_SIGNATURE',
        message: '许可证签名无效，可能是被篡改或伪造',
        userMessage: '许可证验证失败，请联系技术支持',
      };
    }

    if (error.message.includes('expired')) {
      return {
        success: false,
        error: 'EXPIRED',
        message: '许可证已过期',
        userMessage: '您的许可证已过期，请续费以继续使用',
        actionUrl: 'https://example.com/renew',
      };
    }

    if (error.message.includes('binding')) {
      return {
        success: false,
        error: 'BINDING_MISMATCH',
        message: '域名/IP绑定不匹配',
        userMessage: '许可证与当前服务器不匹配，请检查许可证配置',
      };
    }

    // 未知错误
    return {
      success: false,
      error: 'UNKNOWN',
      message: error.message,
      userMessage: '许可证验证失败，请联系技术支持',
    };
  }
}

function getWarnings(license) {
  const warnings = [];

  // 即将过期警告
  if (!license.isExpired()) {
    const expiresAt = new Date(license.data.expiresAt);
    const daysUntilExpiry = Math.floor((expiresAt - new Date()) / (1000 * 60 * 60 * 24));

    if (daysUntilExpiry <= 30) {
      warnings.push({
        type: 'expiring_soon',
        message: `许可证将在 ${daysUntilExpiry} 天后过期`,
        daysRemaining: daysUntilExpiry,
      });
    }
  }

  // 使用量警告
  const limits = license.data.limits;
  // 检查各项使用量...

  return warnings;
}
```

### 3. 日志记录

```javascript
const { logger } = require('./utils/logger');

// 记录许可证验证日志
function logLicenseVerification(license, result, metadata = {}) {
  logger.info('License verification', {
    licenseId: license.data.licenseId,
    clientId: license.data.clientId,
    customerName: license.data.customerName,
    type: license.data.type,
    success: result.success,
    error: result.error,
    expiresAt: license.data.expiresAt,
    isExpired: license.isExpired(),
    isInGracePeriod: license.isInGracePeriod(),
    gracePeriodDaysRemaining: license.getGracePeriodDaysRemaining(),
    // 请求元数据
    ...metadata,
  });
}
```

### 4. 性能优化

```javascript
// 使用缓存减少验证开销
const NodeCache = require('node-cache');
const licenseCache = new NodeCache({ stdTTL: 600 }); // 缓存10分钟

function verifyLicenseWithCache(licenseKey) {
  const cacheKey = `license:${licenseKey}`;

  // 尝试从缓存获取
  const cached = licenseCache.get(cacheKey);
  if (cached) {
    return cached;
  }

  // 验证许可证
  const license = validator.verify(licenseKey);

  // 缓存结果
  licenseCache.set(cacheKey, license);

  return license;
}
```

### 5. 前端集成示例

```javascript
// 前端：发送许可证密钥
const API_BASE_URL = 'https://api.example.com';

async function makeApiRequest(endpoint) {
  const licenseKey = localStorage.getItem('licenseKey');

  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    headers: {
      'X-License-Key': licenseKey,
      'Content-Type': 'application/json',
    },
  });

  if (!response.ok) {
    const error = await response.json();

    // 处理许可证相关错误
    if (error.error === 'LICENSE_EXPIRED') {
      // 显示续费提示
      showRenewalModal();
    } else if (error.error === 'FEATURE_NOT_AUTHORIZED') {
      // 显示功能升级提示
      showUpgradeModal(error.feature);
    }

    throw new Error(error.message);
  }

  return response.json();
}
```

---

## 完整示例项目

### 授权端 (license-issuer)

```javascript
// server.js
const express = require('express');
const { LicenseManager, LicenseType } = require('@your-scope/license-manager');
const fs = require('fs');

const app = express();
app.use(express.json());

const privateKey = fs.readFileSync('./keys/private.key', 'utf8');
const manager = new LicenseManager({ privateKey });

// 生成许可证API
app.post('/api/licenses/generate', (req, res) => {
  try {
    const license = manager.generate(req.body);
    const licenseKey = license.export('base64');

    res.json({
      success: true,
      data: {
        licenseId: license.data.licenseId,
        licenseKey,
        issuedAt: license.data.issuedAt,
        expiresAt: license.data.expiresAt,
      },
    });
  } catch (error) {
    res.status(400).json({
      success: false,
      error: error.message,
    });
  }
});

// 批量生成API
app.post('/api/licenses/batch-generate', (req, res) => {
  const { customers } = req.body;
  const licenses = [];

  customers.forEach(customer => {
    const license = manager.generate(customer);
    licenses.push({
      ...customer,
      licenseKey: license.export('base64'),
      licenseId: license.data.licenseId,
    });
  });

  res.json({
    success: true,
    data: { licenses, total: licenses.length },
  });
});

app.listen(4000, () => {
  console.log('🔐 许可证授权服务运行在 http://localhost:4000');
});
```

### 被授权端 (app-with-license)

```javascript
// server.js
const express = require('express');
const { requireLicense, requireFeature, checkLimit } = require('./middleware/license');
const User = require('./models/User');

const app = express();
app.use(express.json());

// 全局许可证验证
app.use('/api', requireLicense({
  strict: true,
  allowGracePeriod: true,
  checkDomain: true,
}));

// 用户管理（检查用户数限制）
app.post('/api/users', [
  checkLimit('maxUsers', async () => await User.countDocuments()),
], async (req, res) => {
  const user = await User.create(req.body);
  res.json({ success: true, data: user });
});

// AI功能（需要AI助手权限）
app.post('/api/ai/generate', [
  requireFeature('aiAssistant'),
], async (req, res) => {
  // AI功能实现
  res.json({ success: true, data: { result: 'AI生成内容' } });
});

// 许可证信息查询
app.get('/api/license/info', (req, res) => {
  const license = req.license;
  res.json({
    success: true,
    data: {
      licenseId: license.data.licenseId,
      customerName: license.data.customerName,
      type: license.data.type,
      features: license.data.features,
      limits: license.data.limits,
      expiresAt: license.data.expiresAt,
      isExpired: license.isExpired(),
      isInGracePeriod: license.isInGracePeriod(),
    },
  });
});

app.listen(3000, () => {
  console.log('🚀 应用运行在 http://localhost:3000');
});
```

---

## 技术支持

如有问题或建议，请联系：

- 📧 Email: support@example.com
- 📚 文档: https://docs.example.com/license-manager
- 💬 Issues: https://github.com/example/license-manager/issues

---

**最后更新**: 2024-01-24
**版本**: v1.0.0
