【发布时间】:2021-12-09 11:54:36
【问题描述】:
我对 Node 和 mongoose 还是很陌生,我正在尝试在我的节点服务器中实现传入订单的事务以处理 4 个进程并在其中任何一个进程失败时中止,但应用程序崩溃并出现 Unhandled 'error' event错误。
操作顺序为:
- 更新产品销售/可用数量
- 获取商店的 Stripe 详细信息
- 获取客户 Stripe 详细信息
- 下订单
如果在第 3 点客户没有保存的默认付款方式,我只发送一个响应,在客户端应用程序中将提示用户注册一个,并抛出一个错误,该错误应该被捕获并中止交易恢复销售的产品/可用数量恢复为以前的值。
因此,对于事务,我是 mongoose 文档中的 try{} catch{} finally{} 范围。
问题是,当我抛出 new Error('User has not registered a default_Method'); 应用程序崩溃并出现 Unhandled 'error' event 错误时,我没有正确处理/处理错误和/或正确使用事务 API。
你能看出我做错了什么吗? 非常感谢。
exports.createOrder = async (req, res) => {
const { productIdList, productPromotionList, customerId, shopId } = req.body;
console.log('createOreder req.body is : ', req.body);
var amount = 0.00;
var stripeAccountId = '';
var stripeCustomerId = '';
var receiptEmail = '';
var defaultSource = '';
const session = await Order.startSession();
session.startTransaction();
// modify product records
const ids = productIdList;
const isPromotion = productPromotionList;
for (var i = 0; i < ids.length; i++) {
if (isPromotion[i] == false) {
await Product.findByIdAndUpdate(
ids[i],
{
$inc: { soldQuantity: 1, availableQuantity: -1 },
},
{ new: true },
function (err, result) {
if (err) {
console.log('Mongoose Order.createOrder / Product.update error: ', err);
res.status(503).send({ error: "Internal error." });
session.abortTransaction();
return;
}
console.log('Mongoose Order.createOrder / Product.update Inventory updated successfully for product:', result);
});
} else {
await Promotion.findByIdAndUpdate(
ids[i],
{
$inc: { soldQuantity: 1, availableQuantity: -1 },
},
{ new: true },
function (err, result) {
if (err) {
console.log('Mongoose Order.createOrder / Promotion.update error: ', err);
res.status(503).send({ error: "Internal error." });
session.abortTransaction();
return;
}
console.log('Mongoose Order.createOrder / Promotion.update Inventory updated successfully for promotion:', result);
});
}
}
// get customer stipe id
await Shop.findById(
shopId,
function (err, result) {
if (err) {
console.log('Mongoose createOrder / Shop.findById error: ', err);
res.status(503).send({ error: "Internal error." });
session.abortTransaction();
return;
}
if (result != null) {
console.log("Mongoose createOrder / Shop.findById: ", result);
if (result.stripeDetails) {
stripeAccountId = result.stripeDetails.id;
} else {
console.log('Mongoose createOrder / Shop.findById: shop has no stripe id');
res.status(503).send({ error: "Internal error." });
session.abortTransaction();
return;
}
} else {
console.log("Mongoose createOrder / Shop.findById: Shop not found");
res.status(404).send({ error: "Shop not found." });
session.abortTransaction();
return;
}
}
);
// get customer stripe credentials
await User.findById(
customerId,
function (err, result) {
if (err) {
console.log('Mongoose createOrder / User.findOneById error: ', err);
res.status(503).send({ error: "Internal error." });
throw err;
return;
}
if (result != null) {
console.log("Mongoose createOrder / User.findOneById: ", result);
if (result.stripeDetails) {
stripeCustomerId = result.stripeDetails.id;
} else {
console.log('Mongoose createOrder / User.findOneById: User has no stripe id');
res.status(404).send({ message: "User has no stripe id" });
session.abortTransaction();
return;
}
// check if user has registered a pyment_method
if (result.stripeDetails.default_source != null) {
defaultSource = result.stripeDetails.default_source;
receiptEmail = result.stripeDetails.email;
} else {
console.log('Mongoose createOrder / User.findOneById: User has not registered a default_Method');
res.status(402).send({ message: "Stripe: Default Payment Required" });
/// unhandled error and app crashes
session.abortTransaction();
return;
}
} else {
console.log('Mongoose createOrder / User.findOneById: User not found');
res.status(404).send({ error: "User not found." });
session.abortTransaction();
return;
}
}
).catch((e) => {
console.log('User.findById .catch() error is :', e)
});
/// save order + create stripe payment
await Order.create(
req.body,
function (err, result) {
if (err) {
console.log('Mongoose createOrder error: Order.create', error);
res.statut(503).send({ error: "Internal error" });
session.abortTransaction();
return;
}
/// create charge/payment
// stripe.paymentIntents.create({
// customer: stripeCustomerId,
// receipt_email: receiptEmail,
// account: stripeAccountId,
// default_source: defaultSource,
// confirm: true,
// setup_future_usage: "on_session",// makes it pay in one go
// amount: amount,
// application_fee_amount: (amount * 0.13) + 25,
// currency: "eur",
// paymentMethods: ["card"],
// description: `Payment for order: ${result.id}`,
// on_behalf_of: stripeCustomerId,
// })
// .then(paymentIntent => {
// console.log('Mongoose createOrder stripe paymentIntent: ', paymentIntent);
// result.set('stripePayment', paymentIntent);
// result.save();
// })
// .catch(error => {
// console.log('Mongoose createOrder stripe paymentIntent error: ', error);
// });
console.log('Mongoose createOrder: ', result);
res.status(200).send({
message: "Order created successfully!",
data: result
});
});
await session.commitTransaction();
session.endSession();
}
【问题讨论】:
标签: node.js mongoose transactions