Stripe Connect & Online Payments
NexusRMS integrates with Stripe Connect to let your clients pay invoices online by card. The platform uses Express accounts with destination charges, meaning funds flow directly to your connected Stripe account minus a small platform fee. This article covers setup, invoice integration, the public payment page, and webhook handling.
Stripe Connect setup
Navigate to Configuration > Financial Settings > Online Payments to manage your Stripe Connect integration. The page displays the current connection status and available actions.
Connection status indicators
- Not Connected — No Stripe account has been linked. The Connect button is available.
- Setup Incomplete — A Stripe Express account has been created but onboarding (KYC verification) is not finished. The Complete Setup button is available.
- Connected — The account is fully verified and ready to accept payments.
Status details
- Charges enabled — Whether the account can accept card payments
- Payouts enabled — Whether the account can receive payouts to a bank account
- Platform fee — The percentage NexusRMS deducts from each payment (configurable by platform administrators)
Available actions
- Connect — Initiates the OAuth flow. The StripeConnectService creates an Express account with card_payments and transfers capabilities, then redirects you to Stripe to complete verification.
- Complete Setup — Generates a new onboarding link if the initial setup was interrupted
- Refresh Status — Calls syncAccountStatus() to retrieve the latest charges_enabled and payouts_enabled values from Stripe and update the tenant record
- Disconnect — Removes the connection between NexusRMS and your Stripe account. This does not delete the Stripe account itself.
- Enable Online Payments — A tenant-level toggle that controls whether online payment links are available on invoices
StripeConnectService
The StripeConnectService handles the full Stripe Connect lifecycle:
- createConnectedAccount(Tenant) — Creates a Stripe Express account with business type "company", MCC code 7394 (equipment rental and leasing), and returns the account ID and onboarding URL
- generateOnboardingLink(Tenant) — Creates an AccountLink for account_onboarding or account_update, with refresh and return URLs
- syncAccountStatus(Tenant) — Retrieves the account from Stripe and updates stripe_connect_status (pending, active, restricted, or disabled), stripe_connect_charges_enabled, and stripe_connect_payouts_enabled on the tenant
- disconnectAccount(Tenant) — Deletes the connected account from the platform and clears all Stripe Connect fields
- createPaymentIntentWithFee(Invoice, Tenant) — Creates a destination charge PaymentIntent with an application_fee_amount calculated from the tenant's platform fee percentage
StripePaymentService
The StripePaymentService handles direct payment operations:
- createPaymentIntent(Invoice) — Creates a PaymentIntent for the invoice's amount_due, converts to the smallest currency unit (pence/cents), and associates a Stripe Customer
- confirmPayment(paymentIntentId) — Retrieves the succeeded PaymentIntent, creates a Payment record, and updates the invoice's amount_paid, amount_due, and status
- refundPayment(Payment, amount) — Processes a full or partial refund via the Stripe API and updates the Payment and Invoice records accordingly
- getOrCreateStripeCustomer(Client) — Checks for an existing stripe_customer_id on the Client model; if absent, creates a new Stripe Customer and stores the ID
Invoice integration
Each invoice has several fields that control online payment behaviour:
- online_payment_enabled — A per-invoice boolean toggle. When true, the invoice includes a payment link.
- stripe_payment_intent_id — The Stripe PaymentIntent ID associated with this invoice
- stripe_payment_status — The current Stripe status (e.g., requires_payment_method, succeeded, failed)
- public_payment_token — A secure random token used to construct the public payment URL
- payment_link_sent_at — Timestamp recording when the payment link was emailed to the client
Invoice methods
- getOrCreatePaymentToken() — Generates a 64-character hex token via random_bytes(32) if public_payment_token is empty, stores it, and returns it
- getPaymentUrl() — Returns the full public URL to the payment page using the tenant's domain and the payment token
- canAcceptOnlinePayment() — Returns true if the invoice status is payable (draft, sent, viewed, partial, or overdue), the amount_due is greater than zero, and online_payment_enabled is true
- markPaymentLinkSent() — Records the current timestamp in payment_link_sent_at
Public payment page
When a client opens a payment URL, they see the InvoicePayment.vue component with two tabs:
Tab 1 — Pay by Card
- Stripe Elements card form with real-time validation
- Secure payment indicator (SSL badge)
- Invoice amount and currency displayed prominently
- Submit button triggers PaymentIntent creation and confirmation
Tab 2 — I've Already Paid
Allows the client to self-report a payment made outside of Stripe. The form includes:
- Payment method selector — Bank Transfer, Cheque, Cash, PayPal, Direct Debit, or Other
- Reference number — Free text for transaction reference
- Notes — Additional context about the payment
Submitting this form sets client_marked_paid_at and client_marked_paid_note on the invoice. This does not automatically change the invoice status — a team member must verify and record the payment.
Payment processing flow
- Client opens the payment URL (constructed from public_payment_token)
- Client enters card details in the Stripe Elements form
- StripePaymentService creates a PaymentIntent (or StripeConnectService creates a destination charge with platform fee)
- Payment is confirmed — a Payment record is created and the invoice's amount_paid and amount_due are updated
- Stripe webhook confirms the final status and triggers the InvoicePaid event if the invoice is fully paid
Webhook handling
Stripe sends webhook events to NexusRMS for asynchronous payment status updates. The system processes the following events:
- payment_intent.succeeded — Payment completed successfully. The invoice is updated and a Payment record is created.
- payment_intent.payment_failed — Payment failed. The invoice's stripe_payment_status is set to failed, failure details are recorded in invoice metadata, and a PaymentFailedMail is sent to the client with a retry URL.
- charge.refunded — A charge was refunded. Serves as confirmation of refunds initiated via refundPayment().
- account.updated — A connected account's status changed. Triggers syncAccountStatus() to update the tenant's Stripe Connect fields.
The AbstractStripeHandler base class provides common functionality for all webhook handlers including tenant lookup by Stripe customer ID, activity logging, and sync event logging.
Tips
- Always test with Stripe test cards first — Use card number 4242 4242 4242 4242 to simulate successful payments and 4000 0000 0000 0002 to test declined cards before going live.
- Verify the webhook endpoint is configured — In your Stripe Dashboard, ensure the webhook URL points to your production domain and is subscribed to payment_intent.succeeded, payment_intent.payment_failed, charge.refunded, and account.updated events.
- Monitor payment failures — Failed payments are logged with the error message from Stripe. Check invoice metadata for last_payment_failure details when troubleshooting.
- Complete onboarding fully — Both charges_enabled and payouts_enabled must be true before clients can pay. Use Refresh Status to check if your account is fully verified.
Was this article helpful?