Payments, Veldform · vanrossum.dev    

       vanrossum.dev 

Payments, Veldform
==================

  vanrossum.dev  

  [      vanrossum.dev ](https://vanrossum.dev)                      

 [home](https://vanrossum.dev) / [veldform](https://vanrossum.dev/products/veldform) / docs 

 [Veldform](https://vanrossum.dev/products/veldform)  / Docs  · WordPress plugin

 Payments
=========

Veldform can take payments through **Stripe** and **Mollie**. Both use the provider's hosted checkout page and support one-time payments. Developers can add other gateways, see [Action and filter hooks](/products/veldform/docs/hooks).

- [Connecting a provider](#connecting-a-provider)
- [Currency](#currency)
- [Setting up a payment form](#setting-up-a-payment-form)
- [Product fields](#product-fields)
- [The payment action](#the-payment-action)
- [The payment flow](#the-payment-flow)
- [After payment](#after-payment)
- [Payment statuses on entries](#payment-statuses-on-entries)

Connecting a provider
---------------------

Credentials are stored as a [connection](/products/veldform/docs/connections). Go to `Veldform` -&gt; `Connections`, click `Add connection` and pick Stripe or Mollie:

- **Stripe**: fill in your Secret key (`sk_live_...` or `sk_test_...`). Optionally add the Webhook signing secret (`whsec_...`).
- **Mollie**: fill in your API key (`live_...` or `test_...`).

You don't need to configure a webhook URL at the provider, Veldform passes it along automatically when a payment is created.

There is no separate test mode toggle: whether you're in test or live mode is determined by the key you use. To go live, update the connection with your live key.

Currency
--------

The default currency and price formatting live under `Veldform` -&gt; `Settings` -&gt; `Currency & prices`. A form can override the currency under its own `Settings` -&gt; `Currency`.

Setting up a payment form
-------------------------

A payment form usually consists of two parts: product fields, and the payment action.

### Product fields

Add a `Product / price` field for each thing you're selling. A product field has two pricing modes:

- **Fixed price**: one unit price
- **Choice of priced options**: the visitor picks an option, each with its own price

Optionally let the buyer choose a quantity, with a minimum and maximum. Add an `Order total` field to show the running total, it updates live as the visitor picks options.

Prices are always recomputed on the server from the saved form, so buyers can never manipulate what they pay.

### The payment action

On the `Actions` tab, add the `Take payment` action. It has the following settings:

- **Payment provider**: Stripe or Mollie
- **Connection**: the connection with your API credentials
- **Amount**: where the amount comes from:
- `Fixed price`, a fixed amount
- `From product fields`, the computed order total (recommended for sales)
- `Amount the payer enters`, for donations; point it to a number field and optionally set a minimum
- **Description**: the payment description at the provider, merge tags allowed (e.g. `{{ form.title }} #{{ entry.id }}`)

The payment flow
----------------

When the visitor submits the form, they are redirected to the Stripe or Mollie checkout. After paying they return to the page the form is on:

- **Paid**: your form's confirmation message is shown
- **Pending**: a "your payment is being processed" notice is shown; the entry is updated once the provider confirms
- **Failed, canceled or expired**: a notice is shown and the form is rendered again, so the visitor can retry

Payment confirmation always comes from the provider's webhook (or a direct status check), never from the redirect alone. Abandoned checkouts are automatically marked expired after 24 hours.

After payment
-------------

Any other action can be set to run `After payment` instead of `On submit`. That's how you send a receipt: add a `Send notification` action and set its `Run` setting to `After payment`. It will run exactly once, when the payment is confirmed.

Payment statuses on entries
---------------------------

The [entry](/products/veldform/docs/entries) status follows the payment: `Awaiting payment`, `Paid`, `Payment failed`, `Payment expired` or `Payment canceled`. If the payment succeeded but a required after-payment action failed, the status is `Paid, action failed`, the details will be in the entry timeline and the [log](/products/veldform/docs/troubleshooting).

Refunds you issue at the provider are picked up too, and show up in the revenue tiles on the form's `Stats` tab.

For developers: an action hook fires on every payment status change, e.g. `veldform/payment/paid`, see [Action and filter hooks](/products/veldform/docs/hooks).

Stuck?

Feel free to reach out.

 [get in touch →](https://vanrossum.dev/contact) 

   © 2026 Jeffrey van Rossum 

  vanrossum.dev vanrossum.dev
