#krut4rth
1 messages ยท Page 1 of 1 (latest)
"id": "evt_3NdF7fKEOuJhOPhD1X6ZjfOU",
"object": "event",
"api_version": "2022-11-15",
"created": 1691598040,
"data": {
"object": {
"id": "pi_3NdF7fKEOuJhOPhD18AvzCKh",
"object": "payment_intent",
"amount": 99999,
"amount_capturable": 0,
"amount_details": {
"tip": {
}
},
"amount_received": 99999,
"application": null,
"application_fee_amount": null,
"automatic_payment_methods": null,
"canceled_at": null,
"cancellation_reason": null,
"capture_method": "automatic",
"client_secret": "pi_3NdF7fKEOuJhOPhD18AvzCKh_secret_4tw02H6WMVR8y4m1CNlMWCpz0",
"confirmation_method": "automatic",
"created": 1691598035,
"currency": "usd",
"customer": null,
"description": null,
"invoice": null,
"last_payment_error": null,
"latest_charge": "ch_3NdF7fKEOuJhOPhD1dyQv1D0",
"livemode": false,
"metadata": {
},
"next_action": null,
"on_behalf_of": null,
"payment_method": "pm_1NdF7jKEOuJhOPhD2EXecV5f",
"payment_method_options": {
"card_present": {
"request_extended_authorization": false,
"request_incremental_authorization_support": false
}
},
"payment_method_types": [
"card_present"
],
"processing": null,
"receipt_email": null,
"review": null,
"setup_future_usage": null,
"shipping": null,
"source": null,
"statement_descriptor": null,
"statement_descriptor_suffix": null,
"status": "succeeded",
"transfer_data": null,
"transfer_group": null
}
},
"livemode": false,
"pending_webhooks": 2,
"request": {
"id": "req_raYmuq51b9WkoU",
"idempotency_key": "7b5f3a95-8e9c-41ea-b7b3-25b4ec3a390b"
},
"type": "payment_intent.succeeded"
}```
Hello there
That 400 response is coming from your webhook handler code.
So you will want to add some logs to help determine why your code is sending back a 400
My guess is that you are having an issue with signature verification here.
backend code goes like this: app.post( "/api/v1/webhook", bodyParser.raw({ type: "application/json" }), async (request, response) => { const sig = request.headers["stripe-signature"]; let event = request.body; console.log(request.body); try { event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret); } catch (err) { response.status(400).send(`Webhook Error: ${err.message}`); return; } switch (event.type) { case "payment_intent.succeeded": const paymentIntent = event.data.object; console.log( `PaymentIntent for ${paymentIntent.amount} was successful!` ); return; // Then define and call a method to handle the successful payment intent. // handlePaymentIntentSucceeded(paymentIntent); default: // Unexpected event type return; } } );
What do we mean by signature verification?
Can you add a log to your catch (err) block to actually log out that error on your server?
And then test again and let me know what you see there?
this is log from catch block
Okay great
So it is indeed a signature verification issue
How are you testing here? are you using the CLI or an HTTPS endpoint?
The most likely issue is that you aren't passing the raw body of the request to constructEvent because your framework is manipulating it first.
Are you using Express?
https endpoint is used.
Im using nodejs, express.
backend code is like this: ```app.post(
"/api/v1/webhook",
bodyParser.raw({ type: "application/json" }),
async (request, response) => {
const sig = request.headers["stripe-signature"];
let event = request.body;
try {
event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret);
} catch (err) {
console.log(err);
response.status(400).send(Webhook Error: ${err.message});
return;
}
switch (event.type) {
case "payment_intent.succeeded":
const paymentIntent = event.data.object;
console.log(
PaymentIntent for ${paymentIntent.amount} was successful!
);
break;
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
default:
// Unexpected event type
console.log("default");
}
response.send();
}
);
Gotcha yeah this is a common Express issue. Try something like this up above with app.use: app.use((req, res, next) => { if (req.originalUrl === '/api/v1/webhook') { next(); // Do nothing with the body because I need it in a raw state. } else { express.json()(req, res, next); // ONLY do express.json() if the received request is NOT a WebHook from Stripe. } });
still getting the same error
added this above the webhook:
app.use((req, res, next) => {
if (req.originalUrl === "/api/v1/webhook") {
next(); // Do nothing with the body because I need it in a raw state.
} else {
express.json()(req, res, next); // ONLY do express.json() if the received request is NOT a WebHook from Stripe.
}
});```
Here is the whole server.js:
Okay yeah you need to remove the app.use(express.json({})); up above
Since that is what the code I provdied you is handling
You don't want the raw body to be JSONified
For the webhook
great, it worked. I want help in another issue now. I'm not exactly clear on how i can use this webhook for below scenario.
From my react app, I am processing payment to terminal in automatic mode. Now When the payment from terminal is completed webhook will be triggered when payment intent status is changed to succeeded. So whenever webhook has responded with success I want to apply some conditional logic. So how exactly can I know in my frontend that the payment intent status is succedded
What is the conditional logic you want to handle?
Mostly in your frontend you don't rely on the webhook here.
And which Terminal SDK are you using here?
i have a code in place which will print the receipt of transaction. So I need to know when the payment intent status is changed to succeded so that i can enable the button.
Gotcha and which SDK?
I dont know what to reply regarding sdk
Do you have an example PaymentIntent that you have tested with that I can look at?
Why exactly do we need payment intent here?
๐ hopping in here since bismark has to head out soon
Mostly we'd want to see the payment intent to see what you're getting back on your frontend to see what you can check for to know that payment succeeded
i think there is some mismatch in my requirement and what you are trying to help out it.
Ill describe again: so i have a payment process button, on clicking it a payment intent is created and reader is receiving the payment. Now lets suppose that the client completed the payment from terminal, so after the successful payment the status of payment intent will change to succeeded, now whenever the payment intent's status is changed to succeeded i want to enable a button.
So currently im calling an api every 5 seconds checking the status of payment intent, but instead of this i want to see if i can use webhook or not. if it can be used than how exactly can i get the updated status to frontend
Gotcha
and how are you intergrated with terminal currently? Are you using our server-side integration flow? Our JS library?
im using stripe libray..
apiVersion: "2020-08-27",
appInfo: {
// For sample support and debugging, not required for production:
name: "stripe-samples/terminal-series/stripe-terminal-collect-payments",
version: "0.0.1",
url: "https://github.com/stripe-samples",
},
});```
Yup
So if you're using automatic, then you should just be able to listen for the response processPayment and check thet status of the payment intent there right? https://stripe.com/docs/terminal/payments/collect-payment?terminal-sdk-platform=js#process-payment
I dont know how your response is related to my question.
You want to know on your frontend when a terminal payment is complete right?
Are you not using processPayment client-side?
try {
const { amount, readerId } = req.body;
const paymentIntent = await stripe.paymentIntents.create({
currency: "usd",
amount,
payment_method_types: ["card_present"],
capture_method: "automatic",
});
const reader = await stripe.terminal.readers.processPaymentIntent(
readerId,
{
payment_intent: paymentIntent.id,
}
);
res.send({ reader, paymentIntent });
} catch (e) {
res.send({ error: { message: e.message } });
}
});```
process payment code from backend
a button click on frontent is calling the above api
And yes i want to know when the payment intent status is succeeded. Currently im calling api every 5 seconds to fetch status, instead of this i want some more efficient way, webhook came to mind, can it help or is there any thing else which can help?
AH I mixed it up - you're actually using our server-driven integration
now your question makes sense
oh, sorry i couldnt convey it better, but help in this is very much appreciated
no worries (that's part of the reason we asked for an example payment intent ID, we can see what requests are being made once we have the ID and help you better)
here are few payment intent id: pi_3NdGaYKEOuJhOPhD1e9D5ZLd
pi_3NdGZzKEOuJhOPhD0ZlPZVlQ
pi_3NdGYrKEOuJhOPhD1xckPqGu
So you got my question, right? How can i solve the problem?
yup I understand
Yeah right now I think polling either the payment intent or the reader is your only option to know exactly when the payment is completed from your frontend
I didn't completely understand, but do you mean that my current implementation of making api call every 5 seconds to check status is the only solution? Webhooks can't be used?
With a webhook there's no way for you to notify your frontend - that's why we say you can use polling https://stripe.com/docs/terminal/payments/collect-payment?terminal-sdk-platform=server-driven#stripe-api
okay, so currently im retreiving payment intent status every 5 seconds, and that needs to be continued, we cant use webhook in this case, correct?
Yes, if you have a frontend UI that is relying on the payment intent status then webhooks won't help