Payments — Veldform — vanrossum.dev                    

       vanrossum.dev 

Payments — Veldform
===================

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

Veldform / Docs

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).

   © 2026 Jeffrey van Rossum · [privacy](https://vanrossum.dev/privacy) · [terms](https://vanrossum.dev/terms) · [cookies](https://vanrossum.dev/cookies) [𝕏](https://x.com/jeffreyrossum) [YouTube](https://www.youtube.com/@jeffrey.rossum) [GitHub](https://github.com/jeffreyvr) [LinkedIn](https://www.linkedin.com/in/jeffrey-van-rossum-97b27321) [Instagram](https://www.instagram.com/jeffrey.rossum/) [Nomads](https://www.nomads.com/@jeffreyrossum/) [Unsplash](https://unsplash.com/@jeffreyrossum) 

 made with ☕
