appspro_sdk 0.1.0
appspro_sdk: ^0.1.0 copied to clipboard
Native Flutter widgets and a typed client for AppsPro carrier-billed subscriptions (BDApps DCB, Robi/Airtel) — phone, OTP, status and cancel.
import 'package:appspro_sdk/appspro_sdk.dart';
import 'package:flutter/material.dart';
/// Publishable key. Get a sandbox one from your app's API & SDK tab on
/// appspro.dev — sandbox apps accept the fixed OTP `000000` and never charge
/// a real subscriber.
///
/// flutter run --dart-define=APPSPRO_PUBLISHABLE_KEY=pk_...
const String publishableKey = String.fromEnvironment(
'APPSPRO_PUBLISHABLE_KEY',
defaultValue: '',
);
/// API host. Point this at a local backend while developing:
///
/// --dart-define=APPSPRO_BASE_URL=http://10.0.2.2:8000
///
/// `10.0.2.2` is how the Android *emulator* reaches your machine. On a
/// physical device use your machine's LAN address instead (e.g.
/// `http://192.168.1.20:8000`) and start the backend on `--host 0.0.0.0`.
/// Debug builds permit cleartext http for exactly this reason; release
/// builds do not, so ship an https base URL.
const String baseUrl = String.fromEnvironment(
'APPSPRO_BASE_URL',
defaultValue: kDefaultBaseUrl,
);
void main() {
if (publishableKey.isNotEmpty) {
AppsProClient.configure(publishableKey: publishableKey, baseUrl: baseUrl);
}
runApp(const ExampleApp());
}
/// Demonstrates every integration shape the package offers.
class ExampleApp extends StatelessWidget {
/// Creates the example app.
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AppsPro SDK Example',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF3B82F6)),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF3B82F6),
brightness: Brightness.dark,
),
useMaterial3: true,
),
home: publishableKey.isEmpty ? const _MissingKey() : const HomePage(),
);
}
}
class _MissingKey extends StatelessWidget {
const _MissingKey();
@override
Widget build(BuildContext context) => Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(28),
child: Text(
'Run with a publishable key:\n\n'
'flutter run --dart-define=APPSPRO_PUBLISHABLE_KEY=pk_...\n\n'
'Create a sandbox key on the API & SDK tab of your app at appspro.dev.',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium,
),
),
),
);
}
/// Landing screen with one entry point per integration style.
class HomePage extends StatelessWidget {
/// Creates the home page.
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('AppsPro SDK')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
ListTile(
title: const Text('Subscribe screen'),
subtitle: const Text('The one-line integration'),
trailing: const Icon(Icons.chevron_right),
onTap: () async {
final result = await AppsProSubscribeScreen.show(context);
if (context.mounted && result != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Subscribed: ${result.subscriberId}')),
);
}
},
),
ListTile(
title: const Text('Inline card'),
subtitle: const Text('Embedded in your own paywall'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.of(
context,
).push(MaterialPageRoute<void>(builder: (_) => const _CardPage())),
),
ListTile(
title: const Text('Subscription gate'),
subtitle: const Text('Content only subscribers see'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.of(
context,
).push(MaterialPageRoute<void>(builder: (_) => const _GatePage())),
),
ListTile(
title: const Text('Manage subscription'),
subtitle: const Text('Status and cancellation'),
trailing: const Icon(Icons.chevron_right),
onTap: () => AppsProManageScreen.show(context),
),
],
),
);
}
}
class _CardPage extends StatelessWidget {
const _CardPage();
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Inline card')),
body: const Center(
child: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: AppsProSubscribeCard(),
),
),
);
}
class _GatePage extends StatelessWidget {
const _GatePage();
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: const Text('Premium')),
body: AppsProSubscriptionGate(
builder: (context) =>
const Center(child: Text('Premium content unlocked.')),
fallback: (context, subscribe) => Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Subscribe to unlock this.'),
const SizedBox(height: 12),
FilledButton(onPressed: subscribe, child: const Text('Subscribe')),
],
),
),
),
);
}