nimbus_cashier 1.1.0 copy "nimbus_cashier: ^1.1.0" to clipboard
nimbus_cashier: ^1.1.0 copied to clipboard

Nimbus Cashier for Flutter — App Store and Google Play subscriptions verified by your Cashier app, gated on entitlements.

nimbus_cashier #

In-app subscriptions for Flutter apps on iOS and Android, backed by Nimbus Cashier. Purchases go through the App Store and Google Play (via in_app_purchase); Cashier verifies each one with the store, keeps it current through renewals and refunds, and answers one question: is this user entitled to premium?

Beta. The Swift and Kotlin SDKs are the reference; this package follows them. Paywalls designed in the console are drawn natively in Flutter widgets, the same documents the web and iOS SDKs render.

Install #

flutter pub add nimbus_cashier

or from git:

dependencies:
  nimbus_cashier:
    git: https://github.com/CodeSyncr/cashier-flutter.git

Use #

import 'package:nimbus_cashier/nimbus_cashier.dart';

await Cashier.configure(apiKey: 'cshr_pub_…'); // the PUBLIC key

await Cashier.shared.logIn(user.id);            // after your own sign-in

final info = await Cashier.shared.customerInfo();
if (info.isEntitledTo('premium')) unlockPremium();

final offering = (await Cashier.shared.offerings()).current;
final result = await Cashier.shared.purchase(offering!.availablePackages.first);

await Cashier.shared.restorePurchases();

Cashier.shared.customerInfoStream emits every change — see example/lib/main.dart for a gate built on it.

Paywalls #

Design a paywall for an offering in the Cashier console and show it with one call. It is drawn natively (Flutter widgets, no web view), with the store's prices, and buys through the SDK:

final result = await Cashier.presentPaywall(
  context,
  requiredEntitlement: 'premium',   // not shown to users who already have it; closes once granted
  locale: const Locale('es'),       // optional: default is the device's language
  onPurchaseCompleted: (info) {},
  onRestoreCompleted: (info) {},
  onAnswer: (answer) {              // Feedback / Marketing Consent screens
    if (answer.answer == 'yes') requestNotificationPermission();
  },
);
// PaywallResult.purchased | restored | cancelled | notPresented

Or place it yourself — PaywallView is an ordinary widget:

Navigator.of(context).push(MaterialPageRoute(
  fullscreenDialog: true,
  builder: (_) => PaywallView(onPurchaseCompleted: (info) => Navigator.pop(context)),
));

With no offering, PaywallView loads the current one; when that offering has no published paywall, a plain list of its packages is shown (fallbackBuilder replaces it). To render a document with your own purchase handling (previews, tests), use PaywallContent(doc:, packages:, onPurchase:).

What is supported:

  • Every block type and variant of the schema (title, text, image, video, art, icon, stack, custom, sheet, tabs, switch, button, carousel, countdown, timeline, social_proof, testimonial, features, award, packages, cta, header, footer, spacer), per-block look / look_selected styling, plan cards with badges, and multi-screen flows (buttons: next, back, screen, close, restore, url).
  • Themes (per screen too), gradient and image backgrounds, background video, animated effects (glow, aurora, orbs, grid, rays) and entrances (rise, fade, zoom). Motion stops when the platform asks for reduced motion.
  • Text variables: {{app_name}}, {{product_name}}, {{price}}, {{period}}, {{price_per_month}}, {{trial}}, {{savings}} (against the shortest plan of a month or more).
  • Translations: the document's strings for the requested locale (exact tag, else the same language), applied by localize(doc, locale) before drawing.
  • Analytics: a view event when first shown and a close event when dismissed without a purchase (fire-and-forget), with the A/B experiment the user is in. Offerings are requested with the user's id so the server can assign experiments (offerings.experiment, offering.paywallId).
  • Answers: buttons with an answer call onAnswer and are sent to Cashier (POST /paywalls/responses).
  • Cashier.shared.previewOffering('pvw_…') opens an unpublished draft from the editor's "Preview in app" (debug builds).

Prices come from the store: StoreKit 2's subscription period on iOS (and the console's trial length when the user is eligible for the introductory offer), the offer's recurring and free phases on Google Play. Links (terms, privacy, url buttons) open with url_launcher; pass onOpenUrl to handle them yourself. Background and hero videos play muted and looping through video_player; until a clip plays (or when it cannot), its poster is shown. Only https media are loaded.

The full guide is at https://nimbusgo.space/docs/cashier-flutter.

Develop #

flutter pub get
flutter analyze
flutter test

test/fixtures/paywalls.json is the shared paywall fixture set (the same file the iOS and web SDKs test against); regenerate it from nimbus-starter with PAYWALL_FIXTURES=<path> go test ./app/paywall -run Fixtures. test/paywall_widget_test.dart pumps every screen of every fixture at 390×844 and 320×568 and fails on any exception or overflow.

Release #

  1. Update version in pubspec.yaml and CHANGELOG.md.
  2. dart pub publish --dry-run, then dart pub publish.
  3. Tag the commit with the version.

License #

MIT

0
likes
120
points
365
downloads

Documentation

API reference

Publisher

verified publishernimbusgo.space

Weekly Downloads

Nimbus Cashier for Flutter — App Store and Google Play subscriptions verified by your Cashier app, gated on entitlements.

Homepage
Repository (GitHub)
View/report issues

Topics

#subscriptions #in-app-purchase #paywall #storekit #billing

License

MIT (license)

Dependencies

crypto, flutter, http, in_app_purchase, in_app_purchase_android, in_app_purchase_storekit, shared_preferences, url_launcher, video_player

More

Packages that depend on nimbus_cashier