Flutter支付集成插件toss_payment的使用
Flutter支付集成插件toss_payment的使用
本README描述了如何在Flutter应用中使用toss_payment插件来实现支付功能。有关如何编写好的包README,请参阅Dart指南,以及有关开发包的一般信息,请参阅Dart指南和Flutter指南。
Toss Payments Flutter插件
该插件旨在帮助希望在Flutter应用中使用Toss Payments进行应用内支付的开发者。有关Toss Payments的详细信息,请访问官方文档。
功能
- 使用支付窗口和webview连接外部应用。
开始使用
为了实现外部应用的连接,需要根据不同的操作系统进行环境设置。
1. iOS
在Info.plist
文件中添加用于启动外部应用的Scheme。
<key>LSApplicationQueriesSchemes</key>
<array>
<string>supertoss</string> <!-- Toss Pay -->
<string>mpocket.online.ansimclick</string> <!-- Samsung Card App -->
<string>hdcardappcardansimclick</string> <!-- Hyundai Card App -->
<string>smhyundaiansimclick</string> <!-- Hyundai Card Certificate -->
<string>wooripay</string> <!-- Woori Card App -->
<string>shinhan-sr-ansimclick</string> <!-- Shinhan Card App -->
<string>smshinhanansimclick</string> <!-- Shinhan Card Certificate -->
<string>kb-acp</string> <!-- Kookmin Card App -->
<string>lottesmartpay</string> <!-- Lotte Card Mobile Payment -->
<string>lotteappcard</string> <!-- Lotte Card App -->
<string>cloudpay</string> <!-- Hana Card App -->
<string>nhappvardansimclick</string> <!-- NongHyup Card App -->
<string>nonghyupcardansimclick</string> <!-- NongHyup Card Certificate -->
<string>citispay</string> <!-- Citibank Card App -->
<string>citicardappkr</string> <!-- Citibank Card Certificate -->
<string>ispmobile</string> <!-- ISP Mobile -->
</array>
3. Android
a. 设置最小SDK版本为20及以上
在android/app/build.gradle
文件中设置defaultConfig
。
defaultConfig {
...
minSdkVersion 20
...
}
b. 在manifest文件中添加Scheme和权限
在android/app/main/AndroidManifest.xml
文件中添加Scheme和权限。
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<queries>
<!-- Toss -->
<package android:name="viva.republica.toss" />
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="supertoss" />
</intent>
<!-- Samsung Card -->
<package android:name="kr.co.samsungcard.mpocket" />
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="mpocket.online.ansimclick" />
</intent>
<!-- Hyundai Card -->
<package android:name="com.hyundaicard.appcard" />
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="hdcardappcardansimclick" />
</intent>
<!-- Hyundai Card Certificate -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="smhyundaiansimclick" />
</intent>
<!-- Woori Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="wooripay" />
</intent>
<!-- Shinhan Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="shinhan-sr-ansimclick" />
</intent>
<!-- Shinhan Card Certificate -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="smshinhanansimclick" />
</intent>
<!-- Kookmin Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="kb-acp" />
</intent>
<!-- Lotte Card Mobile Payment -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="lottesmartpay" />
</intent>
<!-- Lotte Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="lotteappcard" />
</intent>
<!-- Hana Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="cloudpay" />
</intent>
<!-- NongHyup Card App -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="nhappvardansimclick" />
</intent>
<!-- NongHyup Card Certificate -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="nonghyupcardansimclick" />
</intent>
<!-- Citibank Card Certificate -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="citicardappkr" />
</intent>
<!-- ISP Mobile -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="ispmobile" />
</intent>
</queries>
额外提示
a. 如果无法访问Android Web
将android:usesCleartextTraffic
设置为true
。
<application
...
android:usesCleartextTraffic="true">
...
</application>
b. 如果在Android 12及以上系统中应用无法安装或运行
将android:exported
设置为true
。
<activity
android:name=".MainActivity"
...
android:exported="true">
...
</activity>
使用方法
通过PaymentWebView
可以连接支付窗口。
PaymentWebView(title: "支付页面标题", paymentRequestUrl: Uri.parse("支付网页地址"))
其他信息
注意事项
- 示例应用中使用了Mock Server来模拟Web页面。实际使用时,请创建自己的Web页面并使用。
路线图
- 测试代码。
- 其他。
完整示例代码
import 'dart:developer' as dev;
import 'package:flutter/material.dart';
import 'package:toss_payment/toss_payment.dart';
import 'models/payment_request.dart';
import 'models/product.dart';
import 'services/mock_server.dart';
import 'widgets/order_widget.dart';
import 'widgets/product_widget.dart';
void main() async {
/// 示例中使用的mock server
await MockServer.startServer();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// 应用的根组件
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Toss Payment Demo',
theme: ThemeData(
primarySwatch: Colors.indigo,
),
home: const MyHomePage(title: 'Flutter Toss Payment Demo Page'),
);
}
}
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 Product _product = Product(price: 15000, name: 'Toss T-shirt');
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SafeArea(
child: Column(children: [
Expanded(
child: Center(
child: ProductWidget(
product: _product,
),
),
),
GridView.count(
shrinkWrap: true,
padding: const EdgeInsets.all(4),
crossAxisCount: 3,
children: List.generate(9, (index) {
Widget ret = Container(
margin: const EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
),
);
switch (index) {
case 0:
ret = OrderWidget(
title: '信用卡',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '信用卡',
);
break;
case 1:
ret = OrderWidget(
title: '自动扣款',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '自动扣款',
);
break;
case 2:
ret = OrderWidget(
title: '直接打开卡应用',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '直接打开卡应用',
);
break;
case 3:
ret = OrderWidget(
title: '虚拟账户',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '虚拟账户',
);
break;
case 4:
ret = OrderWidget(
title: '银行转账',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '银行转账',
);
break;
case 5:
ret = OrderWidget(
title: '手机支付',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '手机支付',
);
break;
case 6:
ret = OrderWidget(
title: '图书文化券',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: '图书文化券',
);
break;
case 7:
ret = OrderWidget(
title: 'Toss支付',
product: _product,
onTap: (request) {
_showPayment(context, request);
},
payBy: 'Toss支付',
);
break;
}
return ret;
}),
),
]),
),
);
}
_showPayment(BuildContext context, PaymentRequest request) async {
var ret = await showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
enableDrag: false,
isDismissible: false,
builder: (context) {
bool success = false;
return Container(
margin: const EdgeInsets.only(top: 110),
child: PaymentWebView(
title: _product.name,
paymentRequestUrl: request.url,
onPageStarted: (url) {
dev.log('onPageStarted.url = $url', name: "PaymentWebView");
},
onPageFinished: (url) {
dev.log('onPageFinished.url = $url', name: "PaymentWebView");
// TODO 判断支付是否成功
success = url.contains('success');
},
onDisposed: () {},
onTapCloseButton: () {
Navigator.of(context).pop(success);
},
),
);
});
dev.log('ret = $ret', name: '_showPayment');
}
}
extension PaymentRequestExtension on PaymentRequest {
Uri get url {
// TODO 请替换为您的Toss Pay Web地址。以下仅为示例。
return Uri.http("localhost:8080", "payment", json);
}
}
更多关于Flutter支付集成插件toss_payment的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter支付集成插件toss_payment的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter项目中集成toss_payment
插件以实现支付功能,可以遵循以下步骤和代码示例。toss_payment
插件通常用于集成Toss支付服务,但请注意,实际使用时需要确保你已经获得了Toss支付的相关API密钥和配置。
以下是一个基本的代码示例,展示如何在Flutter应用中集成toss_payment
插件:
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加toss_payment
依赖:
dependencies:
flutter:
sdk: flutter
toss_payment: ^最新版本号 # 替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
2. 配置Android和iOS
根据你使用的平台,你可能需要在AndroidManifest.xml
和Info.plist
文件中添加一些配置,以便正确初始化支付插件。这通常包括设置支付相关的URL Scheme等。具体配置请参考toss_payment
插件的官方文档。
3. 初始化插件和发起支付
在你的Flutter应用中,你可以通过以下代码初始化toss_payment
插件并发起支付请求:
import 'package:flutter/material.dart';
import 'package:toss_payment/toss_payment.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Toss Payment Integration'),
),
body: Center(
child: ElevatedButton(
onPressed: _initiatePayment,
child: Text('Pay with Toss'),
),
),
),
);
}
Future<void> _initiatePayment() async {
// 配置支付参数
final TossPaymentConfig config = TossPaymentConfig(
merchantId: '你的商户ID', // 替换为你的实际商户ID
mid: '你的MID', // 替换为你的实际MID
tid: '你的TID', // 替换为你的实际TID
key: '你的API密钥', // 替换为你的实际API密钥
amount: 1000, // 支付金额,单位通常是韩元(根据Toss的具体要求调整)
currency: 'KRW', // 货币代码
name: '商品名称', // 商品名称
buyerEmail: '买家邮箱', // 买家邮箱
buyerName: '买家姓名', // 买家姓名
buyerPhone: '买家电话', // 买家电话
// 根据需要添加更多配置参数
);
// 初始化Toss支付插件
final TossPayment tossPayment = TossPayment();
try {
// 发起支付请求
final result = await tossPayment.startPayment(config: config);
if (result != null && result.isSuccess) {
// 支付成功处理
print('支付成功: ${result.data}');
} else {
// 支付失败或取消处理
print('支付失败或取消: ${result?.error?.message}');
}
} catch (e) {
// 处理异常
print('支付过程中发生错误: $e');
}
}
}
注意事项
- API密钥和敏感信息:确保不要在代码中硬编码API密钥或其他敏感信息。考虑使用环境变量或安全的密钥管理服务。
- 错误处理:在实际应用中,添加更详细的错误处理逻辑,以提供更好的用户体验。
- 支付回调:根据你的业务需求,处理支付成功或失败后的回调逻辑,比如更新订单状态、发送通知等。
- UI/UX:调整UI/UX以适应你的应用风格和用户体验需求。
请确保参考toss_payment
插件的官方文档和Toss支付的API文档,以获取最新的配置要求和API变化。