更改 Stripe 终端中的连接令牌

问题描述 投票:0回答:1

我们在应用程序中使用了超过 1 个条带帐户,当我尝试在应用程序中切换帐户时,在调用 Terminal.initTerminal() 之前,我正在做:

Terminal.getInstance().clearCachedCredentials(); 我断开读卡器的连接 当我尝试 Terminal.initTerminal() 时,无法初始化终端,然后它显示异常/错误:

java.lang.IllegalStateException:只能在第一次请求 Terminal 实例之前调用 initTerminal。如果您尝试在应用程序中切换帐户,请参阅clearCachedCredentials 方法的文档。 不知道这是否是一个问题,或者 stripe 是否不允许我们在应用程序内更改帐户。

我想知道有什么方法可以更新连接令牌。如果有人知道,请告诉我。我花了很多时间在这上面。谢谢你

我已经看到了:https://github.com/stripe/stripe-terminal-android/issues/88。但我无法解决问题

我的代码=

 private fun initializeTerminal(idUserAppInstitution: Int, token: String, result: MethodChannel.Result) {
        // Set the token globally in ApiClient
        ApiClient.setToken(token)
        val tokenProvider = TokenProvider(idUserAppInstitution)
        if (!Terminal.isInitialized()) {
            try {
                // Initialize the terminal, passing the idUserAppInstitution to TokenProvider
                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")
        }
    }
    
    
    package com.example.np_casse

import android.util.Log  // Import the Log class for debugging purposes
import com.stripe.stripeterminal.external.callable.ConnectionTokenCallback
import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider
import com.stripe.stripeterminal.external.models.ConnectionTokenException
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class TokenProvider(private val idUserAppInstitution: Int) : ConnectionTokenProvider {
    // Override the fetchConnectionToken method
    override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
        // Use ApiClient directly to get the service
        val backendService = ApiClient.service

        // Call the getConnectionToken method from the BackendService
        backendService.getConnectionToken(idUserAppInstitution).enqueue(object : Callback<ConnectionToken> {
            override fun onResponse(call: Call<ConnectionToken>, response: Response<ConnectionToken>) {
                if (response.isSuccessful) {
                    val connectionToken = response.body()
                    if (connectionToken != null && connectionToken.secret != null) {
                        // Log the response for debugging
                        Log.d("TokenProvider", "Successfully fetched connection token: ${connectionToken.secret}")
                        callback.onSuccess(connectionToken.secret)
                    } else {
                        val errorMessage = "Response body or secret is null"
                        Log.e("TokenProvider", errorMessage)
                        callback.onFailure(ConnectionTokenException(errorMessage))
                    }
                } else {
                    // Capture detailed error info from the response
                    val errorMessage = response.errorBody()?.string() ?: "Unknown error"
                    val statusCode = response.code()
                    Log.e("TokenProvider", "Error fetching connection token. Status: $statusCode, Error: $errorMessage")
                    callback.onFailure(ConnectionTokenException("Failed to fetch connection token: $errorMessage"))
                }
            }

            override fun onFailure(call: Call<ConnectionToken>, t: Throwable) {
                // Handle network or other failures
                Log.e("TokenProvider", "Network failure: ${t.message}", t)
                callback.onFailure(ConnectionTokenException("Failed to fetch connection token: ${t.message}"))
            }
        })
    }

}
android stripe-payments
1个回答
0
投票

可以通过使用装饰器模式来完成。我们可以使用允许动态更改提供者的包装类。

更新代码:

令牌提供者类:

package com.example.np_casse

import android.util.Log
import com.stripe.stripeterminal.external.callable.ConnectionTokenCallback
import com.stripe.stripeterminal.external.callable.ConnectionTokenProvider
import com.stripe.stripeterminal.external.models.ConnectionTokenException
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

// Your original TokenProvider that fetches the connection token
class TokenProvider(private val idUserAppInstitution: Int) : ConnectionTokenProvider {

    override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
        val backendService = ApiClient.service

        // Call to the backend to get the connection token
        backendService.getConnectionToken(idUserAppInstitution).enqueue(object : Callback<ConnectionToken> {
            override fun onResponse(call: Call<ConnectionToken>, response: Response<ConnectionToken>) {
                if (response.isSuccessful) {
                    val connectionToken = response.body()
                    if (connectionToken != null && connectionToken.secret != null) {
                        Log.d("TokenProvider", "Successfully fetched connection token: ${connectionToken.secret}")
                        callback.onSuccess(connectionToken.secret)
                    } else {
                        val errorMessage = "Response body or secret is null"
                        Log.e("TokenProvider", "$errorMessage. Response body: $connectionToken")
                        callback.onFailure(ConnectionTokenException(errorMessage))
                    }
                } else {
                    val errorMessage = response.errorBody()?.string() ?: "Unknown error"
                    val statusCode = response.code()
                    Log.e("TokenProvider", "Error fetching connection token. Status: $statusCode, Error: $errorMessage")
                    callback.onFailure(ConnectionTokenException("Failed to fetch connection token: Status: $statusCode, Error: $errorMessage"))
                }
            }

            override fun onFailure(call: Call<ConnectionToken>, t: Throwable) {
                Log.e("TokenProvider", "Network failure: ${t.message}", t)
                callback.onFailure(ConnectionTokenException("Failed to fetch connection token: ${t.message}"))
            }
        })
    }
}

// This is a wrapper class that allows dynamic changes to the provider
class VariableConnectionTokenProvider(var provider: ConnectionTokenProvider) : ConnectionTokenProvider {
    override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
        provider.fetchConnectionToken(callback)
    }
}

初始化终端代码:

    private var variableConnectionTokenProvider: VariableConnectionTokenProvider? = null // No default initialization
    
     private fun initializeTerminal(idUserAppInstitution: Int, token: String, result: MethodChannel.Result) {
        // Set the token globally in ApiClient
        ApiClient.setToken(token)
        val tokenProvider = TokenProvider(idUserAppInstitution)

        if (!Terminal.isInitialized()) {
            try {
                variableConnectionTokenProvider = VariableConnectionTokenProvider(tokenProvider)
                // Initialize the terminal, passing the idUserAppInstitution to TokenProvider
                Terminal.initTerminal(applicationContext, LogLevel.VERBOSE, variableConnectionTokenProvider!!, TerminalEventListener())
                terminalInitialized = true
                result.success("Stripe Initialized")
            } catch (e: TerminalException) {
                terminalInitialized = false
                result.error("INITIALIZATION_ERROR", "Error initializing Terminal: ${e.message}", null)
            }
        } else { 
            if (variableConnectionTokenProvider != null) {
                    // Safely update the provider
                    variableConnectionTokenProvider!!.provider = tokenProvider
                    terminalInitialized = true
                    result.success("Stripe Already Initialized")
                } else {
                    // Handle the rare case where the provider is null unexpectedly
                    result.error(
                        "PROVIDER_ERROR", 
                        "Connection token provider is not initialized.", 
                        null
                    )
                }          
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.