tripos_mobile 1.5.1
tripos_mobile: ^1.5.1 copied to clipboard
Flutter plugin for Worldpay triPOS Mobile SDK. Supports Ingenico Bluetooth readers on Android/iOS and Moby 5500 USB on Android.
triPOS Mobile Flutter Plugin #
基于 Worldpay triPOS Mobile SDK 的 Flutter 插件,支持通过 Ingenico 蓝牙读卡器进行移动支付,并支持 Android Moby 5500 USB 直连。
✨ 功能特性 #
| 功能 | Android | iOS | 说明 |
|---|---|---|---|
| 蓝牙扫描连接 | ✅ | ✅ | 设备扫描与连接 |
| Moby 5500 USB 连接 | ✅ | - | 单台设备自动发现,无需蓝牙扫描 |
| 销售 (Sale) | ✅ | ✅ | 刷卡/插卡/NFC 销售 |
| 退款 (Refund) | ✅ | ✅ | 刷卡退款 |
| 关联退款 | ✅ | ✅ | 无需刷卡退款 |
| 作废 (Void) | ✅ | ✅ | 取消已完成交易 |
| 预授权 | ✅ | ✅ | 冻结/完成/增量授权 |
| Token 支付 | ✅ | ✅ | 无卡交易 |
| 离线模式 (S&F) | ✅ | ✅ | 离线存储转发 |
| 自动恢复 | ✅ | - | 网络错误自动重置连接 |
| 蓝牙设备管理 | ✅ | - | 查询系统已连接蓝牙设备、按 MAC 解除配对 |
🚀 快速开始 #
import 'package:tripos_mobile/tripos_mobile.dart';
final tripos = TriposMobile();
// 1. 配置
final config = TriposConfiguration(
hostConfiguration: HostConfiguration(
acceptorId: 'your_acceptor_id',
accountId: 'your_account_id',
accountToken: 'your_account_token',
),
deviceConfiguration: DeviceConfiguration(
deviceType: DeviceType.ingenicoMoby5500,
),
);
// 2. 扫描设备
final devices = await tripos.scanBluetoothDevices(config);
// 3. 初始化连接
await tripos.initialize(config.copyWith(
deviceConfiguration: config.deviceConfiguration.copyWith(
identifier: devices.first,
),
));
// 4. 销售交易
final response = await tripos.processSale(
SaleRequest(transactionAmount: 10.00),
);
if (response.isApproved) {
print('交易成功! ID: ${response.host?.transactionId}, 批准号: ${response.host?.approvalNumber}');
}
Android Moby 5500 USB #
USB 模式不调用 scanBluetoothDevices()。可以先检测物理连接,再由用户确认初始化:
final usbConfig = TriposConfiguration(
hostConfiguration: HostConfiguration(
acceptorId: 'your_acceptor_id',
accountId: 'your_account_id',
accountToken: 'your_account_token',
),
deviceConfiguration: DeviceConfiguration(
deviceType: DeviceType.ingenicoMoby5500,
connectionType: DeviceConnectionType.usb,
identifier: null,
),
);
final devices = await tripos.getConnectedUsbDevices();
if (devices.length == 1) {
var device = devices.single;
if (!device.hasPermission) {
// 只申请 Android USB 权限,不连接或初始化 triPOS。
device = await tripos.requestUsbDevicePermission(device.deviceId);
}
print('连接前读取的 USB 序列号: ${device.serialNumber}');
await tripos.initialize(usbConfig);
}
tripos.usbDeviceEventStream.listen((event) async {
if (event.type == UsbDeviceEventType.attached) {
final device = event.device;
if (device != null && !device.hasPermission) {
final authorized = await tripos.requestUsbDevicePermission(
device.deviceId,
);
print('连接前读取的 USB 序列号: ${authorized.serialNumber}');
}
}
});
requestUsbDevicePermission() 可能显示 Android 系统授权弹窗,但不会连接或初始化 triPOS。授权后可以在连接前读取设备公开的 USB 描述符序列号;部分固件可能不提供该字段,而且它不保证与 triPOS 连接回调中的业务序列号完全一致。
getConnectedUsbDevices() 和 usbDeviceEventStream 表示设备已物理插入,不代表 SDK 已可交易;仍需等待 initialize() 成功。USB 目前仅支持 Android Moby 5500,且一次连接一台设备。Android 设备必须支持 USB Host/OTG,并使用可传输数据的 USB 线。
Android 普通初始化采用 30 秒无有效进度、60 秒共享总预算,首次尝试与最多一次重试共用预算,连接后稳定延迟也计入。失败清理最多额外 5 秒。手动 USB 授权超时为 30 秒,排队初始化另计 120 秒,OTA 沿用原有超时及手动重连行为。
SDK 返回 java.lang.Exception 且完整消息为 Echo command failed, can't connect to device 时,清理成功后等待 1000ms,最多重试一次。取消、OTA、超时、清理失败及带嵌套异常原因的情况仍不重试;Echo command timeout 和 Echo command suspended 不在本次新增范围内。重试失败仍返回 SDK 原始错误文本。真实 OperationNotAllowedException 的“仍在反初始化”和“已初始化”两条准确消息也纳入白名单,仍须确认正常释放后才重试一次。
同一 Android isolate 内的实例共享初始化队列,相邻同配置请求合并,不同配置按顺序执行。显式反初始化取消活动及排队初始化,返回 INIT_CANCELLED。本次不增加交易期间的忙拦截,也不改变网络错误恢复与交易重试。
释放超时不代表设备已释放。Android Moby 5500 USB 会话在初始化中断后,如果 SDK 反初始化已正常返回、但 Reader 仍保留连接状态,下一次点击连接(调用 initialize(),目标可为 USB 或蓝牙)会等待原释放结果,再尝试一次最多额外 5 秒的受控恢复。恢复使用旧会话捕获的 USB 通信适配器执行取消连接和关闭,绕过 RUA 在首次释放后再次 release() 不产生完成回调的问题。须确认适配器关闭方法返回、独立关闭回调成功、底层连接已断开、通信管理器未初始化、设备管理器不再就绪以及 SDK 未初始化;旧 Reader、管理器和适配器身份一致时才同步 Reader 状态,并在复核通过后开始本次连接。
此恢复仅适配 triPOS 4.7.0 / RUA 2.6.4.2,不用于 OTA、交易或交易清理未结束、扫描未结束、其他 Engine 的会话、SDK 反初始化异常或调用阻塞。重复连接不会重叠执行底层释放。取消或销毁 Engine 会取消待连接请求;恢复超时后晚到成功只解除旧会话门禁,需要再次点击连接,不会自动重放连接或支付交易。设备插入本身不触发插件自动重连。
当前退款、Token 等 SDK 接口尚无统一的交易清理完成证据。因此,只要旧会话期间任一 Engine 调用过交易、交易取消或 Store and Forward 接口,该会话只走正常释放;正常释放失败时不启用额外恢复,即使业务结果已返回也不放行。诊断字段 transactionCleanupUnproven=true 表示这一保守限制。正常连接但未调用上述接口的 USB 会话仍可使用恢复路径。
无法确认释放时仍返回 SDK_SESSION_UNAVAILABLE;真正的底层阻塞仍可能需要重启应用进程。错误 details 提供操作编号、释放阶段、原因、耗时、恢复次数、SDK 调用是否返回、Reader 状态和 canRetry;另含 transportRecoveryStage、transportRecoveryReason、adapterConnected 与 communicationInitialized,用于区分关闭未完成、传输仍活动和对象已替换。canRetry=false 也可能表示原释放尚未结束,并非永久不可恢复。初始化原始失败仍可能带 cleanupErrorCode。该路径已提供真实 AAR 及自动化回归验证,生产 APK 的 USB 拔插循环仍需实机验收,不能仅凭单元测试认定所有现场故障均可恢复。
📖 详细文档 #
| 文档 | 说明 |
|---|---|
| 安装配置 | Android/iOS 配置、权限设置 |
| 配置说明 | 所有配置选项详解 |
| 基础交易 | 销售、退款、作废、预授权 |
| Token 支付 | Token 创建、销售、退款 |
| 离线存储转发 | Store-and-Forward 功能 |
| 蓝牙设备管理 | 查询系统已连接蓝牙设备、按 MAC 解除配对 |
| 状态与事件 | 交易状态、设备事件监听 |
| 故障排除 | 常见问题及解决方案 |
📋 API 概览 #
核心方法 #
| 方法 | 说明 |
|---|---|
scanBluetoothDevices(config) |
扫描附近的蓝牙支付设备 |
getConnectedUsbDevices() |
初始化前查询已插入的 Moby 5500(Android) |
requestUsbDevicePermission(deviceId) |
初始化前申请 USB 权限并读取设备描述信息(Android) |
initialize(config) |
初始化 SDK 并连接设备 |
deinitialize() |
断开设备并释放资源 |
cancelTransaction() |
取消当前交易 |
getDeviceInfo() |
获取已连接设备信息 |
getConnectedBluetoothDevices() |
获取系统当前已连接蓝牙设备列表(Android) |
unpairBluetoothDevice(macAddress) |
按 MAC 地址解除蓝牙配对(Android) |
isDeviceConnected() |
检查设备当前连接状态 |
usbDeviceEventStream |
监听 Moby 5500 USB 物理插拔(Android) |
交易方法 #
| 方法 | 说明 |
|---|---|
processSale(request) |
销售交易 |
processRefund(request) |
退款交易 (需刷卡) |
processLinkedRefund(request) |
关联退款 (无需刷卡) |
processVoid(request) |
作废交易 |
processAuthorization(request) |
预授权 |
processAuthorizationCompletion(request) |
预授权完成 |
processIncrementalAuthorization(request) |
增量授权 |
processReversal(request) |
交易冲正 |
Token 方法 #
| 方法 | 说明 |
|---|---|
createToken(request) |
刷卡创建 Token |
createTokenWithTransactionId(request) |
从交易 ID 创建 Token |
processSaleWithToken(request) |
Token 销售 |
processRefundWithToken(request) |
Token 退款 |
processAuthorizationWithToken(request) |
Token 预授权 |
离线交易方法 #
| 方法 | 说明 |
|---|---|
getAllStoredTransactions() |
获取所有存储交易 |
getStoredTransactionsWithState(state) |
按状态筛选存储交易 |
getStoredTransactionByTpId(tpId) |
按 ID 获取存储交易 |
deleteStoredTransaction(tpId) |
删除存储交易 |
manuallyForwardTransaction(request) |
手动转发交易 |
事件流 #
| 流 | 说明 |
|---|---|
statusStream |
交易状态更新 (Stream<VtpStatus>) |
deviceEventStream |
设备连接事件 (Stream<DeviceEvent>) |
📱 支持的设备 #
- Ingenico Moby 5500(Android 支持 Bluetooth 和 USB;iOS 支持 Bluetooth)
- Ingenico Moby 8500
- Lane 3000/5000/7000/8000:Android 暂不支持,待验证;仅保留枚举
Android triPOS Mobile SDK
4.7.0已移除 BBPOS 2XBT/3XBT 支持。Dart 里的旧枚举仅用于源码兼容,不应再用于 Android 初始化。
💡 示例应用 #
查看 example/lib/main.dart 获取完整示例。
cd example
flutter run
📄 许可证 #
本插件基于 Worldpay triPOS Mobile SDK 开发,使用需遵守 Worldpay 许可协议。
🤝 贡献 #
欢迎提交 Issue 和 Pull Request!