purchase / checkout flow

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-08-31 17:57:29 +08:00
parent 7413a296fb
commit 79203b1654
6 changed files with 40 additions and 19 deletions
@@ -310,13 +310,19 @@ exports.captureOrder = async (req, res) => {
const { order_id } = req.body;
if (!order_id) return R.error(res, 'order_id is required.', 400);
const payment = await mdl_Payments.findOne({
// Matched on provider_payload.order_id, not just "most recent pending" —
// a user can have more than one pending payment at once (e.g. abandoned
// Plan A via browser-back instead of PayPal's cancel button, then started
// checkout on Plan B); picking by recency would miss an older order that
// PayPal legitimately approved.
const pendingPayments = await mdl_Payments.findAll({
where: { status: 'pending', user_id: req.user.user_id },
include: [{ model: mdl_TierPlans, as: 'plan' }],
order: [['createdAt', 'DESC']],
});
const payment = pendingPayments.find((p) => p.provider_payload?.order_id === order_id);
if (!payment || payment.provider_payload?.order_id !== order_id)
if (!payment)
return R.error(res, 'Pending payment not found.', 404);
// Guard: plan was deactivated while user was on PayPal's approval page
@@ -433,12 +439,14 @@ exports.cancelOrder = async (req, res) => {
const { order_id } = req.body;
if (!order_id) return R.error(res, 'order_id is required.', 400);
const payment = await mdl_Payments.findOne({
// See captureOrder above for why this matches on order_id instead of recency.
const pendingPayments = await mdl_Payments.findAll({
where: { user_id: req.user.user_id, status: 'pending' },
order: [['createdAt', 'DESC']],
});
const payment = pendingPayments.find((p) => p.provider_payload?.order_id === order_id);
if (!payment || payment.provider_payload?.order_id !== order_id)
if (!payment)
return R.error(res, 'Pending payment not found.', 404);
await payment.update({