Paypal
PayPal supports subscriptions and invoice previews. Use this page if you prefer PayPal and do not need a customer portal.
Configuration
<?php
return [
'bnomei.klub.provider.handler' => \Bnomei\Klub\Provider\PayPalProvider::class,
'bnomei.klub.providers.paypal' => [
'client_id' => fn() => env('PAYPAL_CLIENT_ID'),
'secret' => fn() => env('PAYPAL_SECRET'),
'environment' => fn() => env('PAYPAL_ENV', 'sandbox'),
'webhook_id' => fn() => env('PAYPAL_WEBHOOK_ID'),
'cancel_behavior' => 'suspend',
'field' => 'paypal',
],
];
Environment variables:
PAYPAL_CLIENT_IDPAYPAL_SECRETPAYPAL_ENV(sandbox,live, orproduction)PAYPAL_WEBHOOK_ID
Optional provider keys:
cancel_behavior(suspendorcancel)checkoutfor provider-specific payload overrides
Webhooks
Configure webhooks to POST /klub/webhooks/paypal.
PayPal requires the verification headers PayPal-Transmission-Id, PayPal-Transmission-Time, PayPal-Transmission-Sig, PayPal-Cert-Url, and PayPal-Auth-Algo. Klub validates them using PAYPAL_WEBHOOK_ID.
Portal and invoices
- Portal: not supported.
- Invoice preview: supported and links to the subscription transaction details.
Plan data
PayPal uses local plans (providers.paypal.plans or site plans YAML):
- Subscriptions: set
idto your PayPal plan ID (P-...) and use the normal subscription route. - One-time payments: set
type: one_timeand provideunit_amount+currencyso Orders payload amounts are generated correctly.
Gotchas
- One-time checkouts need
unit_amountandcurrencyin local plan data. - Webhook verification requires
PAYPAL_WEBHOOK_ID.
Orders custom_id
For one-time Orders checkouts, Klub sets custom_id to {userId}|{priceId} so webhooks can resolve both the user and the price even if the buyer never returns. If no user is available, custom_id is just the priceId.
Avoid using | in price IDs.
Cancel behavior
PayPal supports soft cancel (suspend) and hard cancel. Klub defaults to suspend so users can resume.
- Set
bnomei.klub.providers.paypal.cancel_behaviortocancelfor hard cancellations. POST /klub/renew/{subscriptionId}only resumes suspended subscriptions. Cancelled or expired subscriptions must be restarted via checkout.
See Purchases for flow details.