tuna_sdk 0.1.2 tuna_sdk: ^0.1.2 copied to clipboard
Tuna Gateway SDK.
// ignore_for_file: avoid_print
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:tuna_sdk/tuna_sdk.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:dio/dio.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tuna SDK Test App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Tuna SDK Test App'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final Dio _dio = Dio();
late final ThreeDS _threeDS;
late final Tuna _tuna;
bool _showThreeDS = false;
bool _dataLoaded = false;
String _infoText = "Starting app";
// //-------------// Edit this data //-------------//
final String _env = "prod";
final CustomerData _customer = CustomerData("4321", "john.doe@tuna.uy");
final String _partnerUniqueId = _generateRandomString(10);
final CardData _cardData = CardData(
cardNumber: "4456530000001096",
cardHolderName: "John Doe",
expirationMonth: 1,
expirationYear: 2027,
cvv: "123");
//Sensitive data
final String _appToken = "";
final String _account = "";
//Sensitive data
// //-------------// Edit this data //-------------//
static String _generateRandomString(int i) =>
String.fromCharCodes(List.generate(
i,
(_) =>
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
.codeUnitAt(Random().nextInt(62))));
void callDialog(String message) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('3DS result'),
content: Text(message),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('Close'),
),
],
);
},
);
}
Future<void> startPaymentTransaction() async {
_tuna = await Tuna.create(_appToken, _account, _customer, _partnerUniqueId,
env: _env, is3dsTest: true);
setState(() {
_infoText = "Tuna object created";
});
var generateResponse = await _tuna.tokenizer.generate(_cardData);
setState(() {
_infoText = "Card token generated. \n SessionID: ${_tuna.sessionID}";
});
_threeDS = ThreeDS(
(message) async {
if (message == "Data collection ready") {
setState(() {
_infoText = "3DS data collection done. Calling /Init";
});
final initResponse = await callInit(generateResponse, _cardData);
setState(() {
_infoText = "/Init call ended. 3DS challenge loading";
});
final paymentMethod = initResponse["methods"][0];
final threeDSInfo =
ThreeDSInfo.fromJson(paymentMethod["threeDSInfo"]);
setState(() {
_showThreeDS = true;
});
_threeDS.loadChallengeFrame(threeDSInfo);
_tuna.doStatusLongPolling((statusPollResult) {
if (statusPollResult.code == 1) {
if (statusPollResult.paymentMethodConfirmed) {
if (statusPollResult.paymentApproved ?? false) {
setState(() {
_showThreeDS = false;
_infoText = "3DS payment ended";
});
callDialog("Payment approved!");
} else {
callDialog("Payment refused");
}
} else {
// callDialog("Error");
}
} else {
// callDialog("Error");
}
}, paymentMethod["methodId"], initResponse["paymentKey"]);
}
},
);
final authenticationInfo = generateResponse.authenticationInformation!;
final accessToken = authenticationInfo.accessToken!;
final deviceDataCollectionUrl = authenticationInfo.deviceDataCollectionUrl!;
_threeDS.loadDataCollectionFrame(accessToken, deviceDataCollectionUrl);
setState(() {
_infoText =
"3DS device data collection is running. \n Take a look at console output. \n The webview is invisible this moment";
});
}
Future<dynamic> callInit(
GenerateResponse generateResponse, CardData cardData) async {
try {
Response response = await _dio.post(
'https://engine.tunagateway.com/api/Payment/Init',
options: Options(
headers: {
'accept': 'application/json',
'x-tuna-account': _account,
'x-tuna-apptoken': _appToken,
'Content-Type': 'application/json',
'Idempotency-Key': 'YzHfUsJHm73412df',
},
),
data: {
"PartnerUniqueID": _partnerUniqueId,
"TokenSession": _tuna.sessionID,
"Customer": {
"Email": _customer.email,
"ID": _customer.id,
"Document": "160.756.340-10",
"DocumentType": "CPF"
},
"FrontData": {
"SessionID": "3ca3cc8ff8eac0093a4097de219f2a8c",
"Origin": "WEBSITE",
"IpAddress": "172.18.0.1",
"CookiesAccepted": true
},
"PaymentItems": {
"Items": [
{
"Amount": 10,
"ProductDescription": "Sample Product",
"ItemQuantity": 1,
"CategoryName": "simple",
"AntiFraud": {"Ean": "24-WB04"}
}
]
},
"PaymentData": {
"Countrycode": "BR",
"DeliveryAddress": {
"Street": "Sample Street",
"Number": "288",
"City": "Salvador",
"State": "BA",
"Country": "BR",
"PostalCode": "41341-545",
"Phone": "(71)999999929"
},
"SalesChannel": "ECOMMERCE",
"Amount": 10,
"PaymentMethods": [
{
"PaymentMethodType": "7",
"Amount": 10,
"Installments": 1,
"cardInfo": {
"CardNumber": cardData.cardNumber,
"CardHolderName": cardData.cardHolderName,
"BrandName": generateResponse.brand,
"ExpirationMonth": cardData.expirationMonth,
"ExpirationYear": cardData.expirationYear,
"Token": generateResponse.token,
"TokenProvider": "Tuna",
"TokenSingleUse": cardData.singleUse,
"SaveCard": !(cardData.singleUse ?? true),
"BillingInfo": {
"Document": "160.756.340-10",
"DocumentType": "CPF",
"Address": {}
}
},
"AuthenticationInformation": {
"Code": _tuna.sessionID,
"ReferenceId":
generateResponse.authenticationInformation!.referenceId!,
"TransactionId":
generateResponse.authenticationInformation!.transactionId!
}
}
]
}
},
);
return response.data;
} catch (error, stacktrace) {
print('Error: $error, Stacktrace: $stacktrace');
}
}
@override
void initState() {
super.initState();
startPaymentTransaction().then((_) => setState(() => _dataLoaded = true));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Wrap(
spacing: 5.0,
runSpacing: 5.0,
direction: Axis.vertical,
children: [
Visibility(
visible: !_showThreeDS,
child: Center(
child: Text(_infoText),
)),
_dataLoaded
? SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: SizedBox.expand(
child: Visibility(
visible: _showThreeDS,
child: WebViewWidget(
controller: _threeDS.webViewController))))
: Container(),
],
),
));
}
}