Skip to main content

Your Stripe Account and API Keys

Two Benecaster features use Stripe: Listener Support donations and built-in membership subscriptions. Both need the same things from your Stripe account — an account, a pair of API keys, and a webhook endpoint — and the steps for getting them are identical.

This page covers that shared half: what to do inside the Stripe Dashboard. Where the keys go afterwards, and which webhook events to subscribe to, depends on which feature you are setting up:

Setting up Configure it in Guide
Listener Support donations Settings → Listener Support Setting Up Listener Support (Stripe Mode)
Built-in membership subscriptions Settings → Payments Connecting Stripe for Subscriptions

If you are setting up both, do this page once and then follow both guides.


What You Need

  • A Stripe account. If you don’t have one, create it at stripe.com. Use a Business account, not a personal account — this is what processes payments on behalf of your podcast.
  • Your Stripe API keys, generated in the Stripe Dashboard and pasted into Benecaster.
  • A webhook endpoint registered in Stripe, so Stripe can tell your site when a payment happens.

Getting Your API Keys

  1. Log in to your Stripe Dashboard.
  2. In the top-right corner, make sure you’re in Test mode if you’re setting this up for the first time. You’ll switch to live keys when you’re ready to accept real money.
  3. Go to Developers → API keys.
  4. You’ll see two keys:
    • Publishable key — starts with pk_test_ (test) or pk_live_ (live). This one is safe to expose; it appears in client-side code.
    • Secret key — starts with sk_test_ or sk_live_. Never share this key. It has full access to your Stripe account.
  5. Copy both. Keep them in a password manager until you paste them into Benecaster.

Restricted keys will not work. Stripe also offers restricted keys with narrowed permissions. Benecaster requires standard secret keys.

Whichever panel you paste them into, secret keys are stored encrypted and are never shown back to you — the panel indicates only that a key is saved. To inspect or rotate one, do it in the Stripe Dashboard.

Changing or Removing a Saved Key

To change a key, paste the new one over it and save. You do not need to clear anything first.

Leaving a secret key field blank and pressing Save keeps the key you already have. Blank means “no change” — it does not erase. That is deliberate, because the field is always blank when the screen loads: the secret is stored encrypted and never shown back to you, so a blank field is the normal state rather than an empty one.

To remove a key, use the Clear control. Each mode with something saved gets a Clear test keys / Clear live keys button, on Settings → Payments and on a show’s own Payments tab. It asks first — “Remove the saved test keys?” — and removes only after you confirm.

Clearing removes both keys for that mode, publishable and secret, and cannot be undone: the secret was stored encrypted and is not recoverable from Benecaster, so you would need to copy it from Stripe again. The other mode is untouched.

You never need WP-CLI or database access to disconnect a Stripe account.

The site-wide panels genuinely are interchangeable: Settings → Payments and Settings → Listener Support write the same site-wide keys, so saving in either is reflected in the other. Settings → Payments is the fuller of the two — it shows test and live side by side and is the only place to switch which is active. Per-show keys are a separate store and live at Shows → [show] → Settings → Payments; nothing you enter site-wide changes them.


Registering a Webhook Endpoint

Stripe notifies your site by POSTing events to a URL you register. Without a working webhook, payments succeed at Stripe and your site never finds out — donations go unrecorded, subscriptions go unprovisioned.

  1. In the Stripe Dashboard, go to Developers → Webhooks.

  2. Click Add endpoint.

  3. Paste the webhook URL shown in the Benecaster settings panel you are configuring. Both site-wide panels display it as a read-only field with a copy button, and both show the same endpoint:

    https://yoursite.com/wp-json/benecaster/v1/stripe-webhook
    

    A show on its own Stripe account has a different endpoint, shown on that show’s Settings → Payments tab:

    https://yoursite.com/wp-json/benecaster/v1/stripe-webhook/{show-uuid}
    

    The UUID is that show’s own identifier — you do not need to look it up, because the tab builds the full URL and gives you a Copy button. Register it in that show’s Stripe account, not your main one. Registering the site-wide URL in a different Stripe account produces events that can never verify, because each account signs with its own secret.

  4. Select the events to listen for. This is the part that differs by feature — see the guide for the feature you’re setting up. Subscribe only to what you need; extra events add load and noise for no benefit.

  5. Save, then copy the Signing secret Stripe shows you — a string starting with whsec_. Paste it back into the Benecaster settings panel.

Benecaster validates the signature on every incoming webhook request. Without the signing secret configured, requests are rejected.

One endpoint per Stripe account. Benecaster receives all Stripe events for an account at a single URL and routes them internally, so if you already registered the endpoint for one feature you do not need a second one — add the new events to the existing endpoint instead.

The dividing line is the account, not the feature and not the site. One Stripe account for everything means one endpoint. A show on its own Stripe account means one more endpoint, registered in that account, with its own signing secret pasted into that show’s Payments tab.


Test Mode

Test the full flow before accepting real payments. With test keys active, no real money moves, test activity stays out of your live Stripe dashboard, and a TEST MODE badge appears on Benecaster’s payment screens.

On a staging site cloned from production, you cannot do this — billing calls are refused whatever mode the keys are in. Test the full flow on your production install before going live, or on a staging site that was installed separately rather than copied. See If You Have a Staging Site.

Test cards — use any future expiry date and any 3-digit CVC:

Card number What it simulates
4242 4242 4242 4242 Payment succeeds
4000 0000 0000 9995 Payment declined
4000 0000 0000 3220 Requires 3D Secure authentication
4000 0000 0000 0341 Card attaches but a later payment fails — tests dunning behaviour

Stripe’s full list is at docs.stripe.com/testing.

Testing webhooks locally. On a local environment Stripe cannot reach your site, so use the Stripe CLI to forward events. The CLI needs to be told which events to forward. These are the ones Benecaster itself handles: donations, built-in membership subscriptions, invoices and refunds, and customer.updated, which only matters if a show collects sales tax.

stripe listen --events payment_intent.succeeded,payment_intent.payment_failed,customer.subscription.updated,customer.subscription.deleted,invoice.paid,invoice.payment_failed,charge.refunded,customer.updated --forward-to https://yoursite.local/wp-json/benecaster/v1/stripe-webhook

Testing a show that is on its own Stripe account? Forward to that show’s URL instead:

stripe listen --events payment_intent.succeeded,payment_intent.payment_failed,customer.subscription.updated,customer.subscription.deleted,invoice.paid,invoice.payment_failed,charge.refunded,customer.updated --forward-to https://yoursite.local/wp-json/benecaster/v1/stripe-webhook/{show-uuid}

If an add-on you’re testing handles other Stripe events, add them to the --events list; its own guide names them. Don’t use --all-snapshot to save typing: it forwards every event in the account, and the ones nothing handles are just noise.

This matters more than it looks. Events forwarded to the site-wide URL are checked against the site-wide signing secret, so every forwarded event fails signature verification — and the failure looks like broken webhook handling rather than a misdirected test. Copy the URL from the show’s Settings → Payments tab.

The CLI can also fire specific events on demand — stripe trigger payment_intent.succeeded. This is the recommended way to test webhook handling locally.


Switching to Live Mode

Stripe keeps test and live completely separate, and this is where most setups go wrong. Live keys, live webhook endpoints, and live customers are a different world from their test counterparts — nothing carries over.

When you’re ready to take real payments:

  1. Get your live keys from the Stripe Dashboard (Developers → API keys, with the Test mode toggle off) and enter them in Benecaster.

    ✅ Your existing tiers are handled for you. Saving a complete key set sweeps your active paid tiers and creates the matching Stripe Products and Prices for that mode. You do not need to set keys up before creating tiers, and you do not need to re-save each tier afterwards — build your tiers whenever suits you and add the keys when you are ready. The same applies to giving a show its own Stripe account: its tiers are provisioned into that account on save.

  2. Check whether your webhook endpoint exists under Live mode, not just Test mode. It usually does not — you will need to add it again and copy the new signing secret, which is different from the test one.

  3. Update the signing secret in Benecaster to match the live endpoint.

  4. Check the payment mode banner at the top of your Benecaster admin screens. It is the surface that answers “is any show on this site taking real money through Stripe?”, and on a multi-show install it is the only one that answers it correctly — a show with its own Stripe account keeps whatever mode it has set, so switching the site to live does not move it. See Payment Test Mode.

    The banner is scoped to Stripe. Its headline follows the Stripe install default and its states name shows by their Stripe keysets. It is the right check for this go-live step, which is a Stripe go-live — but it says nothing about a non-Stripe payment gateway add-on. The TEST MODE badge is the surface that aggregates gateways.

    Do not use the disappearance of the TEST MODE badge as your go-live check. It reports payment gateways, not shows: it stays up if a gateway add-on is still in test, and it goes away even while a show of yours is still rehearsing on its own test keys.

  5. Run one small real transaction end to end before announcing anything.

Step 2 is the one people miss. Live keys with a test-only webhook produce the worst failure mode available: the customer is charged for real, and your site never hears about it.

Two Limits on the Automatic Back-Fill

The sweep fills in what is missing. It does not correct what is already there, and there are two cases where that matters.

Repointing a mode at a different Stripe account does not re-mint anything. If a tier already has live Product and Price IDs and you replace your live keys with a different Stripe account’s, the old account’s IDs stay on the tier — the sweep sees IDs present and leaves them alone. Those IDs do not exist in the new account, so checkout fails against them. This is a real scenario when a podcaster moves to a new Stripe account or switches a show from the site account to its own. If you repoint a mode at a different account, clear the affected tiers’ Stripe IDs so they can be minted fresh, and contact support if you are unsure which are affected.

Buy-ups are not swept. Individual episode buy-ups get their Stripe Products and Prices when the buy-up itself is created or edited, not when a key set is saved. After adding a key set, open and re-save any existing buy-ups so they are provisioned for the new mode.


Keeping the Encryption Key Out of Your Database

This is optional hardening for sites taking live payments. By default, Benecaster stores the key that encrypts your Stripe and Turnstile secrets in your WordPress database, next to the secrets it protects, so a copy of your database would contain both. Defining the key in wp-config.php instead means a database backup on its own can’t expose your Stripe keys.

Regenerating the security keys and salts in wp-config.php, by hand or with a security plugin, does not affect your payment settings. It signs everyone out of WordPress, as it always does.

Do it in this order, or your saved keys become unreadable. Benecaster uses the wp-config.php value as soon as it exists, and it does not re-encrypt what you have already saved.

  1. Read the key Benecaster is using now. With WP-CLI: wp option get benecaster_payment_crypto_key. If this returns nothing, you haven’t saved any payment credentials yet; use any long random value instead, such as the output of openssl rand -base64 32.

  2. Add it to wp-config.php, above the line that says That’s all, stop editing!:

    define( 'BENECASTER_PAYMENT_CRYPTO_KEY', 'the-value-from-step-1' );
    
  3. Check that payments still work before going further, for example with a test-mode sign-up (see Test Mode above). A saved key that can no longer be read still looks saved on the settings screen, so a real payment is the only reliable check.

  4. Delete the copy in the database: wp option delete benecaster_payment_crypto_key. Until you do, the key is still in your database backups. Don’t do this step before step 3 checks out: deleting the key while the constant holds a different value loses every saved credential, including API keys your add-ons stored with Benecaster.

Keep the constant for good. Removing it, or changing its value, makes every saved credential unreadable, and you would need to enter them all again. That includes keys your add-ons store with Benecaster, such as an AI Search or Transcription provider key, or an email-platform key. Store the value somewhere safe outside the site, such as a password manager.

If Payments Stopped After You Added the Key

If you added BENECASTER_PAYMENT_CRYPTO_KEY with a new value after saving your Stripe keys, Benecaster can no longer read those keys and payments stop. Administrators see a red notice at the top of every admin screen: “Benecaster: your payment credentials cannot be read with the encryption key in wp-config.php.” Nothing has been lost, and there are two ways out:

  • Click Re-encrypt with the key in wp-config.php on the notice. Benecaster re-encrypts every saved credential with the value in wp-config.php, including keys your add-ons stored with it, then deletes the original key from your database, which leaves you where step 4 above ends. Take a test payment to confirm. If a credential couldn’t be read with either key, the confirmation names it, and you enter that one again on its settings screen. An add-on’s key is named as “{add-on} add-on — {name}”, and is entered again in that add-on’s settings.
  • Remove the constant from wp-config.php. Payments work again immediately, because the original key is still in your database. Then follow the steps above in order.

Benecaster never re-encrypts on its own, so the original key stays in place until you choose. The notice can’t be dismissed; it goes away once the mismatch is fixed. If you added the constant before saving any payment credentials, none of this applies and you won’t see the notice.


If You Have a Staging Site

A staging site is a copy of production, which means your live Stripe keys may be sitting in the copied database. Always use test keys on staging.

Benecaster enforces this at the point of entry. Saving live Stripe keys is refused outright on an install it detects as a staging environment, and on an install it detects as a copy of another one — recognised by comparing the URL the install first recorded against the URL it is running at now, which catches a clone sitting at an ordinary domain that no hostname pattern would match. Nothing is written, and the error names the reason. This applies to the site-wide keyset and to a show’s own keys alike. Test keys are never refused, and clearing a keyset always works.

There is a second guard, and it is the one that changes what you can do on a clone. The refusal above happens when someone saves keys. Separately, on an install detected as a copy of another one, the outbound calls themselves are refused — new subscriptions, cancellations, resumes, renewal retries, buy-ups added or removed, and donation intents — whatever mode the keys are in, test included.

That is the part most likely to surprise you: test keys do not lift it. A clone carries production’s real Stripe subscription IDs, and those stay real no matter which keys are loaded, so an automated path could cancel or re-tier a paying subscriber without moving money. The point-of-entry refusal cannot see that; only knowing the install is a copy can. A refused call reports “Billing changes are temporarily unavailable on this site.”, and the operator’s explanation goes to the debug log.

If a genuine production site trips a detector, there is exactly one way back: add

define( 'BENECASTER_IS_PRODUCTION', true );

to your wp-config.php. This is the realistic case for production hosted at a domain that carries a staging label, or for a production site that has legitimately changed domain — the second being the more common of the two. It must live in wp-config.php rather than a setting, because a database-stored override would be wiped by the next staging refresh and would travel onto a copy if a staging database were ever restored the other way. Do not add it to a staging site to get past the refusal.

See Setting Up a Staging Site for Benecaster for the full workflow, including the warning Benecaster shows if it detects live keys on a site it believes is staging — which still matters, because a clone inherited its live keys with the database rather than saving them, so no save ever happened for the refusal to catch.

See Also

Need this built rather than just documented? See our services →