Issue
I can have a stripe webhook in my typescript backend, or I can have the stripe API - but not both...
I have router setup so any url with "/payment/" calls on my stripe handlers in the paymentActions.tsx
Here is the app.ts:
// app.ts
import bodyParser from "body-parser";
import express from "express";
import { paymentActions } from "../controllers/paymentActions";
const app = express();
app.use(express.static("public"));
app.use(express.urlencoded({ extended: true }));
// IF I DISABLE THIS app.use THE STRIPE WEBHOOK WORKS
app.use(
bodyParser.json({
// Because Stripe needs the raw body, we compute it but only when hitting the Stripe callback URL.
verify: function (req, res, buf) {
var url = req.url;
//@ts-ignore
req.rawBody = buf.toString();
},
})
);
// APIs
app.use("/payment", paymentActions);
export default app;
In paymentActions.tsx I have three endpoints. The two GET requests handle the stripe API to create and update payment intents. This works perfectly.
The third endpoint is a stripe webhook that returns a 400 response. If I disable the app.use(bodyparser...) in app.ts above, the webhook now works (response 200) but the other two GET requests throw errors because the json body contains "amount is NaN".
Any ideas how I can fix this? Thanks!
// paymentActions.tsx
import express from "express";
import * as stripe from "../clients/stripe";
export const paymentActions = express.Router();
// Get payment intent
paymentActions.get<{}>("/intent", async (req, res) => {
const { amount } = req.body;
try {
const paymentIntent = await stripe.createPaymentIntent(amount);
return res.status(200).json(paymentIntent);
} catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
return;
}
});
// Update payment intent
paymentActions.get<{}>("/updatedIntent", async (req, res) => {
const { intentId, amount, metadata } = req.body;
try {
const paymentIntent = await stripe.updatePaymentIntent(intentId, amount, metadata);
return res.status(200).json(paymentIntent);
} catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
return;
}
});
// Stripe payment webhook
paymentActions.post(
"/webhook",
express.raw({ type: "application/json" }),
(request, response) => {
const stripe = require("stripe");
const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
let event = request.body;
// Only verify the event if you have an endpoint secret defined.
// Otherwise use the basic event deserialized with JSON.parse
if (endpointSecret) {
// Get the signature sent by Stripe
const signature = request.headers["stripe-signature"];
try {
event = stripe.webhooks.constructEvent(
request.body,
signature,
endpointSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return response.sendStatus(400);
}
}
// Handle the event
switch (event.type) {
case "payment_intent.succeeded":
// Handle payment intent
break;
default:
// Unexpected event type
}
// Return a 200 response to acknowledge receipt of the event
response.send();
}
);
Solution
Not sure if this is the ideal solution but specifying express.json()
inside the args of each get request solved the issue.
i.e.
// Get payment intent
paymentActions.get<{}>("/intent", express.json(), async (req, res) => {
const { amount } = req.body;
try {
const paymentIntent = await stripe.createPaymentIntent(amount);
return res.status(200).json(paymentIntent);
} catch (err) {
res.status(400).send(`Webhook Error: ${err.message}`);
return;
}
});
Answered By - DarioS
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.