Paddle Payment for LearnPress: Setup & Configuration Guide
This guide covers everything you need to connect Paddle Billing to your LearnPress site — from generating credentials in the Paddle dashboard to accepting live learner payments. Follow each section in order for a smooth first-time setup.
Requirements
Confirm all of the following before activating the add-on:
- WordPress 6.0 or later
- PHP 8.1 or later
- LearnPress 4.4.1 or later (plugin must be active)
- LearnPress Membership 4.0.1 or later — only required when selling recurring membership subscriptions
- A Paddle Billing account with access to both sandbox and production environments. Paddle Classic is not supported.
- A publicly reachable site over HTTPS so Paddle can deliver signed webhook notifications
One-time course purchases do not require a Paddle catalog product. Recurring membership plans use a Paddle Product and recurring Price — the add-on can create and sync these automatically.
Step 1 — Install and Activate
- In your WordPress Dashboard, go to Plugins → Add New → Upload Plugin.
- Upload the
learnpress-paddle-payment.zipfile and click Install Now. - Click Activate Plugin. If LearnPress or PHP requirements are not met, the plugin displays an admin notice and stops loading — resolve the requirement before proceeding.
Step 2 — Create Paddle Credentials
You need three values from each Paddle environment (sandbox and production): an API key, a client-side token, and a webhook secret. Create them separately — never use sandbox values in production fields or vice versa.
2a. Create an API Key
- Sign in to the Paddle dashboard for the environment you are configuring. Verify Test mode is enabled when working with sandbox credentials.
- Open Developer Tools → Authentication.
- On the API keys tab, click New API key.
- Enter a recognizable name, set an appropriate expiry date, and grant these minimum write permissions (write permissions include read access):
transaction.write— create and inspect transactionsproduct.write— create and manage Membership catalog productsprice.write— create and update recurring Membership pricesadjustment.write— submit refund adjustmentscustomer_portal_session.write— open the self-service billing portal for learners
- Save the key. Copy it immediately — Paddle shows the full value only once. Store it securely.
2b. Create a Client-Side Token
- On the same Developer Tools → Authentication page, open the Client-side tokens tab.
- Click New token, enter a name, and save.
- Copy the token value. Sandbox tokens begin with
test_; production tokens begin withlive_. Do not substitute an API key here — these are distinct credential types.
Step 3 — Configure LearnPress Payment Settings
- In WordPress, navigate to LearnPress → Settings → Payments → Paddle.
- Check Enable to activate the gateway.
- Leave Enable test mode checked while you are integrating. Test mode uses only sandbox credentials.
- Enter your Test API key, Test client token, and Test webhook secret (the webhook secret is generated in Step 4).
- Click Save changes.
- Once sandbox testing passes, return here, enter the three Live credential values, uncheck Enable test mode, and save again.
Secret fields are masked after saving — the full value is replaced with dots so it is never exposed in page source. Leave a masked field unchanged when saving to retain its stored value. Clear it deliberately only to remove the credential.
Step 4 — Set the Paddle Default Payment Link
Paddle requires a default payment link before it allows the add-on to create a transaction or open checkout. Without it, checkout fails with transaction_default_checkout_url_not_set.
- In the same Paddle environment as your API key, go to Checkout → Checkout Settings.
- Find the Default payment link field.
- Enter an HTTPS URL on your WordPress site — preferably a checkout or order page that loads Paddle.js.
- Save the checkout settings.
In sandbox, a local or test domain is accepted. In production, the domain must be approved under Checkout → Website Approval. This setting lives entirely in Paddle — there is no additional field in LearnPress.
Step 5 — Register Webhook Notification Destinations
The LearnPress Paddle settings page shows the exact webhook URL for each environment. Copy the displayed URL rather than constructing it manually — WordPress may use a non-default permalink format.
Standard pretty-permalink URLs follow this pattern:
Sandbox: https://example.com/wp-json/lp/paddle/v1/webhook/sandbox
Production: https://example.com/wp-json/lp/paddle/v1/webhook/production
Create a separate notification destination in each Paddle environment:
- Open Developer Tools → Notifications and click New destination.
- Select Webhook as the type.
- Paste the environment URL shown in your LearnPress Paddle settings.
- Enter a recognizable description, keep API version 1, and select Platform usage. In sandbox, selecting Platform and simulation also enables Paddle’s webhook simulator.
- Subscribe the destination to these events and save:
| Purpose | Events to subscribe |
|---|---|
| One-time course checkout | transaction.completed, transaction.payment_failed |
| Membership subscription lifecycle | subscription.created, subscription.trialing, subscription.activated, subscription.past_due, subscription.resumed, subscription.canceled, subscription.updated |
| Refund result | adjustment.updated |
Copy the Webhook Secret
- On the Notifications page, open the destination’s … menu → Edit destination.
- Find Secret key and click the copy button. The value normally begins with
pdl_ntfset_. - Paste it into the matching Test webhook secret or Live webhook secret field in LearnPress, then save.
The secret key is not the destination ID. Treat it like a password — do not share it in screenshots, support messages, or version control. Each destination has its own secret; a sandbox secret is rejected by the production endpoint and vice versa.
Rotating a Webhook Secret Without Downtime
- Copy the current secret into the Previous test/live webhook secret field.
- Set Previous test/live secret expires to a future Unix timestamp (seconds) that gives you enough overlap time.
- Generate a new secret in Paddle, paste it into the main webhook secret field, and save.
- Update the notification destination in Paddle to use the new secret.
- After the overlap period passes, clear the previous secret field or set its expiry to
0.
Step 6 — One-Time Course Checkout
No Paddle catalog product or price is required for one-time course sales. Once the gateway is enabled and the active environment has all three credentials, Paddle appears as a payment option on the standard LearnPress checkout.
The add-on creates a server-side Paddle transaction and opens it with Paddle.js. A LearnPress order stays Pending until a verified transaction.completed webhook arrives. Checkout callbacks in the browser never complete an order on their own.
Step 7 — Recurring Membership Plans
Requires LearnPress Membership 4.0.1 or later. Open the Membership plan editor and set:
- Billing type: Subscription
- Subscription price: amount charged each billing cycle
- Billing interval: day, month, or year, with a positive interval count
- Regular price / Sale price: initial setup fee (Sale price is used when greater than zero; a zero value means no setup fee)
- Free trial: number of trial days — the Paddle Price must have the same trial duration. A free-trial plan must have a zero Regular price.
Under Gateway References, select Paddle and choose a source mode:
| Mode | How it works | When to use |
|---|---|---|
| Auto (recommended) | Saving the plan creates a Paddle Product and recurring Price in the active environment. Pricing changes update those catalog objects automatically. | New plans and plans you want kept in sync without manual Paddle edits. |
| Manual | Paste an existing Paddle recurring Price ID. The add-on verifies it but does not update or archive it. | Plans with a Price already in Paddle, or when you manage catalog objects yourself. |
Before checkout, the Paddle Price must be active and match the LearnPress currency, recurring amount, billing interval, interval count, and trial days exactly. The setup fee is sent as a separate non-recurring line item on the first transaction only.
Sandbox and production catalog IDs are different. When switching environments, clear the old Auto reference so the plan is created fresh, or switch to Manual and enter a Price ID from the correct environment.
Step 8 — Refunds and the Customer Billing Portal
Processing Refunds
Full and partial refunds initiated in LearnPress are submitted to Paddle as adjustments. The local order stays Paid while Paddle reviews the request. The order changes to Refunded only after an approved adjustment.updated webhook arrives. A rejected adjustment leaves the order paid and adds an order note.
Customer Billing Portal
For any completed or refunded Paddle order, the order owner sees a Manage billing action in their LearnPress profile. Clicking it opens a fresh, short-lived Paddle customer portal session where the learner can update their payment method, review charges, and download invoices.
Keep the original environment’s API key and webhook secret available as long as orders, refunds, or active subscriptions from that environment exist. Removing credentials breaks refunds and portal access for those orders.
Sandbox Verification Checklist
Run through this checklist in the Paddle sandbox before switching to production:
- Paddle gateway is hidden when any active-environment credential is missing.
- A one-time course order stays Pending until
transaction.completedarrives, then completes exactly once. - Re-delivering the same
transaction.completedwebhook does not duplicate fulfillment. - A Membership plan with and without a free trial both complete checkout correctly.
- The initial setup fee appears on the first charge only — absent from all renewal invoices.
- Renewal, payment failure, recovery, cancellation, and resume events all update the Membership subscription status correctly.
- Full and partial refunds stay pending until the
adjustment.updatedapproval webhook arrives. - The Manage billing portal action works for the order owner and is unavailable to a different logged-in user.
- Switching between test and live mode never mixes credentials or catalog IDs.
Troubleshooting
Paddle does not appear at checkout
Confirm Enable is checked in LearnPress → Settings → Payments → Paddle and that the selected environment has all three required credentials (API key, client token, webhook secret). For Membership plans, also confirm the plan has Paddle selected under Gateway References and holds a valid Price reference.
Checkout fails with “no default payment link set”
Open Checkout → Checkout Settings in the same Paddle environment as your API key, enter an HTTPS URL in the Default payment link field, and save. Sandbox and production settings are managed separately in Paddle.
LearnPress order stays Pending after checkout
Check that the notification destination uses the exact URL shown in LearnPress, includes transaction.completed in its subscribed events, and has the matching webhook signing secret. Review the LearnPress order notes and the WordPress/PHP error log for a processing error at the time of webhook delivery.
Paddle returns “invalid_signature”
The most common causes are: a secret copied from the wrong environment, a rotated secret used outside its overlap window, or a reverse proxy that modifies the raw request body. Copy the destination secret again from Developer Tools → Notifications → Edit destination and verify the webhook URL ends in the correct environment name (/sandbox or /production).
Membership checkout reports a price mismatch
The Paddle recurring Price and the Membership plan must have identical currency, recurring amount, billing interval, interval count, and trial days. In Auto mode, save the updated Membership plan to push changes to Paddle. In Manual mode, update the Paddle Price directly or enter a different Price ID that matches exactly.
A refund stays Pending indefinitely
Confirm the notification destination includes adjustment.updated in its subscribed events. Paddle’s approval process is asynchronous — the add-on does not mark an order refunded from the initial API response alone. If the event is subscribed and still not arriving, check the destination delivery log in the Paddle dashboard.
Customer billing portal is unavailable
The logged-in user must own a completed or refunded Paddle order, and a verified Paddle webhook must have already associated a Paddle customer ID with that order. The API key for the order’s original environment must still be configured and must include Customer portal sessions (Write) (customer_portal_session.write) permission. Paddle returns 403 Forbidden when this permission is missing; the add-on surfaces it as HTTP 502.
Frequently Asked Questions
Which version of Paddle does this add-on support?
Paddle Billing only. The legacy Paddle Classic platform is not supported.
Does Paddle handle international sales tax and VAT?
Yes. Paddle acts as the Merchant of Record, calculating, collecting, and remitting sales tax, VAT, and GST across international jurisdictions on your behalf. Your site receives net revenue; Paddle handles the tax compliance.
Does credit card data pass through my WordPress server?
No. Payment input is handled entirely by Paddle.js in the learner’s browser using a publishable client-side token. Your WordPress site stores only the transaction ID, subscription ID, and customer ID — no card numbers or bank details ever touch your host.
Can I sell recurring membership subscriptions?
Yes. When LearnPress Membership 4.0.1 or later is installed and active, you can sell subscription plans on daily, monthly, or yearly billing cycles, with optional setup fees and free trial periods.
Can students manage their payment method and download invoices?
Yes. Learners who own a completed or refunded Paddle order see a Manage billing button in their LearnPress profile. It opens a secure, short-lived Paddle customer portal session where they can update their card, view charges, and download invoices without contacting support.
What are the minimum server requirements?
WordPress 6.0 or later, PHP 8.1 or later, LearnPress 4.4.1 or later, and a valid SSL certificate (HTTPS) on your domain so Paddle can deliver signed webhook notifications.
How do I switch from sandbox to production?
In LearnPress → Settings → Payments → Paddle, enter your three Live credential values (API key, client token, webhook secret), uncheck Enable test mode, and save. Confirm a separate production notification destination exists in the Paddle dashboard pointing to the production webhook URL with all required events subscribed.
