| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- import 'dart:async';
- import 'dart:io';
- import 'package:flutter/foundation.dart';
- import 'package:in_app_purchase/in_app_purchase.dart';
- import 'package:in_app_purchase_storekit/in_app_purchase_storekit.dart';
- import 'package:in_app_purchase_storekit/store_kit_wrappers.dart';
- /// 内购工具类
- /// 封装了 in_app_purchase 的常用功能
- class InAppPurchaseUtil {
- InAppPurchaseUtil._();
- static final InAppPurchaseUtil _instance = InAppPurchaseUtil._();
- static InAppPurchaseUtil get instance => _instance;
- /// 内购实例
- final InAppPurchase _inAppPurchase = InAppPurchase.instance;
- /// 购买流订阅
- StreamSubscription<List<PurchaseDetails>>? _subscription;
- /// 是否可用
- bool _available = false;
- /// 产品列表
- List<ProductDetails> _products = [];
- /// 购买状态回调
- Function(List<PurchaseDetails>)? onPurchaseUpdate;
- /// 购买成功回调
- Function(PurchaseDetails)? onPurchaseSuccess;
- /// 购买失败回调
- Function(PurchaseDetails)? onPurchaseError;
- /// 购买取消回调
- Function(PurchaseDetails)? onPurchaseCancelled;
- /// 购买等待中回调
- Function(PurchaseDetails)? onPurchasePending;
- /// 恢复购买成功回调
- Function(PurchaseDetails)? onRestoreSuccess;
- /// 获取内购是否可用
- bool get isAvailable => _available;
- /// 获取产品列表
- List<ProductDetails> get products => _products;
- /// 初始化内购
- ///
- /// [productIds] 产品ID列表
- /// [onUpdate] 购买状态更新回调
- /// [onSuccess] 购买成功回调
- /// [onError] 购买失败回调
- /// [onCancelled] 购买取消回调
- /// [onPending] 购买等待中回调
- /// [onRestore] 恢复购买成功回调
- Future<bool> initialize({
- Function(List<PurchaseDetails>)? onUpdate,
- Function(PurchaseDetails)? onSuccess,
- Function(PurchaseDetails)? onError,
- Function(PurchaseDetails)? onCancelled,
- Function(PurchaseDetails)? onPending,
- Function(PurchaseDetails)? onRestore,
- }) async {
- // 设置回调
- onPurchaseUpdate = onUpdate;
- onPurchaseSuccess = onSuccess;
- onPurchaseError = onError;
- onPurchaseCancelled = onCancelled;
- onPurchasePending = onPending;
- onRestoreSuccess = onRestore;
- // 检查内购是否可用
- _available = await _inAppPurchase.isAvailable();
- if (!_available) {
- debugPrint('内购不可用');
- return false;
- }
- // 初始化平台特定的配置
- if (Platform.isIOS) {
- final iosPlatformAddition = _inAppPurchase
- .getPlatformAddition<InAppPurchaseStoreKitPlatformAddition>();
- await iosPlatformAddition.setDelegate(ExamplePaymentQueueDelegate());
- }
- // 监听购买流
- _subscription = _inAppPurchase.purchaseStream.listen(
- _handlePurchaseUpdate,
- onDone: () {
- _subscription?.cancel();
- },
- onError: (error) {
- debugPrint('购买流错误: $error');
- },
- );
- debugPrint('内购初始化成功');
- return true;
- }
- /// 加载产品信息
- ///
- /// [productIds] 产品ID列表
- /// 返回是否加载成功
- Future<bool> loadProducts(Set<String> productIds) async {
- if (!_available) {
- debugPrint('内购不可用,无法加载产品');
- return false;
- }
- if (productIds.isEmpty) {
- debugPrint('产品ID列表为空');
- return false;
- }
- try {
- final ProductDetailsResponse response = await _inAppPurchase
- .queryProductDetails(productIds);
- if (response.error != null) {
- debugPrint('加载产品失败: ${response.error}');
- return false;
- }
- if (response.productDetails.isEmpty) {
- debugPrint('未找到任何产品');
- return false;
- }
- _products = response.productDetails;
- // 打印产品信息
- for (var product in _products) {
- debugPrint(
- '产品: ${product.id}, 价格: ${product.price}, 标题: ${product.title}',
- );
- }
- return true;
- } catch (e) {
- debugPrint('加载产品异常: $e');
- return false;
- }
- }
- /// 根据产品ID获取产品详情
- ///
- /// [productId] 产品ID
- /// 返回产品详情,如果未找到返回 null
- ProductDetails? getProductById(String productId) {
- try {
- return _products.firstWhere((product) => product.id == productId);
- } catch (e) {
- debugPrint('未找到产品: $productId');
- return null;
- }
- }
- /// 购买产品
- ///
- /// [productDetails] 产品详情
- /// [isConsumable] 是否是消耗型产品,默认为 false(非消耗型产品,如订阅)
- /// 返回是否发起购买成功
- Future<bool> purchaseProduct(
- ProductDetails productDetails, {
- bool isConsumable = false,
- }) async {
- if (!_available) {
- debugPrint('内购不可用');
- return false;
- }
- try {
- final PurchaseParam purchaseParam = PurchaseParam(
- productDetails: productDetails,
- );
- bool success;
- if (isConsumable) {
- success = await _inAppPurchase.buyConsumable(
- purchaseParam: purchaseParam,
- );
- } else {
- success = await _inAppPurchase.buyNonConsumable(
- purchaseParam: purchaseParam,
- );
- }
- if (success) {
- debugPrint('发起购买成功: ${productDetails.id}');
- } else {
- debugPrint('发起购买失败: ${productDetails.id}');
- }
- return success;
- } catch (e) {
- debugPrint('购买异常: $e');
- return false;
- }
- }
- /// 通过产品ID购买产品
- ///
- /// [productId] 产品ID
- /// 返回是否发起购买成功
- Future<bool> purchaseProductById(String productId) async {
- final product = getProductById(productId);
- if (product == null) {
- debugPrint('未找到产品: $productId,请先调用 loadProducts');
- return false;
- }
- return await purchaseProduct(product);
- }
- /// 恢复购买
- ///
- /// 返回是否发起恢复成功
- Future<bool> restorePurchases() async {
- if (!_available) {
- debugPrint('内购不可用');
- return false;
- }
- try {
- await _inAppPurchase.restorePurchases();
- debugPrint('发起恢复购买');
- return true;
- } catch (e) {
- debugPrint('恢复购买异常: $e');
- return false;
- }
- }
- /// 完成购买
- ///
- /// [purchaseDetails] 购买详情
- Future<void> completePurchase(PurchaseDetails purchaseDetails) async {
- await _inAppPurchase.completePurchase(purchaseDetails);
- debugPrint('完成购买: ${purchaseDetails.productID}');
- }
- /// 处理购买更新
- void _handlePurchaseUpdate(List<PurchaseDetails> purchaseDetailsList) {
- // 触发统一回调
- onPurchaseUpdate?.call(purchaseDetailsList);
- // 处理每个购买详情
- for (var purchaseDetails in purchaseDetailsList) {
- debugPrint(
- '购买状态: ${purchaseDetails.status}, 产品: ${purchaseDetails.productID}',
- );
- switch (purchaseDetails.status) {
- case PurchaseStatus.pending:
- // 购买等待中
- onPurchasePending?.call(purchaseDetails);
- break;
- case PurchaseStatus.purchased:
- // 购买成功
- _handlePurchaseSuccess(purchaseDetails);
- break;
- case PurchaseStatus.restored:
- // 恢复购买成功
- _handleRestoreSuccess(purchaseDetails);
- break;
- case PurchaseStatus.error:
- // 购买失败
- _handlePurchaseError(purchaseDetails);
- break;
- case PurchaseStatus.canceled:
- // 购买取消
- onPurchaseCancelled?.call(purchaseDetails);
- if (purchaseDetails.pendingCompletePurchase) {
- completePurchase(purchaseDetails);
- }
- break;
- }
- }
- }
- /// 处理购买成功
- Future<void> _handlePurchaseSuccess(PurchaseDetails purchaseDetails) async {
- // 这里可以添加服务器验证逻辑
- bool valid = await _verifyPurchase(purchaseDetails);
- if (valid) {
- debugPrint('购买验证成功: ${purchaseDetails.productID}');
- onPurchaseSuccess?.call(purchaseDetails);
- } else {
- debugPrint('购买验证失败: ${purchaseDetails.productID}');
- onPurchaseError?.call(purchaseDetails);
- }
- // 完成购买
- if (purchaseDetails.pendingCompletePurchase) {
- await completePurchase(purchaseDetails);
- }
- }
- /// 处理恢复购买成功
- Future<void> _handleRestoreSuccess(PurchaseDetails purchaseDetails) async {
- // 验证恢复的购买
- bool valid = await _verifyPurchase(purchaseDetails);
- if (valid) {
- debugPrint('恢复购买验证成功: ${purchaseDetails.productID}');
- onRestoreSuccess?.call(purchaseDetails);
- }
- // 完成购买
- if (purchaseDetails.pendingCompletePurchase) {
- await completePurchase(purchaseDetails);
- }
- }
- /// 处理购买失败
- Future<void> _handlePurchaseError(PurchaseDetails purchaseDetails) async {
- debugPrint('购买失败: ${purchaseDetails.error}');
- onPurchaseError?.call(purchaseDetails);
- // 完成购买
- if (purchaseDetails.pendingCompletePurchase) {
- await completePurchase(purchaseDetails);
- }
- }
- /// 验证购买(需要根据实际业务实现)
- ///
- /// [purchaseDetails] 购买详情
- /// 返回是否验证通过
- Future<bool> _verifyPurchase(PurchaseDetails purchaseDetails) async {
- // TODO: 在这里实现服务器验证逻辑
- // 1. 将购买凭证发送到你的服务器
- // 2. 服务器向 Apple/Google 验证购买
- // 3. 返回验证结果
- // 临时返回 true,实际使用时需要实现服务器验证
- return true;
- }
- /// 获取过去的购买记录
- ///
- /// 注意:iOS 和 Android 都建议使用 restorePurchases() 方法来恢复购买
- /// 本方法已弃用,建议使用 restorePurchases() 替代
- @Deprecated('使用 restorePurchases() 方法替代')
- Future<List<PurchaseDetails>> getPastPurchases() async {
- if (!_available) {
- debugPrint('内购不可用');
- return [];
- }
- try {
- if (Platform.isIOS) {
- debugPrint('iOS 平台请使用 restorePurchases 来恢复购买');
- return [];
- } else if (Platform.isAndroid) {
- debugPrint('Android 平台请使用 restorePurchases 来恢复购买');
- return [];
- }
- } catch (e) {
- debugPrint('获取过去购买记录异常: $e');
- }
- return [];
- }
- /// 检查用户是否有有效订阅
- Future<bool> hasActiveSubscription(Set<String> subscriptionIds) async {
- if (!_available) {
- return false;
- }
- try {
- // 恢复购买
- await _inAppPurchase.restorePurchases();
- // 这里需要根据实际情况检查订阅状态
- // 通常需要结合服务器验证来判断
- return false;
- } catch (e) {
- debugPrint('检查订阅状态异常: $e');
- return false;
- }
- }
- /// 清理资源
- void dispose() {
- _subscription?.cancel();
- _subscription = null;
- debugPrint('内购资源已清理');
- }
- }
- /// iOS 支付队列代理示例
- class ExamplePaymentQueueDelegate implements SKPaymentQueueDelegateWrapper {
- @override
- bool shouldContinueTransaction(
- SKPaymentTransactionWrapper transaction,
- SKStorefrontWrapper storefront,
- ) {
- return true;
- }
- @override
- bool shouldShowPriceConsent() {
- return false;
- }
- }
|