ctechpay 0.1.0
ctechpay: ^0.1.0 copied to clipboard
Official Flutter and Dart SDK for CtechPay in-app Airtel Money payments and card checkout status checks.
example/main.dart
import 'package:ctechpay/ctechpay.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const CtechPayExampleApp());
}
class CtechPayExampleApp extends StatelessWidget {
const CtechPayExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CtechPay SDK Example',
theme: ThemeData(
useMaterial3: true,
colorSchemeSeed: const Color(0xFF08A9E6),
),
home: const CtechPayExamplePage(),
);
}
}
class CtechPayExamplePage extends StatefulWidget {
const CtechPayExamplePage({super.key});
@override
State<CtechPayExamplePage> createState() => _CtechPayExamplePageState();
}
class _CtechPayExamplePageState extends State<CtechPayExamplePage> {
final ctechpay = CtechPayClient(
token: 'YOUR_CTECHPAY_SERVICE_TOKEN',
// baseUrl: 'https://new-api.ctechpay.com',
);
final phoneController = TextEditingController(text: '99XXXXXXX');
final airtelTransactionController = TextEditingController();
final airtelMoneyIdController = TextEditingController();
final cardOrderReferenceController = TextEditingController();
bool isBusy = false;
String output = 'Ready';
@override
void dispose() {
phoneController.dispose();
airtelTransactionController.dispose();
airtelMoneyIdController.dispose();
cardOrderReferenceController.dispose();
ctechpay.close();
super.dispose();
}
void showOutput(Object value) {
setState(() {
output = value.toString();
});
}
Future<void> runAction(Future<void> Function() action) async {
if (isBusy) {
return;
}
setState(() => isBusy = true);
try {
await action();
} finally {
if (mounted) {
setState(() => isBusy = false);
}
}
}
Future<void> openFullCheckout() async {
await Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => CtechPayCheckoutPage(
client: ctechpay,
amount: 100,
customerReference: 'APP-ORDER-1001',
customerMessage: 'Flutter SDK test payment',
cardSuccessUrl: 'https://example.com/payment-success',
cardCancelUrl: 'https://example.com/payment-cancelled',
onCompleted: (result) {
showOutput('Airtel completed: $result');
},
onCardCompleted: (result) {
showOutput('Card completed: $result');
},
onFailed: (error) {
showOutput('Payment failed: $error');
},
onCancelled: () {
showOutput('Payment cancelled');
},
onCardCheckoutUrl: (checkout) {
cardOrderReferenceController.text = checkout.orderReference;
showOutput('Card checkout created: $checkout');
},
),
),
);
}
Future<void> airtelPayAndPoll() async {
showOutput('Sending Airtel Money prompt...');
final result = await ctechpay.airtel.payAndPoll(
amount: 100,
phone: phoneController.text,
customerReference: 'APP-AIRTEL-1001',
customerMessage: 'Flutter Airtel test',
interval: const Duration(seconds: 5),
timeout: const Duration(seconds: 90),
onPoll: (status) {
showOutput('Airtel polling: $status');
},
);
airtelTransactionController.text = result.transactionId;
showOutput('Airtel final result: $result');
}
Future<void> checkAirtelStatus() async {
final response = await ctechpay.airtel.status(
airtelTransactionController.text,
);
showOutput(response);
}
Future<void> getAirtelDetails() async {
final response = await ctechpay.airtel.details(
airtelTransactionController.text,
);
showOutput(response);
}
Future<void> getAirtelReference() async {
final response = await ctechpay.airtel.reference(
airtelMoneyIdController.text,
);
showOutput(response);
}
Future<void> startCardHostedCheckout() async {
showOutput('Creating card checkout...');
final checkout = await ctechpay.cards.createPaymentPage(
amount: 100,
customerReference: 'APP-CARD-1001',
customerMessage: 'Flutter card test',
redirectUrl: 'https://example.com/payment-success',
cancelUrl: 'https://example.com/payment-cancelled',
);
cardOrderReferenceController.text = checkout.orderReference;
final webResult =
await Navigator.of(context).push<CtechPayCardWebViewResult>(
MaterialPageRoute(
builder: (_) => CtechPayCardWebViewPage(
initialUrl: checkout.paymentPageUrl,
successUrl: 'https://example.com/payment-success',
cancelUrl: 'https://example.com/payment-cancelled',
),
),
);
if (webResult == null || webResult.cancelled) {
showOutput('Card payment cancelled');
return;
}
if (webResult.failed) {
showOutput('Card payment failed');
return;
}
showOutput('Checking card status...');
final result = await ctechpay.cards.pollHostedStatus(
orderReference: checkout.orderReference,
finalUrl: webResult.url,
interval: const Duration(seconds: 2),
timeout: const Duration(seconds: 20),
maxAttempts: 5,
onPoll: (status) {
showOutput('Card polling: $status');
},
);
showOutput('Card final result: $result');
}
Future<void> checkCardStatus() async {
final response = await ctechpay.cards.status(
cardOrderReferenceController.text,
);
showOutput(response);
}
Future<void> rawApiExample() async {
final response = await ctechpay.post(
'/api/v1/hosted/payment',
payload: {
'amount': 100,
'customer_reference': 'RAW-SDK-1001',
'customer_message': 'Raw SDK request',
'redirectUrl': 'https://example.com/success',
'cancelUrl': 'https://example.com/cancelled',
},
);
showOutput(response);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('CtechPay SDK Example'),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
TextField(
controller: phoneController,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
labelText: 'Airtel phone number',
helperText: 'Example: 0999123456 or 999123456',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
TextField(
controller: airtelTransactionController,
decoration: const InputDecoration(
labelText: 'Airtel transaction ID',
helperText: 'Filled after Airtel Pay and Poll succeeds.',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
TextField(
controller: airtelMoneyIdController,
decoration: const InputDecoration(
labelText: 'Airtel Money ID for reference lookup',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
TextField(
controller: cardOrderReferenceController,
decoration: const InputDecoration(
labelText: 'Card order reference',
helperText: 'Filled after card checkout is created.',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 20),
FilledButton(
onPressed: isBusy ? null : openFullCheckout,
child: const Text('Open Full Checkout Page'),
),
FilledButton(
onPressed: isBusy ? null : () => runAction(airtelPayAndPoll),
child: const Text('Airtel Pay and Poll'),
),
OutlinedButton(
onPressed: isBusy ? null : () => runAction(checkAirtelStatus),
child: const Text('Check Airtel Status'),
),
OutlinedButton(
onPressed: isBusy ? null : () => runAction(getAirtelDetails),
child: const Text('Get Airtel Details'),
),
OutlinedButton(
onPressed: isBusy ? null : () => runAction(getAirtelReference),
child: const Text('Get Airtel Reference'),
),
FilledButton(
onPressed: isBusy ? null : () => runAction(startCardHostedCheckout),
child: const Text('Start Card Hosted Checkout'),
),
OutlinedButton(
onPressed: isBusy ? null : () => runAction(checkCardStatus),
child: const Text('Check Card Status'),
),
OutlinedButton(
onPressed: isBusy ? null : () => runAction(rawApiExample),
child: const Text('Raw API Request Example'),
),
const SizedBox(height: 20),
const Text(
'Output',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: const Color(0xFFEAF8FD),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: const Color(0xFFBFE9F8)),
),
child: SelectableText(output),
),
],
),
);
}
}