Skip to main content

Paddle

Paddle is a Merchant of Record (MoR) — Paddle handles tax collection, compliance, and VAT/GST remittance globally. Subscribd integrates with Paddle Billing (the modern API, not Paddle Classic).

Configuration

// config/subscribd.php
'gateways' => [
    'paddle' => [
        'driver'         => \Pixelworxio\Subscribd\Gateways\PaddleGateway::class,
        'api_key'        => env('PADDLE_API_KEY'),
        'webhook_secret' => env('PADDLE_WEBHOOK_SECRET'),
        'sandbox'        => env('PADDLE_SANDBOX', false),
        'checkout' => [
            'success_url' => env('PADDLE_SUCCESS_URL'),
            'cancel_url'  => env('PADDLE_CANCEL_URL'),
        ],
    ],
],

Environment variables

PADDLE_API_KEY=...
PADDLE_WEBHOOK_SECRET=...
PADDLE_SANDBOX=false
PADDLE_SUCCESS_URL=https://yourapp.com/billing/success
PADDLE_CANCEL_URL=https://yourapp.com/billing/cancel
Set PADDLE_SANDBOX=true to use the Paddle sandbox environment.

Webhook-activation flow

Paddle uses a webhook-activation model. CreateSubscription returns an Incomplete subscription with a checkout_url in meta:
use Pixelworxio\Subscribd\Actions\CreateSubscription;

$subscription = app(CreateSubscription::class)->execute($user, $plan, ['gateway' => 'paddle']);

if ($subscription->status->value === 'incomplete') {
    return redirect($subscription->meta['checkout_url']);
}
The user completes payment on Paddle’s checkout page. Paddle then sends a webhook confirming the subscription, at which point Subscribd transitions the subscription to Active and fires SubscriptionCreated. The event is not fired from CreateSubscription.

Webhooks

Register https://yourapp.com/subscribd/webhook/paddle as a notification destination in the Paddle Dashboard. Enable:
  • subscription.created
  • subscription.updated
  • subscription.canceled
  • subscription.paused
  • subscription.resumed
  • transaction.completed
  • transaction.payment_failed
Copy the Secret key from the notification settings and set it as PADDLE_WEBHOOK_SECRET.

Limitations

  • Proration is handled by Subscribd’s built-in ProrationEngine.
  • Trial extension is not supported natively. ExtendTrial updates the local trial_ends_at only.

Next steps