feat: support register gift credits

This commit is contained in:
javayhu 2025-07-10 09:58:48 +08:00
parent 04f7f891a4
commit cd710bb9ed
3 changed files with 35 additions and 7 deletions

View File

@ -21,6 +21,11 @@ export async function getUserCredits(userId: string): Promise<number> {
return record[0]?.currentCredits || 0; return record[0]?.currentCredits || 0;
} }
/**
* Update user's current credit balance
* @param userId - User ID
* @param credits - New credit balance
*/
export async function updateUserCredits(userId: string, credits: number) { export async function updateUserCredits(userId: string, credits: number) {
const db = await getDb(); const db = await getDb();
await db await db
@ -29,6 +34,11 @@ export async function updateUserCredits(userId: string, credits: number) {
.where(eq(userCredit.userId, userId)); .where(eq(userCredit.userId, userId));
} }
/**
* Update user's last refresh time
* @param userId - User ID
* @param date - Last refresh time
*/
export async function updateUserLastRefreshAt(userId: string, date: Date) { export async function updateUserLastRefreshAt(userId: string, date: Date) {
const db = await getDb(); const db = await getDb();
await db await db
@ -63,11 +73,11 @@ export async function saveCreditTransaction({
type, type,
description description
); );
throw new Error('Invalid params'); throw new Error('saveCreditTransaction, invalid params');
} }
if (!Number.isFinite(amount) || amount === 0) { if (!Number.isFinite(amount) || amount === 0) {
console.error('saveCreditTransaction, invalid amount', userId, amount); console.error('saveCreditTransaction, invalid amount', userId, amount);
throw new Error('Invalid amount'); throw new Error('saveCreditTransaction, invalid amount');
} }
const db = await getDb(); const db = await getDb();
await db.insert(creditTransaction).values({ await db.insert(creditTransaction).values({
@ -107,18 +117,18 @@ export async function addCredits({
}) { }) {
if (!userId || !type || !description) { if (!userId || !type || !description) {
console.error('addCredits, invalid params', userId, type, description); console.error('addCredits, invalid params', userId, type, description);
throw new Error('Invalid params'); throw new Error('addCredits, invalid params');
} }
if (!Number.isFinite(amount) || amount <= 0) { if (!Number.isFinite(amount) || amount <= 0) {
console.error('addCredits, invalid amount', userId, amount); console.error('addCredits, invalid amount', userId, amount);
throw new Error('Invalid amount'); throw new Error('addCredits, invalid amount');
} }
if ( if (
expireDays !== undefined && expireDays !== undefined &&
(!Number.isFinite(expireDays) || expireDays <= 0) (!Number.isFinite(expireDays) || expireDays <= 0)
) { ) {
console.error('addCredits, invalid expire days', userId, expireDays); console.error('addCredits, invalid expire days', userId, expireDays);
throw new Error('Invalid expire days'); throw new Error('addCredits, invalid expire days');
} }
// Process expired credits first // Process expired credits first
await processExpiredCredits(userId); await processExpiredCredits(userId);
@ -194,11 +204,11 @@ export async function consumeCredits({
}) { }) {
if (!userId || !description) { if (!userId || !description) {
console.error('consumeCredits, invalid params', userId, description); console.error('consumeCredits, invalid params', userId, description);
throw new Error('Invalid params'); throw new Error('consumeCredits, invalid params');
} }
if (!Number.isFinite(amount) || amount <= 0) { if (!Number.isFinite(amount) || amount <= 0) {
console.error('consumeCredits, invalid amount', userId, amount); console.error('consumeCredits, invalid amount', userId, amount);
throw new Error('Invalid amount'); throw new Error('consumeCredits, invalid amount');
} }
// Process expired credits first // Process expired credits first
await processExpiredCredits(userId); await processExpiredCredits(userId);

View File

@ -9,6 +9,9 @@ export enum CREDIT_TRANSACTION_TYPE {
EXPIRE = 'EXPIRE', // Credits expired EXPIRE = 'EXPIRE', // Credits expired
} }
/**
* Credit package price
*/
export interface CreditPackagePrice { export interface CreditPackagePrice {
priceId: string; // Stripe price ID (not product id) priceId: string; // Stripe price ID (not product id)
amount: number; // Price amount in currency units (dollars, euros, etc.) amount: number; // Price amount in currency units (dollars, euros, etc.)

View File

@ -1,4 +1,6 @@
import { websiteConfig } from '@/config/website'; import { websiteConfig } from '@/config/website';
import { addCredits } from '@/credits/credits';
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
import { getDb } from '@/db/index'; import { getDb } from '@/db/index';
import { defaultMessages } from '@/i18n/messages'; import { defaultMessages } from '@/i18n/messages';
import { LOCALE_COOKIE_NAME, routing } from '@/i18n/routing'; import { LOCALE_COOKIE_NAME, routing } from '@/i18n/routing';
@ -129,6 +131,19 @@ export const auth = betterAuth({
console.error('Newsletter subscription error:', error); console.error('Newsletter subscription error:', error);
} }
} }
// Add register gift credits to the user if enabled in website config
if (
websiteConfig.credits.registerGiftCredits.enable &&
websiteConfig.credits.registerGiftCredits.credits > 0
) {
await addCredits({
userId: user.id,
amount: websiteConfig.credits.registerGiftCredits.credits,
type: CREDIT_TRANSACTION_TYPE.REGISTER_GIFT,
description: 'Register gift credits',
expireDays: websiteConfig.credits.registerGiftCredits.expireDays,
});
}
}, },
}, },
}, },