#salonmonster_best-practices
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/1367277795142795315
📝 Have more to share? Add more details, code, screenshots, videos, etc. below.
We swapped from the JS Stripe implementation to the server driven implementation to deal with hardward connectivity issues through router firewalls.
Since we did that we ocassionally have payments that we don’t successfully recognize the completion of in our app. Most payments work fine, but ocassionally we will get a payment that completes on Stripe, but our app does not recognized that it was completed successfully.
We think we’ve maybe found one of the issues:
If a user takes more than 1 minute to tap their card, the ajax request from our app frontend angular app time at the 1 minute makre, causing our front end to no longer be able to receive the successful payment result.
On the back-end api we poll the reader every 2 seconds to see if it have move out of the “in_progress” state and is now completed or failed.
We want to check if this is the best practice for handling this or if there is a better approach.
We looked at using a webhook to track the completed payment, but we didn’t think the webhook would return the paymentIntentID that it references, just that it was completed.
router
.route("/stripe/terminal/process_payment_intent_reader")
.post(async (req, res, next) => {
try {
// get the payment intent from the request body
const { paymentIntentID, salonID } = req.body;
// get the stripe location id from the salon
const stripeLocationID = (
await stripeModel.getStripeLocationID({ salonID: salonID })
)["stripeLocation"];
// get the firstcard reader id from the stripe location
const cardReaderID = (
await stripe.terminal.readers.list({ location: stripeLocationID })
).data[0].id;
// process with the card reader
await stripe.terminal.readers.processPaymentIntent(cardReaderID, {
payment_intent: paymentIntentID,
});
// Start polling every 2 seconds
const paymentIntent = await pollPaymentIntent(cardReaderID);
async function pollPaymentIntent(readerID) {
try {
// Start polling every 2 seconds until the status changes
let counter = 0;
while (true) {
const reader = await stripe.terminal.readers.retrieve(readerID);
if (reader.action?.status !== "in_progress") {
const paymentIntent =
await stripe.paymentIntents.retrieve(paymentIntentID);
return paymentIntent; // Return the final reader data
}
// Wait 2 seconds before the next check
await new Promise((resolve) => setTimeout(resolve, 2000));
counter++;
}
} catch (error) {
console.log("error: ", error);
throw error; // Handle the error as needed
}
}
res.json({ data: paymentIntent, success: true });
} catch (e) {
const fs = require("fs");
const logMessage = `${new Date().toISOString()} - Error processing payment intent reader: ${e}\n`;
console.log("error processing payment intent reader: ", e);
res.status(500).send(e);
}
});
Hi!
Seems like your logic is reasonable. What's the issue you're running into exactly?
I want to know if this is the best practice, or if there is a better approach
The logic seems reasonable to me .... but I don't know
There are two options we suggest: events, or polling. You're using option 2, so I would say it's best practice.
Ok, we'll keep doing that then
Is there a standard policy /best practice for how long the reader should remain available for tapping/dipping? eg. 1 mins?
Or is it just up to the implementation?
I'm not sure about that one. Give me a sec.
thanks
There's a list of suggested approaches here: https://docs.stripe.com/terminal/payments/collect-card-payment?terminal-sdk-platform=server-driven&lang=node#verify-reader
We suggest having a button to allow the user to refresh the status: https://docs.stripe.com/terminal/payments/collect-card-payment?terminal-sdk-platform=server-driven&lang=node#stripe-api
If I were designing this, I'd likely return the ajax call as soon as the thing was 'handed off', and then have client-side polling that hits another URL on your server to check the status - and separately, a 'work queue' job that requests that status every X seconds from Stripe and which updates the data that the new URL looks at. Does that all make sense?