#AC-terminal
1 messages ยท Page 1 of 1 (latest)
Hi there, seems like your android application can't connect to stripe API endpoint. Do you use SSL Pinning in your android app?
I do not think so?
When I am using this new node.js endpoint I made it doesn't work
However when I just use the default heroku library you guys provide it works fine
Sorry that wasn't clear. When I run the default vanilla endpoint that uses ruby on a heroku server as you guys suggest. It works fine. However using my endpoint it fails.
Not sure why
When you say failed, is it about token creation or connection to Stripe?
It's always the connect to stripe
OK, your android app doesn't have the Couldn't connect to Stripe error when using the example code?
yeah
but it's only getting the token so I'm confused
eitherway I'm running:
callback.onSuccess(token)
Here is what I am getting every time:
Can you share with me your merchant ID? you can find it from the Stripe Dashboard -> Settings ->Account Details
Pasting for context:
Wanted to say that my merchant id is the following: acct_1KdIhIIJZpIjm1tz
Here is my merchant id: acct_1KdIhIIJZpIjm1tz
Hi ๐ so can you recap your concern?
So I made my own token provider that points to my own backend. For some reason I am constantly getting the following error:
com.stripe.stripeterminal.external.models.TerminalException: Could not connect to Stripe. Please retry.
However looking at my stripe logs and my run time logs, I am providing the token fine.
When I do not have this issue when I used the supplied example methods that point to a heroku endpoint that is running the also supplied backend
One second I'll send a screen shot of it working
And what function is executing that is returning the "Could not connect to Stripe" error?
It's my readerCallback.onFailure
Terminal.getInstance().connectBluetoothReader(reader,
connectionConfig,
TerminalBluetoothReaderListener(),
readerCallback
)
Hm, thank you . Please bear with me while I think on this.
Thank you
And when you use the Heroku backend, everything works as expected? With the same bluetooth reader?
yes
At the end of the day both my token providers are running:
callback.onSuccess(token)
and I am just logging the token before they execute in both cases
Is that logging done where the tokens are generated, or back in your app to ensure the tokens make it back there?
I am doing the logging in the android app
I am logging it right before I call the callback.onSuccess(token) method
Interesting. And it has the same form as the other tokens you are sending, is being created by the same API key, and all that?
Can you send me a request ID (req_123) from a time you created this token from your own backend?
node.js: const connectionToken = await stripe.terminal.connectionTokens.create();
Can you check your logs for a request from a time you made this token? https://dashboard.stripe.com/test/logs
Here is a working one:
req_vdORAvyKvmHNm3
Sorry I have to hop on a call. I'll be back in 20 minutes
Thank you. Checking these requests out
Those look the same. Looking at the code again to see what might be the difference there.
What does your fetchConnectionToken function look like?
Just for testing purposes: can you try hard coding that function to directly returns that token "pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LHRxVHRnc2Rnc3FMMjc5Rnpqd1ZZU3VYbGdzNmlXNjI_00EIRoQ4AX"?
val jsonO = object : JsonObjectRequest(Method.POST, BuildConfig.BASE_API_URL + Request.Method.STRIPE_TERMINAL_TOKEN_REQ, jsonObject, {
response -> callback.onsuccess(token)
error-> callback.onFailure(ConnectionTokenException("failed to generate token"))
hard coded value works
working!
Awesome! So maybe your actual version of fetchConnectionToken method isn't returning the string as you would expect? I do know I saw a similar issue a day or two back where the user was accidentally returning their entire json instead of just the token string.
Oh wait or is it completely working now?
Can you see any difference in the hard coded string vs what your fetchConnectionToken function returns normally?
I think they are returning the same thing
Hi ๐ I'm stepping in for @spare tulip
The fact that you see different behavior when you hardcode vs use the function suggests they are not. Could you log the value returned and ensure it is exactly what you are hard-coding?
Okay here is something that I generated with my code:
2022-03-29 09:49:47.238 15127-15127/beam.live.ride V/StripeTerminalActivity: Stripe Token: "pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LGJqSlVmNVN1VDB1NHh3VmxFa1VMbnhZU2ZOUzhSYng_00aGOqucwG"
2022-03-29 09:50:06.699 15127-15127/beam.live.ride V/StripeTerminalActivity: Running Discovery
2022-03-29 09:50:11.741 15127-15858/beam.live.ride V/StripeTerminalActivity: onUpdateDiscoveredReadersCB
2022-03-29 09:50:11.741 15127-15858/beam.live.ride V/StripeTerminalActivity: STRM26138029907
2022-03-29 09:50:11.741 15127-15858/beam.live.ride V/StripeTerminalActivity: Trying to connect to reader
2022-03-29 09:50:11.748 15127-15849/beam.live.ride V/StripeTerminalActivity: Discovery Success Callback
2022-03-29 09:50:15.765 15127-15127/beam.live.ride V/StripeTerminalActivity: Stripe Token: "pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LDV4Z2hLcEtjS1ROREVvOWZYRjNHTWNxd0RRa2VtdGI_00oIZwqvOw"
2022-03-29 09:50:17.905 15127-15849/beam.live.ride V/StripeTerminalActivity: fail reader connection
2022-03-29 09:50:17.906 15127-15849/beam.live.ride V/StripeTerminalActivity: com.stripe.stripeterminal.external.models.TerminalException: Could not connect to Stripe. Please retry.
These two lines:
Log.v("StripeTerminalActivity", "Stripe Token: " + token)
callback.onSuccess(token)
Here is log resulting log line showing what the token parameter is
V/StripeTerminalActivity: Stripe Token: "pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LDV4Z2hLcEtjS1ROREVvOWZYRjNHTWNxd0RRa2VtdGI_00oIZwqvOw"
Okay. And this is the exact same token as what you were hard-coding?
No this is a token I'm generating
It is made with this id: req_torxGIU2dHw0ii
pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LDV4Z2hLcEtjS1ROREVvOWZYRjNHTWNxd0RRa2VtdGI_00oIZwqvOw
Okay and when you use this one it doesn't work, correct?
yes
Implementation('com.stripe:stripe-android:19.2.2')
Implementation("com.stripe:stripeterminal:2.7.0")
Okay and you've configured your Terminal Application set up following these docs?
https://stripe.com/docs/terminal/payments/setup-sdk?terminal-sdk-platform=android#connection-token
Specifically I'm interested in the TokenProvider class
Would it be possible to do a quick call with someone to resolve this?
We don't offer calls at this time.
Also if you look at my fail logs from earlier you can see that the sdk is getting the token:
2022-03-29 08:03:08.190 6278-6278/beam.live.ride V/StripeTerminalActivity: Stripe Token: "pst_test_YWNjdF8xS2RJaElJSlpwSWptMXR6LExLbEc5ZWZpdlh4WjlSTDFtQ3A2WVRaaVZEbDFKS0w_00WdtSFV4L"
2022-03-29 08:03:08.191 6278-6278/beam.live.ride D/StripeTerminal: class=ConnectionTokenManager message=fetchConnectionToken.onSuccess
Yes I saw that. So you've getting the token, now we need to make sure it's getting passed to the Terminal SDK
Since the SDK expects to be provided with a Provider, not the actual token, that is why I'm asking if you created the ToeknProvider class and are using it when initializing the Terminal SDK
Yes I did create the clas
Like this code snippet here:
// Create your listener object. Override any methods that you want to be notified about
TerminalListener listener = new TerminalListener() {};
// Choose the level of messages that should be logged to your console
LogLevel logLevel = LogLevel.VERBOSE;
// Create your token provider.
TokenProvider tokenProvider = new TokenProvider();
// Pass in the current application context, your desired logging level, your token provider, and the listener you created
if (!Terminal.isInitialized()) {
Terminal.initTerminal(getApplicationContext(), logLevel, tokenProvider, listener);
}
// Since the Terminal is a singleton, you can call getInstance whenever you need it
Terminal.getInstance();
Or like this (if you use Kotlin)
// Create your listener object. Override any methods that you want to be notified about
val listener = object : TerminalListener {
}
// Choose the level of messages that should be logged to your console
val logLevel = LogLevel.VERBOSE
// Create your token provider.
val tokenProvider = TokenProvider()
// Pass in the current application context, your desired logging level, your token provider, and the listener you created
if (!Terminal.isInitialized()) {
Terminal.initTerminal(applicationContext, logLevel, tokenProvider, listener)
}
// Since the Terminal is a singleton, you can call getInstance whenever you need it
Terminal.getInstance()
Terminal.initTerminal(
applicationContext, LogLevel.VERBOSE, TokenProvider(this), TerminalEventListener()
)
I had to change my tokenProvider to accept a context
I'm sorry this is taking up so much time, I really appreciate your help
Sure thing! So when you say you needed to change you tokenProvider to accept a context, what did that do to the fetchConnectionToken function?
I did not change any of the parameters of the function it is still:
override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
But inside the function I need to access some local parameters for my servers authentication using the auth
Okay so, sorry to harp on this, but can you assign your TokenProvider(this) to a value and log that? I may be paranoid but I always like to check the value is the same inside the function as out.
class TokenProvider(context: Context) : ConnectionTokenProvider {
private val contextRef = WeakReference(context)
Yes I'm saving the paramter
Right, I'm just looking at this snippet you provided:
Terminal.initTerminal(
applicationContext, LogLevel.VERBOSE, TokenProvider(this), TerminalEventListener()
)
And asking if you can do something like
val tP = TokenProvider(this)
Log.d("TerminalTest", tP)
okay will do
I admit it's probably overly cautious but I just want to make we aren't missing something simple
good idea
So this is what I'm going to run
2022-03-29 10:59:46.629 15127-15127/beam.live.ride D/TerminalTest: TokenProvider@84f4cde
What were you hoping to see?
Wait sorry, I think I know what I'm looking for. Can you try
val tP = TokenProvider(this)
Log.d("TerminalTest", tP.fetchConnectionToken())
what should the callback be?
Sorry I've got a working integration that uses the JavaScript SDK. Under the hood they all use the same APIs but sometimes working with the different objects can be tricky
the callback is what returns the connection token string, if successful, or the error message if not
``
val discoveryCallback = object : Callback {
override fun onSuccess() {
Log.v("TerminalTest", " Success Callback")
}
override fun onFailure(e: TerminalException) {
Log.d("TerminalTest", "Fail Callback")
}
}
``
Are we still talking about the callback that is the parameter for the fetchConnectionToken function?
class TokenProvider : ConnectionTokenProvider {
override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
try {
// Your backend should call /v1/terminal/connection_tokens and return the
// JSON response from Stripe. When the request to your backend succeeds,
// return the `secret` from the response to the SDK.
callback.onSuccess(secret)
} catch (e: Exception) {
callback.onFailure(
ConnectionTokenException("Failed to fetch connection token", e)
)
}
}
}
As far as I can tell, the callback is used here to allow for listening to the onSuccess and onFailure events by the SDK while allowing you to define how your application handles those events
So if the code you shared is what the callback in the Token provider is doing, then it isn't returning the token secret when initializing the Terminal SDK.....I think
I am wondering what callback you want me to provide for the test
I haven't gotten anything to work yet
Right...event driven. I'm just trying to figure out how we test, before we initialize the Terminal, whether the onSuccess callback is actually returning the Connection Token secret.
Which is another thing, can you log out the response from your server?
The test just keeps crashing :/
I'm still a little curious why you appear to be abstracting/customizing the callback here. I do not know enough about Android programming to say whether it's a better approach or not, but I know that the TokenProvider.fetchConnectionToken definition above does work.
As a follow up, we do have a complete Kotlin Terminal Example application here: https://github.com/stripe/stripe-terminal-android/tree/master/Example/kotlinapp/src/main/java/com/stripe/example
I haven't been able to dig through the entire thing but you should be able to clone this and get the example app running with a few configuration steps. Personally I found the TokenProvider and ApiClient definitions rather interesting.