Skip to main content

Setup

What an admin configures once, after installing Flourish Payments, before a payment form can take money.

There are four pieces: the permission set, the Flourish Payments Setting record that holds your Stripe keys, an Experience Cloud site that hosts the public connector, and a webhook in Stripe. The widget on your website will not reach Salesforce until the first three are in place, and payments will not reconcile onto records until the fourth is.

Before you start

You need a Stripe account and access to its dashboard, because three values come from there: the publishable key, the secret key, and the webhook signing secret.

Flourish Payments has no tabs and no app of its own. Everything it does happens on the Opportunity record page, in Flow, or on your own website.

Permission set

One permission set ships with the package.

Permission setGive it to
Flourish Payments: AdminPeople who need to read and edit the payment fields on an Opportunity: Stripe Sync, Payment Custom Data, External Ids, Payment Model, and Initial Stripe Checkout Datetime.

Two things it deliberately does not do. It grants no Apex access, so the guest user of your connector site is a separate grant covered below. And it does not touch Stripe Customer ID on the Contact, so if you want that field visible on a Contact page, grant it through your own permission set or profile.

Flourish Payments Setting

All org-wide configuration lives in one custom metadata record.

Go to Setup > Custom Metadata Types > Flourish Payments Setting > Manage Records. The record is named global, in lower case. If it is not there, click New and set both the label and the record name to global.

FieldWhat it holds
Stripe Public KeyYour Stripe publishable key, pk_live_... or pk_test_.... This one is sent to the browser.
Stripe Secret KeyYour Stripe secret key, sk_live_... or sk_test_.... It is used only server side and is never sent to the browser.
Stripe Webhook SecretThe signing secret Stripe gives you when you create the webhook, whsec_.... Every inbound event is checked against it.
Public Connector URLThe URL of the Experience Cloud page hosting the connector. The payment widget loads this page in a hidden frame.
Opportunity Record TypeDeveloper name of the record type for Opportunities the package creates. Leave blank for the org default.
Default Opportunity StageStage for those Opportunities. Leave blank and the package picks the first open stage.
Pricing Flow NameAPI name of an Autolaunched Flow that computes the charge amount. Leave blank unless you need it. See Server-side pricing.
Stripe Account IDA connected account ID. Nothing reads it yet, so leave it blank.

The package includes the Remote Site Setting for Stripe, so callouts work with no extra configuration.

Keep the secret key and the webhook secret to the people who need them. Anyone who can open this record can read both.

The public connector site

Your payment form runs on your own website, which cannot call Salesforce directly. It reaches Salesforce through Flourish Payments: Public Connector, a component you host on an Experience Cloud page. The widget loads that page in a hidden frame and talks to it. The secret key stays in Apex; only the publishable key crosses into the browser.

  1. Create an Experience Cloud site, or use one you already have. A bare LWR site is enough: nothing on the page is meant to be seen.
  2. Add the Flourish Payments: Public Connector component to a page on that site.
  3. Give the site's guest user access to the pay_StripePublicUtility Apex class. Grant it on the guest profile, or on a permission set assigned to that guest user. Without it the page loads and the widget times out waiting for the handshake.
  4. Publish the site. A deploy alone does not reach the served pages.
  5. Copy the page's URL into Public Connector URL on the global record.

That URL is also what the page author sets as paymentsLwc.siteUrl in the widget config. See Payment widget.

The connector runs in system mode, so it needs no object or field permissions of its own.

The Stripe webhook

Stripe tells Salesforce what happened after the customer pays. Without the webhook, Opportunities created by a checkout stay at their opening stage even when the payment went through.

1. Build the endpoint URL

Take your connector site's base URL and add the package path:

https://YOUR-SITE.my.site.com/SITE_PATH/services/apexrest/payments/webhook

The org's own REST URL also works if you would rather not route it through the site:

https://YOUR-ORG.my.salesforce.com/services/apexrest/payments/webhook

2. Add the endpoint in Stripe

In the Stripe dashboard, go to Developers > Webhooks, click Add endpoint, paste the URL, and subscribe to these five events:

  • checkout.session.completed
  • checkout.session.async_payment_succeeded
  • checkout.session.async_payment_failed
  • checkout.session.expired
  • charge.refunded

3. Save the signing secret

Copy the signing secret Stripe shows you and paste it into Stripe Webhook Secret on the global record.

4. Grant the guest user the webhook class

If the endpoint runs through the Experience Cloud site, give that site's guest user access to the pay_StripeWebhook Apex class the same way you granted the connector class. Stripe is not logged in to your org.

What each event does to a record is on Payments in Salesforce.

Checking it works

  • Open the connector page in a browser. It renders nothing, which is correct. What matters is the browser console: it logs FL Payments connected. If instead it warns about loading connector init, the guest user is missing the Apex class.
  • Run a test payment with Stripe in test mode and a test card. The widget should reach the Stripe payment step; if it stalls before that with a timeout message, the connector URL or the guest grant is wrong.
  • Open the Opportunity the checkout created. Add Flourish Payments: Stripe Sync Viewer to the page if you have not already, and confirm the payment shows as Completed. Still Pending a minute after paying means the webhook is not arriving: check its delivery attempts in the Stripe dashboard.
  • Check the signature. A webhook that returns 401 in Stripe's delivery log is a Stripe Webhook Secret that does not match the endpoint you created.