I want to achieve the following when I cancel my subscription:
nextBillingTime: 2024-05-10T14:59:58.582+00:00
paypalSubscriptionCancelledAt: 2024-05-07T11:59:18.000+00:00
subscriptionPeriodDuration: 3 days, 3 hours, 0 minutes, 40 seconds
I have the following code:
paypalRouter.post("/cancel-subscription/webhook", async (req, res) => {
try {
const webhookEvent = req.body;
if (verifyResponse.data.verification_status === "SUCCESS") {
if (webhookEvent.event_type === "BILLING.SUBSCRIPTION.CANCELLED") {
const userId = webhookEvent.resource.custom_id;
const subscriptionId = webhookEvent.resource.id;
const nextBillingTime = webhookEvent.resource.billing_info.next_billing_time;
const paypalSubscriptionCancelledAt = webhookEvent.resource.status_update_time;
try {
const updatedUserCancelSubscription = await User.findOneAndUpdate(
{ _id: userId, subscriptionId: subscriptionId },
{
$set: {
suscriptionStatusCancelled: true,
subscriptionStatusPending: false,
subscriptionStatusConfirmed: false,
nextBillingTime: nextBillingTime,
isPremium: true,
paypalSubscriptionCancelledAt: paypalSubscriptionCancelledAt,
subscriptionPeriodDuration:
},
},
{ new: true }
);
// ... (other code)
} catch (error) {
// ... (error handling)
}
}
} else {
// ... (other code)
}
} catch (error) {
// ... (error handling)
}
});
I need help calculating the subscriptionPeriodDuration
using the nextBillingTime
and paypalSubscriptionCancelledAt
dates.
Thank you all for the help. After a bit of struggle, I realized that my logic was incorrect. Instead of focusing on PayPalSubscriptionCancelledAt
and subscriptionPeriodDuration
, which are static dates, I should create a dynamic date to update nextBillingTime
according to my logic. In my case, I created a new property in my mongoose.Schema()
getCurrentTimeAfterRefresh
, which is a dynamic date and updates each day thanks to node-cron
, and I can create the desired logic. Here is the solution to my problem:
getCurrentTimeAfterRefresh:{
type: Date,
required: false,
},
Implementing node-cron
let cronJobs = {};
if (!cronJobs[userId]) {
//* this is updated each second
// cronJobs[userId] = cron.schedule("* * * * * *", async () => {
//* this is updated each day
cronJobs[userId] = cron.schedule("0 0 * * *", async () => {
try {
// const users = await User.find({ suscriptionStatusCancelled: true });
const user = await User.findById(userId);
if (!user) {
console.log(`User not found: ${userId}. Stopping cron job.`);
cronJobs[userId].stop();
delete cronJobs[userId];
return;
}
user.getCurrentTimeAfterRefresh = new Date();
console.log(`Updated getCurrentTimeAfterRefresh for user: ${user._id} to ${user.getCurrentTimeAfterRefresh}`);
if (user.suscriptionStatusCancelled == true && user.getCurrentTimeAfterRefresh > user.nextBillingTime) {
user.isPremium = false;
console.log(`Subscription expired for user: ${user._id}. Stopping cron job.`);
// Stop the cron job and delete it from the object
cronJobs[user._id].stop();
delete cronJobs[user._id];
}
await user.save();
console.log("Updated subscription times and statuses for cancelled subscriptions");
} catch (error) {
console.error("Error updating subscription times and statuses:", error);
}
});
}