skipcash 0.0.3
skipcash: ^0.0.3 copied to clipboard
SkipCash SDK.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:skipcash/payment_response_class.dart';
import 'package:skipcash/payment_page_response_class.dart';
import 'package:skipcash/skipcash.dart';
void main() {
runApp(const MaterialApp(
home: MyApp(), // Wrap MyApp with MaterialApp
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _newPayment = Skipcash(
merchantIdentifier: "merchant.vendex.skipcash.payme", //ios - required when integrating (in-app applepay) here you should pass your merchantIdentifier
createPaymentLinkEndPoint: "", /* required only if you're using the webview embeded with this package other wise leave it empty - this is an endpoint you should setup at your backend server,
it basically sends the customer data your endpoint from where you will be creating an new payment by calling skipcash server
then the same endpoint should return skipcash server response back for the plugin to complete the process.
*/
authorizationHeader: "" // optional - set your endpoint authorizartion header
);
StreamSubscription<dynamic>? _applePayResponseSubscription; // ios - applepay
StreamSubscription<dynamic>? responseScPaymentDataSubscription; // android/ios - pay via webview
final TextEditingController _firstNameController = TextEditingController();
final TextEditingController _lastNameController = TextEditingController();
final TextEditingController _phoneController = TextEditingController();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _amountController = TextEditingController();
var loadingIndicator;
@override
void initState() {
super.initState();
loadingIndicator = false;
_setupApplePayResponseListener(); // ios - in-app applepay
scPaymentDataResponseListener();// android/ios - pay via webview
}
@override
void dispose() {
// release resources upon exiting the screen
_applePayResponseSubscription?.cancel(); // ios - in-app applepay
responseScPaymentDataSubscription?.cancel();// android/ios - pay via webivew
super.dispose();
}
// listen for apple pay response
void _setupApplePayResponseListener() { // ios - native applepay
_applePayResponseSubscription = _newPayment.applePayResponseStream.listen((response) {
setState(() {
loadingIndicator = false;
});
PaymentResponse paymentResponse = PaymentResponse.fromJson(response);
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('SkipCash In-App ApplePay'),
content: Text(
"IsSuccess: ${paymentResponse.isSuccess} | transactionId: ${paymentResponse.transactionId} | errorMessage: ${paymentResponse.errorMessage} | returnCode: ${paymentResponse.returnCode}"
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
});
}
// embeded webview example.
void scPaymentDataResponseListener() { // android/ios - pay via webview
_applePayResponseSubscription = _newPayment.responseScPaymentPageStream.listen((response) {
setState(() {
loadingIndicator = false;
});
PaymentPageResponse paymentPageResponse = PaymentPageResponse.fromJson(response);
debugPrint(response.toString());
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('SkipCash PaymentPage Response'),
content: Text(
"id: ${paymentPageResponse.id} | statusId: ${paymentPageResponse.statusId} | status: ${paymentPageResponse.status} | transId: ${paymentPageResponse.transId} | custom1: ${paymentPageResponse.custom1}"
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('skipcash package - example app'),
),
body: Center(
child: Stack(
children: [
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: 280,
child:
TextField(
controller: _firstNameController,
decoration: const InputDecoration(labelText: 'First Name'),
),
),
SizedBox(
width: 280,
child:
TextField(
controller: _lastNameController,
decoration: const InputDecoration(labelText: 'Last Name'),
),
),
SizedBox(
width: 280,
child:
TextField(
controller: _phoneController,
decoration: const InputDecoration(labelText: 'Phone Number'),
),
),
SizedBox(
width: 280,
child:
TextField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
),
),
SizedBox(
width: 300,
child:
TextField(
controller: _amountController,
decoration: const InputDecoration(
labelText: 'Amount',
hintText: "ex.valid values format: 1 and 1.2 and 1.25"
),
),
),
const SizedBox(
height: 30,
),
SizedBox(
width: 220,
child: ElevatedButton(
onPressed: () async {
bool hasCards;
try {
// check if there is a card in the wallet
hasCards =
await _newPayment.isWalletHasCards() ?? false;
if(hasCards){
// setup payment details if there is a card in the wallet
String firstName = _firstNameController.text;
String lastName = _lastNameController.text;
String phone = _phoneController.text;
String email = _emailController.text;
String amount = _amountController.text;
if(firstName.isEmpty || lastName.isEmpty || phone.isEmpty
|| email.isEmpty || amount.isEmpty || amount == "0.0"){
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Invalid Details'),
content: const Text(
"Please fill all of the fields, Also amount must be above 0.0, i.e 1.0 at least."
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
return;
}
_newPayment.setFirstName(firstName);
_newPayment.setLastName(lastName);
_newPayment.setEmail(email);
_newPayment.setPhone(phone);
_newPayment.setAmount(amount);
_newPayment.setProcessApplePayEndPoint(""); // your endpoint for processing the payment.
_newPayment.setMerchantName(""); // official name of the business - required by apple it will appear in the payment sheet.
_newPayment.setTransactionId(""); // transaction (should be unique) track your orders tranasction internally in your system.
_newPayment.setWebhookUrl(""); // optional - (but recommended) you can read about webhooks
// -> here https://dev.skipcash.app/doc/api-integration/web-hooks/
_newPayment.setCustom1(""); _newPayment.setCustom2(""); // optional
_newPayment.setCustom3(""); _newPayment.setCustom4(""); // optional
_newPayment.setCustom5(""); _newPayment.setCustom6(""); // optional
_newPayment.setCustom7(""); _newPayment.setCustom8(""); // optional
_newPayment.setCustom9(""); _newPayment.setCustom10(""); // optional
_newPayment.clearPaymentSummaries(); // clear the summaries before adding new
_newPayment.addPaymentSummaryItem("Tax", "0.0"); //optional - add payment summary for your customer
setState(() {
loadingIndicator = true;
});
_newPayment.startPayment(); // start the payment (applepay)
}else{
/*
If no cards are available in the wallet then prompt the customer to add a new one.
*/
_newPayment.setupNewCard();
}
} on PlatformException {
hasCards = false;
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/skipcash.png',
width: 24,
height: 24,
),
const SizedBox(width: 8),
const Text(
"Pay Using ApplePay",
style: TextStyle(color: Color.fromRGBO(1, 125, 251, 1.0)),
)
],
),
),
),
SizedBox(
width: 220,
child: ElevatedButton(
onPressed: () async {
_newPayment.setupNewCard();
},
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Setup new card in wallet",
style: TextStyle(color: Color.fromRGBO(1, 125, 251, 1.0)),
)
],
),
),
),
SizedBox(
width: 300,
child: ElevatedButton(
onPressed: (){
String firstName = _firstNameController.text;
String lastName = _lastNameController.text;
String phone = _phoneController.text;
String email = _emailController.text; // if email is not required by your platform
// you can use this format phone@yourdomain.com
String amount = _amountController.text;
if(firstName.isEmpty || lastName.isEmpty || phone.isEmpty
|| email.isEmpty || amount.isEmpty || amount == "0.0"){
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Invalid Details'),
content: const Text(
"Please fill all of the fields, Also amount must be above 0.0, i.e 1.0 at least."
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('OK'),
),
],
);
},
);
return;
}
_newPayment.setFirstName(firstName);
_newPayment.setLastName(lastName);
_newPayment.setEmail(email);
_newPayment.setPhone(phone);
_newPayment.setAmount(amount);
_newPayment.setTransactionId("TX1TEST"); // your internal order id (unique)
_newPayment.setWebhookUrl(""); // optional but important
// read about webhooks -> https://dev.skipcash.app/doc/api-integration/web-hooks/
_newPayment.setCustom1(""); _newPayment.setCustom2(""); // optional
_newPayment.setCustom3(""); _newPayment.setCustom4(""); // optional
_newPayment.setCustom5(""); _newPayment.setCustom6(""); // optional
_newPayment.setCustom7(""); _newPayment.setCustom8(""); // optional
_newPayment.setCustom9(""); _newPayment.setCustom10("");// optional
_newPayment.setSubject("Creating a payment from example app."); // optional - appears at the payment page
_newPayment.setDescription("Please pay to complete the orderX!"); // optional - appears at the payment page
// below are some options used to adjust the WEBVIEW SCREEN header (android)
/*
For the colours please use the full hexadecimal representation
not the shorthand representation; cause it can make some issues.
example:
(full hex) #FFFFFF - white (CORRECT ✅)
(short hex) #FFF - white (INCORRECT ❌)
*/
_newPayment.setPaymentModalTitle("Test Payment"); // payment modal header title
_newPayment.setCancelColour("#000000"); // android only
_newPayment.setHeaderBackgroundColour("#FFFFFF"); // android only
_newPayment.setHeaderTitleColour("#000000"); // android only
if(_newPayment.createPaymentLinkEndPoint.isNotEmpty){
if(_newPayment.getFirstName().isNotEmpty && _newPayment.getLastName().isNotEmpty && _newPayment.getEmail().isNotEmpty && _newPayment.getPhone().isNotEmpty && _newPayment.getAmount().isNotEmpty){
setState(() {
loadingIndicator = true;
});
// android - to check for errors filter logcat using keyword -> 'showPaymentModal'
_newPayment.showPaymentModal(
"", // return url can be any correct url,
// its used mainly by SkipCash server to redirect the client back to your website, with parameters related to
// the transaction made by the client, Here its used to get transaction details to be passed further to the response listener
// of your flutter code to complete your *(order) process.
);
}
}
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/skipcash.png',
width: 24,
height: 24,
),
const SizedBox(width: 8),
const Text(
"Android/iOS - Native WebView",
style: TextStyle(color: Color.fromRGBO(1, 125, 251, 1.0)),
)
],
),
),
),
],
),
),
if (loadingIndicator)
Container(
color: Colors.black54,
child: Center(
child: Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
child: const CircularProgressIndicator(),
),
),
),
],
)
),
);
}
}