in_app_purchase_readme.md 7.4 KB

In-App Purchase 工具使用说明

概述

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

功能特性

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

快速开始

1. 初始化内购

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

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. 加载产品信息

// 定义产品 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. 购买产品

// 方法 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. 恢复购买

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

完整示例

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

Controller 中使用示例

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. 根据验证结果处理业务逻辑

示例验证流程:

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
  • ✅ 完整的购买流程处理
  • ✅ 恢复购买功能

相关资源

支持

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