in_app_subscription_bundle 0.0.12
in_app_subscription_bundle: ^0.0.12 copied to clipboard
A plugin to make in app purchase easy.
in_app_subscription_bundle #
A powerful, reusable, BLoC-based Flutter plugin for managing In-App Purchases (IAP) and Subscriptions on Android and iOS without requiring a backend server.
It dynamically fetches product details, handles purchase streams, parses subscription billing periods via native Google Play & Apple App Store APIs, and supports both consumable (e.g., coins, credits) and non-consumable (e.g., subscriptions, permanent unlocks) products.
Features #
- Backend-Less Architecture: Works 100% offline using native store APIs.
- Subscriptions & Non-Consumables: Auto-renewable subscriptions, one-time purchases, upgrade/downgrade logic.
- Consumable Products: Auto-consuming support with
onConsumablePurchasedcallback to credit local inventories. - Dynamic Duration Parsing: Automatically reads billing periods from Google Play (ISO 8601) and Apple StoreKit at runtime.
- Robust Error & Partial Load Handling: Successfully loads available store products even if some IDs are pending or missing.
- Flutter BLoC Integration: Clean state management with
SubsBlocNewandSubscriptionState.
Installation #
Add in_app_subscription_bundle to your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
in_app_subscription_bundle: ^0.0.12
Usage Guide #
Step 1: Import the Package #
import 'package:in_app_subscription_bundle/in_app_subscription_bundle.dart';
Step 2: Initialize SubsBlocNew #
Wrap your subscription/store screen with BlocProvider:
class ProductsView extends StatelessWidget {
const ProductsView({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => SubsBlocNew(
context: context,
subscriptionProductIds: ["monthly_plan", "yearly_plan"], // Subscriptions & Non-Consumables
consumableProductIds: ["100_coins", "500_coins"], // Consumable Product IDs
isSandbox: kDebugMode, // Uses sandbox in debug mode
sharedSecret: "YOUR_IOS_APP_SPECIFIC_SHARED_SECRET", // Optional: iOS App Store Connect shared secret
onConsumablePurchased: (purchaseDetails) {
// Triggered when a consumable product is successfully purchased.
// Credit your local inventory (e.g. Hive, SharedPreferences, SQLite) here.
AppLogs.showInfoLogs("Consumable Purchased: ${purchaseDetails.productID}");
},
)..add(SubscriptionInitEvent(context: context)),
child: const _ProductsBody(),
);
}
}
Step 3: Build the UI #
Use BlocBuilder to react to state changes and trigger events:
class _ProductsBody extends StatelessWidget {
const _ProductsBody({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<SubsBlocNew, SubscriptionState>(
builder: (context, state) {
final bloc = context.read<SubsBlocNew>();
return Scaffold(
appBar: AppBar(
title: const Text("In-App Store"),
),
body: state.loader == true
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
child: Column(
children: [
// Product List
ListView.builder(
itemCount: state.products.length,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (_, index) {
final product = state.products[index];
if (product.rawPrice == 0.0) return const SizedBox.shrink();
final isSelected = state.products[state.selectedItem].id == product.id;
return ListTile(
tileColor: isSelected ? Colors.green.shade100 : null,
title: Text(bloc.getValueBeforeBracket(product.title)),
subtitle: Text(product.description),
trailing: Text(product.price),
onTap: () {
context.read<SubsBlocNew>().add(
ChangeSelectedItemEvent(index, productId: product.id),
);
},
);
},
),
// Purchase Button
ElevatedButton(
onPressed: () {
context.read<SubsBlocNew>().add(
BuyProductEvent(context: context, restore: false),
);
},
child: Text(
state.isSubscribed == true ? "Upgrade / Downgrade" : "Buy Product",
),
),
// Restore Purchases Button
TextButton(
onPressed: () {
context.read<SubsBlocNew>().add(
BuyProductEvent(context: context, restore: true),
);
},
child: const Text("Restore Purchases"),
),
],
),
),
);
},
);
}
}
API Reference #
SubsBlocNew Constructor Parameters #
| Parameter | Type | Required | Description |
|---|---|---|---|
context |
BuildContext |
Yes | BuildContext for showing notifications/snackbars. |
subscriptionProductIds |
List<String> |
Yes | Product IDs for auto-renewable subscriptions & non-consumables. |
consumableProductIds |
List<String> |
No | Product IDs for consumables (coins, lives, credits). Defaults to []. |
isSandbox |
bool |
Yes | Pass kDebugMode to enable sandbox testing. |
sharedSecret |
String |
No | App Store Connect shared secret for iOS receipt verification. |
onConsumablePurchased |
Function(PurchaseDetails) |
No | Callback fired when a consumable purchase is finalized. |
Events #
SubscriptionInitEvent(context: context): Initializes store connection and queries product details.BuyProductEvent(context: context, restore: false): Purchases the selected product (or restores ifrestore: true).ChangeSelectedItemEvent(index, productId: id): Changes selected product index in state.GetOldPurchaseEvent(): Queries store history to compute active subscription status.
State Properties (SubscriptionState) #
isSubscribed:boolindicating if the user has an active subscription.products: List ofProductDetailsfetched from Google Play & App Store.selectedItem: Index of the currently selected product.subsExpiryDate: Calculated expiry date string for active subscriptions.loader:boolindicating loading state.
License #
MIT License.