javascript - 如何从 webhook 获取 Stripe 的“payment_intent.suceeded”响应以处理订单?
问题描述
我正在使用快速服务器运行 Vue 应用程序。在客户端,我使用 createPaymentIntent、createPaymentMethod 和 confirmCardPayment api。文档清楚地说明了付款意图,验证状态
您的集成不应尝试在客户端处理订单履行,因为客户可能会在付款完成后但在履行流程启动之前离开页面。相反,使用 webhook 监控 payment_intent.succeeded 事件并异步处理其完成,而不是尝试在客户端启动履行。
下单流程如下:
- 使用客户详细信息和产品创建订单 - newOrder。
- 调用 createPaymentIntent(newOrder)
- 调用 stripe.createPaymentMethod({type, card})
- 从 stripe.confirmCardPayment(secret, {payment_method: paymentMethodRequest.paymentMethod.id, shipping: billingDetails,}) 收集结果
- if result.error - 在客户端向客户显示错误消息
- 否则,我处理加载并设置successfulPayment = true 以触发客户端上的操作(动画等)。重要的是,我调用我的 OrderService.postOrder(newOrder) 将订单发送到后端以便在 Mongo 中进行处理。
async createOrder() {
this.loading(true);
this.$v.$touch();
if (!this.$v.$invalid) {
// order item details....
const cardElement = elements.getElement("card");
const billingDetails = {
name: user.name,
address: {
city: user.city,
line1: user.street,
state: "NY"
},
phone: user.phone
};
try {
const response = await OrderService.createPaymentIntent(newOrder);
const secret = response.data.clientSecret;
this.deliveryFee = response.data.deliveryFee;
this.totalAmount = response.data.totalAmount;
const paymentMethodRequest = await stripe.createPaymentMethod({
type: "card",
card: cardElement
});
const result = await stripe.confirmCardPayment(secret, {
payment_method: paymentMethodRequest.paymentMethod.id,
shipping: billingDetails,
receipt_email: "kevinturney01@gmail.com"
});
// ! DO NOT CONFIRM A SUCCESS ON THE CLIENT, RELY ON THE WEBHOOK!!!!!
// console.log("LINE 443", result, result.error);
if (result.error) {
const error = result.error;
this.showErrorMessage(error);
} else {
this.successfullPayment = true;
this.isLoading = false;
//! NEED TO REDIRECT TO SUCCESSS PAGE
OrderService.postOrder(newOrder).catch(error => {
// https://guillim.github.io/vue/2019/03/20/damn-vuejs-observer.html
this.updateErrors(Object.assign([], error.response.data.errors));
});
console.log("success");
this.updateOrder(newOrder);
}
} catch (error) {
console.log(error);
}
}
我的 webhook 端点几乎直接来自 Stripe 文档:
/webhook
static async apiPostWebhookEvent(req, res) {
let data, eventType
let paymentIntent
let event = null
console.log("HITTING STRIPE WEBHOOK")
// Check if webhook signing is configured.
if (process.env.WHSNGROK) { //WHSNGROK hits endpoint
// Retrieve the event by verifying the signature using the raw body and secret.
let signature = req.headers['stripe-signature'];
console.log("SIGNATURE",signature)
try {
event = stripe.webhooks.constructEvent(
req.rawBody,
signature,
process.env.WHSNGROK
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`);
return res.sendStatus(400);
}
data = event.data;
eventType = event.type;
} else {
// Webhook signing is recommended, but if the secret is not configured in `config.js`,
// we can retrieve the event data directly from the request body.
data = req.body.data;
eventType = req.body.type;
console.log("LINE 38 WEBHOOK", eventType)
console.log("LINE 39", event.type)
}
// event.type || eventType || eventType.type
switch (event.type) {
case 'payment_intent.created':
paymentIntent = event.data.object;
break;
case 'payment_intent.payment_failed':
paymentIntent = event.data.object;
payment_intent.payment_failed
const message = intent.last_payment_error && intent.last_payment_error.message;
console.log('❌ Payment failed.', paymentIntent.id, message);
break;
case 'payment_intent.processing':
paymentIntent = event.data.object;
break;
case 'payment_intent.succeeded':
paymentIntent = event.data.object;
// Then define and call a function to handle the event payment_intent.succeeded
// Funds have been captured
// Fulfill any orders, e-mail receipts, etc
// At this point how do I or can I send the order to MongoDB and get the payment_intent.succeeded confirmation from the webhook to the client?
console.log(' Payment captured!', paymentIntent.id);
break;
// ... handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
return res.sendStatus(200);
}
}
所以总结一下。在 webhook 中的 switch/case 中,我如何才能将 payment_intent.succeeded 从 webhook 发送到我的客户端(我知道这是 Stripe 向我的服务器发出的发布请求)。那,而不是在客户端上调用 confirmCardPayment() 并依赖该结果?是否可以从那里调用 post my newOrder 或者我仍然需要从客户端调用我的 OrderService.postOrder(newOrder) 。
解决方案
我认为检查 webhook 是否已命中服务器的最简洁方法是让客户端每 X 秒 ping 服务器以检查订单状态,或者您可以在客户端和服务器之间建立 web-socket 连接,以便服务器可以向客户端推送一条消息,告诉它paymentIntent
已经成功(或任何其他状态消息)。
这些选项中的任何一个都很好,尽管我认为 webhook 在服务器上触发对 Order 的更新而不是客户端在收到响应后才这样做会更安全。否则,如果客户端和服务器之间的连接断开,则可能会支付订单但未标记为已支付,然后客户端将执行的任何其他相关操作都不会发生。一旦用户支付了订单,它基本上消除了对客户端的任何依赖,以便完成订单工作流程。
推荐阅读
- android - 无法将诺基亚 6.1 Plus 连接到 Android Studio 以运行应用程序
- docker-compose - 如何从 Azure Pipeline 中的 Docker Compose Task 获取多容器应用程序的 URL?
- apache-spark - Spark Container 中的 Fluent-bit
- arrays - 如何将数组合并为一个
- python - 如何循环遍历json文件
- php - 如何用加号或减号显示数字字符串值
- python - 寻找将多列聚合到单行的“熊猫”方式
- graylog - 在 Graylog 中自动创建流
- mongodb - 如何根据 lat long mongodb 计算距离
- php - 有没有办法更改php中的默认链接?