![](/img/trans.png)
[英]How can I protect an HTTP POST request from only being received by an approved javascript client?
[英]How can I delay a POST request from a user form until AFTER a webhook POST from Stripe is received?
我希望用户在处理来自前端表单的 POST 请求之前支付费用。 我有一个在后端可以正常工作的 Stripe webhook,但我不确定如何将表单的前端发布延迟到收到付款确认之后。
在下面的代码中,现在createTour
和createTourPay
同时运行。 我希望createTourPay
首先执行,并且createTour
仅在 Stripe 从 webhook 发布到我的应用程序后触发。 我怎样才能做到这一点?
Controller 文件(webhook):
exports.webhookCheckout = (req, res, next) => {
const signature = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body,
signature,
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
return res.status(400).send(`Webhook error: ${err.message}`);
}
if (
event.type === 'checkout.session.completed' &&
event.line_items.name === 'New Job Purchase'
) {
res.status(200).json({ recieved: true });
// Somehow, I want this to trigger the execution of the POST request in my front end JS file.
} else {
if (event.type === 'checkout.session.completed')
createBookingCheckout(event.data.object);
res.status(200).json({ recieved: true });
}
};
前端JS文件:
export const createTourPay = async myForm => {
try {
// 1) Get the checkout session from API response
const session = await axios(`/api/v1/tours/tour-pay`);
const complete = 1;
// console.log(session);
// 2) Create checkout form + charge the credit card
await stripe.redirectToCheckout({
sessionId: session.data.session.id
});
} catch (err) {
// console.log(err);
showAlert('error', err);
}
};
export const createTour = async myForm => {
try {
const startLocation = {
type: 'Point',
coordinates: [-10.185942, 95.774772],
address: '123 Main Street',
description: 'Candy Land'
};
const res = await axios({
method: 'POST',
headers: {
'Content-Type': `multipart/form-data; boundary=${myForm._boundary}`
},
url: '/api/v1/tours',
data: myForm
});
if (res.data.status === 'success') {
showAlert('success', 'NEW TOUR CREATED!');
window.setTimeout(() => {
location.assign('/');
}, 1500);
}
} catch (err) {
showAlert('error', err.response.data.message);
}
};
广泛地说:不要这样做。 相反,您实际上应该在系统中创建一些待定/未付费版本的“旅游”(或任何其他产品/服务),然后在创建时将唯一 ID(例如: tour_123
)附加到结帐 session ,或者使用client_reference_id
( doc ) 或metadata
( doc ):
const session = await stripe.checkout.sessions.create({
// ... other params
client_reference_id: 'tour_123',
metadata: { tour_id: 'tour_123' },
});
然后,您将使用 webhook 来检查这些值,并更新您自己的数据库以指示已付款并且您可以向客户履行订单(运送产品、发送代码、允许访问服务等)。
如果您真的想继续使用更同步的流程,您可以使用单独的身份验证和捕获来对您的客户体验进行排序,并在授权和创建您的旅游实体后捕获资金。
编辑:关于安全的说明
您永远不应该相信客户端逻辑来进行受限操作,例如创建“付费”旅游。 例如,有动力的用户可以简单地调用您的/api/v1/tours
创建端点,而无需通过您的支付流程。 除非您验证付款并在您的服务器上跟踪 state,否则您将无法知道其中哪些实际支付了您。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.