Migrate billing from Paddle to Lemon Squeezy

This commit is contained in:
Codex Agent
2026-02-03 10:59:54 +01:00
parent 2f4ebfefd4
commit a0ef90e13a
228 changed files with 4369 additions and 4067 deletions

View File

@@ -5,70 +5,70 @@ return [
'reminder_days' => 7,
'expiry_reminder_days' => 14,
// Map voucher tiers to Paddle price IDs (create matching prices in Paddle Billing).
// Map voucher tiers to Lemon Squeezy variant IDs (create matching variants in Lemon Squeezy).
'tiers' => [
[
'key' => 'gift-starter',
'label' => 'Geschenk Starter',
'amount' => 29.00,
'currency' => 'EUR',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STARTER', 'pri_01kbwccfe1mpwh7hh60eygemx6'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STARTER'),
],
[
'key' => 'gift-starter-usd',
'label' => 'Gift Starter (USD)',
'amount' => 32.00,
'currency' => 'USD',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STARTER_USD'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STARTER_USD'),
],
[
'key' => 'gift-starter-gbp',
'label' => 'Gift Starter (GBP)',
'amount' => 25.00,
'currency' => 'GBP',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STARTER_GBP'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STARTER_GBP'),
],
[
'key' => 'gift-standard',
'label' => 'Geschenk Classic',
'amount' => 59.00,
'currency' => 'EUR',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STANDARD', 'pri_01kbwccfvzrf4z2f1r62vns7gh'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STANDARD'),
],
[
'key' => 'gift-standard-usd',
'label' => 'Gift Classic (USD)',
'amount' => 65.00,
'currency' => 'USD',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STANDARD_USD'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STANDARD_USD'),
],
[
'key' => 'gift-standard-gbp',
'label' => 'Gift Classic (GBP)',
'amount' => 55.00,
'currency' => 'GBP',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_STANDARD_GBP'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_STANDARD_GBP'),
],
[
'key' => 'gift-premium',
'label' => 'Geschenk Premium',
'amount' => 129.00,
'currency' => 'EUR',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_PREMIUM', 'pri_01kbwccg8vjc5cwz0kftfvf9wm'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_PREMIUM'),
],
[
'key' => 'gift-premium-usd',
'label' => 'Gift Premium (USD)',
'amount' => 139.00,
'currency' => 'USD',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_PREMIUM_USD'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_PREMIUM_USD'),
],
[
'key' => 'gift-premium-gbp',
'label' => 'Gift Premium (GBP)',
'amount' => 119.00,
'currency' => 'GBP',
'paddle_price_id' => env('PADDLE_GIFT_PRICE_PREMIUM_GBP'),
'lemonsqueezy_variant_id' => env('LEMONSQUEEZY_GIFT_VARIANT_PREMIUM_GBP'),
],
],

12
config/lemonsqueezy.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
$testMode = filter_var(env('LEMONSQUEEZY_TEST_MODE', false), FILTER_VALIDATE_BOOLEAN);
return [
'api_key' => env('LEMONSQUEEZY_API_KEY'),
'store_id' => env('LEMONSQUEEZY_STORE_ID', '284860'),
'test_mode' => $testMode,
'webhook_secret' => env('LEMONSQUEEZY_WEBHOOK_SECRET'),
'webhook_events' => array_filter(array_map('trim', explode(',', (string) env('LEMONSQUEEZY_WEBHOOK_EVENTS', 'order_created,order_updated,order_payment_failed,order_refunded,subscription_created,subscription_updated,subscription_cancelled,subscription_expired,subscription_paused')))),
'base_url' => env('LEMONSQUEEZY_BASE_URL', 'https://api.lemonsqueezy.com/v1'),
];

View File

@@ -80,14 +80,14 @@ return [
'days' => env('LOG_DAILY_DAYS', 14),
'replace_placeholders' => true,
],
'paddle-sync' => [
'lemonsqueezy-sync' => [
'driver' => 'stack',
'channels' => explode(',', env('PADDLE_SYNC_LOG_STACK', 'paddle-sync-file')),
'channels' => explode(',', env('LEMONSQUEEZY_SYNC_LOG_STACK', 'lemonsqueezy-sync-file')),
'ignore_exceptions' => false,
],
'paddle-sync-file' => [
'lemonsqueezy-sync-file' => [
'driver' => 'daily',
'path' => storage_path('logs/paddle-sync.log'),
'path' => storage_path('logs/lemonsqueezy-sync.log'),
'level' => env('LOG_LEVEL', 'info'),
'days' => env('LOG_DAILY_DAYS', 14),
'replace_placeholders' => true,

View File

@@ -1,31 +1,31 @@
<?php
return [
// Keyed add-ons with display and Paddle mapping. Amounts are base increments; multiply by quantity.
// Keyed add-ons with display and Lemon Squeezy mapping. Amounts are base increments; multiply by quantity.
'extra_photos_small' => [
'label' => 'Extra photos (500)',
'price_id' => env('PADDLE_ADDON_EXTRA_PHOTOS_SMALL_PRICE_ID'),
'variant_id' => env('LEMONSQUEEZY_ADDON_EXTRA_PHOTOS_SMALL_VARIANT_ID'),
'increments' => [
'extra_photos' => 500,
],
],
'extra_photos_large' => [
'label' => 'Extra photos (2,000)',
'price_id' => env('PADDLE_ADDON_EXTRA_PHOTOS_LARGE_PRICE_ID'),
'variant_id' => env('LEMONSQUEEZY_ADDON_EXTRA_PHOTOS_LARGE_VARIANT_ID'),
'increments' => [
'extra_photos' => 2000,
],
],
'extra_guests' => [
'label' => 'Extra guests (100)',
'price_id' => env('PADDLE_ADDON_EXTRA_GUESTS_PRICE_ID'),
'variant_id' => env('LEMONSQUEEZY_ADDON_EXTRA_GUESTS_VARIANT_ID'),
'increments' => [
'extra_guests' => 100,
],
],
'extend_gallery_30d' => [
'label' => 'Gallery extension (30 days)',
'price_id' => env('PADDLE_ADDON_EXTEND_GALLERY_30D_PRICE_ID'),
'variant_id' => env('LEMONSQUEEZY_ADDON_EXTEND_GALLERY_30D_VARIANT_ID'),
'increments' => [
'extra_gallery_days' => 30,
],

View File

@@ -1,48 +0,0 @@
<?php
$sandbox = filter_var(env('PADDLE_SANDBOX', false), FILTER_VALIDATE_BOOLEAN);
$environment = env('PADDLE_ENVIRONMENT', $sandbox ? 'sandbox' : 'production');
$apiKey = env('PADDLE_API_KEY') ?: env('PADDLE_SANDBOX_API_KEY');
$clientToken = $sandbox
? (env('PADDLE_SANDBOX_CLIENT_TOKEN') ?: env('PADDLE_SANDBOX_CLIENT_ID') ?: env('PADDLE_CLIENT_TOKEN') ?: env('PADDLE_CLIENT_ID'))
: (env('PADDLE_CLIENT_TOKEN') ?: env('PADDLE_CLIENT_ID'));
$webhookSecret = env('PADDLE_WEBHOOK_SECRET') ?: ($sandbox ? env('PADDLE_SANDBOX_WEBHOOK_SECRET') : null);
$publicKey = env('PADDLE_PUBLIC_KEY') ?: ($sandbox ? env('PADDLE_SANDBOX_PUBLIC_KEY') : null);
$baseUrl = env('PADDLE_BASE_URL');
if (! $baseUrl) {
$baseUrl = $sandbox ? 'https://sandbox-api.paddle.com' : 'https://api.paddle.com';
}
$consoleUrl = env('PADDLE_CONSOLE_URL');
if (! $consoleUrl) {
$consoleUrl = $sandbox ? 'https://sandbox-dashboard.paddle.com' : 'https://dashboard.paddle.com';
}
return [
'api_key' => $apiKey,
'client_token' => $clientToken,
'environment' => $environment,
'base_url' => $baseUrl,
'console_url' => $consoleUrl,
'webhook_secret' => $webhookSecret,
'public_key' => $publicKey,
'webhook_events' => [
'transaction.created',
'transaction.processing',
'transaction.completed',
'transaction.failed',
'transaction.cancelled',
'subscription.created',
'subscription.updated',
'subscription.paused',
'subscription.resumed',
'subscription.cancelled',
'subscription.past_due',
],
];

View File

@@ -45,11 +45,11 @@ return [
'sandbox' => env('PAYPAL_SANDBOX', true),
],
'paddle' => [
'api_key' => env('PADDLE_API_KEY'),
'client_id' => env('PADDLE_CLIENT_ID'),
'sandbox' => env('PADDLE_SANDBOX', false),
'webhook_secret' => env('PADDLE_WEBHOOK_SECRET'),
'lemonsqueezy' => [
'api_key' => env('LEMONSQUEEZY_API_KEY'),
'store_id' => env('LEMONSQUEEZY_STORE_ID'),
'webhook_secret' => env('LEMONSQUEEZY_WEBHOOK_SECRET'),
'test_mode' => env('LEMONSQUEEZY_TEST_MODE', false),
],
'google' => [

View File

@@ -60,7 +60,7 @@ return [
'resources' => [
'tenants' => [
'model' => Tenant::class,
'search' => ['name', 'slug', 'contact_email', 'paddle_customer_id'],
'search' => ['name', 'slug', 'contact_email', 'lemonsqueezy_customer_id'],
'with' => ['user', 'activeResellerPackage'],
'abilities' => [
'read' => ['support:read'],