You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何验证In App Purchase的订阅支付状态?

Solution for Subscription Status Tracking & Validation with in_app_purchase 3.0.8

Core Issue Breakdown

The buyConsumable/buyNonConsumable methods only return a boolean to confirm if the purchase flow was initiated successfully. All critical purchase status updates (authorized, denied, failed, pending) are delivered via the purchaseStream. You must listen to this stream to track and validate subscription completions.


Step 1: Implement Purchase Stream Listener

Add this logic early in your app (e.g., in the initState of your subscription screen) to capture real-time purchase events:

late StreamSubscription<List<PurchaseDetails>> _purchaseSubscription;

@override
void initState() {
  super.initState();
  _setupPurchaseStream();
}

void _setupPurchaseStream() {
  final purchaseStream = InAppPurchase.instance.purchaseStream;
  _purchaseSubscription = purchaseStream.listen(
    _handlePurchaseUpdates,
    onError: (error) => _handlePurchaseError(error as IAPError),
    onDone: () => _purchaseSubscription.cancel(),
  );
}

void _handlePurchaseUpdates(List<PurchaseDetails> purchases) {
  for (final purchase in purchases) {
    switch (purchase.status) {
      case PurchaseStatus.pending:
        // Show loading state for pending purchases
        break;
      case PurchaseStatus.error:
        _handlePurchaseError(purchase.error!);
        break;
      case PurchaseStatus.purchased:
      case PurchaseStatus.restored:
        // Validate purchase (client + server-side)
        _validateSubscription(purchase);
        // Complete the purchase for non-consumables/subscriptions
        if (purchase.pendingCompletePurchase) {
          InAppPurchase.instance.completePurchase(purchase);
        }
        break;
      default:
        break;
    }
  }
}

void _handlePurchaseError(IAPError error) {
  String errorMessage;
  switch (error.code) {
    case IAPErrorCode.canceled:
      errorMessage = "Purchase canceled";
      break;
    case IAPErrorCode.paymentInvalid:
      errorMessage = "Invalid payment method";
      break;
    default:
      errorMessage = "Purchase failed: ${error.message}";
  }
  // Display error to user (e.g., SnackBar, AlertDialog)
}

Future<void> _validateSubscription(PurchaseDetails purchase) {
  // 1. Basic client-side check (not secure alone)
  if (purchase.productID == "your_subscription_sku") {
    // Update local UI state temporarily
  }
  // 2. Mandatory server-side validation (secure)
  return _sendPurchaseToBackend(purchase);
}

Future<void> _sendPurchaseToBackend(PurchaseDetails purchase) {
  // Send verification data to your backend for validation with Apple/Google
  // Example:
  // await http.post(
  //   Uri.parse("https://your-backend.com/verify-subscription"),
  //   body: {
  //     "token": purchase.verificationData.serverVerificationData,
  //     "product_id": purchase.productID,
  //     "user_id": currentUser.id,
  //   },
  // );
  // Handle backend response to confirm valid subscription
}

@override
void dispose() {
  _purchaseSubscription.cancel();
  super.dispose();
}

Step 2: iOS Configuration

  1. App Store Connect Setup:
    • Navigate to your app → Features → In-App Purchases.
    • Create subscription products and ensure they are marked "Ready to Submit" or "Approved".
  2. Xcode Capabilities:
    • Open your project in Xcode → Target → Signing & Capabilities → Add Capability → Enable In-App Purchase.
  3. Sandbox Testing:
    • Create sandbox tester accounts in App Store Connect → Users and Access → Sandbox Testers.
    • Sign out of the App Store on your test device, then use the sandbox account when prompted during purchase.
  4. Restore Purchases:
    • Add a "Restore Purchases" button that calls InAppPurchase.instance.restorePurchases(); restored subscriptions will appear in the purchaseStream.

Step 3: Android Configuration

  1. Google Play Console Setup:
    • Go to your app → Monetization → Products → Subscriptions.
    • Create and activate your subscription products.
  2. Manifest Permission:
    • Add this line to android/app/src/main/AndroidManifest.xml:
      <uses-permission android:name="com.android.vending.BILLING" />
      
  3. Test with Internal App Sharing:
    • Upload your app to Google Play Console via Internal App Sharing.
    • Use a license testing account (added in Play Console → Settings → Account details → License testing) to test purchases.
  4. Restore Purchases:
    • Implement a "Restore Purchases" button that calls InAppPurchase.instance.restorePurchases() to retrieve past subscriptions.

Critical Security Notes

  • Never trust client-side validation: Users can tamper with local data. Always validate purchase tokens via your backend using Apple's App Store API or Google's Play Developer API.
  • Enable Server-to-Server Notifications:
    • For iOS: Set up S2S notifications in App Store Connect to receive updates on subscription renewals, cancellations, or expirations.
    • For Android: Enable Real-Time Developer Notifications in Google Play Console to track subscription status changes.

内容的提问来源于stack exchange,提问作者Felippe Negrão de Oliveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:31:00