yii.
← Writing
Flutter 技術 · · 20 min read

Flutter In-App Purchases Simplified with RevenueCat: Tips and Sales Strategies

We can make app monetization easier.

In today’s competitive mobile app landscape, building a great product is only half the battle — monetizing it effectively is the other. For Flutter developers, implementing in-app purchases (IAP) across platforms can be complex, time-consuming, and full of edge cases. That’s where RevenueCat comes in.

This article is crafted for developers, product owners, and indie makers looking to simplify their IAP implementation and boost their app revenue with smart sales strategies. Whether you’re launching your first subscription-based app or optimizing an existing monetization flow, this guide will walk you through practical tips, technical insights, and proven strategies, using Flutter and RevenueCat as the foundation.


I want to start by sharing this image — does it feel a little too familiar? Kind of like our daily life as developers, right?

You’ve probably been using all kinds of LLM tools — letting AI or ChatGPT help you write code, design UI, even generate documentation.

These days, all it takes is a late-night idea, and within just a few evenings, you’ve built a product. By the next day, you’re posting it on X or Threads, asking friends to give it a try.

This is what I like to call: “The vibe-to-shipping era” — if you’ve got the vibe, you can ship. And once you can ship, you might even make money from it!

So today, I want to explore one simple question: When you already have the vibe, the product, and some users, what’s next?

If you’re planning to launch a mobile product and let users pay for the value you provide, then In-App Purchases are likely the first big hurdle you’ll have to face.

In this article, I’ll walk you through how we use RevenueCat to help our product monetize efficiently and with high quality.

What is In-App Purchase(IAP)?#

IAP refers to the purchase of digital items directly within your app. And there are three main types, each suited for different user needs and product experiences.

Consumable#

These are items that users can use up and buy again, like energy points, potions, or in-game currency. In gaming apps, this is very common.

Non-Consumable#

These are one-time purchases that users keep forever, like unlocking a feature, removing ads, or buying a special tool. Once you buy it, it’s yours for life.

Subscription#

This gives users access to premium content or features over time. It could be monthly, quarterly, or yearly, and it usually renews automatically. Think of things like Pro access or unlocking advanced features.

Each of these has its own best use case and plays a big role in how we design the user experience around monetization.

Why Most Apps Use IAP Subscriptions?#

If you look around, you’ll notice that some successful apps today are using IAP subscriptions. But why is that?

The biggest advantage is predictable recurring revenue. Once a user makes their first purchase and links a payment method, the subscription renews automatically. This encourages long-term retention and gives the product team more stability in planning and forecasting.

It’s not just indie developers — major apps like Notion and CapCut are also monetizing through IAP subscriptions. So it’s not just a trend — it’s a proven, scalable business model.

What’s the efficient way to turn it into a monetizable product?

RevenueCat!#

The truth is, integrating IAP isn’t just about adding a button to your app.
It involves a lot of behind-the-scenes processes, like validating receipts, handling cancellations, and more. Building all of that on your own can be overwhelming.

That’s why we chose RevenueCat. It takes care of all the heavy lifting, so we don’t need to build a full IAP system from scratch.

Design For Mobile Apps#

RevenueCat is a one-stop platform designed specifically for mobile apps and subscription features.

It integrates Apple and Google and takes care of the most complicated parts, like receipt validation and server webhooks.

Analytics#

Even better — it gives you built-in analytics, like churn rate, monthly recurring revenue (MRR), active subscriptions, and more.

You get a clear view of your app’s performance over time.

Real-time Subscriber Insights#

With RevenueCat, your team can stay on top of every subscriber’s status in real time — when they start, cancel, renew, upgrade, or change plans. You can fully understand every user.

If we do IAP — Flow#

Let’s first take a look at the in-app purchase flow. If you’re building everything yourself, there are several stages to manage: your app talks to the Store SDK (both Apple and Google), you handle receipt validation, and you’ll need a backend server to track subscription status and logic. It’s complex and time-consuming.

Every stage of the IAP flow can go wrong. On the app side, you might run into SDK integration issues. On the store side, payment can fail or get stuck. And on the backend, you need to handle receipt validation and make sure the user status stays in sync.

These are all critical points that require careful handling if you’re building your own IAP system.

📦 APP ↔ Store SDK

  • SDK integration error (initialization incomplete)
  • Wrong product ID
  • Error code not handled

🔄 Store SDK ↔ Apple/Google Store

  • Platform service delay
  • User cancellation, payment failure
  • Store response format changes have not kept up

🧾 Receipt validation (usually handled by the App Server)

  • The receipt was forged
  • The authentication API is invalid or formatted incorrectly
  • Different receipt formats on different platforms lead to processing errors

💾 App Server ↔ User Status Management

  • Permission update failed
  • Server crash causes data to become out of sync
  • No instant notification of app status changes

RevenueCat IAP Flow#

Once we adopted RevenueCat, we reduced our development and maintenance effort.

From the moment a purchase is triggered in the app, RevenueCat takes care of receipt validation, subscription status updates, and even syncing between platforms. All we have to do is listen for the success or failure callbacks and then grant the user the appropriate access or feature.

From this moment on, you can stop worrying about building your own IAP infrastructure — and instead focus on what matters: your product and user experience.

Basic Work: Set up products in stores & RevenueCat#

Before we start integrating IAP, there’s one important setup step: We need to add the products to both the app stores and RevenueCat. Each product represents an actual in-app item the user can purchase.

And remember — every product has a unique Product ID that can’t be changed later. So it’s a good idea to use clear and consistent naming, like based on version, promotion, or season — for example, “v1,” “promo,” or “spring2024” This makes future tracking and management much easier.

Next: Let’s talk about one of the core elements in RevenueCat — the Package.

1️⃣ Package#

A Package is used to group the same product across different platforms.

This ensures that no matter where your user makes a purchase — Apple, Google, or even Stripe — it’s mapped back to the same logical item in your app. This cross-platform alignment makes handling purchases a lot smoother.

Example: Package A → Product A on all platforms

from RevenueCat
from RevenueCat

2️⃣ Entitlement#

Entitlement defines what feature or access is granted after a purchase.

The second key concept in RevenueCat is the Entitlement. It defines what a user gets after a purchase, like premium access or ad removal. This makes it easy to manage what features each purchase unlocks.

Example: Buying product A might grant the “Gold” entitlement, and buying product C could grant “Diamond”

from RevenueCat
from RevenueCat

Remind: If it is a consumable product (such as game currency, points), it should generally not be bound to an Entitlement. This is different from the design concept of consumables (it can be purchased multiple times, and it is gone once it is used up).

3️⃣ Offering#

Offering is the set of products shown to users on the paywall.

The last key concept is the Offering. It defines what users see when they’re deciding to subscribe. An Offering can include multiple packages, like “Pro Monthly” and “Pro Yearly — 30% Off.” This structure is perfect for testing price points and promotional campaigns.

Example: Astandard Pro plan and a special New Year deal.

from RevenueCat
from RevenueCat

You can use an API or feature flag to decide which offering group to display and dynamically switch product combinations. Allows you to flexibly switch which group of products to display to users, such as limited-time annual plans, student plans, etc.

Once Offerings are in place, we can move into building the actual paywall and subscription flow.

Integrating RevenueCat SDK in Flutter#

Now we move into implementation, which is actually a pretty lightweight process. The first step is to add the official RevenueCat Flutter SDK, called purchases_flutter, into your pubspec.yaml.

💡 Initialize RevenueCat SDK#

After adding the SDK, the next step is initialization. You just need to provide your API key. It’s a straightforward setup, no complicated configuration required.

Purchases.configure(
  PurchasesConfiguration('your_revenuecat_api_key'),
);

💡Fetch Offerings#

Then, call getOfferings() to fetch the available Offerings. Typically, you’ll present these in your subscription UI. If you only have one Offering, you can simply call the current one to retrieve the default set.

final offerings = await Purchases.getOfferings();

// Default offering
final currentOffering = offerings.current;

💡 Fetch Packages from Offering#

The next step is to access its available Packages. Each Package maps to a product ID on Apple, Google, like “monthly_pro”, “annual_promo”, etc. These are the actual items your users will subscribe to.

You can now display them in your UI however you like — cards, price tiles, or your own custom layout.

final availablePackages = offering.availablePackages;

// package for platform product
final monthlyPackage = offering.monthly;
final quarterlyPackage = offering.threeMonth;
final annualPackage = offering.annual;
final lifetimePackage = offering.lifetime;

💡 Purchase Package#

We can let users start the purchase by tapping a button. Just call purchasePackage() and pass in the selected Package.

This handles everything: opening the store dialog, confirming payment, and verifying the purchase behind the scenes.

await Purchases.purchasePackage(package);

💡 Verify User Entitlements#

Once a purchase is complete, it returns a CustomerInfo object. This contains the list of active entitlements for the current user. Based on this, you can unlock premium features.

Remember: always check entitlements rather than trying to track purchases manually.

final customerInfo = await Purchases.getCustomerInfo();

final activeEntitlements = customerInfo.entitlements.active;
final hasActiveEntitlements = activeEntitlements.isNotEmpty;

final isPlus = customerInfo.entitlements.all['plus']?.isActive ?? false;
final isPro = customerInfo.entitlements.all['pro']?.isActive ?? false;
final isVip = customerInfo.entitlements.all['vip']?.isActive ?? false;

🙋🏻 Sync Existing Subscribers#

If you say: you’re migrating from your own IAP system or switching to RevenueCat mid-project, I also want to synchronize existing subscribers to RevenueCat.

That’s of course no problem. Use syncPurchases() to upload the user’s local purchase history from the device. After syncing, the user’s entitlements will also be updated accordingly.

RevenueCat Console
RevenueCat Console

Congrats!#

From here, with RevenueCat integrated, your Flutter app is ready to start monetizing and welcome its first paying user.

Can it get any easier?#

At this point, some developers might ask — Can it get even easier? What if I don’t want to spend time designing my paywall UI? Maybe I just want something that works out of the box and lets me validate ideas quickly.

Well, RevenueCat has something for that, too.

It’s Paywall🧱#

Paywall is a visual editor for your subscription UI. It’s like Figma, but for monetization. Drag components, bind packages, tweak templates — and you’re live.

It’s perfect for lazy devs or vibe coders that want to test ideas fast without building from scratch.

  1. Use RevenueCatUI.presentPaywall() to display the paywall.
  2. Use RevenueCatUI.presentPaywallIfNeeded(“pro”) The paywall will be displayed only if the customer has not unlocked the Entitlement.
  3. You can also embed PaywallView into your own UI and use callbacks for full integration.
void presentPaywall() async {
  final paywallResult = await RevenueCatUI.presentPaywall();
  log('Paywall result: $paywallResult');
}

void presentPaywallIfNeeded() async {
  final paywallResult = await RevenueCatUI.presentPaywallIfNeeded("pro");
  log('Paywall result: $paywallResult');
}

Embed PaywallView in your custom widget.

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Center(
        child: PaywallView(
          offering: offering, // Optional Offering object obtained through getOfferings
          onRestoreCompleted: (CustomerInfo customerInfo) {
            // Optional listener. Called when a restore has been completed.
            // This may be called even if no entitlements have been granted.
          } 
          onDismiss: () {
            // Dismiss the paywall, i.e. remove the view, navigate to another screen, etc.
            // Will be called when the close button is pressed (if enabled) or when a purchase succeeds.
          },
        ),
      ),
    ),
  );
}

At the same time, you can use the provided callbacks to react to user operations. Available ones are:

  • onPurchaseStarted
  • onPurchaseCompleted
  • onPurchaseError
  • onRestoreCompleted
  • onRestoreError
  • onDismiss

Pitfalls & FAQs#

🙋 Subscription Switching: Upgrade & Downgrade in Apple#

When users today switch plans during some discount periods, they will ask what will happen after subscribing.

  • Upgrade(Monthly to Yearly): When a user upgrades from a monthly to a yearly plan, Apple charges immediately and refunds or credits the unused portion of the current subscription.
  • Downgrade: the change takes effect only after the current subscription period ends, and the user will be charged the new price in the next billing cycle.

🙋 Subscription Switching: Upgrade & Downgrade in Google#

Google allows multiple strategies for upgrading during the free trial, unlike Apple. We recommend using it CHARGE_PRORATED_PRICE because it mimics Apple’s immediate upgrade behavior. Users get instant access and a prorated refund. It’s intuitive and fair.

🙋 Apple Sandbox Delay in Testing#

When testing during development, if you notice that Apple’s Sandbox environment responds slowly, sometimes taking over 10 seconds to complete a purchase.

The App Store Sandbox has lower performance, but that doesn’t mean there’s anything wrong with your integration. In production, purchase flows are much smoother and faster.

🙋 How to detect subscription cancellation?#

You might wonder: how do we know when a user cancels or their subscription expires?

This information isn’t available directly on the mobile side. To track subscription status accurately, you need to configure a backend Webhook with RevenueCat or periodically call their API to sync the latest status. It’s crucial for access control, security, and user communication.

🙋 IAP purchases are bound to the platform account#

Regardless of Android or iOS, the effective permissions and records after purchase are related to the Google Play and Apple login accounts, not the associated APP-related accounts.

This point needs to be explained clearly to users, as it is a very common confusion. Because it is related to platform binding, if the user uses different memberships to operate in the APP, if the platform account is the same, just click Restore Purchase after purchase to obtain the original permissions

🙋 Product prices are different#

Different countries may display different numbers due to currency exchange rates, so the calculated amount may not be the same as the amount in your country. In some places, taxes may be added.

🙋 Restoring purchases and device transfer#

RevenueCat provides restorePurchases(), which is your good friend. When the user changes the phone, you can get the previous subscription back. Usually, a “Restore Purchases” button is added to the settings page, which is also recommended by Apple.

// RevenueCat
await Purchases.restorePurchases();

🙋 Different testing settings for IAP#

iOS

  • Developer settings, set up SANDBOX account
  • Using TestFlight builds

Android

  • Create a license tester
  • Use internal or alpha testing versions

IAP Tips & Sales Strategies#

Here are a few proven IAP tips and strategies to boost your sales.

🪝 Webhook Matters#

Webhook is your secret weapon for understanding user behavior.

If a user cancels a subscription, upgrades, or gets refunded, the webhook lets you react instantly to these events. You can automatically send an email, push notification, or update your database when something happens.

It brings transparency and better user engagement to your monetization journey.

🤩 Attractive Experience#

The key to a high-converting experience is making users feel the value instantly, and getting them used to being Pro.

  • Clear value: Don’t just list features — explain why users should subscribe now.
  • Experience first: Let users try the Pro experience before asking for payment.

In my product HerFIT, we tell users: “This is a personalized body-sculpting plan for stay-at-home moms — you’ll see results in just 3 months.”

We also offer free flows and limited trials of advanced features so users fall in love with the Pro experience before committing. Once they feel the difference, they’ll think:

“This is too good — I don’t want to lose it.”

🧠 Smart Sales Hooks#

  • Create urgency with “FOMO”
    FOMO is your best friend when it comes to boosting conversions. Try a 48-hour free trial or a limited-time welcome discount — just add a countdown animation to spark urgency.
  • Recover users at the point of churn
    When users try to cancel, don’t let them leave without a fight. Send a quick survey to ask why, and offer something like a 50% stay discount.
  • Track user behavior for personalized offers
    And don’t forget behavioral targeting — if someone visits the paywall multiple times but doesn’t subscribe, that’s your chance to push a personalized offer and close the deal.

Giving users as much incentive as possible in every aspect of the APP is a key skill

A great purchasing experience makes users feel excited to buy now like they’d miss out if they don’t rather than feeling pressured or forced.

🏛️ Stay Updated on Policy#

One last thing that often gets overlooked. In-app purchases aren’t just about coding features — they’re bound by policy, law, and financial compliance.

  • Platforms (Apple / Google)
    A single change in Apple’s rules (like clearly showing post-trial pricing) or Google’s UX guidelines for cancellations can force you to redesign your flow.
  • Local and government regulations
    Countries like South Korea, India, and those in the EU have very different rules around tax, commission fees, and billing policies.
  • Service providers (RevenueCat)
    They release webhook updates or API improvements every few weeks — keep tabs on those or you’ll miss important fixes.

As a developer or a product lead, you need to be proactive and informed. Policy changes aren’t just admin stuff; they shape your entire user journey.

Apple’s recent policy priorities (May, 2025)

One big update from Apple recently — it’s a huge deal.
One big update from Apple recently — it’s a huge deal.

Starting May 1st, Apple must allow iOS apps to support external payment systems, and they can’t charge that infamous 15–30% commission anymore.

This is great news for developers! For years we’ve been stuck paying platform fees we couldn’t avoid — and this shift is largely thanks to Epic Games and their ongoing legal battle.

But keep in mind — it only applies to U.S. apps for now, and reader apps (like Spotify).

This policy change brings several real benefits to developers and businesses.

  1. First, more revenue stays in your hands. Without the 15–30% platform cut, you can reinvest that money into growth, marketing, or product improvements.
  2. Second, you get to use custom payment solutions like Stripe or local providers. That means a smoother, more branded checkout experience tailored to your users.
  3. Third, faster iteration. Since pricing and product changes happen on your own web pages, you skip App Store reviews and can push updates instantly. That gives your marketing team so much more flexibility.
  4. And finally, faster payouts. No more waiting 1–2 months for Apple or Google to settle. For startups and lean teams, quicker cash flow can make a huge difference.

Of course, external payment comes with its own set of challenges.

  1. First, there’s a shift in user behavior. When users are taken out of the app to complete a purchase on the web. They may wonder, “Is this secure?” That drop in confidence can hurt your conversion rate.
  2. Second, there’s added friction and operational cost. Apple and Google usually handle things like refunds, fraud prevention, and tax compliance. But when you go external, those responsibilities fall on your team.
  3. Finally, let’s talk numbers. RevenueCat ran an A/B test and found that using external payments led to a 25% to 45% drop in conversion rate. And that’s not even counting the cost of setting up and maintaining your own payment system.

So while external payment gives you more freedom, it also comes with trade-offs you’ll need to carefully weigh.


So, this article is about how to approach In-App Purchases with more professionalism and strategy.

Once you’ve mastered these concepts, you’ll understand IAP better than many developers. And with that understanding, I believe you’re ready to take on the challenge of monetizing your product with confidence 💪

Now’s the time — turn those ideas in your head into real products and start sharing them with the world!

Video (Flutter Global Summit’25)#

Reference#

  1. https://www.linkedin.com/posts/skydoves_unveiling-industry-secrets-revenuecats-activity-7327673396861763584-EeJ8/
  2. https://x.com/RevenueCat/status/1917844456356696552

“Free citations are welcome, but source must be cited”

本文原刊登於 Medium。