Paddle Setup
This guide explains how Laratic integrates with Paddle Billing via Laravel Cashier Paddle and how to configure your Paddle account, sandbox mode, and environment variables.
1. Create Paddle Sandbox Account
Sign up for a Paddle sandbox account complete all onboarding steps in the Paddle dashboard before continuing.
2. Enable Sandbox Mode
For development and testing, enable Sandbox mode in the Paddle dashboard > Developer Tools > Authentication. Create the following tokens:
- API key
- Client side token
These values should be stored in your .env file; see the example in the code snippet below.
PADDLE_SANDBOX=true # Do not add this to your production environment
PADDLE_CLIENT_SIDE_TOKEN=XXXXXXXXXXXXXXXXXXXXX
PADDLE_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PADDLE_WEBHOOK_SECRET=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX # After you create the webhook in the Paddle dashboard
After changing these values, clear and cache your configuration:
php artisan config:clear
php artisan config:cache
3. Add App URL to Checkout Overlay Tab
Laratic uses the Checkout Overlay feature to display the Paddle checkout overlay. You need to add your app URL to the Checkout Overlay tab in the Paddle dashboard > Checkout > Checkout Settings > General > Default Payment Linke. in developmene you can use https://127.0.0.1:8000.
See the dedicated Paddle Webhooks page for details on configuring and testing webhooks.
Webhooks
Webhooks are used to receive events from Paddle and keep your local database in sync. See the dedicated Paddle Webhooks page for details on configuring and testing webhooks.
Switching Between Sandbox & Production
When you are ready to go live:
- Set
PADDLE_SANDBOX=false. - Replace your sandbox credentials with live Paddle Vendor ID, auth code, and public key.
- Verify that webhooks are configured for the live environment.
Always test new billing flows thoroughly in sandbox before switching your production credentials.
References
| Category | Path / Name | Description |
|---|---|---|
| Model | App\Models\Order | Order model with Paddle transaction relationship |
| Model | App\Models\Plan | Subscription plan model with Paddle price ID |
| Model | App\Models\Product | One-time product model with Paddle price ID |
| Controller | App\Http\Controllers\PlanController | Handles subscription plan viewing and checkout |
| Controller | App\Http\Controllers\ProductController | Handles one-time product viewing and checkout |
| Controller | App\Http\Controllers\OrderController | Handles user order viewing and status checks |
| Controller | App\Http\Controllers\TransactionController | Handles user transaction viewing and invoice downloads |
| Controller | App\Http\Controllers\SubscriptionController | Handles subscription status and pending pages |
| Controller | App\Http\Controllers\Admin\OrderController | Admin controller for viewing orders and transactions |
| Livewire | App\Livewire\Subscription\Manage | Subscription management component (swap, cancel, update payment) |
| Livewire | App\Livewire\Orders\OrdersTable | User orders table with search and pagination |
| Livewire | App\Livewire\Transactions\TransactionsTable | User transactions table with pagination |
| Livewire | App\Livewire\Admin\Subscription\CancelSubscription | Admin component for canceling user subscriptions |
| Livewire | App\Livewire\Admin\Transactions\TransactionsTable | Admin transactions table component |
| Listener | App\Listeners\PaddleEventListener | Handles Paddle webhook events (price.created, price.updated, transaction.completed) |
| Helper | app/Helpers/paddle_helpers.php | Helper functions for processing Paddle webhook payloads |
| Command | App\Console\Commands\DeleteOldIncompleteOrders | Artisan command to clean up incomplete orders older than 24 hours |
| Migration | create_orders_table | Migration for orders table with paddle_id field |
| Migration | create_plans_table | Migration for plans table with paddle_id field |
| Migration | create_products_table | Migration for products table with paddle_id field |
| Migration | create_subscriptions_table | Laravel Cashier migration for subscriptions with paddle_id |
| Migration | create_customers_table | Laravel Cashier migration for customers with paddle_id |
| Migration | create_transactions_table | Laravel Cashier migration for transactions with paddle_id |
| Routes | GET /plans/start (plans.start) | Route to view available subscription plans |
| Routes | GET /plans/{price_id} (plans.show) | Route to initiate subscription checkout |
| Routes | GET /products (products.index) | Route to view available products |
| Routes | GET /products/{product} (products.show) | Route to initiate product checkout |
| Routes | GET /orders (orders.index) | Route to view user orders |
| Routes | GET /orders/pending/{order_id} (orders.pending) | Route to view order pending page after checkout |
| Routes | GET /orders/status/{order_id} (orders.status) | Route to check order status (returns JSON) |
| Routes | GET /subscription/pending (subscription.pending) | Route to view subscription pending page after checkout |
| Routes | GET /subscription/status (subscription.status) | Route to check subscription status (returns JSON) |
| Routes | GET /subscription (subscription.manage) | Route to manage subscription (requires subscribed middleware) |
| Routes | GET /transactions (transactions.index) | Route to view user transactions |
| Routes | GET /admin/orders (admin.orders.index) | Admin route to view all orders |