chore: add credits when subscription renewal and lifetime payment
This commit is contained in:
parent
b5997ded4c
commit
b4e8585929
@ -167,7 +167,6 @@ TURNSTILE_SECRET_KEY=""
|
|||||||
# https://mksaas.com/docs/jobs#setup
|
# https://mksaas.com/docs/jobs#setup
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
INNGEST_SIGNING_KEY=""
|
INNGEST_SIGNING_KEY=""
|
||||||
INNGEST_EVENT_KEY=""
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# AI
|
# AI
|
||||||
|
@ -120,7 +120,7 @@ export const websiteConfig: WebsiteConfig = {
|
|||||||
credits: {
|
credits: {
|
||||||
enable: true,
|
enable: true,
|
||||||
amount: 1000,
|
amount: 1000,
|
||||||
expireDays: 90,
|
expireDays: 30,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
lifetime: {
|
lifetime: {
|
||||||
@ -139,7 +139,7 @@ export const websiteConfig: WebsiteConfig = {
|
|||||||
credits: {
|
credits: {
|
||||||
enable: true,
|
enable: true,
|
||||||
amount: 2000,
|
amount: 2000,
|
||||||
expireDays: 120,
|
expireDays: 30,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -169,7 +169,7 @@ export const websiteConfig: WebsiteConfig = {
|
|||||||
id: 'standard',
|
id: 'standard',
|
||||||
popular: true,
|
popular: true,
|
||||||
credits: 200,
|
credits: 200,
|
||||||
expireDays: 60,
|
expireDays: 30,
|
||||||
price: {
|
price: {
|
||||||
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_STANDARD!,
|
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_STANDARD!,
|
||||||
amount: 1490,
|
amount: 1490,
|
||||||
@ -181,7 +181,7 @@ export const websiteConfig: WebsiteConfig = {
|
|||||||
id: 'premium',
|
id: 'premium',
|
||||||
popular: false,
|
popular: false,
|
||||||
credits: 500,
|
credits: 500,
|
||||||
expireDays: 90,
|
expireDays: 30,
|
||||||
price: {
|
price: {
|
||||||
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_PREMIUM!,
|
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_PREMIUM!,
|
||||||
amount: 3990,
|
amount: 3990,
|
||||||
@ -193,7 +193,7 @@ export const websiteConfig: WebsiteConfig = {
|
|||||||
id: 'enterprise',
|
id: 'enterprise',
|
||||||
popular: false,
|
popular: false,
|
||||||
credits: 1000,
|
credits: 1000,
|
||||||
expireDays: 120,
|
expireDays: 30,
|
||||||
price: {
|
price: {
|
||||||
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_ENTERPRISE!,
|
priceId: process.env.NEXT_PUBLIC_STRIPE_PRICE_CREDITS_ENTERPRISE!,
|
||||||
amount: 6990,
|
amount: 6990,
|
||||||
|
@ -354,45 +354,6 @@ export async function processExpiredCredits(userId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add subscription renewal credits
|
|
||||||
* @param userId - User ID
|
|
||||||
* @param priceId - Price ID
|
|
||||||
*/
|
|
||||||
export async function addSubscriptionRenewalCredits(
|
|
||||||
userId: string,
|
|
||||||
priceId: string
|
|
||||||
) {
|
|
||||||
const pricePlan = findPlanByPriceId(priceId);
|
|
||||||
if (
|
|
||||||
!pricePlan ||
|
|
||||||
pricePlan.isFree ||
|
|
||||||
!pricePlan.credits ||
|
|
||||||
!pricePlan.credits.enable
|
|
||||||
) {
|
|
||||||
console.log(
|
|
||||||
`addSubscriptionRenewalCredits, no credits configured for plan ${priceId}`
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const credits = pricePlan.credits.amount;
|
|
||||||
const expireDays = pricePlan.credits.expireDays;
|
|
||||||
const now = new Date();
|
|
||||||
|
|
||||||
await addCredits({
|
|
||||||
userId,
|
|
||||||
amount: credits,
|
|
||||||
type: CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL,
|
|
||||||
description: `Subscription renewal credits: ${credits} for ${now.getFullYear()}-${now.getMonth() + 1}`,
|
|
||||||
expireDays,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`addSubscriptionRenewalCredits, ${credits} credits for user ${userId}, priceId: ${priceId}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add register gift credits
|
* Add register gift credits
|
||||||
* @param userId - User ID
|
* @param userId - User ID
|
||||||
@ -492,6 +453,45 @@ export async function addMonthlyFreeCreditsIfNeed(userId: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add subscription renewal credits
|
||||||
|
* @param userId - User ID
|
||||||
|
* @param priceId - Price ID
|
||||||
|
*/
|
||||||
|
export async function addSubscriptionRenewalCredits(
|
||||||
|
userId: string,
|
||||||
|
priceId: string
|
||||||
|
) {
|
||||||
|
const pricePlan = findPlanByPriceId(priceId);
|
||||||
|
if (
|
||||||
|
!pricePlan ||
|
||||||
|
pricePlan.isFree ||
|
||||||
|
!pricePlan.credits ||
|
||||||
|
!pricePlan.credits.enable
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
`addSubscriptionRenewalCredits, no credits configured for plan ${priceId}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const credits = pricePlan.credits.amount;
|
||||||
|
const expireDays = pricePlan.credits.expireDays;
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
await addCredits({
|
||||||
|
userId,
|
||||||
|
amount: credits,
|
||||||
|
type: CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL,
|
||||||
|
description: `Subscription renewal credits: ${credits} for ${now.getFullYear()}-${now.getMonth() + 1}`,
|
||||||
|
expireDays,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`addSubscriptionRenewalCredits, ${credits} credits for user ${userId}, priceId: ${priceId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add lifetime monthly credits
|
* Add lifetime monthly credits
|
||||||
* @param userId - User ID
|
* @param userId - User ID
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import { randomUUID } from 'crypto';
|
import { randomUUID } from 'crypto';
|
||||||
import { addCredits, addSubscriptionRenewalCredits } from '@/credits/credits';
|
import { websiteConfig } from '@/config/website';
|
||||||
|
import {
|
||||||
|
addCredits,
|
||||||
|
addLifetimeMonthlyCreditsIfNeed,
|
||||||
|
addSubscriptionRenewalCredits,
|
||||||
|
} from '@/credits/credits';
|
||||||
import { getCreditPackageById } from '@/credits/server';
|
import { getCreditPackageById } from '@/credits/server';
|
||||||
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
||||||
import { getDb } from '@/db';
|
import { getDb } from '@/db';
|
||||||
import { payment, user } from '@/db/schema';
|
import { payment, user } from '@/db/schema';
|
||||||
import { findPlanByPlanId, findPriceInPlan } from '@/lib/price-plan';
|
import {
|
||||||
|
findPlanByPlanId,
|
||||||
|
findPlanByPriceId,
|
||||||
|
findPriceInPlan,
|
||||||
|
} from '@/lib/price-plan';
|
||||||
import { sendNotification } from '@/notification/notification';
|
import { sendNotification } from '@/notification/notification';
|
||||||
import { desc, eq } from 'drizzle-orm';
|
import { desc, eq } from 'drizzle-orm';
|
||||||
import { Stripe } from 'stripe';
|
import { Stripe } from 'stripe';
|
||||||
@ -580,6 +589,15 @@ export class StripeProvider implements PaymentProvider {
|
|||||||
`<< No payment record created for Stripe subscription ${stripeSubscription.id}`
|
`<< No payment record created for Stripe subscription ${stripeSubscription.id}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conditionally handle credits after subscription creation
|
||||||
|
if (websiteConfig.credits?.enableCredits) {
|
||||||
|
// Add subscription renewal credits if plan config enables credits
|
||||||
|
const pricePlan = findPlanByPriceId(priceId);
|
||||||
|
if (pricePlan?.credits?.enable) {
|
||||||
|
await addSubscriptionRenewalCredits(userId, priceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -771,6 +789,17 @@ export class StripeProvider implements PaymentProvider {
|
|||||||
`<< Created one-time payment record for user ${userId}, price: ${priceId}`
|
`<< Created one-time payment record for user ${userId}, price: ${priceId}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Conditionally handle credits after one-time payment
|
||||||
|
if (websiteConfig.credits?.enableCredits) {
|
||||||
|
// If the plan is lifetime and credits are enabled, add lifetime monthly credits if needed
|
||||||
|
const lifetimePlan = Object.values(
|
||||||
|
websiteConfig.price?.plans || {}
|
||||||
|
).find((plan) => plan.isLifetime && plan.credits?.enable);
|
||||||
|
if (lifetimePlan?.prices?.some((p) => p.priceId === priceId)) {
|
||||||
|
await addLifetimeMonthlyCreditsIfNeed(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Send notification
|
// Send notification
|
||||||
const amount = session.amount_total ? session.amount_total / 100 : 0;
|
const amount = session.amount_total ? session.amount_total / 100 : 0;
|
||||||
await sendNotification(session.id, customerId, userId, amount);
|
await sendNotification(session.id, customerId, userId, amount);
|
||||||
|
Loading…
Reference in New Issue
Block a user