Stripe webhook 需要与标准 api 请求不同的 json 主体
Stripe webhook needs different json body than standard api requests
我可以在我的打字稿后端有一个条纹 webhook,或者我可以有条纹 API - 但不能两者都...
我设置了路由器,因此 paymentActions.tsx
中任何带有“/payment/”的 url 调用我的条带处理程序
这里是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;
在 paymentActions.tsx 我有三个端点。两个 GET 请求处理条带 API 以创建和更新支付意图。这非常有效。
第三个端点是一个 stripe webhook,它 returns 一个 400 响应。如果我禁用上面 app.ts 中的 app.use(bodyparser...),webhook 现在可以工作(响应 200)但是其他两个 GET 请求会抛出错误,因为 json 正文包含“数量是 NaN”。
有什么办法可以解决这个问题吗?谢谢!
// 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();
}
);
请尝试 app.use(express.json())
并删除 bodyParse
app.use。
不确定这是否是理想的解决方案,但在每个 get 请求的参数中指定 express.json()
解决了这个问题。
即
// 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;
}
});
我可以在我的打字稿后端有一个条纹 webhook,或者我可以有条纹 API - 但不能两者都...
我设置了路由器,因此 paymentActions.tsx
中任何带有“/payment/”的 url 调用我的条带处理程序这里是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;
在 paymentActions.tsx 我有三个端点。两个 GET 请求处理条带 API 以创建和更新支付意图。这非常有效。
第三个端点是一个 stripe webhook,它 returns 一个 400 响应。如果我禁用上面 app.ts 中的 app.use(bodyparser...),webhook 现在可以工作(响应 200)但是其他两个 GET 请求会抛出错误,因为 json 正文包含“数量是 NaN”。
有什么办法可以解决这个问题吗?谢谢!
// 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();
}
);
请尝试 app.use(express.json())
并删除 bodyParse
app.use。
不确定这是否是理想的解决方案,但在每个 get 请求的参数中指定 express.json()
解决了这个问题。
即
// 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;
}
});