### Events and Notifications Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to list events, get event types, list notifications, get notification logs, and replay notifications. ```APIDOC ## Events and Notifications ### Description Manage events and notifications using the Paddle facade. ### Methods - `Paddle::events()->list(array $filters)` - List events with optional filters. - `Paddle::events()->types()` - Get available event types. - `Paddle::notifications()->list(array $filters)` - List notifications with optional filters. - `Paddle::notifications()->logs(string $notificationId)` - Get logs for a notification. - `Paddle::notifications()->replay(string $notificationId)` - Replay a notification. ### Example ```php Paddle::events()->list(['after' => 'evt_123']); Paddle::events()->types(); Paddle::notifications()->list(['status' => 'failed']); Paddle::notifications()->logs('ntf_123'); Paddle::notifications()->replay('ntf_123'); ``` ``` -------------------------------- ### Install the Laravel Paddle package Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Use Composer to install the jeffersongoncalves/laravel-paddle package. This is the initial step to add the package to a Laravel project. ```text composer require jeffersongoncalves/laravel-paddle ``` -------------------------------- ### Manage events and notifications with Paddle facade Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md List events, get event types, list notifications, get notification logs, and replay notifications. The `events()->list()` method accepts Paddle filters like `after`. The `notifications()->list()` method accepts filters like `status`. ```php Paddle::events()->list(['after' => 'evt_123']); Paddle::events()->types(); Paddle::notifications()->list(['status' => 'failed']); Paddle::notifications()->logs('ntf_123'); Paddle::notifications()->replay('ntf_123'); ``` -------------------------------- ### Products and Prices Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to list, create, update, and archive products, and create prices using the Paddle facade. ```APIDOC ## Products and Prices ### Description Use the Paddle facade to manage products and prices. Each method returns a dedicated resource class. ### Methods - `Paddle::products()->list(array $filters)` - List products with optional filters. - `Paddle::products()->create(array $attributes)` - Create a new product. - `Paddle::products()->update(string $productId, array $attributes)` - Update an existing product. - `Paddle::products()->archive(string $productId)` - Archive a product. - `Paddle::prices()->create(string $productId, int $amount, string $currencyCode, string $description, array $attributes)` - Create a price for a product. ### Parameters - `list()` accepts Paddle's filters: `status`, `after`, `per_page`, `order_by`, `id`, etc. Default `per_page` is `default_per_page`. - `create()` for products requires `name` and `tax_category`. - `amount` is in the lowest denomination (e.g., 1990 = US$ 19.90). ### Example ```php use JeffersonGoncalves\Paddle\Facades\Paddle; $products = Paddle::products()->list(['status' => 'active']); $product = Paddle::products()->create([ 'name' => 'Pro Plan', 'tax_category' => 'saas', 'description' => 'Everything in one plan', ]); Paddle::products()->update($product['data']['id'], ['name' => 'Pro Plan (annual)']); Paddle::products()->archive($product['data']['id']); $price = Paddle::prices()->create( productId: $product['data']['id'], amount: 1990, currencyCode: 'USD', description: 'Monthly', attributes: ['billing_cycle' => ['interval' => 'month', 'frequency' => 1]], ); ``` ``` -------------------------------- ### Manage transactions, discounts, and adjustments with Paddle facade Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Create transactions, invoice them, create discounts, and create adjustments (refunds). The `transactions()->create()` method uses named arguments for items and attributes. The `discounts()->create()` method takes amount, type, description, and optional attributes. The `adjustments()->create()` method requires a transaction ID, action, reason, and items. ```php $transaction = Paddle::transactions()->create( items: [['price_id' => 'pri_123', 'quantity' => 1]], attributes: ['customer_id' => 'ctm_123', 'collection_mode' => 'manual'], ); Paddle::transactions()->invoice($transaction['data']['id']); Paddle::discounts()->create(25, 'percentage', 'Launch', ['code' => 'LAUNCH25']); // Refund a transaction item Paddle::adjustments()->create( transactionId: $transaction['data']['id'], action: 'refund', reason: 'Customer request', items: [['item_id' => 'txnitm_123', 'type' => 'full']], ); ``` -------------------------------- ### Manage customers with Paddle facade Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Create, update, retrieve credit balances, and archive a customer. The `create()` method takes an email and an optional attributes array. The `creditBalances()` method retrieves the customer's credit balances. ```php $customer = Paddle::customers()->create('jane@example.com', ['name' => 'Jane Doe']); Paddle::customers()->update($customer['data']['id'], ['name' => 'Janet Doe']); Paddle::customers()->creditBalances($customer['data']['id']); Paddle::customers()->archive($customer['data']['id']); ``` -------------------------------- ### Transactions, Discounts and Adjustments Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to create transactions, invoice them, create discounts, and create adjustments for refunds. ```APIDOC ## Transactions, Discounts and Adjustments ### Description Manage transactions, discounts, and adjustments using the Paddle facade. ### Methods - `Paddle::transactions()->create(array $items, array $attributes)` - Create a new transaction. - `Paddle::transactions()->invoice(string $transactionId)` - Invoice a transaction. - `Paddle::discounts()->create(int $amount, string $type, string $description, array $attributes)` - Create a discount. - `Paddle::adjustments()->create(string $transactionId, string $action, string $reason, array $items)` - Create an adjustment (e.g., refund). ### Example ```php $transaction = Paddle::transactions()->create( items: [['price_id' => 'pri_123', 'quantity' => 1]], attributes: ['customer_id' => 'ctm_123', 'collection_mode' => 'manual'], ); Paddle::transactions()->invoice($transaction['data']['id']); Paddle::discounts()->create(25, 'percentage', 'Launch', ['code' => 'LAUNCH25']); Paddle::adjustments()->create( transactionId: $transaction['data']['id'], action: 'refund', reason: 'Customer request', items: [['item_id' => 'txnitm_123', 'type' => 'full']], ); ``` ``` -------------------------------- ### Customers Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to create, update, retrieve credit balances, and archive customers. ```APIDOC ## Customers ### Description Manage customers using the Paddle facade. ### Methods - `Paddle::customers()->create(string $email, array $attributes)` - Create a new customer. - `Paddle::customers()->update(string $customerId, array $attributes)` - Update an existing customer. - `Paddle::customers()->creditBalances(string $customerId)` - Retrieve credit balances for a customer. - `Paddle::customers()->archive(string $customerId)` - Archive a customer. ### Example ```php $customer = Paddle::customers()->create('jane@example.com', ['name' => 'Jane Doe']); Paddle::customers()->update($customer['data']['id'], ['name' => 'Janet Doe']); Paddle::customers()->creditBalances($customer['data']['id']); Paddle::customers()->archive($customer['data']['id']); ``` ``` -------------------------------- ### Manage products and prices with Paddle facade Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Manage products and prices via the Paddle facade. The `list()` method accepts Paddle filters like `status` and defaults `per_page` to `default_per_page`. The `create()` method for products requires `name` and `tax_category`; missing fields throw `InvalidArgumentException` before any HTTP call. The `prices()->create()` method uses named arguments and expects the amount in the lowest denomination (e.g., 1990 for US$ 19.90). ```php use JeffersonGoncalves\Paddle\Facades\Paddle; $products = Paddle::products()->list(['status' => 'active']); $product = Paddle::products()->create([ 'name' => 'Pro Plan', 'tax_category' => 'saas', 'description' => 'Everything in one plan', ]); Paddle::products()->update($product['data']['id'], ['name' => 'Pro Plan (annual)']); Paddle::products()->archive($product['data']['id']); $price = Paddle::prices()->create( productId: $product['data']['id'], amount: 1990, // lowest denomination — 1990 = US$ 19.90 currencyCode: 'USD', description: 'Monthly', attributes: ['billing_cycle' => ['interval' => 'month', 'frequency' => 1]], ); ``` -------------------------------- ### Set Paddle environment variables Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Shows the environment variables for Paddle credentials. CREATE the API key under Developer Tools > Authentication. Note that sandbox and live keys are separate, and a sandbox key only works when PADDLE_SANDBOX is true. ```bash PADDLE_API_KEY=your-api-key PADDLE_SANDBOX=false PADDLE_WEBHOOK_SECRET=your-notification-secret ``` -------------------------------- ### Webhooks Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to verify webhook signatures and handle incoming webhook requests. ```APIDOC ## Webhooks ### Description Verify the `Paddle-Signature` header against the raw request body before trusting a webhook. ### Methods - `Paddle::webhooks()->verifyRequest(Request $request)` - Verify the webhook request signature. - `Paddle::webhooks()->verify(string $payload, string $signature, int $maxAge = 5)` - Verify a raw payload and signature. Signatures older than `$maxAge` seconds are rejected (pass `0` to disable). ### Parameters - `$payload` must be the raw body; a re-encoded array will not match. ### Example ```php use Illuminate\Http\Request; use JeffersonGoncalves\Paddle\Facades\Paddle; Route::post('/paddle/webhook', function (Request $request) { abort_unless(Paddle::webhooks()->verifyRequest($request), 403); $event = $request->json()->all(); // handle $event['event_type'] ... return response()->noContent(); })->withoutMiddleware([VerifyCsrfToken::class]); ``` ``` -------------------------------- ### Publish the Paddle config file Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Runs the Artisan vendor:publish command to publish the package's configuration file. This is required to configure the package credentials. ```text php artisan vendor:publish --tag=paddle-config ``` -------------------------------- ### Paddle configuration file Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md This is the config/paddle.php configuration file. It reads the API key, sandbox flag, webhook secret, and default per-page limit from environment variables. The base URL defaults to the sandbox or live API depending on the PADDLE_SANDBOX variable, and can be overridden with PADDLE_BASE_URL. ```php // config/paddle.php return [ 'api_key' => env('PADDLE_API_KEY'), 'sandbox' => (bool) env('PADDLE_SANDBOX', false), 'base_url' => env('PADDLE_BASE_URL', env('PADDLE_SANDBOX', false) ? 'https://sandbox-api.paddle.com' : 'https://api.paddle.com'), 'webhook_secret' => env('PADDLE_WEBHOOK_SECRET'), 'default_per_page' => env('PADDLE_DEFAULT_PER_PAGE', 50), ]; ``` -------------------------------- ### Manage subscriptions with Paddle facade Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md List, update, cancel, pause, resume, activate, charge, and update payment method for subscriptions. The `cancel()` method without a second argument cancels at period end; passing `'immediately'` cancels immediately. The `pause()` method accepts an optional timestamp; omitting it pauses indefinitely. The `activate()` method moves a subscription from trialing to active. ```php $subscriptions = Paddle::subscriptions()->list(['customer_id' => 'ctm_123']); Paddle::subscriptions()->update('sub_123', [ 'proration_billing_mode' => 'prorated_immediately', 'items' => [['price_id' => 'pri_123', 'quantity' => 3]], ]); Paddle::subscriptions()->cancel('sub_123'); // at period end Paddle::subscriptions()->cancel('sub_123', 'immediately'); Paddle::subscriptions()->pause('sub_123', '2026-12-01T00:00:00Z'); // omit to pause indefinitely Paddle::subscriptions()->resume('sub_123'); Paddle::subscriptions()->activate('sub_123'); // trialing -> active // One-off charge on top of the subscription Paddle::subscriptions()->charge('sub_123', [['price_id' => 'pri_123', 'quantity' => 1]], 'immediately'); // Transaction that lets the customer update their card Paddle::subscriptions()->updatePaymentMethodTransaction('sub_123'); ``` -------------------------------- ### Subscriptions Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to list, update, cancel, pause, resume, activate, charge, and update payment method for subscriptions. ```APIDOC ## Subscriptions ### Description Manage subscriptions using the Paddle facade. ### Methods - `Paddle::subscriptions()->list(array $filters)` - List subscriptions with optional filters. - `Paddle::subscriptions()->update(string $subscriptionId, array $attributes)` - Update a subscription. - `Paddle::subscriptions()->cancel(string $subscriptionId, string $mode = 'at_period_end')` - Cancel a subscription. Use `'immediately'` for immediate cancellation. - `Paddle::subscriptions()->pause(string $subscriptionId, string $effectiveFrom = null)` - Pause a subscription. Omit `effectiveFrom` to pause indefinitely. - `Paddle::subscriptions()->resume(string $subscriptionId)` - Resume a paused subscription. - `Paddle::subscriptions()->activate(string $subscriptionId)` - Activate a trialing subscription. - `Paddle::subscriptions()->charge(string $subscriptionId, array $items, string $chargeMode)` - Add a one-off charge to a subscription. - `Paddle::subscriptions()->updatePaymentMethodTransaction(string $subscriptionId)` - Create a transaction to update the customer's payment method. ### Example ```php $subscriptions = Paddle::subscriptions()->list(['customer_id' => 'ctm_123']); Paddle::subscriptions()->update('sub_123', [ 'proration_billing_mode' => 'prorated_immediately', 'items' => [['price_id' => 'pri_123', 'quantity' => 3]], ]); Paddle::subscriptions()->cancel('sub_123'); Paddle::subscriptions()->cancel('sub_123', 'immediately'); Paddle::subscriptions()->pause('sub_123', '2026-12-01T00:00:00Z'); Paddle::subscriptions()->resume('sub_123'); Paddle::subscriptions()->activate('sub_123'); Paddle::subscriptions()->charge('sub_123', [['price_id' => 'pri_123', 'quantity' => 1]], 'immediately'); Paddle::subscriptions()->updatePaymentMethodTransaction('sub_123'); ``` ``` -------------------------------- ### Run tests with composer test Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Runs the test suite for the package. Use this command to execute all tests defined in the project. ```bash composer test ``` -------------------------------- ### Error Handling Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Demonstrates how to catch and handle PaddleException and InvalidArgumentException. ```APIDOC ## Error Handling ### Description Any non-2xx API response throws `JeffersonGoncalves\Paddle\Exceptions\PaddleException`, which exposes the decoded error body and Paddle's machine-readable code. Missing required fields throw `InvalidArgumentException` before any HTTP call. ### Methods - `PaddleException::errorCode()` - Get the machine-readable error code. - `PaddleException::errorBody()` - Get the decoded error body. ### Example ```php use JeffersonGoncalves\Paddle\Exceptions\PaddleException; try { Paddle::subscriptions()->get('sub_missing'); } catch (PaddleException $e) { if ($e->errorCode() === 'entity_not_found') { // ... } logger()->error($e->getMessage(), $e->errorBody()); } ``` ``` -------------------------------- ### Verify Paddle webhook signature with verifyRequest Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Handle a Paddle webhook by verifying the `Paddle-Signature` header against the raw request body. The `verifyRequest()` method returns a boolean; if false, the request is aborted with a 403. The route must exclude the CSRF middleware. The `verify()` method is also available for raw payloads, with a `$maxAge` parameter (default 5 seconds) to reject old signatures. ```php use Illuminate\Http\Request; use JeffersonGoncalves\Paddle\Facades\Paddle; Route::post('/paddle/webhook', function (Request $request) { abort_unless(Paddle::webhooks()->verifyRequest($request), 403); $event = $request->json()->all(); // handle $event['event_type'] ... return response()->noContent(); })->withoutMiddleware([VerifyCsrfToken::class]); ``` -------------------------------- ### Handle Paddle API errors with PaddleException Source: https://github.com/jeffersongoncalves/laravel-paddle/blob/main/README.md Catch `PaddleException` for non-2xx API responses. The exception exposes the decoded error body via `errorBody()` and Paddle's machine-readable code via `errorCode()`. Missing required fields (e.g., `name`/`tax_category` on `products()->create()`) throw `InvalidArgumentException` before any HTTP call. ```php use JeffersonGoncalves\Paddle\Exceptions\PaddleException; try { Paddle::subscriptions()->get('sub_missing'); } catch (PaddleException $e) { if ($e->errorCode() === 'entity_not_found') { // ... } logger()->error($e->getMessage(), $e->errorBody()); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.