Stripe Refund Approval Workflow
When a refund is requested (form/Teams/agent), the flow validates the original charge in Stripe, routes an approval based on amount and reason, on approval issues the refund via Stripe, updates the order in Dataverse, and notifies the customer. Adds governed approvals to Stripe refunds.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
FlowLibs - Stripe Refund Approval Workflow (CF-730) adds a governed approval gate to Stripe refunds. On a schedule it polls a Dataverse refund-request ledger for new Pending requests, validates each original charge in Stripe, routes an amount-based approval (standard vs. senior approver), and on approval issues the refund via Stripe, writes the outcome back to Dataverse, and notifies the customer. Rejected and unvalidatable requests are recorded and routed for follow-up.
Why it matters: Unchecked refunds are a leakage and fraud risk. An approval gate with charge validation controls refunds while keeping small amounts fast, and the Dataverse ledger gives finance a complete, auditable record of every decision.
Built API-first as a Dataverse workflows (cloud flow) record. Ships Off — going live requires only authorizing the three connections and setting the env var values (Stripe key, approver emails, threshold). Flow Checker: 0 errors / 0 warnings.
Use Case
Finance wants every customer refund approved per policy and then executed automatically, with a durable audit trail. Intake systems (a form, a Teams request, or an agent) drop refund requests into a Dataverse ledger table; this flow processes the queue: it confirms the charge is real and refundable, gets the right person to approve based on the refund amount, issues the refund, and closes the loop with the customer.
Flow Architecture
Recurrence Poll Refund Requests
Recurrence (Hour / 1)Polls the ledger on a schedule because intake is asynchronous (form/Teams/agent write rows; the flow drains the Pending queue).
Initialize Correlation Id
InitializeVariable (string guid())Trace id for this run, stamped on every Stripe call, Dataverse write, and notification.
Initialize Selected Approver
InitializeVariable (string)Holds the per-request approver.
Initialize Status Pending / Refunded / Rejected / Invalid
InitializeVariable (string)Configurable status labels.
Initialize Approver Standard / Senior
InitializeVariable (string)Approver emails from env vars.
Initialize Threshold Cents
InitializeVariable (integer)Senior-approval threshold (cents).
List Pending Refund Requests
Microsoft Dataverse — ListRecordsGet all Pending ledger rows.
Apply to each Request
Foreach (sequential, concurrency 1)Process each request in order.
Get Stripe Charge
HTTP — GET /charges/{id}Validate the original charge.
Condition Charge Valid
If (refunded == false AND status == succeeded)Gate on a refundable charge.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_StripeApiBaseUrl | String | https://api.stripe.com/v1 | Stripe REST base URL. |
| flowlibs_StripeApiKey | String | sk_live_REPLACE_… | Stripe secret key (Bearer) — replace with a restricted key. |
| flowlibs_RefundApproverEmail | String | finance-approvals@flowlibs.local | Standard finance approver (below threshold). |
| flowlibs_RefundSeniorApproverEmail | String | finance-director@flowlibs.local | Senior approver (at/above threshold). |
| flowlibs_RefundApprovalThresholdCents | String | 10000 | Amount (cents) routing to the senior approver. |
| flowlibs_RefundRequestEntitySet | String | flowlibs_refundrequests | Ledger entity set name. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| Microsoft Dataverse | shared_commondataserviceforapps | ListRecords UpdateRecord |
| Approvals | shared_approvals | StartAndWaitForAnApproval |
| Office 365 Outlook | shared_office365 | SendEmailV2 |
| HTTP | http | GET /charges/{id} POST /refunds |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Approval tiers
- Set Selected Approver is a single threshold today. Add more tiers (manager / director / VP) by extending the if() into nested conditions or a Switch keyed on amount bands.
- Partial refunds
- The refund amount comes from flowlibs_amountcents; an upstream system can request less than the original charge. Add a guard comparing it to the charge's amount minus amount_refunded to prevent over-refunding.
- Reason-based routing
- Route by flowlibs_reason (e.g. fraud → senior, duplicate → auto) alongside amount.
- Auto-approve floor
- Short-circuit the approval for trivial amounts (skip Start Refund Approval when amountcents is below a small floor) to keep low-value refunds instant.
- Idempotency
- The Stripe refund POST stamps metadata[correlation_id]; add a Stripe idempotency key header for safe retries.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Approver selection
Pick senior vs. standard approver by amount.
EXPR.02Charge validity gate
Only proceed when the charge is refundable.
EXPR.03Stripe refund body (form-encoded)
Form-encoded body for POST /refunds.
EXPR.04Amount for display
Convert cents to major units for messages.
EXPR.05Approver comments
Read the approver's comments from the approval response.
Customize & download
Generate a ready-to-import copy of this solution with your environment-variable values baked in — available on Base, Pro, or Team.
Upgrade to customize
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.