You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter通过MethodChannel集成Stripe Terminal Android SDK时无法检测到Wisepad 3读卡器

Flutter通过MethodChannel集成Stripe Terminal Android SDK时无法检测到Wisepad 3读卡器

看起来你已经把Stripe Terminal的基础集成框架搭起来了,但卡在Wisepad 3读卡器的检测环节,我帮你梳理几个核心问题点和对应的修复方案:


1. Android 12+蓝牙权限缺失(最常见原因)

你的代码里只请求了基础的BLUETOOTH权限,但Android 12及以上系统对蓝牙权限做了细分,需要额外申请BLUETOOTH_SCAN和BLUETOOTH_CONNECT权限,同时位置权限的检查逻辑也需要适配版本:

第一步:更新AndroidManifest.xml

在AndroidManifest.xml中添加完整权限声明:

<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

第二步:修复权限检查逻辑

修改Android端的checkBluetoothPermissions方法,适配不同系统版本:

private fun checkBluetoothPermissions(): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED
    } else {
        ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED
    }
}

2. 读卡器发现逻辑的BUG

你的discoverReaders方法存在两个关键问题:

  • 每次发现读卡器就调用result.success(),导致MethodChannel只能接收第一个结果,后续发现的读卡器会被忽略
  • 只启动了发现流程,但没有主动尝试连接Wisepad 3

修改Android端的discoverReaders方法,改为收集所有读卡器并主动连接目标设备:

private fun discoverReaders(result: MethodChannel.Result) {
    if (checkLocationPermissions() && checkBluetoothPermissions()) {
        val discoveryConfig = DiscoveryConfiguration.BluetoothDiscoveryConfiguration(isSimulated = false)
        val discoveryCallback = object : Callback {
            override fun onSuccess() {
                // 发现流程启动成功,等待读卡器回调
            }

            override fun onFailure(e: TerminalException) {
                result.error("DISCOVERY_ERROR", e.message, null)
            }
        }

        val discoveryListener = object : DiscoveryListener {
            override fun onUpdateDiscoveredReaders(readers: List<Reader>) {
                if (readers.isNotEmpty()) {
                    // 查找Wisepad 3(根据label或序列号匹配)
                    val wisepadReader = readers.firstOrNull { 
                        it.label.contains("Wisepad 3", ignoreCase = true) 
                    }
                    wisepadReader?.let {
                        // 主动连接找到的Wisepad 3
                        Terminal.getInstance().connectReader(it, object : ReaderCallback {
                            override fun onSuccess(reader: Reader) {
                                result.success("成功连接到Wisepad 3: ${reader.label}")
                            }

                            override fun onFailure(e: TerminalException) {
                                result.error("CONNECT_ERROR", "连接读卡器失败: ${e.message}", null)
                            }
                        })
                    } ?: run {
                        // 没找到Wisepad 3,返回所有发现的设备
                        val readerList = readers.joinToString(", ") { it.label }
                        result.success("发现读卡器:$readerList,但未找到Wisepad 3,请检查设备是否处于配对模式")
                    }
                } else {
                    result.success("未发现任何读卡器,请确保Wisepad 3长按电源键进入配对模式(指示灯蓝红闪烁)")
                }
            }
        }

        Terminal.getInstance().discoverReaders(discoveryConfig, discoveryListener, discoveryCallback)
    } else {
        requestPermissions()
        result.error("PERMISSION_MISSING", "需要授予位置和蓝牙权限才能搜索读卡器", null)
    }
}

3. Flutter端连接状态判断修正

不要假设发现流程成功就标记读卡器已连接,应该根据Android端返回的连接结果来更新状态:

Future<void> _discoverReaders() async {
  if (!isTerminalInitialized) {
    setState(() {
      _cardInfo = 'Terminal is not initialized yet. Please initialize first.';
    });
    return;
  }

  try {
    final result = await platform.invokeMethod('discoverReaders');
    setState(() {
      _cardInfo = result;
      // 只有连接成功才标记为已连接
      isReaderConnected = result.contains("成功连接到Wisepad 3");
    });

    // 连接成功后再获取设备信息
    if (isReaderConnected) {
      final connectedDevice = await platform.invokeMethod('getConnectedDeviceInfo');
      setState(() {
        _connectedDeviceInfo = connectedDevice ?? 'No connected device information available';
      });
    } else {
      setState(() {
        _connectedDeviceInfo = 'No reader connected';
      });
    }
  } catch (e) {
    setState(() {
      _cardInfo = 'Error discovering readers: $e';
      isReaderConnected = false;
      _connectedDeviceInfo = 'Error fetching connected device info';
    });
  }
}

4. 额外检查点

  • 确保Wisepad 3处于配对模式:长按电源键3-5秒,直到指示灯蓝红交替闪烁
  • 测试设备蓝牙功能正常,能搜索到其他蓝牙设备
  • 确认Stripe后台已注册该Wisepad 3读卡器,并且你的API密钥拥有对应权限
  • 检查TokenProvider是否返回有效的连接令牌,无效令牌会影响读卡器发现流程

备注:内容来源于stack exchange,提问作者sai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:03:11