triPOS Mobile Flutter Plugin

Platform Flutter

基于 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!

Libraries

firmware_update_ui
models/configuration
Configuration models for triPOS Mobile SDK
models/device_interaction_request
models/enums
models/firmware_update
models/requests
Request models for triPOS Mobile SDK transactions
models/responses
Response models for triPOS Mobile SDK transactions
models/usb_device
tripos_mobile
triPOS Mobile SDK Flutter Plugin
tripos_mobile_method_channel
tripos_mobile_platform_interface