Ship only publishable keys (pk_live_… / pk_test_…) in your app. Secret keys
(csk_sk_…) belong on your backend.
Flutter SDK
Add in-app purchases and paywalls to your Flutter app with a single Dart package.
The CashSDK Flutter SDK is one Dart package that runs on both iOS (StoreKit 2) and Android (Play Billing). Fetch offerings, run purchases, and read entitlements with the same async code on every target.
Install#
flutter pub add cashsdk
This adds the dependency to your pubspec.yaml:
dependencies:
cashsdk: ^1.0.0
Configure#
Initialize CashSDK once in main(), before runApp. Use your publishable
key.
import 'package:flutter/material.dart';
import 'package:cashsdk/cashsdk.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await CashSDK.configure(apiKey: 'pk_live_...');
runApp(const MyApp());
}
Fetch offerings#
An offering holds the packages you present on a paywall, such as monthly and
annual.
final offering = await CashSDK.offerings();
final monthly = offering.monthly;
final annual = offering.annual;
Purchase#
Pass a package to purchase. CashSDK drives the native store flow, validates the
receipt, and returns the customer's updated entitlements.
final result = await CashSDK.purchase(offering.monthly);
if (result.entitlements['pro']?.isActive == true) {
unlockPro();
}
Check entitlements#
Read entitlements from any purchase or restore result to gate features.
if (result.entitlements['pro']?.isActive == true) {
// Show premium content
} else {
// Show the paywall
}
Restore purchases#
Let customers recover access on a new device or after a reinstall.
final result = await CashSDK.restorePurchases();
if (result.entitlements['pro']?.isActive == true) {
unlockPro();
}
Identify the customer#
Link the SDK to your own user ID so entitlements follow the customer across
devices and platforms. Call identify once the user has signed in.
CashSDK.identify('u_812');
A paywall widget#
Fetch the offering in initState, present its packages, and unlock on success.
import 'package:flutter/material.dart';
import 'package:cashsdk/cashsdk.dart';
class Paywall extends StatefulWidget {
const Paywall({super.key, required this.onUnlock});
final VoidCallback onUnlock;
@override
State<Paywall> createState() => _PaywallState();
}
class _PaywallState extends State<Paywall> {
Offering? _offering;
@override
void initState() {
super.initState();
CashSDK.offerings().then((o) => setState(() => _offering = o));
}
Future<void> _buy(Package package) async {
final result = await CashSDK.purchase(package);
if (result.entitlements['pro']?.isActive == true) widget.onUnlock();
}
@override
Widget build(BuildContext context) {
final offering = _offering;
if (offering == null) return const CircularProgressIndicator();
return Column(
children: [
const Text('Unlock Pro'),
FilledButton(
onPressed: () => _buy(offering.monthly),
child: Text(offering.monthly.localizedPrice),
),
TextButton(
onPressed: CashSDK.restorePurchases,
child: const Text('Restore purchases'),
),
],
);
}
}