Flow actions
Four actions Flourish Payments adds to Flow: two that charge a card the customer already saved, and two that read the data a payment form collected.
In Flow Builder, add an Action element and look under the Flourish Payments category.
Charging a saved card
When a customer ticks the box to save their card at checkout, the package keeps a token for it. The token is not the card: it is a reference Stripe accepts on your behalf, for that customer, with no one at the keyboard. That is what both charging actions spend.
The token is stored with the rest of the payment history in Stripe Sync on the Opportunity, in this shape:
{
"stripeCustomerId": "cus_...",
"paymentMethodToken": "pm_...",
"paymentMethodStatus": "active"
}
Charge Payment Token
The action to use for anything recurring. It reads the credential out of a field rather than taking it as an input, which means the token can live in one place and every record that needs it can point at that place.
| Input | Required | What it takes |
|---|---|---|
| Credential JSON Field | Yes | The field holding the JSON above. A path through a parent works, so npe03__Recurring_Donation__r.Stripe_Credentials__c reads the token off the parent rather than needing a copy on every child. |
| Amount Field | Yes | The field holding the dollar amount to charge, for example Amount. |
| Record ID | One of these two | Charge this one record now, and wait for the answer. |
| SOQL Query | One of these two | Charge every row this query returns, in the background. |
| Currency | No | ISO currency code. Defaults to usd. |
| Description | No | A description sent to Stripe with the charge. |
| Chunk Size | No | How many charges run per transaction on the background path. Defaults to 50, capped at 90. |
| Output | What it tells you |
|---|---|
| Success | The single charge went through. Only meaningful on the Record ID path. |
| Payment Intent ID, Status, Error Message | The result of that single charge. |
| Enqueued | The background run started. |
| Records Queued | How many rows it will charge. |
| Records Skipped | How many rows it refused to charge, and why is on each record's result. |
Two paths, and they behave differently. Give it a Record ID and the charge happens while the Flow waits, so a Screen Flow can tell the person at the desk what happened. Give it a SOQL Query and it hands the work off and returns straight away: a scheduled Flow that charges a month of installments gets Enqueued and a count, not an outcome per row. Check the records themselves for those.
Pass one query rather than looping records and calling the action per row. The query is what keeps a large run inside Salesforce's limits, and the action charges in chunks, each chunk its own transaction.
Rows it will not charge. A row whose credential field is empty, whose JSON has no token or no customer, or whose paymentMethodStatus is anything but active, is skipped before any money moves and counted in Records Skipped. Put the same conditions in your query's WHERE clause anyway; the guard is there for the rows that slip through.
Charging twice is guarded against. Each charge carries a key built from the record and the date, and Stripe honors it: if a background run dies partway and is retried the same day, the rows it already charged return their original result instead of charging again.
A successful charge writes a receipt and stops there. It appends the payment to Stripe Sync and nothing else. It does not set the stage to Closed Won and does not mark a payment record paid, because what a recurring charge means for your records is yours to decide. Do it in the same Flow, after the action.
The query is checked before it runs. It has to be a single SELECT with no semicolon, and it must select the credential field and the amount field you named.
Charge Saved Payment Method
The same charge, with the credentials handed to it directly. Use it when the Flow already has the customer and token in variables, or when the token does not live in a field on the record.
| Input | Required | What it takes |
|---|---|---|
| Stripe Customer ID | Yes | The cus_... customer. |
| Payment Method ID | Yes | The pm_... token saved at a previous checkout. |
| Amount | Yes | Dollars, for example 25.00. |
| Output | What it tells you |
|---|---|
| Success | Whether the charge went through. |
| Payment Intent ID | Stripe's ID for the charge. |
| Status | What Stripe reported. |
| Error Message | The decline reason or the error, when Success is false. |
This one charges and returns. It writes nothing to the Opportunity, so anything you want recorded, record it in the Flow.
Reading what the form collected
Both of these read Payment Custom Data, where every form field the package does not handle itself ends up. See Payments in Salesforce.
Get Custom Data Value
Pulls one value out by name.
| Input | Required | What it takes |
|---|---|---|
| Key Name | Yes | The field name from the form. Dot notation reaches nested values, for example pricing.source. |
| Opportunity ID | If no JSON String | The Opportunity to read. |
| JSON String | If no Opportunity ID | The JSON itself. In a record-triggered Flow, pass $Record.pay_Custom_Data__c and save the query. |
The output is Value.
Filter by Custom Data
Narrows a list of Opportunities to the ones whose custom data matches.
| Input | Required | What it takes |
|---|---|---|
| Opportunity IDs | Yes | Comma-delimited list to test. |
| Key Name | Yes | The field name, dot notation allowed. |
| Operator | No | equals (the default), not_equals, contains, not_contains, is_blank, is_not_blank. |
| Key Value | No | What to compare against. Not needed for is_blank and is_not_blank. |
The output is Matching IDs, comma-delimited. Comparisons are case-sensitive.