Flutter支付终端管理插件stripe_terminalx的使用
Flutter支付终端管理插件stripe_terminalx的使用
stripe_terminalx
一个用于扫描Stripe读卡器并连接到它们以获取支付方式的Flutter插件。
安装
Android
无需配置,开箱即用。
iOS
您需要在Info.plist
文件中提供权限请求字符串。示例内容如下:
<key>NSLocationWhenInUseUsageDescription</key>
<string>位置访问是为了接受付款所必需的。</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>蓝牙访问是为了连接支持的蓝牙卡读卡器所必需的。</string>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>此应用使用蓝牙连接到支持的卡读卡器。</string>
您还需要授权后台模式以启用bluetooth-central
。将以下内容添加到您的Info.plist
文件中:
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
</array>
使用
初始化SDK
stripeTerminal = StripeTerminal(
fetchToken: () async {
// 调用后端以获取连接令牌并返回给此函数
// 示例令牌可以是:
const token = "pst_test_XXXXXXXXXX....";
return token;
},
);
示例后端代码(Node.js)
import Stripe from "stripe";
import express from "express";
const stripe = new Stripe("sk_test_XXXXXXXXXXXXXXXXXX", {
apiVersion: "2020-08-27",
});
const app = express();
app.get("/connectionToken", async (req, res) => {
const token = await stripe.terminal.connectionTokens.create();
res.send({
success: true,
data: token.secret,
});
});
app.post("/createPaymentIntent", async (req, res) => {
const pi = await stripe.paymentIntents.create({
amount: 1000,
currency: "USD",
capture_method: "manual",
payment_method_types: ["card_present"],
});
res.send({
success: true,
paymentIntent: pi,
});
});
app.listen(8000, () => {
console.log("Server started");
});
发现附近的设备并显示给用户
stripeTerminal
.discoverReaders(simulated: true)
.listen((List<StripeReader> readers) {
setState(() {
this.readers = readers;
});
});
连接到蓝牙读卡器
bool connected = await stripeTerminal.connectBluetoothReader(readers[0].serialNumber);
if (connected) {
print("Connected to a device");
}
从读卡器读取卡片信息
stripeTerminal
.readReusableCardDetail()
.then((StripePaymentMethod paymentMethod) {
print("A card was read, the last four digits are ${paymentMethod.card?.last4}");
});
使用刷卡、插卡或轻触方式从读卡器扫描支付方式
// 从后端获取此内容,创建新的支付意图
Future<String> createPaymentIntent() async {
Response invoice = await _dio.post("/createPaymentIntent");
return invoice.data["paymentIntent"]["client_secret"];
}
String payment_intent_client_secret = await createPaymentIntent();
stripeTerminal
.collectPaymentMethod(payment_intent_client_secret)
.then((StripePaymentIntent paymentIntent) {
print("A payment intent has captured a payment method, send this payment intent to your backend to capture the payment");
});
完成!
当前支持的功能
- 初始化终端SDK
- 扫描读卡器
- 连接到设备(仅限Android上的蓝牙设备)
- 检查连接状态
- 检查已连接的设备
- 从设备读取支付方式
缺少的功能
- 创建支付意图
- 处理支付
- 捕获支付
未来计划
如果您需要更多功能,请随时发送PR或在仓库中创建相关问题。
由于我无法长期维护此包,一旦flutter_stripe在其SDK中添加支持,此包将会被弃用。
支持创作者
免费开发软件需要时间和努力,请考虑买一杯咖啡支持我。这一定会让我开心,并激励我贡献更多。
完整示例代码
以下是完整的示例代码,展示了如何使用stripe_terminalx
插件。
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:stripe_terminalx/stripe_terminalx.dart';
void main() {
runApp(
const MaterialApp(home: MyApp()),
);
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final Dio _dio = Dio(
BaseOptions(
// TODO: THIS URL does not work
baseUrl: "https://deb8-103-163-182-241.in.ngrok.io",
),
);
Future<String> getConnectionString() async {
Response response = await _dio.get("/connectionToken");
if (!(response.data)["success"]) {
throw Exception(
"Failed to get connection token because ${response.data["message"]}",
);
}
return (response.data)["data"];
}
Future<void> _pushLogs(StripeLog log) async {
debugPrint(log.code);
debugPrint(log.message);
}
Future<String> createPaymentIntent() async {
Response invoice = await _dio.post("/createPaymentIntent", data: {
"email": "awazgyawali@gmail.com",
"order": {"test": "1"},
"ticketCount": 3,
"price": 5,
});
return jsonDecode(invoice.data)["paymentIntent"]["client_secret"];
}
late StripeTerminal stripeTerminal;
[@override](/user/override)
void initState() {
super.initState();
_initStripe();
}
_initStripe() async {
stripeTerminal = await StripeTerminal.getInstance(
fetchToken: getConnectionString,
);
stripeTerminal.onNativeLogs.listen(_pushLogs);
}
bool simulated = true;
StreamSubscription? _sub;
List<StripeReader>? readers;
String? paymentIntentId;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
children: [
ListTile(
onTap: () {
setState(() {
simulated = !simulated;
_initStripe();
});
},
title: const Text("Scanning mode"),
trailing: Text(simulated ? "Simulator" : "Real"),
),
TextButton(
child: const Text("Init Stripe"),
onPressed: () async {
_initStripe();
},
),
TextButton(
child: const Text("Get Connection Token"),
onPressed: () async {
String connectionToken = await getConnectionString();
_showSnackbar(connectionToken);
},
),
if (_sub == null)
TextButton(
child: const Text("Scan Devices"),
onPressed: () async {
setState(() {
readers = [];
});
_sub = stripeTerminal
.discoverReaders(
DiscoverConfig(
discoveryMethod: DiscoveryMethod.bluetooth,
simulated: simulated,
),
)
.listen((readers) {
setState(() {
this.readers = readers;
});
});
},
),
if (_sub != null)
TextButton(
child: const Text("Stop Scanning"),
onPressed: () async {
setState(() {
_sub?.cancel();
_sub = null;
});
},
),
TextButton(
child: const Text("Connection Status"),
onPressed: () async {
stripeTerminal.connectionStatus().then((status) {
_showSnackbar("Connection status: ${status.toString()}");
});
},
),
TextButton(
child: const Text("Connected Device"),
onPressed: () async {
stripeTerminal
.fetchConnectedReader()
.then((StripeReader? reader) {
_showSnackbar("Connection Device: ${reader?.toJson()}");
});
},
),
if (readers != null)
...readers!.map(
(e) => ListTile(
title: Text(e.serialNumber),
trailing: Text(describeEnum(e.batteryStatus)),
leading: Text(e.locationId ?? "No Location Id"),
onTap: () async {
await stripeTerminal
.connectToReader(
e.serialNumber,
locationId: "tml_EoMcZwfY6g8btZ",
)
.then((value) {
_showSnackbar("Connected to a device");
}).catchError((e) {
if (e is PlatformException) {
_showSnackbar(e.message ?? e.code);
}
});
},
subtitle: Text(describeEnum(e.deviceType)),
),
),
TextButton(
child: const Text("Read Reusable Card Detail"),
onPressed: () async {
stripeTerminal
.readReusableCardDetail()
.then((StripePaymentMethod paymentMethod) {
_showSnackbar(
"A card was read: ${paymentMethod.card?.toJson()}",
);
});
},
),
TextButton(
child: const Text("Set reader display"),
onPressed: () async {
stripeTerminal.setReaderDisplay(
ReaderDisplay(
type: DisplayType.cart,
cart: DisplayCart(
currency: "USD",
tax: 130,
total: 1000,
lineItems: [
DisplayLineItem(
description: "hello 1",
quantity: 1,
amount: 500,
),
DisplayLineItem(
description: "hello 2",
quantity: 1,
amount: 500,
),
],
),
),
);
},
),
TextButton(
child: const Text("Collect Payment Method"),
onPressed: () async {
paymentIntentId = await createPaymentIntent();
stripeTerminal
.collectPaymentMethod(paymentIntentId!)
.then((StripePaymentIntent paymentIntent) async {
_dio.post("/confirmPaymentIntent", data: {
"paymentIntentId": paymentIntent.id,
});
_showSnackbar(
"A payment method was captured",
);
});
},
),
TextButton(
child: const Text("Misc Button"),
onPressed: () async {
StripeReader.fromJson(
{
"locationStatus": 2,
"deviceType": 3,
"serialNumber": "STRM26138003393",
"batteryStatus": 0,
"simulated": false,
"availableUpdate": false,
},
);
},
),
],
),
),
);
}
_showSnackbar(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
behavior: SnackBarBehavior.floating,
content: Text(
message,
style: const TextStyle(color: Colors.red),
),
),
);
}
}
更多关于Flutter支付终端管理插件stripe_terminalx的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter支付终端管理插件stripe_terminalx的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
stripe_terminalx
是一个用于在 Flutter 应用中集成 Stripe 终端设备的插件。它允许你通过 Stripe Terminal SDK 来管理支付终端设备,如 Stripe Reader,从而处理面对面的支付交易。
以下是如何在 Flutter 中使用 stripe_terminalx
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 stripe_terminalx
插件的依赖:
dependencies:
flutter:
sdk: flutter
stripe_terminalx: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 初始化 Stripe Terminal
在你的 Flutter 应用中,首先需要初始化 Stripe Terminal。通常,你可以在 main.dart
或某个初始化函数中进行初始化。
import 'package:stripe_terminalx/stripe_terminalx.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 Stripe Terminal
await StripeTerminalx.initialize(
apiKey: 'your_stripe_secret_key',
);
runApp(MyApp());
}
3. 发现和连接终端设备
接下来,你可以使用 stripe_terminalx
来发现和连接 Stripe 终端设备。
import 'package:stripe_terminalx/stripe_terminalx.dart';
class PaymentScreen extends StatefulWidget {
@override
_PaymentScreenState createState() => _PaymentScreenState();
}
class _PaymentScreenState extends State<PaymentScreen> {
List<Reader> _readers = [];
Reader? _selectedReader;
@override
void initState() {
super.initState();
_discoverReaders();
}
Future<void> _discoverReaders() async {
try {
List<Reader> readers = await StripeTerminalx.discoverReaders();
setState(() {
_readers = readers;
});
} catch (e) {
print('Error discovering readers: $e');
}
}
Future<void> _connectReader(Reader reader) async {
try {
await StripeTerminalx.connectReader(reader);
setState(() {
_selectedReader = reader;
});
} catch (e) {
print('Error connecting reader: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stripe Terminal'),
),
body: Column(
children: [
if (_readers.isNotEmpty)
..._readers.map((reader) {
return ListTile(
title: Text(reader.label),
onTap: () => _connectReader(reader),
);
}).toList(),
if (_selectedReader != null)
Text('Connected to: ${_selectedReader!.label}'),
],
),
);
}
}
4. 处理支付
一旦你连接了终端设备,你可以开始处理支付。以下是一个简单的支付处理示例:
Future<void> _processPayment() async {
try {
// 创建一个支付意图
PaymentIntent paymentIntent = await StripeTerminalx.createPaymentIntent(
amount: 1000, // 金额以最小货币单位表示,例如 1000 表示 $10.00
currency: 'usd',
);
// 开始支付流程
await StripeTerminalx.collectPaymentMethod(paymentIntent);
// 确认支付
PaymentIntent confirmedIntent = await StripeTerminalx.confirmPaymentIntent(paymentIntent);
if (confirmedIntent.status == 'succeeded') {
print('Payment succeeded!');
} else {
print('Payment failed or was canceled.');
}
} catch (e) {
print('Error processing payment: $e');
}
}
5. 断开连接
在支付完成后,你可以断开与终端设备的连接:
Future<void> _disconnectReader() async {
try {
await StripeTerminalx.disconnectReader();
setState(() {
_selectedReader = null;
});
} catch (e) {
print('Error disconnecting reader: $e');
}
}