1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

[Flutter] Stripe terminal Wisepad 3 reader not get detected in android Flutter

Discussão em 'Mobile' iniciado por Stack, Novembro 13, 2024.

  1. Stack

    Stack Membro Participativo

    I am working with stripe terminal android SDK https://docs.stripe.com/terminal/quickstart?reader=wp3 in flutter because there is no SDK available for Flutter. I am trying for many days. Stripe terminal got initialized but it is not detecting Wisepad 3 reader.

    Flutter code =

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';

    class BluetoothConfigurationScreen extends StatefulWidget {
    const BluetoothConfigurationScreen({super.key});

    @override
    State<BluetoothConfigurationScreen> createState() =>
    _BluetoothConfigurationScreenState();
    }

    class _BluetoothConfigurationScreenState
    extends State<BluetoothConfigurationScreen> {
    static const platform = MethodChannel('com.example.case/stripe');
    TextEditingController textEditingController = TextEditingController();
    String resultText = '';
    String _batteryLevel = 'Unknown battery level.';
    String _cardInfo = 'No card scanned';
    String _connectedDeviceInfo = 'No device connected';
    bool isTerminalInitialized = false;
    bool isReaderConnected = false;

    // Method to initialize Stripe terminal
    Future<void> _initializeStripe() async {
    try {
    // Initialize the Stripe terminal by invoking the method on the native side
    final result = await platform.invokeMethod('initializeStripe');
    setState(() {
    isTerminalInitialized = true; // Mark terminal as initialized
    });
    print(result);
    } catch (e) {
    setState(() {
    isTerminalInitialized = false; // Handle initialization failure
    });
    print("Error initializing terminal: $e");
    }
    }

    // Method to get battery level
    Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
    final result = await platform.invokeMethod<int>('getBatteryLevel');
    batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
    batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
    _batteryLevel = batteryLevel;
    });
    }

    // Method to start card scan
    Future<void> _startCardScan() async {
    if (!isTerminalInitialized || !isReaderConnected) {
    setState(() {
    _cardInfo = 'Terminal or Reader is not connected. Please initialize and connect first.';
    });
    return;
    }

    try {
    final cardData = await platform.invokeMethod('scanCard');
    setState(() {
    _cardInfo = cardData;
    });
    } catch (e) {
    setState(() {
    _cardInfo = 'Error scanning card: $e';
    });
    }
    }

    // Method to discover Bluetooth devices and fetch connected device info
    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 = true; // Assuming reader is connected after discovery
    });

    // Fetch connected device info
    final connectedDevice = await platform.invokeMethod('getConnectedDeviceInfo');
    setState(() {
    _connectedDeviceInfo = connectedDevice ?? 'No connected device information available';
    });
    } catch (e) {
    setState(() {
    _cardInfo = 'Error discovering readers: $e';
    isReaderConnected = false;
    _connectedDeviceInfo = 'Error fetching connected device info';
    });
    }
    }

    // Method to make a 0.1 cent payment
    Future<void> _makePayment() async {
    if (!isTerminalInitialized || !isReaderConnected) {
    setState(() {
    _cardInfo = 'Terminal or Reader is not connected. Please initialize and connect first.';
    });
    return;
    }

    try {
    final paymentResult = await platform.invokeMethod('makePayment');
    setState(() {
    _cardInfo = paymentResult;
    });
    } catch (e) {
    setState(() {
    _cardInfo = 'Error processing payment: $e';
    });
    }
    }

    @override
    void dispose() {
    textEditingController.dispose();
    super.dispose();
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    children: [
    ElevatedButton(
    onPressed: () async {
    await _initializeStripe(); // Initialize Stripe Terminal
    if (isTerminalInitialized) {
    setState(() {
    _cardInfo = "Terminal Initialized. You can now scan cards.";
    });
    } else {
    setState(() {
    _cardInfo = "Initialization failed. Try again.";
    });
    }
    },
    child: const Text("Initialize Stripe Terminal"),
    ),
    const SizedBox(height: 30),
    ElevatedButton(
    onPressed: _getBatteryLevel,
    child: const Text('Get Battery Level'),
    ),
    Text(_batteryLevel),
    const SizedBox(height: 30),
    ElevatedButton(
    onPressed: _startCardScan, // Trigger card scan
    child: const Text('Scan Card'),
    ),
    Text(_cardInfo), // Display scanned card information
    const SizedBox(height: 30),
    ElevatedButton(
    onPressed: _discoverReaders, // Discover Bluetooth readers
    child: const Text('Discover Bluetooth Readers'),
    ),
    Text(_cardInfo), // Display reader information
    Text('Connected Device Info: $_connectedDeviceInfo'), // Display connected device info
    const SizedBox(height: 30),
    ElevatedButton(
    onPressed: _makePayment, // Trigger payment of 0.1 cent
    child: const Text('Make 0.1 Cent Payment'),
    ),
    Text(_cardInfo), // Display payment result
    const SizedBox(height: 30),
    Padding(
    padding: const EdgeInsets.symmetric(horizontal: 30),
    child: TextField(
    controller: textEditingController,
    decoration: const InputDecoration(
    labelText: 'Enter UserName',
    ),
    ),
    ),
    const SizedBox(height: 30),
    ElevatedButton(
    onPressed: () async {
    final userName = textEditingController.text;
    await callNativeCode(userName);
    setState(() {});
    },
    child: const Text('Send Data'),
    ),
    Text(resultText),
    ],
    ),
    ),
    );
    }

    // Method to send user data to the native code
    Future<void> callNativeCode(String userName) async {
    try {
    resultText =
    await platform.invokeMethod('userName', {'username': userName});
    setState(() {});
    } catch (e) {
    print("Failed to send user data: $e");
    }
    }
    }


    Android code =

    package com.example.np_casse

    import android.Manifest
    import android.content.Context
    import android.content.pm.PackageManager
    import android.os.BatteryManager
    import androidx.annotation.NonNull
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat
    import io.flutter.embedding.android.FlutterActivity
    import io.flutter.embedding.engine.FlutterEngine
    import io.flutter.plugin.common.MethodChannel
    import com.stripe.stripeterminal.Terminal
    import com.stripe.stripeterminal.external.callable.*
    import com.stripe.stripeterminal.external.models.*
    import com.stripe.stripeterminal.log.LogLevel
    import android.util.Log
    import com.stripe.stripeterminal.external.models.Reader

    class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.case/stripe"
    private var terminalInitialized = false

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)

    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
    when (call.method) {
    "initializeStripe" -> initializeTerminal(result)
    "discoverReaders" -> {
    if (terminalInitialized) {
    discoverReaders(result)
    } else {
    result.error("TERMINAL_NOT_INITIALIZED", "Terminal must be initialized first", null)
    }
    }
    "scanCard" -> {
    if (terminalInitialized) {
    startCardScan(result)
    } else {
    result.error("TERMINAL_NOT_INITIALIZED", "Terminal must be initialized first", null)
    }
    }
    "makePayment" -> {
    if (terminalInitialized) {
    makePayment(result)
    } else {
    result.error("TERMINAL_NOT_INITIALIZED", "Terminal must be initialized first", null)
    }
    }
    "getBatteryLevel" -> getBatteryLevel(result)
    "getConnectedDeviceInfo" -> getConnectedDeviceInfo(result) // Fetch device info
    else -> result.notImplemented()
    }
    }
    }

    private fun initializeTerminal(result: MethodChannel.Result) {
    if (!Terminal.isInitialized()) {
    try {
    Terminal.initTerminal(applicationContext, LogLevel.VERBOSE, TokenProvider(), TerminalEventListener())
    terminalInitialized = true
    result.success("Stripe Initialized")
    } catch (e: TerminalException) {
    terminalInitialized = false
    result.error("INITIALIZATION_ERROR", "Error initializing Terminal: ${e.message}", null)
    }
    } else {
    terminalInitialized = true
    result.success("Stripe Already Initialized")
    }
    }

    private fun discoverReaders(result: MethodChannel.Result) {
    if (checkLocationPermissions() && checkBluetoothPermissions()) {
    val discoveryConfig = DiscoveryConfiguration.BluetoothDiscoveryConfiguration(isSimulated = false)
    val discoveryCallback = object : Callback {
    override fun onSuccess() {
    result.success("Reader discovery started")
    }

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

    val discoveryListener = object : DiscoveryListener {
    override fun onUpdateDiscoveredReaders(readers: List<Reader>) {
    if (readers.isEmpty()) {
    result.success("No readers detected.")
    } else {
    for (reader in readers) {
    result.success("Reader found: ${reader.label}")
    }
    }
    }
    }

    Terminal.getInstance().discoverReaders(discoveryConfig, discoveryListener, discoveryCallback)
    } else {
    requestPermissions()
    }
    }

    // New method to get connected device info
    private fun getConnectedDeviceInfo(result: MethodChannel.Result) {
    val reader: Reader? = Terminal.getInstance().connectedReader
    if (reader != null) {
    val deviceInfo = "Label: ${reader.label}, Serial Number: ${reader.serialNumber}"
    result.success(deviceInfo)
    } else {
    result.success("No reader connected")
    }
    }

    private fun startCardScan(result: MethodChannel.Result) {
    val reader = Terminal.getInstance().connectedReader
    if (reader != null) {
    val paymentIntentParams = PaymentIntentParameters.Builder(listOf(PaymentMethodType.CARD_PRESENT))
    .setAmount(1)
    .setCurrency("usd")
    .build()

    Terminal.getInstance().createPaymentIntent(paymentIntentParams, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    Terminal.getInstance().collectPaymentMethod(paymentIntent, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    Terminal.getInstance().confirmPaymentIntent(paymentIntent, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    result.success("Payment Successful")
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_CONFIRM_ERROR", "Error confirming payment: ${e.message}", null)
    }
    })
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_METHOD_ERROR", "Error collecting payment method: ${e.message}", null)
    }
    })
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_INTENT_ERROR", "Error creating payment intent: ${e.message}", null)
    }
    })
    } else {
    result.error("NO_READER", "No reader connected", null)
    }
    }

    private fun makePayment(result: MethodChannel.Result) {
    val reader = Terminal.getInstance().connectedReader
    if (reader != null) {
    val paymentIntentParams = PaymentIntentParameters.Builder(listOf(PaymentMethodType.CARD_PRESENT))
    .setAmount(1)
    .setCurrency("usd")
    .build()

    Terminal.getInstance().createPaymentIntent(paymentIntentParams, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    Terminal.getInstance().collectPaymentMethod(paymentIntent, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    Terminal.getInstance().confirmPaymentIntent(paymentIntent, object : PaymentIntentCallback {
    override fun onSuccess(paymentIntent: PaymentIntent) {
    result.success("Payment Successful")
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_CONFIRM_ERROR", "Error confirming payment: ${e.message}", null)
    }
    })
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_METHOD_ERROR", "Error collecting payment method: ${e.message}", null)
    }
    })
    }

    override fun onFailure(e: TerminalException) {
    result.error("PAYMENT_INTENT_ERROR", "Error creating payment intent: ${e.message}", null)
    }
    })
    } else {
    result.error("NO_READER", "No reader connected", null)
    }
    }

    private fun getBatteryLevel(result: MethodChannel.Result) {
    val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
    val batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    result.success(batteryLevel)
    }

    private fun checkLocationPermissions(): Boolean {
    return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
    }

    private fun checkBluetoothPermissions(): Boolean {
    return ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED
    }

    private fun requestPermissions() {
    ActivityCompat.requestPermissions(
    this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.BLUETOOTH), 1
    )
    }
    }


    I tried different things but I am not able to find any solution. If someone had faces same issue and knows how to fix it then please let me know. Thank you

    Continue reading...

Compartilhe esta Página