Skip to content

Let clients pay online

Applies to Workletto 1.x.

You can let clients pay invoices online through your own Stripe account. The money goes from your client to your Stripe account. It never passes through the app, or through the makers of the app, and they take no part of it.

Click the picture to zoom in.
Manage, Payments: connecting your Stripe account
  1. In the Stripe Dashboard, create a restricted key with Checkout Sessions: Write. Add Webhook Endpoints: Write too, so that Stripe can tell the app about payments straight away. A full secret key (sk_) works as well, but a restricted key (rk_) is safer.
  2. In the app, open Manage, then Payments. Only admins see it.
  3. Paste the key into Stripe key and click Connect.

The app checks the key with Stripe. If it isn’t a key (it must start with rk_ or sk_), the page says so; if Stripe refuses it, you see Stripe’s reason. After connecting, the page says “Connected to Stripe (Test mode)” or “(Live mode)” and shows the last characters of the key. The key is stored encrypted and never shown again. Replace key swaps it for another.

If your app is on an HTTPS address that Stripe can reach, the app also registers a webhook with Stripe. If you later move the app to another address, Manage → Payments says where Stripe still sends its notifications and offers Send them here. If the webhook was never set up, it offers Set it up. Without it (for example when you try the app on your own computer), the page says “Payments are checked with Stripe every few minutes.”

A key that starts with rk_test_ or sk_test_ connects in test mode. Use the card 4242 4242 4242 4242, any future date and any security code. No real money moves. Connect a live key when you’re ready.

Once Stripe is connected, every invoice that isn’t a draft has an online payment link. You see it on the invoice page as Pay online link, with a Copy link button. The emails you send from the app (see Email an invoice) also include it, as a button (“Pay” and the total) and, in the plain-text version, a “Pay online” link. You can send the link yourself too.

When the client opens it they go to a Stripe page for the invoice’s current total, titled with the invoice number. After paying they come back to a page that thanks them. Stripe emails them a receipt if they gave an email address. If an invoice is already paid, the link says “Thank you. There’s nothing more to pay.”

An invoice is marked paid only after the app has asked Stripe, with your key, and Stripe confirms the full amount, in the invoice’s currency, for that invoice. What the client’s browser reports and what Stripe’s notification contains are never enough on their own to mark it paid.

The invoice page then shows “Paid online” with the amount and date, and Manage → History records it as “Online payment (Stripe)”.

If the invoice was changed after the client opened the link (so its total no longer matches), or was already paid by hand, it is not marked paid. History says: “Paid online, but not marked paid: the invoice changed or was already paid.” Check it in Manage → History and decide, refunding the client in Stripe if they paid twice.

An invoice has at most one open checkout, so a client can’t pay twice by mistake:

  • Opening the link again goes back to the same Stripe page.
  • Marking the invoice paid by hand, moving it back to draft, or disconnecting Stripe ends the open checkout.
  • A checkout lasts 24 hours. After that the link starts a new one.

If a second payment still gets through, History says to refund it in Stripe, and you do that in Stripe.

Some methods, such as bank debits, are accepted before the money arrives. The client sees “Your payment is being processed”. While it’s being processed the link takes no other payment (“A payment for this invoice is being processed”). The app asks Stripe about it every hour, for up to 30 days, and marks the invoice paid when it arrives.

  • A yen total with a fraction of a yen can’t be charged. The link says to contact you.
  • A total below the smallest amount Stripe takes.

Open checkouts are checked with Stripe every 5 minutes anyway, so payments are recorded without the webhook, a few minutes later. The Payments page shows the last Stripe error if there was one.

On Manage → Payments, click Disconnect and confirm. Open checkouts are ended, the webhook is removed at Stripe, and the invoices lose their Pay now link until you connect again. Invoices already paid stay paid.

If you restore a backup on an install with another BETTER_AUTH_SECRET, the saved key can’t be read and you connect again. See Back up and restore.

With Stripe connected, the app contacts api.stripe.com, only to make or check a checkout, and only for your invoices. What it sends is the invoice number, the total and currency, and the client’s email address if you have one. Client names and invoice lines aren’t sent.