Flutter集成HALO SDK插件halo_sdk_flutter_plugin的使用
Flutter集成HALO SDK插件halo_sdk_flutter_plugin的使用
Halo SDK Flutter Plugin
一个基于Flutter实现的Halo Dot SDK。
Halo Dot SDK 是一种隔离式MPoC支付处理软件,具有认证和监控能力。
下图描述了这种隔离式MPoC支付软件的架构。
下图还展示了SDK边界及其与集成渠道和第三方支付网关之间的交互。它还描述了SDK边界以及它如何与集成商和第三方支付进行交互,并包含有关数据在边界之间通信的详细信息。
目录
需求
以下是实现Halo Dot SDK所需的需求列表:
- 开发者账户(在开发者门户注册)
- 签署的保密协议/NDA(可在开发者门户找到)
- 生成JWT所需的公钥和私钥(公钥提交到开发者门户)
- Kotlin 2.0.21(@注释:更高版本正在开发中)
- Flutter 3.27.3(@注释:更高版本正在开发中)
- Dart 3.6.1(@注释:随Flutter捆绑)
- Java 21
- IDE(推荐使用Android Studio)
- 推荐库:
- permission_handler:^11.3.1
- dart_jsonwebtoken:^2.16.2
- 常见问题解答
开发者门户注册
在测试生产环境之前,您需要在我们的QA(UAT - 用户验收测试环境)上注册。
开发者门户允许您:
- 接受保密协议
- 访问SDK
- 提交您的公钥(用于验证JWT)
- 获取JWT的相关细节
注册
- 访问开发者门户并注册。
- 通过OTP验证您的账户。
- 点击访问SDK按钮:
- 下载并接受保密协议。
- 提交您的公钥并创建一个发行人名称。这将用于验证您创建的JWT:
- 将生成访问密钥和秘密密钥。这些将在您的IDE中用于访问Halo SDK:
开始使用
确保您已设置好构建Flutter应用的环境。您可以按照这里的说明进行操作。
Flutter应用
创建一个新的Flutter应用或将其集成到现有的应用程序中。确保添加了Android支持,这是目前唯一支持的平台。
# 使用flutter
flutter create . --project-name my_sdk_flutter_plugin --org za.co.synthesis.halo.test.plugin
# 使用fvm
fvm spawn 3.27.3 create . --project-name my_sdk_flutter_plugin --org za.co.synthesis.halo.test.plugin
环境
- SDK使用Java 21进行了测试。我们不能确认更高的版本是否能正常工作。
- SDK使用Flutter
3.27.3
和 Dart3.6.1
进行了测试(DevTools2.40.2
)。 - Android项目的
minSdkVersion
应为29
或更高。请在android/app/build.gradle
文件中检查此值。
defaultConfig {
applicationId "za.co.synthesis.halo.sdkflutterplugin_example"
minSdkVersion 29 // 应该为29或更高
// ...
}
- 如果遇到设置
minSdkVersion
的问题,请查看常见问题解答。
插件安装
- 运行
flutter pub add halo_sdk_flutter_plugin
以将Flutter插件添加到您的项目中。 - 我们建议同时安装
flutter pub add permission_handler
。 - 插件需要从Halo Maven存储库(托管在AWS S3上)下载SDK二进制文件。为此,您需要凭据。在开发者门户中找到您的
accesskey
和secretkey
:
将其添加到您的android/local.properties
文件中(如果不存在则创建一个):
aws.accesskey=<accesskey>
aws.secretkey=<secretkey>
注意大小写
- 然后将以下内容添加到您的
android/app/build.gradle
文件中(可能已经存在):
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) }}
移动后端需求
JWT
所有调用Halo SDK的操作都需要有效的JWT。
有关创建JWT的详细信息可以在开发者门户中找到。
我们建议安装flutter pub add dart_jsonwebtoken
来生成JWT。
config.dart
class Config {
static const String privateKeyPem = String.fromEnvironment('PRIVATE_KEY', defaultValue: '');
static const String issuer = "{get from the [Developer portal]}";
static const String username = "{get from the [Developer portal]}";
static const String merchantId = "{get from the [Developer portal]}";
static const String host = "{get from the [Developer portal]}";
static const String aud = "{get from the [Developer portal]}";
static const String ksk = "{get from the [Developer portal]}";
}
jwt_token.dart
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import './config.dart'; // 引入上述配置文件
class JwtToken {
static String getJwt() {
final jwt = JWT(
{'aud_fingerprints': Config.aud, 'ksk_pin': Config.ksk, 'usr': Config.username},
audience: Audience([Config.host]),
issuer: Config.issuer,
subject: Config.merchantId,
);
final key = RSAPrivateKey(Config.privateKeyPem);
final token = jwt.sign(key, algorithm: JWTAlgorithm.RS512);
return token;
}
}
私钥不应存储在代码仓库中。
当Halo Dot SDK调用onRequestJWT
时,您应该将生成的JWT传递给回调函数。
JWT生命周期
由于JWT本质上授权特定商户用户进行支付接受,因此应尽可能缩短JWT的有效期,以限制攻击者破解密钥的时间,并在密钥泄露的情况下限制损害范围。
推荐的生命周期为15分钟。
JWT签名公钥格式
JWT公钥应作为证书发布,以文本友好的格式,例如B64编码的PEM(.crt、.pem)。
JWT声明
JWT必须包含以下声明——除了aud_fingerprints
(受众指纹)之外,其他均为标准声明:
字段 | 类型 | 备注 |
---|---|---|
alg | String | 签名算法为RSA签名SHA-256哈希,别名为RS256。需要非对称加密方案以允许Kernel Server验证令牌而不生成它。 |
sub | String | 支付处理器商户用户ID或应用ID |
iss | String | JWT发行者的唯一标识符(从Halo服务器的角度看),由JWT发行者和Synthesis预先协商并在Halo服务器中配置。 |
aud | String | Halo服务器TLS端点的URL,例如kernelserver.qa.haloplus.io 。此值应从Synthesis获取(每个环境不同)。 |
usr | String | 执行交易的用户详细信息,通常是登录到集成商应用程序的用户名。 |
iat | NumericDate | JWT生成的UTC时间戳。 |
exp | NumericDate | JWT的过期UTC时间。 |
aud_fingerprints | String | Kernel Server TLS端点预期的SHA-256指纹的CSV列表。此列表可能包含多个值以支持证书轮换。 |
所有这些值都可以通过向https://kernelserver.qa.haloplus.io/<sdk-version>/tokens/checkjwt
发起请求进行验证。
方法:POST
头部:Bearer Auth
使用
- 首先,您需要请求SDK所需的权限。在您的
AndroidManifest.xml
文件中添加以下权限:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="za.co.synthesis.halo.sdkflutterplugin_example">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<!-- .... -->
</manifest xmlns:android="http://schemas.android.com/apk/res/android">
- 在Flutter应用中添加插件以帮助请求权限。在您的
pubspec.yaml
文件中添加以下内容:
dependencies:
permission_handler: ^11.3.1 # ...
确保在android/app/build.gradle
中,compileSdkVersion
和targetSdkVersion
设置为34
或更高。
记住在更改pubspec.yaml
文件后运行flutter pub get
- 在初始化SDK之前,在Flutter应用中请求权限。这是一个示例(请处理用户拒绝权限的情况):
我们建议创建一个名为permission.dart
的文件来请求所有需要的权限,如下所示:
Future<void> checkPermissions() async {
var permissions = [
Permission.camera,
Permission.bluetoothConnect,
Permission.bluetoothScan,
Permission.location,
];
for (var permission in permissions) {
await requestPermission(permission);
}
}
Future<void> on(Permission permission) async {
var permissionStatus = await permission.status;
if (permissionStatus.isGranted) {
debugPrint("${permission} permission is granted, not requesting");
} else if (permissionStatus.isPermanentlyDenied) {
debugPrint("${permission} permission is permanently denied, enable in settings");
} else {
var requestResult = await permission.request();
if (requestResult.isGranted) {
debugPrint("${permission} permission is granted");
} else if (requestResult.isPermanentlyDenied) {
debugPrint("${permission} permission is permanently denied, enable in settings");
}
}
}
- 您的Android
MainActivity
(通常位于app/src/main/kotlin/
)
例如:
import za.co.synthesis.halo.sdkflutterplugin.HaloActivity
class MainActivity: HaloActivity() {
}
- 在您的Flutter项目中,现在可以使用插件与SDK交互。这是一个示例:
- 首先,您需要在Flutter项目中实现
IHaloCallbacks
接口,以便接收来自SDK的回调。这是一个示例:
// 调用此文件为 halo_sdk.dart
import './jwt_token';
class HaloCallbacks implements IHaloCallbacks {
@override
void onAttestationError(HaloAttestationHealthResult details) {
debugPrint("example app: attestation error: $details");
}
@override
void onHaloTransactionResult(HaloTransactionResult result) {
debugPrint("example app: transaction result: $result");
}
@override
void onHaloUIMessage(HaloUIMessage message) {
debugPrint("example app: UI message: $message");
}
@override
void onInitializationResult(HaloInitializationResult result) {
debugPrint("example app: initialization message: $result");
}
@override
void onRequestJWT(void Function(String jwt) callback) {
debugPrint("example app: onRequestJWT");
// JwtToken 导入自 jwt_token.dart
var jwt = JwtToken.getJwt(); // 您需要传递创建的JWT。
callback(jwt);
}
@override
void onSecurityError(errorCode) {
debugPrint("example app: security error: $errorCode");
}
@override
void onCameraControlLost() {
debugPrint("example app: camera control lost");
}
}
您可以根据SDK通过回调发送的内容决定如何影响UI。
- 接下来,您希望在处理交易的Widget打开时初始化SDK。这是一个示例:
void onInitializeSdk(BuildContext context) {
var haloCallbacks = HaloCallbacks(); // 定义在之前的代码中
String package = "za.co.synthesis.halo.sdkflutterplugin_example";
String appVersion = "0.0.2";
int onStartTransactionTimeOut = 300000;
try {
Sdkflutterplugin.initializeHaloSDK(haloCallbacks, package, appVersion, onStartTransactionTimeOut);
} on PlatformException catch (e) {
String message = "SDK initialisation error: ${e.code} ${e.message}";
setUiMessage(UiMessage(message, Colors.red));
}
}
- 接下来,您可以启动交易。这是一个示例:
Sdkflutterplugin.startTransaction(1.00, 'Some merchant reference', 'ZAR');
从这一点开始,一系列UI消息将被推送到注册的回调中。
您将使用这些消息向用户提供适当的UI/文本。
文档
测试
所有交易在签署保密协议(NDA)之前均无效。
您可以使用虚拟卡(如Vida Mobile CDET)进行测试。
常见问题解答
问题:如何设置我的compileSdkVersion
,如果当前设置为flutter.compileSdkVersion
?
答案:
您可以在local.properties
文件中设置compileSdkVersion
:
sdk.dir=/home/{me}/android-sdk/
flutter.sdk=/home/{me}/fvm/versions/3.27.3
flutter.buildMode=debug
flutter.versionName=1.0.0
flutter.versionCode=1
flutter.compileSdkVersion=34
flutter.minSdkVersion=29
然后在android/app/build.gradle
文件中引用此值:
compileSdkVersion localProperties.getProperty('flutter.compileSdkVersion').toInteger()
更多关于Flutter集成HALO SDK插件halo_sdk_flutter_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter集成HALO SDK插件halo_sdk_flutter_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter项目中集成HALO SDK插件 halo_sdk_flutter_plugin
可以帮助你快速接入HALO平台的功能。下面是一个简单的步骤指南,帮助你开始使用 halo_sdk_flutter_plugin
。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 halo_sdk_flutter_plugin
的依赖。
dependencies:
flutter:
sdk: flutter
halo_sdk_flutter_plugin: ^<version> # 请替换为最新版本
然后,运行 flutter pub get
来获取依赖。
2. 初始化HALO SDK
在你的Flutter应用的 main.dart
文件中,初始化HALO SDK。通常,你可以在 main
函数中进行初始化。
import 'package:flutter/material.dart';
import 'package:halo_sdk_flutter_plugin/halo_sdk_flutter_plugin.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化HALO SDK
await HaloSdkFlutterPlugin.init(
appId: 'your_app_id', // 替换为你的App ID
appKey: 'your_app_key', // 替换为你的App Key
// 其他可选配置
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
3. 使用HALO SDK的功能
根据你的需求,你可以使用 halo_sdk_flutter_plugin
提供的各种功能。以下是一些常见的用法示例:
3.1 用户登录
void loginUser() async {
try {
await HaloSdkFlutterPlugin.login(username: 'user', password: 'password');
print('Login successful');
} catch (e) {
print('Login failed: $e');
}
}
3.2 获取用户信息
void getUserInfo() async {
try {
var userInfo = await HaloSdkFlutterPlugin.getUserInfo();
print('User Info: $userInfo');
} catch (e) {
print('Failed to get user info: $e');
}
}
3.3 发送事件
void sendEvent() async {
try {
await HaloSdkFlutterPlugin.trackEvent(eventName: 'button_click', properties: {'button_id': 'login_button'});
print('Event sent');
} catch (e) {
print('Failed to send event: $e');
}
}
4. 处理回调
你可以通过设置回调来处理一些事件,例如用户登录状态的变化。
void setCallbacks() {
HaloSdkFlutterPlugin.setOnLoginStatusChangedListener((isLoggedIn) {
print('Login status changed: $isLoggedIn');
});
}
5. 处理权限和配置
根据你的应用需求,你可能需要在 AndroidManifest.xml
和 Info.plist
中添加一些权限和配置。
Android
在 android/app/src/main/AndroidManifest.xml
中添加必要的权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
iOS
在 ios/Runner/Info.plist
中添加必要的权限:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
6. 运行应用
完成上述步骤后,你可以运行你的Flutter应用,并测试HALO SDK的功能。
flutter run
7. 调试和日志
你可以启用调试日志来帮助调试。
void enableDebugLogging() {
HaloSdkFlutterPlugin.setDebugEnabled(true);
}
8. 处理错误
在使用过程中,可能会遇到一些错误。你可以通过捕获异常来处理这些错误。
void handleErrors() async {
try {
// 调用HALO SDK的方法
} catch (e) {
print('An error occurred: $e');
}
}