Somebody wants to pay you $150 for a booking deposit.
You have a WordPress site. You have a contact form. And the standard advice for connecting those two facts is: install WooCommerce, configure a store, create a product, set up a cart, style a checkout, and route the customer through all of it — to collect one payment, one time, on one form.
That is a shopping cart being asked to do the job of a card reader.
This guide covers the other approach: putting the payment on the form itself. No store, no cart, no checkout page. By the end you’ll have a working payment form on your site and you’ll understand the one technical detail that separates a safe implementation from an exploitable one.
Why WooCommerce is usually the wrong tool for this
WooCommerce is excellent software. It’s also built for a specific job — running a store with a catalog, inventory, shipping, tax rules, and customers who browse before they buy.
Most people who need “a payment on a form” have none of that. They have:
- A booking deposit
- A registration fee for one event
- A donation with a suggested amount
- An invoice a client needs to settle
- A single service, sold at a single price
For these, a store is overhead you maintain forever in exchange for a transaction that takes four seconds. You inherit product pages you don’t want indexed, a cart page you don’t need, database tables you’ll never query, and a plugin that updates on its own schedule and occasionally breaks your theme.
There’s a subtler cost too. Every extra page between “I want to pay you” and “payment complete” is a place people leave. A form that collects the details and the money in one submission has no such gaps.
What you actually need
Before picking a tool, it’s worth being precise about the requirements. A payment form needs to:
- Collect the payment on the page. No redirect to a third-party checkout and back.
- Show a live total. If someone adds a quantity or picks a more expensive option, the button should say what they’re about to be charged.
- Verify the amount on the server. This is the one that gets skipped, and it matters more than everything else. More below.
- Support the payment methods people actually use. Cards, plus Apple Pay and Google Pay, which convert dramatically better on phones.
- Keep a record. A submission you can find later, tied to the payment.
- Not take a cut. Some form plugins charge a percentage of every transaction on top of what the payment processor takes.
Anything that does all six without asking you to run a store is a reasonable answer. Below is how it works in Custom Contact Forms Pro, which is the plugin I build — I’m telling you that up front so you can weigh the rest accordingly. The principles apply whatever you choose.
Setting it up
1. Install the form builder
Start with the free Custom Contact Forms plugin from WordPress.org. It’s a drag-and-drop builder with a Gutenberg block, form templates, and submission management. Pro installs on top of it and adds the payment fields — the builder stays the same, your existing forms keep working.
2. Connect Stripe
In your Stripe Dashboard, go to Developers → API keys and copy the publishable and secret keys into the plugin’s Stripe settings.
Use the test keys first. Stripe gives you a separate set. With test mode active, card number 4242 4242 4242 4242 (any future expiry, any CVC) places a successful test order, and 4000 0000 0000 0002 simulates a decline. Run both before you touch live keys. Testing a decline is the step people skip and then discover in production.
While you’re in Stripe, turn on customer receipts under Settings → Emails → “Successful payments.” The plugin hands Stripe each buyer’s email address and Stripe handles the receipt from there.
If you want Apple Pay, register your domain once at Settings → Payment methods → Apple Pay → Add domain. Google Pay and Link need no setup.
3. Build the form
Create a form and drag in a Product field. It has three pricing modes, and which one you pick depends on what you’re selling:
| Mode | What it does | Use it for |
|---|---|---|
| Single product | One item, one fixed price | Deposits, registration fees, merchandise |
| Multiple options | A dropdown where each choice carries its own price | Ticket tiers, packages, donation levels |
| Customer chooses amount | The visitor types the figure | Donations, invoice payments, tips |
Add a Total field so buyers see a running total, and a Stripe Card field for the payment itself. The submit button becomes a payment button that reads “Pay $150.00” and updates as they make choices.
A form can hold as many product fields as you like — a main item, optional add-ons, a fee cover — and they all sum into the total.
4. Publish it
Embed the form with the Gutenberg block or the shortcode. Page builders work fine; the payment flow is self-contained.
Then purge your cache. Caching plugins and CDNs serve old JavaScript, which is the single most common cause of “the payment field looks wrong after I changed something.” Test in a private window to confirm you’re seeing the live version.
The part that actually matters: server-side verification
Here’s the requirement I flagged earlier, and it’s worth understanding even if you use a different plugin.
A payment form calculates a total in the browser so the visitor can see it. The browser is not trustworthy. Anyone with developer tools open can change what the page reports back to your server. If your form charges whatever amount the browser submits, someone can buy your $500 service for $0.50.
The correct behavior is that the server recalculates the total from scratch — the actual products, the actual quantities, the actual coupon, the actual conditional logic — and charges that, ignoring whatever the browser claimed. The price charged is always the price you configured.
The sequence should be: visitor submits → server recomputes the total → Stripe charges the verified amount → only then is the submission saved and marked paid. That ordering matters. A failed or abandoned payment never creates an order, and every saved order has a verified charge behind it. You never have to reconcile a submission that claims to be paid but isn’t.
Before you commit to any payment form plugin, ask whether it verifies totals server-side. If the documentation doesn’t say, assume it doesn’t.
Common variations
Booking deposits. Single product field at a fixed price, plus your normal contact fields. The Service Booking Deposit template is this, pre-assembled.
Donations with suggested amounts. Multiple-options product for the preset tiers, plus a customer-chooses-amount field revealed by conditional logic when someone picks “Other.” Set a minimum so nobody donates a penny — the plugin enforces it in the browser and again on the server. Stripe’s own floor is $0.50 regardless.
Covering processing fees. A “Cover the processing fee?” yes/no question that conditionally reveals a small priced field. This is where conditional logic and money intersect, so the rule is worth stating plainly: a priced field hidden by conditional logic is never charged. Hidden means not billed, verified on the server.
Paid event registration. Ticket tiers as a multiple-options product, quantity enabled, attendee details as regular fields.
Multi-step forms. Drop a Page Break where each new step starts and visitors get a progress indicator with per-step validation. Put the payment on the final step.
Signatures, consent, and receipts
Once payment lives on the form, adjacent problems become solvable in the same place.
Signatures. A signature field lets people sign with a mouse, finger, or stylus. The signature saves as a PNG with the submission and appears as actual ink in PDF exports. Waivers and service agreements stop needing a separate e-signature subscription.
Versioned consent. A consent field presents scrollable terms with an agreement checkbox, and — this is the useful part — snapshots the exact text that was agreed to, permanently. Update your terms next month and every prior submission still shows the version that person accepted. If you’ve ever needed to prove what somebody agreed to, you know why that matters.
PDF receipts. Paid submissions attach a PDF receipt to the notification email with the amount, a paid stamp, the payment reference, and the submitted details. Any submission can be downloaded as a PDF on demand.
What it costs
Stripe takes its standard processing rate. That’s unavoidable and every option has it.
The variable is what the form plugin takes. Some charge a percentage of each transaction on top of Stripe’s, particularly on lower-priced tiers — which means your plugin cost scales with your revenue forever.
Custom Contact Forms Pro is $80/year, every feature included, on unlimited sites you own, with no added transaction fees. The free plugin stays free and keeps getting updates.
Full breakdown on the pricing page.
Frequently asked questions
Do I need WooCommerce installed? No. Nothing in this setup touches WooCommerce. If you already run a store for other reasons, the two coexist fine.
Can I take payments without any plugin at all? You can hand-code a Stripe integration, and if you’re comfortable with server-side verification, webhooks, and idempotency, that’s a legitimate path. Most people are buying the correctness, not the form.
What payment methods are supported? Cards, Apple Pay, Google Pay, and Link — all completing on-page. Redirect-based and delayed methods like bank debits and buy-now-pay-later are deliberately excluded, because they can’t complete safely inside an on-page form flow.
How do I find a payment later? Every submission stores the Stripe payment reference, which begins pi_. Search it in your Stripe Dashboard and you’re looking at the same transaction.
Why isn’t Apple Pay showing on my iPhone? Register your domain in Stripe first. It also only appears in Safari, on a device with a card in Apple Wallet.
Does this work with Elementor, Divi, or Bricks? Yes. Embed with the shortcode or block as usual.
Getting started
Install the free plugin from WordPress.org and build a form. When you’re ready to take money on it, Custom Contact Forms Pro installs on top and adds the payment fields to the builder you already know.
The full documentation covers the Stripe setup in detail, including test mode, conditional pricing, and troubleshooting. If you want the feature-by-feature tour instead, that’s in the Pro announcement post.
Start in test mode. Run a successful charge and a declined one. Then switch the keys.