Flutter多功能插件flutterduplo的使用
Flutter多功能插件flutterduplo的使用
Flutter插件用于通过Duplo支付系统进行付款。完全支持所有平台。
功能特性
当前功能包括:
- 卡支付
- 银行支付
安装
要使用此插件,在pubspec.yaml
文件中添加flutterduplo
依赖项。
然后在您的widget的initState
方法中初始化插件。
import 'package:flutterduplo/flutterduplo.dart';
class _ExamplePayementPageState extends State<ExamplePayementPage> {
var publicKey = '添加你的Duplo公共密钥';
var secretKey = '添加你的Duplo私有密钥';
final plugin = Duplo();
[@override](/user/override)
void initState() {
plugin.initialize(publicKey: publicKey, secretKey: secretKey);
}
}
进行支付
您可以选择两种方式进行支付:
1. 结账(推荐)
这是一种简单的方法;插件处理所有涉及的付款过程(除了交易初始化和验证,这些应从您的后端完成)。
Charge charge = Charge()
..amount = 10000
..reference = _getReference()
..email = 'customer@email.com';
CheckoutResponse response = await plugin.checkout(
context,
method: CheckoutMethod.card, // 默认为CheckoutMethod.selectable
charge: charge,
);
plugin.checkout()
返回一个包含支付状态和详细信息的CheckoutResponse
实例。
2. 刷卡
这是一种更复杂的方法;您需要处理所有回调和UI状态。
Charge charge = Charge();
charge.card = _getCardFromUI();
charge
..amount = 2000
..email = 'user@email.com'
..reference = _getReference()
..putCustomField('Charged From', 'Flutter PLUGIN');
_chargeCard();
验证卡详情
您需要但不强制要求构建用户输入其付款详情的UI。为了更简单的验证,将TextFormField
包裹在一个Form
小部件内。如果您对此不熟悉,请参阅这篇文章:如何使用Flutter轻松验证表单和用户输入。
注意:您不必向Charge
传递卡对象。插件会调用一个UI供用户输入他们的卡信息。
您可以使用以下方法验证字段:
card.validNumber
此方法帮助检查卡号是否有效。
card.validCVC
此方法检查卡安全码是否有效。
card.validExpiryDate
此方法检查过期日期(年月组合)是否有效。
card.isValid
此方法检查卡是否有效。在刷卡之前始终进行此检查。
card.getType
此方法返回卡类型(发行者)的字符串表示估计值。
运行示例项目
对于如何开始使用Flutter,请参阅在线文档:Flutter文档。
在这个插件中提供了一个示例项目。克隆此仓库并导航到example
文件夹。使用支持的IDE打开它,或者从该文件夹在终端执行flutter run
。
贡献、问题和错误报告
该项目对公众开放贡献。请自由贡献。 遇到问题或想报告错误?请在此处报告:报告问题。记得尽可能详细描述。
示例代码
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutterduplo/flutterduplo.dart';
import 'themeclass.dart';
// 定义您的后端URL和Duplo公共密钥。
String backendUrl = '{YOUR_BACKEND_URL}';
String DuploPublicKey = '{YOUR_duplo_PUBLIC_KEY}';
const String appName = 'Buplo Example';
void main() {
runApp(const MyApp());
}
// MyApp是主要的应用程序小部件。
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
// 从任何上下文中获取MyApp小部件的状态。
static _MyAppState of(BuildContext context) =>
context.findAncestorStateOfType<_MyAppState>()!;
}
class _MyAppState extends State<MyApp> {
// 默认主题模式为系统。
ThemeMode _themeMode = ThemeMode.system;
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: appName,
debugShowCheckedModeBanner: false,
themeMode: _themeMode,
theme: ThemeClass.lightTheme,
darkTheme: ThemeClass.darkTheme,
home: const Newpage(),
);
}
// 更改主题模式的函数。
void changeTheme(ThemeMode themeMode) {
setState(() {
_themeMode = themeMode;
});
}
}
// 检查应用是否运行在暗模式下。
bool get isDarkMode {
var brightness = SchedulerBinding.instance.window.platformBrightness;
return brightness == Brightness.dark;
}
// Newpage是应用程序的主要界面。
class Newpage extends StatefulWidget {
const Newpage({Key? key}) : super(key: key);
[@override](/user/override)
_NewpageState createState() => _NewpageState();
}
class _NewpageState extends State<Newpage> {
var currency = ["USD", "NGN"]; // 支持的货币。
String dropdownvalue = 'NGN'; // 默认货币。
TextEditingController phoneController = TextEditingController(); // 金额文本框控制器。
bool isloading = false; // 结账按钮加载状态。
final plugin = Duplo(); // Duplo插件实例。
final _formKey = GlobalKey<FormState>(); // 表单键以验证表单。
bool check = false; // 暗模式复选框状态。
[@override](/user/override)
void initState() {
check = isDarkMode;
plugin.initialize(
secretKey: 'sk_test_qez90izgknchzxjejas1nw8pdnhrli7khdr6hq9',
publicKey: 'pk_live_cllwoquh6duwcojl6ils7mhoieene068gc3dgv',
); // 替换为您的密钥
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black,
title: const Text("DUPLO SDK SAMPLE"),
),
body: Center(
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: check,
onChanged: (bool? value) {
setState(() {
check = !check;
});
if (!check) {
MyApp.of(context).changeTheme(ThemeMode.light);
} else {
MyApp.of(context).changeTheme(ThemeMode.dark);
}
}),
const SizedBox(
height: 20,
),
DropdownButton(
// 初始值
value: dropdownvalue,
// 下箭头图标
icon: const Icon(Icons.keyboard_arrow_down),
// 选项列表
items: currency.map((String items) {
return DropdownMenuItem(
value: items,
child: Text(items),
);
}).toList(),
// 选择新选项时,更改按钮值
onChanged: (String? newValue) {
setState(() {
dropdownvalue = newValue!;
});
},
),
const SizedBox(
height: 30,
),
Container(
decoration: const BoxDecoration(
color: Color(0xffF4F4F6),
borderRadius: BorderRadius.all(Radius.circular(15.0))),
padding: const EdgeInsets.symmetric(horizontal: 15),
child: TextFormField(
decoration: InputDecoration(
fillColor: const Color(0xffF4F4F6),
hintText: "1000",
hintStyle: TextStyle(
fontSize: 16.56,
fontWeight: FontWeight.w500,
color: isDarkMode ? null : Colors.black),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: Color(0xffF4F4F6)),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: Color(0xffF4F4F6)),
),
disabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
borderSide: BorderSide(color: Color(0xffF4F4F6)),
),
),
style: TextStyle(
fontSize: 16.56,
fontWeight: FontWeight.w500,
color: isDarkMode ? null : Colors.black),
controller: phoneController,
keyboardType: TextInputType.phone,
onChanged: (value) {
if (value.isEmpty) {
setState(() {
// widget.emailfield(true);
});
} else {
setState(() {});
}
},
validator: (value) {
if (value!.isEmpty) {
return "This field can't be empty";
}
return null;
},
),
),
const SizedBox(
height: 50,
),
GestureDetector(
child: Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15)),
color: Colors.black),
height: 65,
padding: const EdgeInsets.symmetric(vertical: 15),
margin: const EdgeInsets.symmetric(
horizontal: 50, vertical: 10),
alignment: Alignment.center,
child: isloading
? loadingWidget
: const Text(
"Checkout",
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
onTap: () {
if (_formKey.currentState!.validate()) {
_handleCheckout(context);
}
},
)
],
),
),
),
);
}
_handleCheckout(BuildContext context) async {
setState(() => isloading = true);
_formKey.currentState?.save();
Charge charge = Charge()
..amount = int.parse(phoneController.text) // 基础货币单位
..email = 'sdkapp1@email.com'
..currency = dropdownvalue;
charge.reference = _getReference();
try {
var response = await plugin.checkout(
context,
charge: charge,
);
log('Response = $response');
setState(() => isloading = false);
_updateStatus(response.reference, '$response');
} catch (e) {
setState(() => isloading = false);
_showMessage("Check console for error");
rethrow;
}
}
String _getReference() {
String platform;
if (!kIsWeb) {
if (Platform.isIOS) {
platform = 'iOS';
} else {
platform = 'Android';
}
} else {
platform = "WEB";
}
return 'ChargedFrom${platform}_${DateTime.now().millisecondsSinceEpoch}';
}
_updateStatus(String? reference, String message) {
_showMessage('Reference: $reference \n Response: $message',
const Duration(seconds: 7));
}
_showMessage(String message,
[Duration duration = const Duration(seconds: 4)]) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message),
duration: duration,
action: SnackBarAction(
label: 'CLOSE',
onPressed: () =>
ScaffoldMessenger.of(context).removeCurrentSnackBar()),
));
}
}
const loadingWidget = SpinKitThreeBounce(
color: Colors.white,
size: 30.0,
);
更多关于Flutter多功能插件flutterduplo的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter多功能插件flutterduplo的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,flutterduplo
是一个假想的 Flutter 插件名称,因为实际上并没有一个广泛认可的名为 flutterduplo
的插件。不过,我可以基于 Flutter 插件开发的通用模式,给出一个多功能插件使用的示例代码框架,来帮助你理解如何在 Flutter 应用中使用多功能插件。
假设我们有一个名为 multifunctional_plugin
的多功能插件,它提供了文件操作、网络请求和设备信息获取等功能。以下是如何在 Flutter 应用中使用这个插件的示例代码:
1. 添加插件依赖
首先,你需要在 pubspec.yaml
文件中添加插件依赖:
dependencies:
flutter:
sdk: flutter
multifunctional_plugin: ^x.y.z # 假设这是插件的版本号
然后运行 flutter pub get
来获取插件。
2. 导入插件并使用其功能
在你的 Dart 文件中导入插件,并使用其提供的功能。以下是一个示例,展示了如何使用文件操作、网络请求和设备信息获取功能:
import 'package:flutter/material.dart';
import 'package:multifunctional_plugin/multifunctional_plugin.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _deviceInfo = '';
String _fileContent = '';
String _networkResponse = '';
@override
void initState() {
super.initState();
_getDeviceInfo();
_readFile();
_makeNetworkRequest();
}
Future<void> _getDeviceInfo() async {
String deviceInfo = await MultifunctionalPlugin.deviceInfo();
setState(() {
_deviceInfo = deviceInfo;
});
}
Future<void> _readFile() async {
String filePath = 'path/to/your/file.txt'; // 替换为你的文件路径
String fileContent = await MultifunctionalPlugin.readFile(filePath);
setState(() {
_fileContent = fileContent;
});
}
Future<void> _makeNetworkRequest() async {
String url = 'https://api.example.com/data'; // 替换为你的API URL
Map<String, String> headers = {'Content-Type': 'application/json'};
String networkResponse = await MultifunctionalPlugin.networkRequest(
url: url,
method: 'GET',
headers: headers,
);
setState(() {
_networkResponse = networkResponse;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Multifunctional Plugin Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Device Info:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text(_deviceInfo, style: TextStyle(fontSize: 16)),
SizedBox(height: 20),
Text('File Content:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text(_fileContent, style: TextStyle(fontSize: 16)),
SizedBox(height: 20),
Text('Network Response:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Text(_networkResponse, style: TextStyle(fontSize: 16)),
],
),
),
),
);
}
}
3. 插件功能实现(假设)
虽然这不是你要求的,但为了完整性,这里简要说明一下插件可能如何实现这些功能。在插件的 Dart 代码中,你会定义这些功能的接口,并在原生代码(iOS 的 Swift/Objective-C 和 Android 的 Kotlin/Java)中实现它们。
Dart 接口
class MultifunctionalPlugin {
static const MethodChannel _channel = MethodChannel('com.example.multifunctional_plugin');
static Future<String> deviceInfo() async {
final String deviceInfo = await _channel.invokeMethod('getDeviceInfo');
return deviceInfo;
}
static Future<String> readFile(String filePath) async {
final String fileContent = await _channel.invokeMethod('readFile', {'filePath': filePath});
return fileContent;
}
static Future<String> networkRequest({required String url, required String method, Map<String, String>? headers}) async {
final Map<String, dynamic> arguments = <String, dynamic>{
'url': url,
'method': method,
'headers': headers,
};
final String response = await _channel.invokeMethod('networkRequest', arguments);
return response;
}
}
原生代码实现
在原生代码中,你需要监听这些方法的调用,并实现相应的逻辑。由于篇幅限制,这里不展示具体的原生代码实现,但你可以参考 Flutter 官方文档了解如何在原生代码中实现插件功能。
这个示例框架展示了如何在 Flutter 应用中使用一个假设的多功能插件。实际使用时,你需要根据插件的具体文档和 API 来调整代码。