import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:in_app_purchase/in_app_purchase.dart'; import '../../core/log/app_logger.dart'; /// 调起 Google Play 内购(三方为 false 时使用;三方为 true 且 ceremony==GooglePay 时用 launchPurchaseAndReturnData) abstract final class GooglePlayPurchaseService { static final _log = AppLogger('GooglePlayPurchase'); /// 发起购买并返回服务器凭据(用于三方支付选 GooglePay 时上报 /v1/payment/googlepay)。 /// 成功返回 purchaseData(serverVerificationData),取消/失败返回 null。 static Future launchPurchaseAndReturnData(String productId) async { _log.d('谷歌支付请求商品 ID(helm): "$productId"'); if (defaultTargetPlatform != TargetPlatform.android) { _log.d('非 Android,跳过内购'); return null; } final iap = InAppPurchase.instance; if (!await iap.isAvailable()) { _log.w('Billing 不可用'); return null; } final response = await iap.queryProductDetails({productId}); if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) { _log.w('商品未找到: 请求的 productId="$productId", notFoundIDs=${response.notFoundIDs}, 请核对与 Play 后台配置的「产品 ID」是否完全一致(区分大小写)'); return null; } final product = response.productDetails.first; final completer = Completer(); StreamSubscription>? sub; sub = iap.purchaseStream.listen( (purchases) { for (final p in purchases) { if (p.productID != productId) continue; if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) { if (!completer.isCompleted) { final data = p.verificationData.serverVerificationData; iap.completePurchase(p); completer.complete(data); } sub?.cancel(); return; } if (p.status == PurchaseStatus.error || p.status == PurchaseStatus.canceled) { if (!completer.isCompleted) completer.complete(null); sub?.cancel(); return; } } }, onError: (_) { if (!completer.isCompleted) completer.complete(null); sub?.cancel(); }, ); final success = await iap.buyConsumable( purchaseParam: PurchaseParam(productDetails: product), ); if (!success) { sub.cancel(); return null; } return completer.future.timeout( const Duration(seconds: 120), onTimeout: () { sub?.cancel(); return null; }, ); } /// 发起购买,商品 ID 为 [productId](即 ActivityItem.code / helm)。 /// 返回 true 表示购买完成,false 表示取消或失败。 static Future launchPurchase(String productId) async { if (defaultTargetPlatform != TargetPlatform.android) { return false; } final iap = InAppPurchase.instance; final available = await iap.isAvailable(); if (!available) { return false; } final response = await iap.queryProductDetails({productId}); if (response.notFoundIDs.isNotEmpty || response.productDetails.isEmpty) { _log.w('商品未找到: productId="$productId", notFoundIDs=${response.notFoundIDs}'); return false; } final product = response.productDetails.first; final completer = Completer(); StreamSubscription>? sub; sub = iap.purchaseStream.listen( (purchases) { for (final p in purchases) { if (p.productID != productId) continue; if (p.status == PurchaseStatus.purchased || p.status == PurchaseStatus.restored) { if (!completer.isCompleted) { iap.completePurchase(p); completer.complete(true); } sub?.cancel(); return; } if (p.status == PurchaseStatus.error) { if (!completer.isCompleted) { completer.complete(false); } sub?.cancel(); return; } if (p.status == PurchaseStatus.canceled) { if (!completer.isCompleted) { completer.complete(false); } sub?.cancel(); return; } } }, onError: (Object e) { if (!completer.isCompleted) completer.complete(false); sub?.cancel(); }, ); final purchaseParam = PurchaseParam(productDetails: product); final success = await iap.buyConsumable(purchaseParam: purchaseParam); if (!success) { sub.cancel(); return false; } return completer.future.timeout(const Duration(seconds: 120), onTimeout: () { sub?.cancel(); return false; }); } }