Flutter功能扩展插件tuna_sdk的应用
Flutter功能扩展插件tuna_sdk的应用
插件tuna_sdk特性
- Tokenization方法:您可以调用
/Generate
,/Bind
,/Delete
,/List
。 - 3DS方法:允许您创建一个更安全的支付步骤。
Flutter功能扩展插件tuna_sdk使用方法
Tokenization示例
var tokenizer = await Tokenizer.create('a3823a59-66bb-49e2-95eb-b47c447ec7a7', 'demo', customer, "14", env: "sandbox");
var cardData = CardData(cardNumber: "4756169062715850", cardHolderName: "Example Card", expirationMonth: 10, expirationYear: 2025, cvv: "257");
var generateResponse = await tokenizer.generate(cardData);
3DS示例
_threeDS = ThreeDS(
(message) async {
if (message == "Data collection ready") {
var initResponse = await callInit(generateResponse, _cardData);
var threeDSInfo = ThreeDSInfo.fromJson(initResponse["methods"][0]["threeDSInfo"]);
_threeDS.loadChallengeFrame(threeDSInfo);
}
},
);
_threeDS.loadDataCollectionFrame(generateResponse.authenticationInformation!.accessToken!, generateResponse.authenticationInformation!.deviceDataCollectionUrl!);
完整示例
完整的示例代码可以在 tuna_sdk_test.dart
中找到。要查看3DS支付方法,可以运行 /example
文件夹下的示例Flutter应用。
示例代码
以下是完整的示例代码:
// 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](/user/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](/user/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"]);
} else if (message == "Challenge done") {
setState(() {
_showThreeDS = false;
_infoText = """
The challenge is done and the Webview is closed now.
This does not mean that the purchase was approved,
it only means that the challenge was completed.
To know if the payment was approved,
check the payment status.
""";
});
}
},
);
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](/user/override)
void initState() {
super.initState();
startPaymentTransaction().then((_) => setState(() => _dataLoaded = true));
}
[@override](/user/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(),
],
),
));
}
}
更多关于Flutter功能扩展插件tuna_sdk的应用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter功能扩展插件tuna_sdk的应用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
由于tuna_sdk
是一个未明确文档化或广泛认知的Flutter插件,以下内容将基于一般Flutter插件的使用方式以及可能的插件功能进行合理推测,并提供一个假设性的代码案例。请注意,实际使用时需要根据tuna_sdk
的真实功能和API进行调整。
假设性的tuna_sdk
插件功能
假设tuna_sdk
是一个用于扩展Flutter应用功能的插件,可能提供了一些高级功能,如数据加密、设备硬件访问、或者特定的第三方服务集成等。
插件安装
首先,你需要在pubspec.yaml
文件中添加对tuna_sdk
的依赖(假设它已经在pub.dev上发布,或者你已经将其作为一个本地插件):
dependencies:
flutter:
sdk: flutter
tuna_sdk: ^x.y.z # 替换为实际的版本号
然后运行flutter pub get
来安装插件。
导入插件
在你的Dart文件中导入tuna_sdk
:
import 'package:tuna_sdk/tuna_sdk.dart';
假设性的功能使用代码案例
假设功能1:数据加密
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Tuna SDK Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// 假设TunaSDK有一个encrypt方法用于数据加密
String plainText = "Hello, Tuna SDK!";
String encryptedText = await TunaSDK.encrypt(plainText);
print("Encrypted Text: $encryptedText");
},
child: Text('Encrypt Text'),
),
),
),
);
}
}
在这个假设性的例子中,我们假设TunaSDK
类有一个静态的encrypt
方法,用于将明文加密。
假设功能2:设备硬件访问(如摄像头)
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Tuna SDK Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// 假设TunaSDK有一个captureImage方法用于从摄像头捕获图像
File? imageFile = await TunaSDK.captureImage();
if (imageFile != null) {
// 显示或处理捕获的图像
print("Image captured and saved to ${imageFile.path}");
} else {
print("Failed to capture image");
}
},
child: Text('Capture Image'),
),
),
),
);
}
}
在这个例子中,我们假设TunaSDK
类有一个静态的captureImage
方法,用于从设备摄像头捕获图像并返回一个File
对象。
注意事项
- 由于
tuna_sdk
的具体功能和API未知,上述代码仅为假设性示例。 - 在实际使用时,应参考
tuna_sdk
的官方文档或源代码以了解其功能和使用方法。 - 如果
tuna_sdk
是一个私有或内部插件,请确保你有权限访问其文档和源代码。
希望这些假设性的代码案例能帮助你理解如何在Flutter中使用一个未知的插件。如果有更多关于tuna_sdk
的具体信息,可以进一步调整和优化代码。