#radu-m_api
1 messages ยท Page 1 of 1 (latest)
๐ Welcome to your new thread!
โฒ๏ธ We'll be here soon! Typically we respond in a few minutes, but sometimes we might take a bit longer if the server is busy or if you have a particularly tricky question.
โฑ๏ธ We close idle threads, which makes them read-only. Once a thread is closed it won't be reopened, but you can always start a new thread if you have another question.
๐ This thread will always be available, even after it's closed. You can find it again using Discord's search, or you can save this link: https://discord.com/channels/841573134531821608/1499015001749327913
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Hello
sure, pasting it now:
The offline reader doesn't get disconnected, even after the token refresh times out.
Because of that, the device remains offline and doesn't take transactions online, nor does it send the offline stored transactions.
This is a change compared to Stripe Terminal Android SDK, v4.7.3 that we were using before.
In that version, once the device went online (after being offline), the reader was disconnected immediately.
Then we got the same timeout, but because the reader was disconnected, our app attempted to re-discover and re-connect to the handoff reader.
Hey! Taking over for my colleague. Let me catch up.
Let me catch up here and better understand your integration. You are using Apps on device with an S700 right ?
Yes
Can you share what guide you are following exactly ?
https://docs.stripe.com/terminal/features/apps-on-devices/build#discover-and-connect-a-reader
Why the need for the Connection token in this case ?
Are your referring to this section? :
In version 5.0.0 of the Android SDK, you can use the easyConnect method to combine reader discovery and connection into a single API call to simplify integration. See the SDK migration guide for details.
That's an new method to combine discovery and connect to the reading on a single call
the device waits for ~3 minutes to retrieve the token from the backend
I'm referring to this part, what token and what backend are you referring to here ?
We are using Stripe Connect.
I am now trying to find the Stripe documentation page where the reader connection token process is described.
Regardless of using Connection here, if you want to discover and connect your apps-in-device to the host S700 reader, you need to follow the guide I shared above
I found the documentation page:
https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=android&lang-android=java
We have 1300 S700 devices in production, and have now upgraded to the latest Stripe Terminal version (v5.4.1)
With this SDK, whever a device comes online (after being offline), the device remains offline, no transactions are taken online, and the stored offline transactions are not forwarded online.
The guide you provided is probably correct, but from what I can tell, is not enough to fully configure and initialize Terminal.
This isn't an apps- on device. Can you first confirm what integration are you doing here?
So you have an Android device (acting as a Point of Sales) and a reader S700 ?
Hmm, I was under the impression that this is what we are using: Apps-on-Devices. We have our own Android app running on an S700, integrating with Stripe Terminal SDK.
By looking over the documentation you provided, this is what we have: Point of sale app on a Stripe smart reader
If you are using Apps-on-Devices then you are following the wrong guide. The Apps-on-device guide is this one:
https://docs.stripe.com/terminal/features/apps-on-devices/build#discover-and-connect-a-reader
And you don't need a connection token here
OK, let's then suppose it's not Apps-on-Devices, but a regular Android integration.
What you're saying is that this Android integration would require a connection token, but it's intended to be used when you have your own Android device, and a separate Stripe Reader?
OK, let's then suppose it's not Apps-on-Devices, but a regular Android integration.
Sorry, we need to confirm what integration you are using, because these are completly different integrations.
What you're saying is that this Android integration would require a connection token, but it's intended to be used when you have your own Android device, and a separate Stripe Reader?
Yes you need to generate a connection token if you have an Android device that will tries to connect to a S700 reader (via bluetooth or internet)
The issue with the "Apps-on-Devices" is that is requires a locationId to discover the reader.
Our devices don't have this locationId.
With the regular Android integration (https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=android) you don't need a locationId to connect to a reader. You get a connection token from your backend, that can be used for readers in any locations.
OK, to clarify, we are using the https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=android integration, not Apps-on-Devices.
The issue with the "Apps-on-Devices" is that is requires a locationId to discover the reader.
Our devices don't have this locationId.
Even with the other integration you'll need a Location Id
https://docs.stripe.com/terminal/payments/connect-reader?terminal-sdk-platform=android&reader-type=bluetooth#connect-reader
you don't need a locationId to connect to a reader. You get a connection token from your backend, that can be used for readers in any locations.
That's for setting the terminal SDK, but when you connect to the reader you'll need a location Id
What guide are you following to connect to a reader ?
This is how I discover and connect to a reader: https://docs.stripe.com/terminal/features/apps-on-devices/build?lang-android=java#discover-and-connect-a-reader
You are mixing two integrations here. This isn't correct. You should follow the same integration flow from the begining to the end.
If you are doing apps-on-devices then you need to use the apps-on-devices flow.
Also, where are you seeing the usage of Location Id here?
https://docs.stripe.com/terminal/features/apps-on-devices/build#discover-and-connect-a-reader
I see that the locationId is marked as "@Nullable" in this method:
the Apps-on-Devices documentation you shared contains this section:
https://docs.stripe.com/terminal/features/apps-on-devices/build?lang-android=java#configure-your-application
when you click on "Setting up your integration", you end up in the other guide (the one I was using to setup Terminal):
https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=android
Yeah that's it it's nullable. But in all cases the location Id is required in both integrations
So why are you saying these are 2 different integration flows?
By the looks of it, in order to initialise Terminal, you need to go over this documentation: https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=android
In order to discover and connect to a reader, you go back to https://docs.stripe.com/terminal/features/apps-on-devices/build?lang-android=java#discover-and-connect-a-reader
Yes, but you need to choose the Apps-on-device here and not Android
https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=apps-on-devices
One is called Android and the other is called Apps-on-device
These are two completly different integrations.
So how do you setup Terminal here, with Apps-on-Devices?
Following this guide:
https://docs.stripe.com/terminal/features/apps-on-devices/build
OK, so basically you're taken to the same page where you started ๐
Let's go with Apps-on-Devices. Since when you discoverReaders, the locationId can be null (so no locationId), where exactly are you required to provide it?
Actually try to pass it null and see if that works, but usually you should pass the locationId, I'm hesitating here when you shared that the Java SDK is accepting nullable value.
If it wokrs without passing a location Id then that's even better for use case.
Between when you advance on the integration and will look for accepting a payment, the guide will become the same for Apps on device and Android:
https://docs.stripe.com/terminal/payments/collect-card-payment?terminal-sdk-platform=android#create-payment
(there is no tab for Apps on device)
OK, so basically you're suggesting to follow this guide: https://docs.stripe.com/terminal/features/apps-on-devices/build
And don't provide a locationId (it being "@Nullable" in discoverReaders), and get rid of the Connection Token mechanism that is not required for Apps-on-Devices?
Yes
Out of your knowledge, besides the discoverReaders(@Nullable locationId), is there any other place where you actually need the locationId present?
once the reader si connect you no more need to provide the locationId
I just tried following that guide (https://docs.stripe.com/terminal/features/apps-on-devices/build?lang-android=java#setup-app), and the first step is:
- Setup Integration: https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=apps-on-devices
Which takes me to this page:
How am I supposed to initialize Terminal using the Apps-on-Devices integration? If I call "discoverReaders" (https://docs.stripe.com/terminal/features/apps-on-devices/build#discover-and-connect-a-reader) without first calling Terminal.init(...), I get an exception: Caused by: java.lang.IllegalStateException: init must be called before attempting to get the instance
Ah so sorry, the doc got updated the setup part is now the same for Android and Apps on devices ๐ค , let me check further ..
I know this is confusing the Apps on device and the Android integration, there are some part are commun and others are different
Yes, indeed, very confusing ๐
that's why probably I went down the road of Apps-on-Devices, but then still implemented my own ConnectionTokenProvider
OK, so how I did it, to ensure I am using the Apps-On-Devices integration, is:
Terminal.init( mainActivity, LogLevel.VERBOSE, new AppsOnDevicesConnectionTokenProvider(), stripeContainer, offlineListener);
with AppsOnDevicesConnectionTokenProvider imported like: import com.stripe.stripeterminal.appsondevices.AppsOnDevicesConnectionTokenProvider
but when I bring the device online (connect to Wi-Fi) after it was offline, I get this error:
Yeah actually you need to implement your own connection_token provider (like you were doing initially)
Something like this:
class CustomConnectionTokenProvider : ConnectionTokenProvider {
override fun fetchConnectionToken(callback: ConnectionTokenCallback) {
}
}
I checked your reader's error in the past 7 days and I'm seeing the error
com.stripe.stripeterminal.external.models.TerminalException: Execution error while retrieving connection token
happened only one time
is this accurate ?
Yes, because I just now switched from my own ConnectionTokenProvider implementation to the AppsOnDevicesConnectionTokenProvider
Up until this point, I was having other issues with the integration, as mentioned in my initial message that started this conversation.
Now that I tried using the com.stripe.stripeterminal.appsondevices.AppsOnDevicesConnectionTokenProvider, I am bumping into this error I pasted earlier: com.stripe.stripeterminal.external.models.TerminalException: Execution error while retrieving connection token and you found for this DevKit logs.
Now, might it be that our app (com.goodbox) is not enabled for Apps-On-Devices?
Now, might it be that our app (com.goodbox) is not enabled for Apps-On-Devices?
No no you should use your custom token provider
You need to switch back sorry for the confusion initially.
I'm trying to understand the inital issue now, your integration seems good so far (the initial one)
Sorry as I don't have a full vision on your full code base I'm not able to 100% understand your stack.
Alright, that's a fair point, kind of difficult to understand each individual implementation for the many clients that use Stripe Terminal.
Now back to the connection token issue, you are facing this all the time ? because as I mentioned above I'm noticing this happened only once in the past 7 days
So, back to my original issue:
- I have this device offline.
- When it starts, Stripe asks for a connection token, but because there's no internet connectivity, I call
connectionTokenCallback.onFailure(new ConnectionTokenException(errorMessage)); - I bring it online
- The device asks for a connection token (which is retrieved from the backend using gRPC)
- Because the device was offline when it was powered-on the initially, the call to our backend
stripe.api.rsm.goodbox.comto retrieve the connection token (step 2 above) was cached in the Android negative DNS cache. This means that it attempted to call that FQDN, failed, and cached the failure. - Now since the device is online, calls to
stripe.api.rsm.goodbox.comwill not go through until this negative DNS cache entry is invalidated. This takes about 3 minutes. - After 3 minutes, the call to the backend goes through successfully and I return a valid token to my ConnectionTokenProvider and call
connectionTokenCallback.onSuccess(token); - Then I get this error message :
This is with Stripe Terminal Android SDK v5.4.1.
With v4.7.3, once the device was connected to the internet, the (offline) connected reader would get disconnected.
For 3 minutes, the reader would stay disconnected, and when a token was eventually retrieved, our app would see that the reader is disconnected and attempt to re-discover and re-connect to the reader.
Because with v5.4.1 the reader doesn't disconnect after going online, and eventually throws this TimeoutException, the device/reader stays offline even if the device is connected to the internet. Another side-effect is that the stored offline transactions are not forwarded out.
So if you wait 3min before going online from the last offline attempts, you won't get the issue ?
The only solution we have right now is to restart the device, or let the user press a "Reset reader connection" button which in turn disconnects the reader, performs reader discovery and re-connects to the reader.
Yes these are good workarounds.
You confirm this also ?
We cannot control the time between when the reader is started offline and when it gets connected to the internet. This depends on our clients.
The issue I see here is that the offline reader no longer disconnects when it comes online. If that were to happen, we would go through an automated process of "performs reader discovery and re-connects to the reader"
I can give it a go...
In the meantime, do you know of any changes that might've happened in the Stripe Terminal Android SDK around how the reader disconnects or doesn't disconnect when the device goes online?
I just finished my testing, and even if I wait 3 minutes between when the device gets powered on (and tries to fetch a token) and when I bring the device online, I still have to wait for ~ 3 minutes before the gRPC channel is READY and I can retrieve a connection token from my backend.
By the time the 3 minutes are up, I get this TimeoutException:
Can you see it in the reader logs (in Sentry, I presume) on your side?
@balmy rivet - are you still around?
Yes yes I'm still with you
phew, I thought this conversation will be closed and then I'll have to explain everything to someone else ๐
before the gRPC channel is READY
is this happening with an HTTP endpoint too ?
the call to our backend stripe.api.rsm.goodbox.com to retrieve the connection token (step 2 above) was cached in the Android negative DNS cache. This means that it attempted to call that FQDN, failed, and cached the failure.
You call your backend via gRPC here right ?
I don't know, we just use gRPC here.
Yes
Is there a way I might catch this TimeoutException and go through the process of re-discover and re-connect for the reader?
This seems something specific to gRPC, I don't think you'll face the same issue if it was HTTP
You should be able to catch it with a try/Catch that wraps the Terminal.init function, no ?
Do you have currently a try catch block for all runtime exceptions ?
Probably not, I didn't try to actually get a token through HTTP, but I tried to connect to my backend using HTTP, and the calls went through just fine.
The fact that my gRPC channel waits for 3 minutes until the connection to the backend is established is one problem, indeed.
This problem was mitigated by the fact that the reader disconnected immediately after the device went online.
This is no longer the case, with v5.4.1. The reader just stays connected, offline.
This is no longer the case, with v5.4.1. The reader just stays connected, offline.
Yeah and I think this is aligned with the fact that you can accept offline payments with the reader even if it's not connected to the Wifi
there's no element leading to my code in this TimeoutException Terminal throws, so it's kind of difficult to know where to catch it
because the status connect/not connected isn't for the WIFI/connectivity, it's a connection status between your android app and the reader
The fact that my gRPC channel waits for 3 minutes until the connection to the backend is established is one problem, indeed.
I think you need to fix this, as this is particular thing to your integration
It shouldn't happen normaly, when the reader tried to fetch another connection token it won't get a cached response.
I spent days on end trying to get to the bottom of why the gRPC channel takes this long to get through to the backend.
I implemented a custom DNS resolver that would avoid going through the FQDN and would resolve the IPs using an external DNS service (8.8.8.8 - Google DNS).
Then I am creating the gRPC channel using the actual IP.
However, the InetAddress implementation in Android still attempts to get the FQDN associated with the IP, somewhere in its implementation.
Hence I'm back to square one with these 3 minutes.
Ok, I will have to go get my son from the kindergarden.
Is there a way we could continue this conversation, perhaps through the Support email, in order to get to the bottom of:
- Where do I need to catch the TimeoutException Terminal throws upon waiting for 3 minutes to get the token?
- Why was Terminal SDK v4.7.3 disconnecting from the reader upon device coming online (connected to Wi-Fi) and v5.4.1 doesn't disconnect from the reader?
I think you need to find a solution for the 3 min issue here
Why was Terminal SDK v4.7.3 disconnecting from the reader upon device coming online (connected to Wi-Fi) and v5.4.1 doesn't disconnect from the reader?
Probably this is a recent change. And I as said previouslt this seems aligned because you can accept offline payments.
So the reader is considered conencted to the Android App (not to the wifi)