Fillin Forge integrates with Stripe to let you collect credit card payments directly within your forms. This is the right solution for order forms, donation forms, service bookings, event registrations with fees, and any situation where you need to charge visitors at the time of submission. The payment field is powered by Stripe Elements, which means card data is entered into Stripe’s iframe and never touches your WordPress server.
Fillin Forge takes no commission on payments — 100% goes to your Stripe account (minus Stripe’s standard processing fees). You control everything from your Stripe dashboard.
What You Need Before Starting
- A Stripe account (sign up free at stripe.com if you do not have one)
- Your Stripe Publishable Key and Secret Key (found in your Stripe dashboard)
- Your Stripe Webhook Signing Secret (created during setup)
Setup Walkthrough
- Log in to your Stripe Dashboard at dashboard.stripe.com.
- Click the Developers menu, then API Keys.
- You will see two keys: Publishable Key (starts with
pk_) and Secret Key (starts withsk_). Start with your Test mode keys to verify the setup works before going live. - Copy both keys.
- In WordPress, go to Fillin Forge > Settings (the Stripe Payments card).
- Paste the Publishable Key into the first field.
- Paste the Secret Key into the second field.
- Make sure the Mode toggle is set to Test (since you are using test keys).
- Now set up the webhook. In Stripe, go to Developers > Webhooks and click Add Endpoint.
- Enter the webhook URL shown on the Fillin Forge Stripe settings page (it will look like
https://yourdomain.com/wp-json/formforge/v1/stripe/webhook). - Under “Events to send,” select
payment_intent.succeeded,payment_intent.payment_failed, andcharge.refunded. - Click Add Endpoint, then copy the Webhook Signing Secret that Stripe generates.
- Back in Fillin Forge settings, paste the Webhook Signing Secret into the corresponding field.
- Click Save Settings.
Adding a Payment Field to Your Form
- Open your form in the builder.
- Drag the Payment (Stripe) field from the PRO fields section into your form. Place it near the bottom, typically as the last field before the submit button.
- Click the pencil icon on the payment field to open the right-hand Field Settings panel. The Payment (Stripe) section there has these controls:
– Amount (when Fixed) — type the price in the currency’s own unit, like 49.99 for USD 49.99 or 1000 for JPY 1000. A currency with hundredths takes up to two decimals. The smallest payment Fillin Forge takes is 50 of the currency’s smallest unit: 0.50 in USD, EUR, GBP and the other currencies with hundredths, and 50 in JPY.
– Linked Calculation field (when Dynamic) — pick the Calculation field whose result should become the charge. The displayed amount on the form updates live as the visitor changes inputs that feed the calculation.
– Currency — USD, EUR, GBP, CAD, AUD, JPY, RUB, CNY, INR, BRL, or MXN. JPY has no hundredths, so a price of 1000 is charged as 1000 yen; in each of the other currencies of the list a price of 10.00 is charged as ten units of that currency.
– Mode — normally leave on “Inherit from global Stripe settings” so the form uses your global Test/Live toggle. Use Test or Live to force a specific mode for this one field (rare; useful for staging a single live form on an otherwise test site).
– Description — shown on the visitor’s Stripe receipt and recorded in your Stripe dashboard. Keeps your accounting tidy (“Premium subscription monthly”, “Conference 2026 ticket”, etc.).
- Save the form. The payment field does not expose the generic Placeholder setting because Stripe’s Card Element does not support a normal text-input placeholder.
Dynamic payment amounts are validated twice: the browser blocks values below Stripe’s minimum before creating a PaymentIntent, and the server checks the amount before the visitor is charged. For a fixed price it holds the amount to the price of the field. For a Calculation field whose formula is made of numbers, + – * / and brackets over fields that hold a number or a choice, it works the total out itself from the values of the same request and refuses an amount that is more than one smallest unit of the currency away from it. A formula it cannot repeat (one that uses another Calculation field, for example) is held only to the total the browser reports, and the form editor tells you so when you save the form. A single payment cannot be more than 1,000.00 in USD, EUR, GBP and the other currencies with hundredths, or more than 100,000 in JPY. If the calculated amount is missing, negative, below the minimum, above that limit, or does not match the client-sent amount, no charge is created.
Testing with Stripe Test Cards
Always test before going live. Stripe provides test card numbers:
| Card number | What it simulates |
|---|---|
| 4242 4242 4242 4242 | Successful payment |
| 4000 0000 0000 0002 | Declined card |
| 4000 0025 0000 3155 | Requires 3D Secure authentication |
Use any future expiration date (like 12/30) and any three-digit CVC (like 123) with test cards.
Going Live
Once testing is complete:
- In your Stripe dashboard, switch to Live mode and copy your live Publishable Key and Secret Key.
- In Fillin Forge settings, replace the test keys with live keys.
- Toggle the Mode to Live.
- Create a new webhook endpoint in Stripe for live mode (using the same URL) and update the Webhook Signing Secret.
- Save settings.
Troubleshooting Stripe
| Problem | Most likely cause | Solution |
|---|---|---|
| Payment field does not appear | Stripe keys not saved or mode mismatch | Verify keys in Settings and check the Mode toggle |
| Payment field is locked in the builder | Free plan | Activate Fillin Forge PRO; crafted saves are also downgraded server-side |
| Dynamic amount stays at 0.00 | Linked Calculation field not selected, formula has no inputs, or stale frontend JS | Select the Calculation field, test the formula in Live preview, then hard-refresh cached pages |
| “Payment amount must be at least…” | The fixed or calculated amount is below Stripe’s minimum | Raise the fixed amount or correct the Calculation formula before testing |
| “Card declined” on test card | Using the wrong test card number | Use 4242 4242 4242 4242 for a successful test payment |
| Payment status does not update after refund/failure | Webhook not configured correctly | Verify the webhook URL in Stripe and the Signing Secret in Fillin Forge |
| “Unauthorized” error in console | Secret Key is invalid or expired | Regenerate keys in Stripe and update Fillin Forge settings |
| Payments work in Test but not Live | Using test keys in live mode (or vice versa) | Make sure you switched both keys and the Mode toggle |
Optional Email field says pi_... is missing an @ after payment | Older Stripe runtime wrote the PaymentIntent ID into the wrong visible input when field IDs collided | Update Fillin Forge and clear page/script cache |
> Tip: Start in Test Mode, submit several test payments, verify they show up in your Stripe Test Dashboard, then switch to Live Mode keys only when you are confident everything works correctly.
> Good to know: Fillin Forge takes no commission on payments. Without PRO, the Payment field is not available. Card data is handled entirely by Stripe through their embedded form element and never stored on your WordPress server. Fillin Forge validates the submission before charging the card; reCAPTCHA, required-field, Calendar Picker, map-address, or server validation errors stop before Stripe capture. If Stripe declines the card, Fillin Forge shows the Stripe error only and does not save a successful submission. During payment/submission processing, conversational forms disable the visible submit button and show a loading label just like standard forms. A payment is stored as payment_status = succeeded only when Stripe says so. Fillin Forge looks the payment up in Stripe with your own secret key, and it has to be paid, made for this form and this payment field, in the currency of the field, for the amount of the form (one smallest currency unit of difference is allowed; a calculated amount whose formula the server cannot repeat is held only to the total the browser reported, and the form editor tells you so when you save the form), and not already belong to another submission. A payment made in Stripe’s test mode is never accepted on a site in live mode. A payment that fails one of these checks (it is not paid, it was made for another form or field, in another currency, or in test mode on a live site, or it already belongs to another submission) is refused: the submission is not saved, and the visitor reads “Payment could not be verified. If you were charged, please contact us before trying again.” Two cases are saved with a status of their own: Payment not confirmed when Stripe could not be asked and Paid amount differs when the payment is for another amount than the values of the submission come to. A saved submission that Stripe could not be asked about is asked again. Fillin Forge asks again by itself, through WP-Cron: the first time about 2 minutes after the submission, then after pauses of 10 minutes, 1 hour, 6 hours and 24 hours, and after that at most once every 6 hours. It stops after 12 checks in all (a press of the button counts as one), which is roughly three days after the submission. The checks up to the pause of 24 hours are one-time tasks: if WP-Cron does not start one on time, a notice on the Fillin Forge screens lists it as a task that did not run on time and offers a Run them now button. The checks after that are made by an hourly walk, which the notice does not list. The Check payment in Stripe button in the submission asks at once; it is there for Payment not confirmed, Not paid and a payment Stripe still reports as processing or requires_capture, and it is not offered for Paid amount differs. Not paid is set only by such a later check, when Stripe holds no completed payment for the submission. Webhooks can later update the status to failed or refunded.
[Screenshot: The Stripe settings page in Fillin Forge showing fields for Publishable Key, Secret Key, Webhook Signing Secret, and the Test/Live mode toggle]
—