#natschz_code
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/1230156730143604798
๐ Have more to share? Add more details, code, screenshots, videos, etc. below.
Are you turning the reader off after you've connected to it?
Yes exactly
I believe we'd invoke UnexpectedReaderDisconnect callback when the reader gets disconnected
https://docs.stripe.com/terminal/payments/connect-reader?terminal-sdk-platform=js&reader-type=internet#handling-disconnects
ah you have it set to onUnexpectedReaderDisconnect: () => { }
which is why you're not seeing the callback
This is the exception that i get
So I've set the callback (just reduced the sample because only 480 charakters are allowed) :
onUnexpectedReaderDisconnect: () => {
console.log("Currently: unexpectedDisconnect")
}
And I'm getting the console output, but it still throws the Unhandled promise rejection Error: Could not communicate with the Reader. error.
I mean you shouldn't try to run any other actions except for reconnection flow once you receive onUnexpectedReaderDisconnect
So currently, I'm not even trying to reconnect:
const terminal = StripeTerminal.create({
onFetchConnectionToken: fetchConnectionToken(),
onUnexpectedReaderDisconnect: () => {
console.log("Disconnected")
},
onConnectionStatusChange: (data) => {
console.log("onConnectionStatusChange", {data})
},
});
terminal.discoverReaders().then(discoverResult => {
const reader = discoverResult.discoveredReaders.find(reader => reader.serial_number === "SERIAL_NUMBER")
terminal.connectReader(reader).then(connectResult => {
console.log("Connected to reader", connectResult)
}).catch(error => {
console.error("Error connecting to reader", error)
})
}).catch(error => {
console.error("Error discovering readers", error)
})
This is all I'm doing right now. Then turning the reader off, will result in the exception shown above.
Sorry, I feel like I am missing something. Can you clarify exactly when you see the promise rejection error?
also onFetchConnectionToken: fetchConnectionToken() feels wrong
You're invoking the function fetchConnectionToken yourself there.
Ideally, you should only pass function definition, the SDK invokes it on its own
Yea sorry this are two nested functions where I pass the URL to the outer one and then the other es returned but this works fine
So just for clarification, I'm executing the code above, then the terminal connects and everything works fine.
Then I'm turning the terminal off, it then takes ~2min until I get the error (without doing anything else)
This is the full console output
Besides that, I noticed calling getConnectionStatus in the meantime, before the error happens, will also always return connected, even though the terminal is powered off.
Besides that, I noticed calling getConnectionStatus in the meantime, before the error happens, will also always return connected, even though the terminal is powered off
That's expected due to how the SDK has been designed today. The status of the reader is updated when the SDK makes a request for something
I already though soemthing like that, but this is negligible.
A workaround there is to use a non user-facing function like: https://docs.stripe.com/terminal/references/api/js-sdk#clear-reader-display which returns a promise that throws an error if the reader isn't connected.
So just to clarify, you're seeing promise rejected error automatically after the reader is disconnected? Are you sure no other function is running that triggers this error?
Can you share your complete code?
Sure
-content_for :javascript do
%script{src: "https://js.stripe.com/terminal/v1/"}
-content_for :javascript do
:javascript
function fetchConnectionToken(connectionTokenUrl) {
console.log("Currently: fetchConnectionToken")
return () => {
// Do not cache or hardcode the ConnectionToken. The SDK manages the ConnectionToken's lifecycle.
return fetch(connectionTokenUrl, {method: "POST"})
.then(function (response) {
return response.json();
})
.then(function (data) {
return data.token;
});
}
}
const terminal = StripeTerminal.create({
onFetchConnectionToken: fetchConnectionToken("INTERNAL_URL"),
onUnexpectedReaderDisconnect: () => {
console.log("Disconnected")
},
onConnectionStatusChange: (data) => {
console.log("onConnectionStatusChange", {data})
},
});
terminal.discoverReaders().then(discoverResult => {
const reader = discoverResult.discoveredReaders.find(reader => reader.serial_number === "SERIAL_NUMBER")
terminal.connectReader(reader).then(connectResult => {
console.log("Connected to reader", connectResult)
}).catch(error => {
console.error("Error connecting to reader", error)
})
}).catch(error => {
console.error("Error discovering readers", error)
})
so both of them are just placed inside the footer of our layout file
There is also just the javascript code:
function fetchConnectionToken(connectionTokenUrl) {
console.log("Currently: fetchConnectionToken")
return () => {
// Do not cache or hardcode the ConnectionToken. The SDK manages the ConnectionToken's lifecycle.
return fetch(connectionTokenUrl, {method: "POST"})
.then(function (response) {
return response.json();
})
.then(function (data) {
return data.token;
});
}
}
const terminal = StripeTerminal.create({
onFetchConnectionToken: fetchConnectionToken("INTERNAL_URL"),
onUnexpectedReaderDisconnect: () => {
console.log("Disconnected")
},
onConnectionStatusChange: (data) => {
console.log("onConnectionStatusChange", {data})
},
});
terminal.discoverReaders().then(discoverResult => {
const reader = discoverResult.discoveredReaders.find(reader => reader.serial_number === "SERIAL_NUMBER")
terminal.connectReader(reader).then(connectResult => {
console.log("Connected to reader", connectResult)
}).catch(error => {
console.error("Error connecting to reader", error)
})
}).catch(error => {
console.error("Error discovering readers", error)
})
Is just reducted the serial number and our internal url
can you add error handling code in fetchConnectionToken function?
to catch any rejected promises?
It is possible that fetching connection token is failing
sure
takes a few minutes to wait for the timeout happening
I updated the fetchConnectionToken function like so:
function fetchConnectionToken(connectionTokenUrl) {
console.log("Currently: fetchConnectionToken")
return () => {
// Do not cache or hardcode the ConnectionToken. The SDK manages the ConnectionToken's lifecycle.
return fetch(connectionTokenUrl, {method: "POST"})
.then(function (response) {
return response.json();
})
.then(function (data) {
return data.token;
}).catch(function (error) {
console.error("Error fetching ConnectionToken", error);
throw error;
})
}
}
But still getting the unhandled promise error
But you can see that the onUnexpectedReaderDisconnect callback is fired but then afterwards the Unhandled promise rejection error still happens.
Gotcha. However, onUnexpectedReaderDisconnect unblocks you right?
Like you can handle that gracefully in the UI and trigger a reconnection flow
At least thats what i wanted to do. The example you are seeing is just a simplified version, to show the issue. But we are creating a react app and there the unhandled exception is an issue, because it causes the react app to crash, or at least go into an error state.
So I need some way of preventing this unhandled error from happening.
Thats why I cant handled it gracefully, in our react app. ๐ฆ
I see. Let me check if I can reproduce
Sure ๐
Hmm I see the uncaught promise error but it isn't crashing my react application
I have a state variable that gets updated when onUnexpectedReaderDisconnect is trigger (which conditionally changes the UI on the page)
But do you have a ErrorBoundry set up?
Ah I don't
I'm trying to remove the error boundary on our site, to check
Might also be webpacker catching the error.
Yeah I think that'd be a good workaround for now.
I don't think there's a better way to handle this today.
I'll make sure to flag this internally though
to see if we can make some improvement
Yea so it also happens without error boundary. So wepacker shows the error.
So we kind of need this unhandled exception to be somehow handled
Taking a step back, I assume you're working with a smart reader like WisePOS E or S700 here?
Is there a reason you're using JS SDK over Server-Driven flow?
https://docs.stripe.com/terminal/payments/setup-integration?terminal-sdk-platform=server-driven
not particularly, but it was the sample provided
I mean we don't need it today, but i think this should be fixed anyway, it's just an issue if this takes weeks until it's fixed.
Then we have to reconsider and look for a different solution.
Yup I agree, I'll flag this internally and see what the terminal team says. You could write in via following in case you want to stay updated on the progress
https://support.stripe.com/?contact=true
Overall IMO, Server-driven flow is better compared to JS as it eliminates the connection requirements around SDK and the Reader as well as simplifies the code you'd need to work with. I'd recommend just giving it a go to see if you find it better.
Find help and support for Stripe. Our support site provides answers on all types of situations, including account information, charges and refunds, and subscriptions information. Get your questions answered and find international support for Stripe.
What do i need to do, to get updated, the link just gets me to artices site
And maybe we'll take a look at the serverside approach the next couple of days.
Cool thanks
But yea it would be really awesome if you guys could fix this, since for the server driven approach, we would have too rewrite a portion of our app.
But could you keep me up to date, the progress?