# SSL证书问题解决方案

## 【背景意义】

在开发环境中连接WordPress API时，经常遇到SSL证书相关错误，特别是`DEPTH_ZERO_SELF_SIGNED_CERT`错误。这类问题会阻止API正常调用，影响开发进度。

## 【概念定义】

### SSL证书错误类型对比表

| 错误类型 | 错误代码 | 含义 | 常见场景 |
|---------|---------|------|---------|
| DEPTH_ZERO_SELF_SIGNED_CERT | self-signed certificate | 自签名证书 | 本地开发环境 |
| CERT_HAS_EXPIRED | certificate has expired | 证书已过期 | 测试环境 |
| UNABLE_TO_VERIFY_LEAF_SIGNATURE | unable to verify the first certificate | 无法验证证书链 | 配置错误的服务器 |
| CERT_UNTRUSTED | certificate not trusted | 证书不受信任 | 使用了未知CA的证书 |

## 【使用流程】

### 方案一:忽略SSL验证(仅开发环境）

#### 1. 修改axios配置

在`src/service/wp.service.ts`中的`fetchPagedData`方法添加SSL配置:

```typescript
// 在fetchPagedData方法中修改config配置
const config: AxiosRequestConfig = {
  method: 'GET',
  url: `${wpApiUrl}/wp-json${endpoint}`,
  headers: {
    Authorization: `Basic ${auth}`, // 基础认证头
  },
  params: {
    page, // 当前页码
    per_page: perPage, // 每页数量
  },
  // 添加SSL配置 - 仅用于开发环境
  httpsAgent: new (require('https').Agent)({
    rejectUnauthorized: false // 忽略SSL证书验证
  }),
  // 设置超时时间
  timeout: 30000 // 30秒超时
};
```

#### 2. 全局axios配置

在项目入口文件中添加全局配置:

```typescript
// 在src/configuration.ts或app.ts中添加
import axios from 'axios';
import https from 'https';

// 仅在开发环境中忽略SSL验证
if (process.env.NODE_ENV === 'development') {
  axios.defaults.httpsAgent = new https.Agent({
    rejectUnauthorized: false // 忽略自签名证书
  });
}
```

### 方案二:环境变量控制(推荐）

#### 1. 创建环境配置

在`.env`文件中添加:

```bash
# SSL配置
NODE_TLS_REJECT_UNAUTHORIZED=0  # 仅开发环境使用
WP_API_TIMEOUT=30000           # API超时时间
WP_API_VERIFY_SSL=false        # 是否验证SSL
```

#### 2. 动态SSL配置

```typescript
// 在wp.service.ts中添加动态配置
import { Config } from '@midwayjs/core';

@Provide()
export class WPService {
  @Config('wpSite')
  sites: Site[];

  // 获取SSL配置
  private getHttpsAgent() {
    const verifySSL = process.env.WP_API_VERIFY_SSL !== 'false';
    
    if (!verifySSL) {
      return new (require('https').Agent)({
        rejectUnauthorized: false // 开发环境忽略SSL验证
      });
    }
    
    return undefined; // 生产环境使用默认配置
  }

  async fetchPagedData<T>(
    endpoint: string,
    site: Site,
    page: number = 1,
    perPage: number = 100
  ): Promise<T[]> {
    const { wpApiUrl, consumerKey, consumerSecret } = site;
    const allData: T[] = [];
    
    // Base64编码认证信息
    const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64');
    
    let hasMore = true;
    while (hasMore) {
      const config: AxiosRequestConfig = {
        method: 'GET',
        url: `${wpApiUrl}/wp-json${endpoint}`,
        headers: {
          Authorization: `Basic ${auth}`, // 基础认证
          'Content-Type': 'application/json', // 内容类型
        },
        params: {
          page, // 分页参数
          per_page: perPage, // 每页条数
        },
        httpsAgent: this.getHttpsAgent(), // 动态SSL配置
        timeout: parseInt(process.env.WP_API_TIMEOUT || '30000'), // 超时配置
      };

      try {
        const response = await axios.request(config);
        
        // 添加当前页数据
        allData.push(...response.data);

        // 检查是否还有更多页
        const totalPages = parseInt(response.headers['x-wp-totalpages'] || '1', 10);
        hasMore = page < totalPages;
        page += 1;
        
      } catch (error) {
        // 增强错误处理
        if (error.code === 'DEPTH_ZERO_SELF_SIGNED_CERT') {
          console.error('SSL证书错误:请检查证书配置或在开发环境中忽略SSL验证');
        }
        throw error;
      }
    }

    return allData;
  }
}
```

### 方案三:安装自签名证书(生产环境推荐）

#### 1. 生成证书

```bash
# 生成私钥
openssl genrsa -out server.key 2048

# 生成证书签名请求
openssl req -new -key server.key -out server.csr

# 生成自签名证书
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```

#### 2. 配置服务器

将生成的证书配置到WordPress服务器的SSL设置中。

## 安全最佳实践

### 环境配置对比表

| 环境类型 | SSL验证 | 推荐方案 | 安全级别 |
|---------|---------|---------|---------|
| 开发环境 | 可忽略 | 环境变量控制 | 低 |
| 测试环境 | 建议验证 | 使用测试证书 | 中 |
| 生产环境 | 必须验证 | 有效SSL证书 | 高 |

### 代码示例:环境检测

```typescript
// 环境安全检测
class SSLSecurityChecker {
  static checkEnvironment(): void {
    // 检查是否在生产环境中禁用了SSL验证
    if (process.env.NODE_ENV === 'production' && 
        process.env.NODE_TLS_REJECT_UNAUTHORIZED === '0') {
      throw new Error('生产环境不允许禁用SSL验证！');
    }
    
    // 开发环境警告
    if (process.env.NODE_ENV === 'development' && 
        process.env.WP_API_VERIFY_SSL === 'false') {
      console.warn('⚠️  开发环境已禁用SSL验证，请勿在生产环境使用此配置');
    }
  }
}

// 在应用启动时调用
SSLSecurityChecker.checkEnvironment();
```

## 故障排查步骤

### 排查流程表

| 步骤 | 检查项目 | 命令/方法 | 预期结果 |
|------|---------|----------|---------|
| 1 | 网络连通性 | `ping wp-test.local` | 能够ping通 |
| 2 | SSL证书状态 | `openssl s_client -connect wp-test.local:443` | 显示证书信息 |
| 3 | API端点可访问性 | `curl -k https://wp-test.local/wp-json/wc/v3/` | 返回API信息 |
| 4 | 认证信息正确性 | 检查Consumer Key/Secret | 密钥格式正确 |

## 参考文档

- [Node.js HTTPS文档](https://nodejs.org/api/https.html)
- [Axios配置文档](https://axios-http.com/docs/config_defaults)
- [WooCommerce REST API文档](https://woocommerce.github.io/woocommerce-rest-api-docs/)
- [OpenSSL证书生成指南](https://www.openssl.org/docs/)