# In-App Purchase 工具使用说明

## 概述

`InAppPurchaseUtil` 是一个基于 `in_app_purchase: ^3.2.3` 封装的内购工具类，提供了简单易用的 API 来处理应用内购买功能。

## 功能特性

- ✅ 单例模式，全局统一管理
- ✅ 支持 iOS 和 Android 双平台
- ✅ 自动处理购买流程和状态更新
- ✅ 支持订阅型和消耗型产品
- ✅ 支持恢复购买
- ✅ 完整的回调机制
- ✅ 详细的日志输出

## 快速开始

### 1. 初始化内购

在应用启动或需要使用内购的页面初始化：

```dart
final InAppPurchaseUtil _iapUtil = InAppPurchaseUtil.instance;

// 初始化并设置回调
await _iapUtil.initialize(
  onSuccess: (purchaseDetails) {
    print('购买成功: ${purchaseDetails.productID}');
    // 处理购买成功逻辑
  },
  onError: (purchaseDetails) {
    print('购买失败: ${purchaseDetails.error?.message}');
  },
  onCancelled: (purchaseDetails) {
    print('购买取消');
  },
  onPending: (purchaseDetails) {
    print('购买处理中');
  },
  onRestore: (purchaseDetails) {
    print('恢复购买成功: ${purchaseDetails.productID}');
  },
);
```

### 2. 加载产品信息

```dart
// 定义产品 ID
final productIds = {
  'com.yourapp.weekly',     // 周订阅
  'com.yourapp.monthly',    // 月订阅
  'com.yourapp.yearly',     // 年订阅
  'com.yourapp.lifetime',   // 终身会员
};

// 加载产品
bool success = await _iapUtil.loadProducts(productIds);

if (success) {
  // 获取产品列表
  List<ProductDetails> products = _iapUtil.products;
  
  // 显示产品信息
  for (var product in products) {
    print('${product.title}: ${product.price}');
  }
}
```

### 3. 购买产品

```dart
// 方法 1: 通过产品 ID 购买（推荐）
await _iapUtil.purchaseProductById('com.yourapp.yearly');

// 方法 2: 通过产品详情购买
final product = _iapUtil.getProductById('com.yourapp.yearly');
if (product != null) {
  await _iapUtil.purchaseProduct(product);
}

// 购买消耗型产品
await _iapUtil.purchaseProduct(product, isConsumable: true);
```

### 4. 恢复购买

```dart
await _iapUtil.restorePurchases();
// 恢复结果会在初始化时设置的 onRestore 回调中返回
```

## 完整示例

参考 `in_app_purchase_example.dart` 文件查看完整使用示例。

### Controller 中使用示例

```dart
class MyController extends GetxController {
  final InAppPurchaseUtil _iapUtil = InAppPurchaseUtil.instance;
  final isLoading = false.obs;
  final products = <ProductDetails>[].obs;

  @override
  void onInit() {
    super.onInit();
    _initIAP();
  }

  Future<void> _initIAP() async {
    // 初始化
    await _iapUtil.initialize(
      onSuccess: _handleSuccess,
      onError: _handleError,
    );

    // 加载产品
    await _loadProducts();
  }

  Future<void> _loadProducts() async {
    final productIds = {'com.yourapp.premium'};
    await _iapUtil.loadProducts(productIds);
    products.value = _iapUtil.products;
  }

  void _handleSuccess(PurchaseDetails details) {
    // 更新用户状态
    // 解锁高级功能
    // 显示成功提示
  }

  void _handleError(PurchaseDetails details) {
    // 显示错误提示
  }

  // 购买
  Future<void> purchase(String productId) async {
    await _iapUtil.purchaseProductById(productId);
  }

  // 恢复购买
  Future<void> restore() async {
    await _iapUtil.restorePurchases();
  }
}
```

## API 文档

### 初始化方法

#### `initialize()`

初始化内购功能并设置回调。

**参数：**
- `onUpdate`: 购买状态更新回调（可选）
- `onSuccess`: 购买成功回调（可选）
- `onError`: 购买失败回调（可选）
- `onCancelled`: 购买取消回调（可选）
- `onPending`: 购买等待中回调（可选）
- `onRestore`: 恢复购买成功回调（可选）

**返回值：** `Future<bool>` - 是否初始化成功

### 产品管理方法

#### `loadProducts(Set<String> productIds)`

加载产品信息。

**参数：**
- `productIds`: 产品 ID 集合

**返回值：** `Future<bool>` - 是否加载成功

#### `getProductById(String productId)`

根据产品 ID 获取产品详情。

**参数：**
- `productId`: 产品 ID

**返回值：** `ProductDetails?` - 产品详情，未找到返回 null

### 购买方法

#### `purchaseProduct(ProductDetails productDetails, {bool isConsumable = false})`

购买产品。

**参数：**
- `productDetails`: 产品详情
- `isConsumable`: 是否是消耗型产品，默认 false

**返回值：** `Future<bool>` - 是否发起购买成功

#### `purchaseProductById(String productId)`

通过产品 ID 购买产品。

**参数：**
- `productId`: 产品 ID

**返回值：** `Future<bool>` - 是否发起购买成功

#### `restorePurchases()`

恢复购买。

**返回值：** `Future<bool>` - 是否发起恢复成功

### 其他方法

#### `completePurchase(PurchaseDetails purchaseDetails)`

完成购买（通常由工具类自动调用）。

#### `dispose()`

清理资源（在应用退出时调用）。

## 配置说明

### iOS 配置

1. 在 App Store Connect 中创建内购商品
2. 配置 StoreKit Configuration 文件（用于本地测试）
3. 在 `Runner/Info.plist` 中添加必要的配置

### Android 配置

1. 在 Google Play Console 中创建应用内商品
2. 配置结算权限
3. 在 `AndroidManifest.xml` 中添加必要的权限

## 注意事项

### 服务器验证

⚠️ **重要**: 当前工具类中的 `_verifyPurchase()` 方法只是一个占位实现。在生产环境中，你必须：

1. 将购买凭证发送到你的后端服务器
2. 服务器验证凭证的真实性（调用 Apple/Google 验证 API）
3. 根据验证结果处理业务逻辑

示例验证流程：

```dart
Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
  try {
    // 发送到服务器验证
    final response = await dio.post('/api/verify-purchase', data: {
      'receipt': purchaseDetails.verificationData.serverVerificationData,
      'productId': purchaseDetails.productID,
      'platform': Platform.isIOS ? 'ios' : 'android',
    });
    
    return response.data['valid'] == true;
  } catch (e) {
    debugPrint('验证购买失败: $e');
    return false;
  }
}
```

### 测试建议

1. **沙盒测试**: 在 iOS 和 Android 上使用测试账号进行沙盒测试
2. **本地测试**: iOS 可以使用 StoreKit Configuration 文件进行本地测试
3. **真实测试**: 在发布前进行真实的购买和恢复测试

### 常见问题

**Q: 为什么产品加载失败？**

A: 检查以下几点：
- 产品 ID 是否正确
- 是否已在 App Store Connect/Google Play Console 中创建商品
- 商品状态是否为"准备提交"或"批准销售"
- 是否使用了正确的 Bundle ID/Package Name

**Q: 购买后如何同步到服务器？**

A: 在 `onSuccess` 回调中：
1. 验证购买凭证
2. 将购买信息同步到服务器
3. 更新用户订阅状态

**Q: 如何处理离线购买？**

A: 工具会自动保存未完成的购买，在下次启动时自动处理。确保在应用启动时调用 `initialize()`。

## 更新日志

### v1.0.0 (2025-11-13)
- ✨ 首次发布
- ✅ 支持 iOS 和 Android
- ✅ 完整的购买流程处理
- ✅ 恢复购买功能

## 相关资源

- [in_app_purchase 官方文档](https://pub.dev/packages/in_app_purchase)
- [Apple In-App Purchase 文档](https://developer.apple.com/in-app-purchase/)
- [Google Play Billing 文档](https://developer.android.com/google/play/billing)

## 支持

如有问题，请查看示例代码或提交 Issue。

