17 min read
Stop Paying for a Store You Do Not Need
Set up a paid course on most WordPress LMS plugins and you’ll hit the same wall within the first hour: the LMS handles your lessons, but not your money. For that, install WooCommerce, configure a product for every course, wire up a payment gateway plugin, install a bridge plugin to connect the two systems, and now you’re maintaining three plugins to sell one thing. WooCommerce alone adds a full second commerce system to your site, with its own settings, its own database tables, its own updates to track, and its own way of doing something your course platform should have just done itself.
This is one of the most common, least examined costs in building a course business on WordPress: you end up paying (in setup time, in plugin conflicts, in monthly overhead) for a general-purpose online store you don’t actually need, just to accept payment for a course. Nobody sets out to build a shipping-and-inventory system for something that has no inventory and nothing to ship. It happens by default, because the LMS didn’t handle payment on its own, and WooCommerce was the path of least resistance everyone else took first.
Here’s what it looks like when a course platform just handles payment itself, and why that’s a meaningfully different product than “an LMS that integrates with WooCommerce.”
The Actual Cost of “Just Add WooCommerce”
WooCommerce is genuinely excellent software for what it’s built for: running a store with physical or downloadable products, shipping, inventory, and a checkout flow built around a shopping cart. None of that maps cleanly onto selling access to a course.
When a course platform’s real answer to “how do students pay” is “install WooCommerce,” a few things happen:
You’re running two commerce systems that need to agree with each other. The LMS has to somehow know when a WooCommerce order for a “course product” was completed, then grant access on your actual platform. That handoff is a place bugs live: a webhook that fires late, a product that gets deleted and orphans the connection, a refund in WooCommerce that doesn’t actually revoke course access because nothing told the LMS about it.
Every course needs a matching WooCommerce product, maintained in parallel with the actual course. Change your course price and forget to update the linked product, and now your course page says one thing and checkout charges another.
You inherit WooCommerce’s entire settings surface (shipping zones you’ll never use, tax classes irrelevant to digital access, inventory tracking for a product that has infinite stock) just to reach the one screen you actually needed, which is “take a card payment.”
You’re paying the maintenance tax on a second major plugin permanently. WooCommerce updates, extension conflicts, and its own security surface are now part of your stack, for a feature (checkout) that a course platform should own natively.
None of this is a criticism of WooCommerce. It’s a mismatch between what WooCommerce is built for and what a course actually needs to sell: access, not inventory.
What Learnomy Does Instead
Learnomy accepts payment natively, through Stripe and PayPal, with no WooCommerce requirement at all. Here’s the actual settings screen:
Read what that panel actually says: “Route Learnomy purchases through WooCommerce checkout. Optional: installing WooCommerce does not change anything on its own. When off, Learnomy uses its own Stripe and PayPal checkout.” WooCommerce isn’t required, isn’t assumed, and isn’t quietly doing work in the background. It’s an optional integration for sites that already run WooCommerce for other products and want a single unified checkout, not a dependency bolted underneath the LMS.
Real Gateway Configuration, Not a Redirect to Someone Else’s Setup Guide
Here’s the actual Stripe configuration screen, live inside the Learnomy settings:
A few details that separate a real integration from a surface-level one:
- A Test / Live mode switch built into the gateway itself. Test mode uses Stripe test keys, Live mode charges real cards, and switching between them doesn’t require touching code or a separate plugin setting.
- A ready-made webhook URL, generated automatically and scoped to Learnomy’s own REST namespace, meant to be pasted directly into the Stripe dashboard.
- A specific, correct list of webhook events to subscribe to, including the two async payment events (covering delayed payment methods like SEPA, Bacs, boleto, and Konbini) that a shallower integration commonly forgets, silently leaving international buyers charged but never actually enrolled.
- PayPal gets the same treatment, with its own sandbox and live credentials and a Test PayPal Connection button, so you can confirm the integration actually works before a real customer hits checkout.
This is the difference between a plugin that technically “supports Stripe” by exposing a publishable key field, and one where someone actually implemented the webhook contract Stripe expects, including the edge cases that only show up once real international customers start paying with something other than a plain credit card.
Every Payment Method Available at Checkout, Not Just Cards
Between Stripe and PayPal, a Learnomy checkout can accept:
- Credit and debit cards, direct through Stripe Checkout.
- PayPal, for the large population of buyers who trust and prefer it over entering card details on an unfamiliar site.
- Delayed and local payment methods Stripe supports through the async webhook flow (SEPA direct debit, Bacs, boleto, Konbini, and others depending on your Stripe account’s enabled methods), which matters the moment you’re selling outside your home country and a chunk of your addressable market simply doesn’t pay by card by default.
There’s also a Test Gateway, explicitly labeled Development Only, that completes checkout synchronously without touching any external service. This exists for a specific, legitimate reason: demoing a course flow, running QA, or building out a course catalog before you’ve connected a live gateway, without faking your way through Stripe’s own test mode for every click-through.
What This Looks Like at Actual Checkout
For a student, none of the gateway plumbing is visible. What they see is the price and a buy button, right on the course page:
Card or PayPal, the checkout happens without leaving the flow of buying a course to land in a separate store interface with its own header, its own cart icon, and its own unrelated “you might also like” product recommendations pulled from a WooCommerce catalog. The buyer’s whole path is: see the course, see the price, pay, get access.
Where the Money Actually Goes: A Real Ledger
Every transaction, from every gateway, lands in one unified ledger, not scattered across a payment processor’s own dashboard and a separate WooCommerce orders table:
This single screen answers questions that get genuinely difficult once payment is split across two systems: which gateway is actually converting better, which purchases were refunded and when, which transactions came through the test gateway during a demo and should be excluded from real revenue reporting. Filterable by status and by gateway, searchable by customer, order ID, or the provider’s own transaction reference, because eventually someone (a student, a bank, your own bookkeeping) is going to ask about a specific charge and “check the Stripe dashboard and then check WooCommerce and hope they agree” is not an acceptable answer.
Checkout Details That Aren’t an Afterthought
Beyond just accepting a card, the checkout settings cover the details that make a purchase feel legitimate rather than improvised:
- Business name, shown on receipt PDFs and invoice emails, defaulting to your site title if left blank.
- A configurable money-back guarantee window, in days, surfaced automatically on both the course sales page and at checkout itself, not just mentioned somewhere in a terms page nobody reads.
- A plain-language refund policy field, shown at checkout and on receipts, because “email support with your order ID” is a more useful refund policy to a nervous buyer than silence.
None of this requires a second plugin’s settings screen. It’s part of the same checkout configuration as the payment gateways themselves, because refund policy and payment method are the same decision from a buyer’s perspective: can I trust this purchase.
What Actually Happens the Moment a Payment Succeeds
Accepting a card number is the easy part. What separates a real payment integration from a fragile one is what happens in the seconds after Stripe or PayPal says “this payment succeeded,” because that’s where access actually gets granted, and it’s also exactly where naive integrations quietly break.
A payment succeeding triggers a specific, ordered sequence rather than a single monolithic function trying to do everything at once:
- The webhook arrives and is logged first, before anything else happens. Every inbound event from Stripe or PayPal is recorded with the provider’s own event ID, so if the same webhook fires twice (which payment providers do deliberately, as a reliability guarantee, not a bug) it’s only ever processed once. Without this, a duplicate webhook delivery can mean double-charging internal records, sending a student two receipt emails, or worse, granting and then confusingly re-granting the same access.
- A transaction record is created, an immutable ledger entry: who paid, how much, for what, through which provider. This record doesn’t get edited later. If something needs to change (a refund, a dispute), that’s a new record referencing the original, not an edit to history.
- Only then does access actually get granted, enrollment created, membership activated, whatever the purchase was actually for. This ordering matters: the payment record exists independently of whether the access-granting step succeeds, so a bug in enrollment logic can’t silently make it look like a payment never happened.
This is the boring, unglamorous plumbing that determines whether “customer paid but didn’t get access” is a rare, fixable edge case or a recurring support fire. It’s also exactly the part of “just add a payment gateway” that a shallow integration skips, because it doesn’t show up in a demo. It only shows up three months in, the first time a webhook gets delivered twice on the same afternoon a refund also happens to process.
Receipts and Invoices, Generated Automatically
Every completed purchase generates a receipt without a separate invoicing plugin or a manual step from you. The business name field from checkout settings appears directly on the receipt PDF and the confirmation email, and the refund policy text you configured shows up there too, so a student who wants to request a refund six weeks later doesn’t have to go hunting for your terms page. They have it in the same email that confirmed their purchase.
This matters more than it sounds like it should, for a specific reason: receipts are one of the few pieces of a transaction a buyer actually keeps and refers back to. A generic, unbranded receipt (or worse, no receipt at all until someone asks) reads as an amateur operation handling money. A receipt with your business name, a clear itemized charge, and your actual refund policy reads as a business that expected to be trusted with a credit card number in the first place.
Subscriptions Need Retry Logic, Not Just a Charge Button
The moment a course platform supports recurring billing (a membership, a payment plan, anything that charges more than once) a whole category of payment problems shows up that a one-time purchase never has to deal with: cards expire, banks decline renewal charges that look unfamiliar, and international cards sometimes fail a recurring charge that would have gone through as a one-time payment.
This is why billing retry logic exists as its own dedicated settings area, separate from the initial checkout gateways. A failed renewal charge doesn’t just silently lapse a student’s access on the first attempt. It goes through a retry schedule, the same pattern any serious subscription business runs, giving a card time to be updated or a temporary decline to resolve itself before access actually lapses. Handling this well is the difference between a membership business with steady, predictable revenue and one quietly leaking paying members to expired cards nobody noticed in time.
Instructor Payouts Run Through the Same System
On a platform with more than one instructor earning commission, the same payment infrastructure that took the original charge is what eventually pays instructors out. Stripe Payouts, visible as its own item in the commerce navigation alongside Earnings and Transactions, connects to the identical transaction ledger used for the original sale: what a student paid, what the platform kept, and what’s owed to the instructor are all derived from the same source of truth rather than reconciled by hand between a sales report and a separate payout spreadsheet.
This closes a loop that a bolted-together WooCommerce-plus-bridge-plugin setup usually can’t: if the sale itself lives in one system and the instructor payout math lives somewhere else entirely, keeping the two in agreement becomes a manual, error-prone process the moment you have more than a handful of instructors and transactions.
Why This Matters Beyond Convenience
The case for native payments isn’t just “one less plugin to install.” It’s about what happens at the moments that actually matter:
Refunds have to actually revoke access. When a refund and a course platform are two separate systems talking through webhooks and product mappings, a refund that doesn’t correctly propagate back to “revoke this student’s enrollment” is a real, recurring support burden. A native system where the transaction record and the enrollment record are the same system doesn’t have that seam to fail across.
International buyers need more than a credit card field. A course platform that only accepts cards is quietly turning away everyone whose default payment method is something else. Real Stripe integration with the async payment methods, plus PayPal as a second option, covers meaningfully more of the world than “add a Stripe plugin and call it done.”
Every additional commerce plugin is another thing that can break during a launch. The worst time to discover a WooCommerce-to-LMS bridge plugin has a bug is the day you open cart for a cohort with a deadline. Fewer moving parts between “customer clicks buy” and “customer has access” is fewer places for a launch-day failure to hide.
Your actual profit margin includes what you’re not paying for. A second commerce plugin, potential premium extensions to bridge it to your LMS, and the time spent maintaining both are real costs against a course business’s margin, even when nothing is actively broken.
Discounts Without a Separate Coupon Plugin
Running a promotion (a launch discount, an affiliate code, a limited-time offer for an email list) is another job that a WooCommerce-based setup usually hands off to yet another plugin or extension. Native coupon support means percentage or fixed-amount discounts, usage limits per code and per customer, and expiry dates, all scoped to specific courses or applied platform-wide, configured in the same admin area as everything else rather than a separate discount-code system that has to be kept in sync with what you’re actually selling.
The practical benefit shows up the first time you run a real promotion: a coupon that’s actually aware of your course catalog, your pricing, and your transaction records can enforce a one-per-customer limit or cap total redemptions without a developer wiring together two unrelated systems’ definitions of “customer” and “purchase.”
What “Native” Actually Buys You, Compared to Bridged
It’s worth being precise about the difference, because “supports Stripe” and “supports Stripe” can mean very different levels of integration depending on the platform.
A bridged setup, the WooCommerce-plus-connector-plugin pattern, means: two separate databases of what was purchased, two separate admin screens to check when something goes wrong, and a dependency on a third-party bridge plugin staying compatible with both the payment plugin’s updates and the LMS’s updates indefinitely. When something breaks, the first diagnostic question is always “which of the three plugins is actually at fault,” which is a genuinely hard question to answer under pressure.
A native setup means: one transaction table, one enrollment system, one place a refund has to propagate to, and webhook handling built by the same team that built the enrollment logic it’s supposed to trigger, so the contract between “payment succeeded” and “access granted” was designed as one system instead of stitched together after the fact. The failure modes are fewer, not because native code is magically bug-free, but because there are fewer integration seams for a bug to hide in.
Where This Actually Shows Up in a Real Course Business
Launching to an international audience. The moment a course sells outside your home country, “accept credit cards” stops being sufficient. A meaningful share of buyers in parts of Europe and Asia default to bank transfers, local wallets, or delayed payment methods rather than cards. A platform that only wired up card payments quietly caps its own addressable market without anyone deciding to do that on purpose.
A cohort-based launch with a hard deadline. Cart-close launches concentrate purchase volume into a short window, which is exactly when a fragile webhook bridge between two systems is most likely to reveal a race condition nobody hit during slow, steady sales. Idempotent webhook handling and a single transaction ledger matter far more on launch day than on a quiet Tuesday.
A membership business living or dying on renewal rate. For a subscription-based academy, the real revenue number isn’t new signups, it’s how many renewals actually succeed. Retry logic on failed recurring charges is directly responsible for how much revenue quietly survives an expired card versus how much silently churns without anyone noticing until the monthly numbers come in lower than expected.
Scaling to multiple instructors sharing revenue. Once payouts depend on commission splits calculated from real transaction data, having sale and payout derived from the same ledger is what keeps instructor trust intact. An instructor who has to take your word for their earnings, because the payout math lives in a spreadsheet nobody else can audit, is an instructor who eventually starts asking uncomfortable questions.
Setting Up Payments Without a Store
If you’re configuring this for your own course platform, here’s the real sequence:
- Decide if you need WooCommerce at all. If you’re only selling courses, skip it entirely. If you already sell physical or downloadable products through WooCommerce and want one unified cart, that’s the specific case the optional integration exists for.
- Start in Test mode on both gateways. Confirm the full purchase flow, including what a student sees immediately after paying, before any real money is involved.
- Set up the Stripe webhook exactly as specified, including both async payment events. Skipping these is the single most common cause of “customer was charged but never got access” tickets for delayed payment methods.
- Connect PayPal and use Test PayPal Connection before going live, not after your first real customer hits a broken button.
- Write a real refund policy, even a short one, and set an actual money-back guarantee window rather than leaving it at a default you never reviewed.
- Flip both gateways to Live mode only once a real test transaction has gone through cleanly on Test mode from a student’s point of view, not just from the admin settings screen.
- Check the Transactions screen after your first week of real sales, filtered by provider, to confirm both gateways are actually converting and nothing is silently failing on one payment method while working fine on the other.
Frequently Asked Questions
Do I need WooCommerce to sell courses with Learnomy? No. Stripe and PayPal are both built in and fully functional without WooCommerce installed at all. WooCommerce is available as an optional integration only for sites that already use it and want a single combined cart.
What happens if I already have WooCommerce installed for other products? Nothing changes automatically. Installing WooCommerce does not redirect course purchases through it. You can explicitly opt in to routing Learnomy purchases through the WooCommerce cart if you want one unified checkout experience across everything you sell.
Can I accept payment methods other than credit cards? Yes. Beyond direct card payment, Stripe’s async payment methods (SEPA, Bacs, boleto, Konbini, and others depending on your account configuration) are supported through the webhook integration, and PayPal is available as a fully separate gateway option.
What’s the Test Gateway for, and is it safe to leave on? It’s a synchronous, in-memory gateway that completes checkout instantly without contacting any real payment processor, meant strictly for development, demos, and QA. It’s explicitly labeled Development Only and should be turned off before a course goes live to real customers.
Does using native payments mean I lose access to WooCommerce’s reporting and extensions ecosystem? For course sales specifically, yes, you’re trading WooCommerce’s general-purpose store reporting for a transaction ledger built specifically around courses, enrollments, and instructor payouts. If your business genuinely needs WooCommerce-level store functionality (physical products, complex shipping, a large extension ecosystem) alongside your courses, that’s precisely the case the optional WooCommerce routing exists to serve, rather than forcing every course-only site to carry that weight by default.
How do refunds affect a student’s access to a course? Refund handling is part of the same transaction record the purchase created, rather than a separate action in an unconnected store system, which is what allows a refund to reliably propagate back to revoking enrollment instead of depending on a webhook bridge working correctly between two different platforms.
What happens if the same payment webhook gets delivered twice? It’s processed once. Every inbound webhook event is logged against the provider’s own event ID before anything else happens, so a duplicate delivery, which both Stripe and PayPal send deliberately as part of their reliability guarantees, doesn’t result in double-processing, duplicate receipts, or conflicting enrollment records.
Can I run a discount or promotion without installing a separate coupon plugin? Yes. Percentage and fixed-amount coupons, usage limits, per-customer limits, and expiry dates are all handled natively, scoped to specific courses or applied across the whole catalog, without needing a coupon system built for a different kind of store.
The Simple Version
A course platform’s job is to sell access to knowledge, not to run a general-purpose store. The moment “accept payment for a course” requires installing a full e-commerce plugin, configuring shipping settings you’ll never use, and hoping a bridge plugin keeps two separate systems in sync, you’ve taken on complexity that has nothing to do with actually running your course business. Stripe and PayPal, built in, correctly wired to the webhook events that actually matter, with one unified ledger for every transaction: that’s not a smaller version of a real payment system. It’s what a payment system built specifically for selling courses looks like when nobody made you buy a store to get it.
Related reading