Credit System
Learn how to integrate the credit system in EasyApp
Overview
The EasyApp Credit System is a complete user credit management solution that provides credit earning, spending, transaction records, and anti-abuse protection features. The system supports multiple credit sources including registration bonuses, subscriptions, in-app purchases, promotional activities, and includes comprehensive anti-fraud mechanisms.
Core Features
1. Credit Management
- FIFO Consumption Mechanism: Credits are consumed on a first-in-first-out basis, ensuring that earlier earned credits are used first
- Validity Period Support: Supports both permanent and temporary credits with configurable expiration times
- Multi-source Tracking: Detailed recording of credit sources (registration, subscription, purchase, promotion, refund, admin distribution, etc.)
- Real-time Balance Query: Quick retrieval of user credit balance, including permanent credits, temporary credits, and credits about to expire
2. Transaction System
- Complete Transaction Records: Detailed history of all credit operations including earning, spending, expiration, and refunds
- Balance Tracking: Records user balance changes after each transaction
- Batch Management: Supports batch credit operations for easy management and tracking
3. Feature Billing
- Flexible Billing: Set different credit consumption standards for different features
- Dynamic Configuration: Support for runtime adjustment of feature credit consumption costs
- Feature Toggle: Dynamically enable or disable billing for specific features
4. Anti-Abuse System
- Email Restrictions: Limit registration count and bonus distribution per email address
- Device Fingerprinting: Monitor device fingerprints to prevent multi-account abuse
- Risk Scoring: Calculate risk scores based on user behavior to automatically identify suspicious activities
- Cooldown Mechanism: Set cooldown periods for registration bonuses to prevent frequent account creation
5. In-App Purchase Integration
- RevenueCat Integration: Complete support for RevenueCat in-app purchase platform
- One-time Purchases: Support for credit package purchases, allowing users to directly buy credits
- Subscription Services: Support for monthly/yearly subscriptions with automatic credit distribution
Database Configuration
Credit Package Configuration (credit_packages)
Currently only supports configuring credit packages in SQL. A management system will be implemented later to support configuring credit packages without modifying SQL code, reducing the barrier to entry.
The credit packages table is used to configure one-time credit packages available for user purchase:
CREATE TABLE credit_packages (
id UUID PRIMARY KEY,
name TEXT NOT NULL, -- Credit package name
credits INTEGER NOT NULL, -- Credit amount
price DECIMAL(10,2) NOT NULL, -- Price
product_id TEXT UNIQUE NOT NULL, -- RevenueCat product ID
is_permanent BOOLEAN DEFAULT true, -- Whether it's permanent credits
is_active BOOLEAN DEFAULT true, -- Whether enabled
sort_order INTEGER DEFAULT 0 -- Sort order
);RevenueCat In-App Purchase Product Configuration Example:
INSERT INTO credit_packages (name, credits, price, product_id) VALUES
('Starter Pack', 1000, 9.99, 'easyapp_credits_1000'),
('Popular Pack', 5000, 39.99, 'easyapp_credits_5000'),
('Professional Pack', 10000, 69.99, 'easyapp_credits_10000'),
('Value Pack', 50000, 299.99, 'easyapp_credits_50000');Configuration Points:
product_idmust exactly match the product ID in the RevenueCat console- Credit packages are typically set as permanent credits (
is_permanent = true) - Control display order in the app through
sort_order - Temporarily disable specific credit packages through
is_active
Subscription Product Configuration (subscription_products)
The subscription products table is used to configure monthly/yearly subscription services:
CREATE TABLE subscription_products (
id UUID PRIMARY KEY,
product_id TEXT UNIQUE NOT NULL, -- RevenueCat subscription product ID
product_name TEXT NOT NULL, -- Product name
subscription_type TEXT NOT NULL, -- Subscription type: 'monthly' or 'yearly'
credits_per_month INTEGER NOT NULL, -- Credits distributed per month
price DECIMAL(10,2), -- Price
currency TEXT DEFAULT 'USD', -- Currency unit
is_active BOOLEAN DEFAULT true -- Whether enabled
);RevenueCat Subscription Product Configuration Example:
INSERT INTO subscription_products (
product_id, product_name, subscription_type, credits_per_month, price
) VALUES
('subscription_credit_monthly_basic_1', 'Premium Monthly', 'monthly', 2000, 9.99),
('subscription_credit_yearly_basic_1', 'Premium Yearly', 'yearly', 2000, 83.99);Configuration Points:
product_idmust exactly match the subscription product ID in the RevenueCat console- Monthly and yearly subscriptions typically set the same
credits_per_month(yearly users get the same monthly credits) - Yearly subscription prices are usually cheaper than monthly price × 12 (like the 30% discount in the example)
- The system automatically handles credit distribution cycles based on subscription type
Feature Billing Configuration (feature_credit_costs)
The feature billing table defines credit consumption standards for various features:
INSERT INTO feature_credit_costs (feature_name, credit_cost, description) VALUES
('text2image', 100, 'Text to Image Generation'),
('image2image', 150, 'Image to Image Conversion'),
('receipt_analysis', 50, 'Receipt Analysis'),
('receipt_analysis_pro', 100, 'Advanced Receipt Analysis');RevenueCat Integration Configuration
1. Product ID Mapping
Credit Packages
- RevenueCat Product ID →
credit_packages.product_id - Used for one-time credit package purchases
- Credits are distributed immediately after successful purchase
Next, let's introduce how to create one-time credit package products.
You must have an Apple Developer account and have already created an App to create one-time credit package products. If you forgot how to create in-app purchase products, you can refer back to
1: First, go to App Store Connect and select In-App Purchases. Since we're creating one-time credit package products, select In-App Purchases, not Subscriptions.

Click + to create a one-time credit package product.
Select Type as Consumable, representing consumable products. (Credits are consumable products)
Reference Name and Product ID: The Product ID should match the product_id field you defined in the credit_packages table. It must be consistent because during purchase, it determines which credit package is being purchased based on product_id.
As for Reference Name, you can make it the same as product_id or different - this is your own definition.
The Product ID should match the product_id field you defined in the credit_packages table. It must be consistent because during purchase, it determines which credit package is being purchased.
When setting the price, also keep it consistent with the price field you defined in the credit_packages table.
The "Learn how to integrate RevenueCat" chapter provides detailed instructions on how to create in-app purchase products, including: internationalization, sales scope, and required screenshots for review. If you forgot, you can refer back. We won't repeat how to create in-app purchase products here.
RevenueCat
Learn how to integrate RevenueCat service
Using EasyApp as an example, here's how to fill it out: According to the credit_packages table, 4 credit packages were created

2: Next, configure RevenueCat
Login to RevenueCat

-
Select
Product catalog -
Select
Product -
Select
New Product -
Click
New Product

It will automatically pull the in-app purchase products you just created. Select your desired credit packages.
After importing the in-app purchase products, we need to configure Offerings. EasyApp will pull credit packages based on Offerings.

Click New Offering

- Fill in your
Identifier,Display Name, andPackages. ForPackagesIdentifier, you can chooseCustom, and forProduct, select the in-app purchase products you just imported.

Using EasyApp as an example, fill it out as follows:

Again emphasizing:
The Product ID should match the product_id field you defined in the credit_packages table. It must be consistent because during purchase, it determines which credit package is being purchased.
When setting the price, also keep it consistent with the price field you defined in the credit_packages table.
3: Go to the EasyAppSwiftUI project, and in the Constants/Constants.swift file, configure the creditPackagesEntitlementID value for RevenueCat.
enum RevenueCat {
// ...
/// Credit Packages entitlement ID
static let creditPackagesEntitlementID = "easyapp_credits"
// ...
}At this point, the credit package configuration is completely finished.
Subscriptions
- RevenueCat Product ID →
subscription_products.product_id - Used for monthly/yearly subscription services
- Automatically distribute credits based on subscription cycle
The steps for subscription products are the same as credit packages, except you're configuring subscription products.

For the remaining steps, please refer to the article below
Fill in the subscription product's price, id, name, and subscription duration. This section is covered in detail in RevenueCat subscription product creation, please check.
Using EasyApp as an example, our created subscription product information is as follows:

1: After creating the subscription in App Store Connect, return to RevenueCat to configure Offerings.
2: In the steps above for creating credit packages, we've already detailed how to configure Offerings. We won't repeat it here.
3: For subscription products, in addition to creating Offerings, we also need to create Entitlements.

- Fill in
Identifier - Fill in
Description - Associate with the subscription products you created in App Store Connect
Using EasyApp as an example, the created Entitlements are filled out as follows:

4: Go to the EasyAppSwiftUI project, and in the Constants/Constants.swift file, configure the creditSubscriptionEntitlementID value for RevenueCat.
enum RevenueCat {
// ...
/// Credit Packages entitlement ID
static let creditSubscriptionEntitlementID = "subscription_credit"
// ...
}When creating subscription products: The Product ID should match the product_id field you defined in the subscription_products table. It must be consistent because during purchase, it determines which subscription product is being purchased.
When setting the price, also keep it consistent with the price field you defined in the subscription_products table.
2. Webhook Configuration
The system automatically handles purchase and subscription events through RevenueCat Webhook:
Supported Event Types:
INITIAL_PURCHASE: First purchase/subscriptionRENEWAL: Subscription renewalCANCELLATION: Subscription cancellationEXPIRATION: Subscription expirationPRODUCT_CHANGE: Subscription upgrade/downgradeBILLING_ISSUE: Payment issues
Webhook URL Configuration:
https://your-project.supabase.co/functions/v1/subscription-webhookFor development environment webhook URL configuration, we recommend using ngrok for setup.
For ngrok installation and usage, please refer to ngrok.
Execute the command:
ngrok http 54321Then configure RevenueCat's Webhook URL as https://your-ngrok-url/functions/v1/subscription-webhook.
As shown in the figure below:

When we're ready to go live, don't forget to configure the production environment Webhook URL. RevenueCat supports configuring multiple Webhook URLs. You can add a new Webhook URL and specifically configure the production environment Webhook URL.
Renewal Trigger Time:
For the test environment, sandbox subscription trigger time can be configured in App Store Connect. That is, if you set it to 5-minute intervals, the Webhook URL will trigger every 5 minutes.

3. User ID Mapping
We have already set RevenueCat's app_user_id to the Supabase user's UUID during EasyApp login, ensuring the system can correctly identify user identity.
// logInRevenueCat
try await logInRevenueCat(userId: response.user.id.lowercasedString)System Configuration
Dynamic Configuration System
The system supports runtime dynamic configuration adjustment without service restart:
Credit System Configuration (system_config.credit_system):
{
"enabled": true,
"registration_bonus": 3000,
"enable_anti_abuse": true,
"refund_on_failure": true
}Feature Toggle Configuration (system_config.features):
{
"image_generation": true,
"receipt_analysis": true
}Anti-Abuse Configuration (system_config.anti_abuse):
{
"max_registrations_per_email": 1,
"max_bonus_per_email": 3000,
"max_accounts_per_device": 10,
"registration_cooldown_days": 30,
"risk_score_threshold": 70,
"refund_time_limit_hours": 24
}Security Features
- Row Level Security (RLS): All data tables have RLS enabled, ensuring users can only access their own data
- Permission Control: Edge Functions use Service Role for management operations
- Parameter Validation: Strict parameter validation for all interfaces
- Duplicate Prevention: Ensure Webhook events are not processed repeatedly through event IDs
- Audit Logging: Complete audit trail for all credit operations
Best Practices
- Regular Cleanup: Recommend regular cleanup of expired credit records and transaction logs
- Monitoring Alerts: Set up monitoring alerts for abnormal credit consumption and batch operations
- Performance Optimization: Use pre-computed views to improve credit balance query performance
- Backup Strategy: Regularly backup credit-related data to ensure data security
- Test Validation: Thoroughly test in sandbox environment before production deployment
Through the above configuration and integration, you will have a fully functional, secure, and reliable credit management system that supports various business scenarios and monetization models.
Last updated on