我们在应用程序中使用了超过 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}"))
}
})
}
}
可以通过使用装饰器模式来完成。我们可以使用允许动态更改提供者的包装类。
更新代码:
令牌提供者类:
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
)
}
}
}