#krut4rth

1 messages ยท Page 1 of 1 (latest)

autumn mangoBOT
plucky gull
#
  "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"
}```
mellow rock
#

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.

plucky gull
#

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?

mellow rock
#

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?

plucky gull
mellow rock
#

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?

plucky gull
#

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();
}
);

mellow rock
#

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. } });

plucky gull
#

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.
  }
});```
mellow rock
#

Can you show me your full webhook handler code?

#

Not just the route

plucky gull
mellow rock
#

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

plucky gull
#

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

mellow rock
#

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?

plucky gull
#

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.

mellow rock
#

Gotcha and which SDK?

plucky gull
#

I dont know what to reply regarding sdk

mellow rock
#

Do you have an example PaymentIntent that you have tested with that I can look at?

autumn mangoBOT
plucky gull
#

Why exactly do we need payment intent here?

rare condor
#

๐Ÿ‘‹ 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

plucky gull
#

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

rare condor
#

Gotcha

#

and how are you intergrated with terminal currently? Are you using our server-side integration flow? Our JS library?

plucky gull
#

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",
  },
});```
rare condor
#

awesome, so that's our JS library

#

and are you doing manual capture?

plucky gull
#

automatic

#

hey, there?

rare condor
#

Yup

plucky gull
#

I dont know how your response is related to my question.

rare condor
#

You want to know on your frontend when a terminal payment is complete right?

#

Are you not using processPayment client-side?

plucky gull
#
  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?

rare condor
#

AH I mixed it up - you're actually using our server-driven integration

#

now your question makes sense

plucky gull
#

oh, sorry i couldnt convey it better, but help in this is very much appreciated

rare condor
#

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)

plucky gull
#

here are few payment intent id: pi_3NdGaYKEOuJhOPhD1e9D5ZLd

#

pi_3NdGZzKEOuJhOPhD0ZlPZVlQ

#

pi_3NdGYrKEOuJhOPhD1xckPqGu

#

So you got my question, right? How can i solve the problem?

rare condor
#

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

plucky gull
#

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?

rare condor
plucky gull
#

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?

autumn mangoBOT
rare condor
#

Yes, if you have a frontend UI that is relying on the payment intent status then webhooks won't help