mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
revise ads and alerts
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
/***********************************************************************************************************************************************************************
|
||||
* File Name : fail_stale_payments.cron.js
|
||||
* Type : Cron Job
|
||||
* Description : Marks abandoned checkout attempts as 'failed' instead of
|
||||
* leaving them stuck on 'pending' forever.
|
||||
*
|
||||
* A payment/purchase row is created as 'pending' the moment
|
||||
* PayPal's create-order call succeeds (createOrder / createCourseOrder),
|
||||
* before the buyer ever reaches PayPal's approval page. If PayPal's
|
||||
* own hosted checkout then fails to load ("Things don't appear to
|
||||
* be working at the moment") or the buyer just abandons the tab,
|
||||
* the browser never gets redirected back to our return_url/cancel_url —
|
||||
* so captureOrder/cancelOrder is never called, and the row sits as
|
||||
* 'pending' indefinitely even though no money ever moved.
|
||||
*
|
||||
* This job sweeps 'pending' rows older than STALE_MINUTES and
|
||||
* marks them 'failed', so payment history correctly reflects
|
||||
* that nothing was charged, instead of silently doing nothing.
|
||||
*
|
||||
* Schedule : Every 10 minutes ("*\/10 * * * *"). Registered by cron/client.cron.js.
|
||||
*
|
||||
* Author: Kenneth Obsequio (@lash0000)
|
||||
* Date Created: Aug. 3, 2026
|
||||
***********************************************************************************************************************************************************************/
|
||||
'use strict';
|
||||
|
||||
const { Op } = require('sequelize');
|
||||
const mdl_Payments = require('../../models/tiers/payments.mdl');
|
||||
const mdl_CoursePurchase = require('../../models/courses/course_purchases.mdl');
|
||||
|
||||
const STALE_MINUTES = 30;
|
||||
|
||||
async function run() {
|
||||
const cutoff = new Date(Date.now() - STALE_MINUTES * 60_000);
|
||||
|
||||
try {
|
||||
const stalePayments = await mdl_Payments.findAll({
|
||||
where: { status: 'pending', createdAt: { [Op.lt]: cutoff } },
|
||||
});
|
||||
|
||||
for (const payment of stalePayments) {
|
||||
await payment.update({
|
||||
status: 'failed',
|
||||
provider_payload: {
|
||||
...payment.provider_payload,
|
||||
failed_reason: 'abandoned_checkout',
|
||||
marked_failed_at: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (stalePayments.length) {
|
||||
console.log(`[CRON][FAIL STALE PAYMENTS] Marked ${stalePayments.length} abandoned tier payment(s) as failed.`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[CRON][FAIL STALE PAYMENTS] Failed sweeping payments:', err);
|
||||
}
|
||||
|
||||
try {
|
||||
const stalePurchases = await mdl_CoursePurchase.findAll({
|
||||
where: { status: 'pending', createdAt: { [Op.lt]: cutoff } },
|
||||
});
|
||||
|
||||
for (const purchase of stalePurchases) {
|
||||
await purchase.update({
|
||||
status: 'failed',
|
||||
provider_payload: {
|
||||
...purchase.provider_payload,
|
||||
failed_reason: 'abandoned_checkout',
|
||||
marked_failed_at: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (stalePurchases.length) {
|
||||
console.log(`[CRON][FAIL STALE PAYMENTS] Marked ${stalePurchases.length} abandoned course purchase(s) as failed.`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[CRON][FAIL STALE PAYMENTS] Failed sweeping course purchases:', err);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
name: 'failStalePayments',
|
||||
schedule: '*/10 * * * *',
|
||||
run,
|
||||
};
|
||||
Reference in New Issue
Block a user