EspoCRM and Stripe payments integration

Collecting one-time payments from EspoCRM through the official Stripe integration, which needs the Sales Pack, EspoCRM 9.1 or later and an instance Stripe can reach. This page covers the setup sequence, webhook events, payment statuses and testing behind a firewall.

On this page

How the EspoCRM Stripe integration collects one-time payments

The supported way to collect customer payments from EspoCRM is the official Stripe integration extension, which requires the Sales Pack and EspoCRM 9.1 or later. The extension covers one-time payments only, so any plan that depends on recurring billing, subscriptions or other Stripe features should be confirmed against the extension documentation before design starts. Stripe reports the outcome of each payment back to EspoCRM through webhooks, which means the instance must be reachable from Stripe's servers. An instance that exists only on an internal network will not receive those results without a planned route.

The work is divided between two systems. EspoCRM holds the business record: a payment request is created against a customer or deal, and the request carries the amount and the status the sales or finance team tracks. Stripe handles the customer-facing step: it hosts the Checkout page where the payer enters card or other supported payment details, processes the payment, and sends the result. Your team should decide which EspoCRM roles can create payment requests, who may see them, and whether a request can be edited after the customer has been sent a link, since those choices determine how well the CRM record matches what Stripe actually processed.

Before building, confirm three things with the vendor and in your own environment: the Sales Pack and Stripe extension versions you will install, the payment channels and methods your Stripe account has enabled for your country and currency, and the public hostname that Stripe will call. The extension documentation lists the webhook events the integration subscribes to and the endpoint path, which your network and reverse proxy team must allow. Confirm these early, because a firewall or proxy rule discovered late is a common reason a payment appears unpaid in EspoCRM when it was paid in Stripe. For the exact event names and setup steps, read the EspoCRM Stripe integration documentation.

What you need before connecting Stripe to EspoCRM

Four things must be in place before you configure the Stripe integration: the right EspoCRM version, the Sales Pack extension, a Stripe account with API access, and an instance that Stripe can reach over the internet. Each card covers one of these, plus the server baseline and the checks you should confirm with Stripe before you start.

EspoCRM 9.1 or later

The Stripe integration requires EspoCRM 9.1 or later. Check the version under Administration before you plan anything else, because an older instance needs an upgrade first. Major upgrades change extensions, PHP requirements and the upgrade process, so a version change should be planned and tested on a copy of the instance before you touch production. Confirm the exact release you will run against the EspoCRM releases page.

Sales Pack extension

The Stripe integration is delivered as part of the official Sales Pack extension, so the Sales Pack must be installed and compatible with your EspoCRM version. Install it on a staging copy first and confirm that the Stripe-related entities and settings appear. Record which extension version you installed, because you will need it when you plan upgrades and when you troubleshoot.

Stripe account with API access

You need a Stripe account that can create API keys and configure webhook endpoints. Decide which Stripe environment you will use for testing and which for production, and keep their keys separate. Ask Stripe to confirm the current account requirements, identity checks and whether your country and business type are supported for the payment methods you plan to offer. Restrict who in your organization can view or rotate secret keys.

Internet-reachable endpoint

Stripe delivers payment status changes to a webhook URL on your instance, so the EspoCRM host must be reachable from the internet over HTTPS. A host that sits only on an internal network or behind a VPN will not receive events, and payment requests will not change to Paid automatically. Confirm the public DNS name, the TLS certificate and that your firewall and reverse proxy forward the webhook path to EspoCRM.

Server requirements and cron

The Stripe integration runs on the normal EspoCRM server stack. The documented baseline is PHP 8.3 to 8.5, MySQL 8.0 or newer, MariaDB 10.6 or newer or PostgreSQL 15, served by Apache, Nginx or IIS. Background jobs need cron or a scheduled task, so confirm that it is running before you test payment requests. Check these items against your own environment, because your web server and database choice will shape the work.

Test environment and tunnel

Plan a test path before production. The EspoCRM docs suggest the Stripe CLI or a tunnel service when you test in a local environment, since Stripe cannot reach a laptop directly. Decide who will run the test payments, which test data they will use, and how you will confirm that a completed test checkout moves the payment request to Paid. Keep test webhook secrets out of shared documents.

Configuring the Stripe integration step by step

This sequence takes an EspoCRM instance from a bare install to a state where a payment request created in the CRM reflects a Stripe Checkout payment without manual updates. Each step ends with a check you can run before moving on.

  1. Confirm version and public reachability

    Before installing anything, confirm that the instance runs EspoCRM 9.1 or later, since the Stripe integration requires that version or newer. Confirm that the instance's public host name resolves and accepts HTTPS requests from the internet, because Stripe must be able to deliver webhook calls to it. An instance that only sits on a private network needs a tunnel or a reachable staging host for this integration to work. Your administrator performs this check. It is done when a request to the public host name reaches the EspoCRM login page from outside your network.

  2. Install the Sales Pack and Stripe extension

    Your administrator installs the Sales Pack extension first, then the Stripe integration, through the Administration area of EspoCRM. The Stripe integration depends on the Sales Pack, so installing it alone will not provide the payment features. Open the Extensions screen after each install and confirm both packages show as installed with no errors in the log. It is done when both extensions are listed as active and the Stripe settings page opens without an error.

  3. Enter Stripe credentials and test mode keys

    In the Stripe integration settings, your administrator enters the secret and publishable keys from the Stripe account that will receive payments. Start with test mode keys so that no live charges can occur during setup. Store the webhook signing secret in the same settings screen once you create the endpoint in the next step. Keep the secret keys out of shared documentation and limit who holds Administration rights in EspoCRM. It is done when the settings save without a validation error and the integration reports that it is connected.

  4. Create the webhook endpoint in Stripe

    In the Stripe dashboard, create a webhook endpoint that points to your instance's public host followed by the path /api/v1/Stripe/webhook. Replace the host with the public name you confirmed in the first step. Subscribe the endpoint to the four Checkout events the integration uses: checkout.session.async_payment_failed, checkout.session.async_payment_succeeded, checkout.session.completed and checkout.session.expired. Copy the signing secret that Stripe displays and paste it into the EspoCRM settings. It is done when the endpoint shows the four events as subscribed and Stripe lists no delivery errors for a test event.

  5. Configure payment channels and methods

    Decide which payment channels and methods your sales team may offer, then enable only those in the EspoCRM Stripe settings. Each enabled method must also be turned on in your Stripe account, or the Checkout session will not offer it. Confirm the currency and any default settings with your finance team before the first live use. Record the decision in your configuration notes so that future changes are reviewed. It is done when the settings page shows the chosen methods and a test session offers only those methods in Stripe's hosted page.

  6. Create a payment request in test mode

    Open a record that carries the payment, such as an opportunity or invoice, and create a payment request from it using the Sales Pack. Use a test card supplied by Stripe for test mode, complete the hosted Checkout page, and leave the request open until the webhook arrives. Note the request's status immediately after creation, which should show the pending state. It is done when the request record and the Stripe test payment both exist and reference the same amount.

  7. Confirm the status change to paid

    After the test payment completes, check that Stripe shows the completion event delivered to the webhook endpoint with a successful response. Then refresh the payment request in EspoCRM and confirm that its status has changed to Paid without manual editing. If the status does not change, check the endpoint's delivery log in Stripe and the EspoCRM logs before retrying. It is done when the request shows Paid and the webhook log in Stripe shows a successful delivery for the matching event.

How a payment request moves from Sent to Paid

A payment request in EspoCRM moves to Paid on its own once Stripe confirms the payment through a webhook, so the team's job is to make sure that confirmation path works and to plan for every outcome that does not end in success. The sequence starts when a user creates a payment request and sends the customer a Stripe Checkout session. The customer pays on the Stripe-hosted page, Stripe calls the instance at ` and EspoCRM updates the request. Because the webhook is the only trigger, the instance must be reachable from Stripe, and a firewall rule that blocks inbound calls will leave paid requests sitting in their open state.

The webhook events map to four outcomes. checkout.session.completed and checkout.session.async_payment_succeeded both indicate a payment that has settled, and the request changes to Paid. checkout.session.async_payment_failed means a delayed payment method, such as a bank debit, did not clear after the customer finished checkout, so the request should not be treated as paid even though the customer saw a confirmation page. checkout.session.expired means the session lapsed without payment. Teams should decide who follows up on failed and expired requests, how many days a customer has before a new request is issued, and whether an asynchronous payment in progress is shown to sales as pending. Confirm with the Stripe documentation and the EspoCRM Stripe integration docs which events your configured payment methods can produce before you finalize these rules.

Reconciliation with accounting is not handled by the integration. EspoCRM records the status change, but matching Stripe payouts, fees, refunds and disputes against the general ledger is a process your finance team must design and own, and it may need a separate export or an accounting integration. Plan a periodic comparison between Paid requests in EspoCRM and settled balances in Stripe, and define who resolves a mismatch. Test each of the four event paths in a non-production instance, including a webhook that fails and is redelivered, before relying on the status for revenue or customer commitments.

Which Stripe events and EspoCRM statuses correspond

This table compares the four Stripe Checkout events that the EspoCRM Stripe integration receives with the payment request outcome the documentation describes and the action a team should take. Treat the second column as documented behavior, and verify any entry marked for confirmation on your test instance before go-live. The main takeaway is that EspoCRM updates payment status only when these webhook events arrive, so the endpoint must be reachable and tested first.

Stripe eventExpected payment request outcomeAction for the team
checkout.session.completedPayment request changes to Paid automatically when the Checkout payment is paidConfirm the amount and currency in Stripe match the payment request, then close the order or service
checkout.session.async_payment_succeededDelayed payment method has cleared; confirm the request moves to Paid on your test instanceRelease goods or services after this event, and confirm which payment methods trigger it
checkout.session.async_payment_failedNot stated in the docs; confirm whether the request stays open or changes statusContact the customer, decide on a new payment request, and hold fulfillment
checkout.session.expiredNot stated in the docs; confirm whether the request returns to an open stateCheck that no payment was taken, then decide whether to send a new Checkout link
Any other event or missing webhookNot covered by the documented integration; confirm before relying on itCheck the Stripe event log and EspoCRM logs, and resend the event from Stripe if needed

Choosing payment channels and methods for your customers

Customers who pay by card at a hosted Stripe Checkout page are the simplest case. The payment is confirmed in a single step, and the webhook events for a completed session tell EspoCRM whether the payment request should move to Paid. Your decision here is mainly which card and wallet options you allow and whether the checkout page should show them to every customer or only some.

  • Enabled methods: Decide which card and wallet methods are offered on the Stripe side, since availability can depend on the customer's country and currency.
  • Currency and amount rules: Confirm which currencies your account can charge and how amounts are entered in EspoCRM before a payment request is sent.
  • Completed sessions: Check that the completed event moves the payment request to Paid in your test environment.
  • Abandoned sessions: Confirm how an expired session appears in EspoCRM so sales staff know to send a new link.
  • Refund handling: Decide whether refunds are issued in Stripe only or recorded back in EspoCRM, because the integration documentation focuses on one-time payment collection.

Ask the team who owns the Stripe account to confirm which methods are active before you promise them to customers.

Securing the Stripe webhook and API credentials

The Stripe integration touches three things that need protection: the Stripe secret key stored in EspoCRM, the public webhook endpoint Stripe calls back into, and the users and API accounts that can create payment requests. The cards below cover each one, along with the general EspoCRM hardening that limits what a compromised account can do.

Store the Stripe secret key carefully

The integration needs a Stripe secret key to create Checkout sessions and read payment status. Restrict who can view or edit the integration settings, and treat the key as a credential with its own rotation process. Ask your team to confirm in the extension settings whether the secret is stored encrypted and where the key is visible to administrators. Keep test and live keys separate so a test configuration never reaches production payments.

Verify that webhooks come from Stripe

The webhook endpoint at the /api/v1/Stripe/webhook path accepts events for checkout.session.completed, async_payment_succeeded, async_payment_failed and expired. Because the endpoint is reachable from the internet, a forged request could try to mark a payment request as paid. Before relying on it, confirm with the extension documentation how signature verification against the Stripe webhook signing secret works, and test that an unsigned or incorrectly signed request is rejected.

Restrict who administers the integration

Payment settings and webhook configuration should belong to a small group of administrators who do not use their admin accounts for daily sales work. Enforce a strong password policy and require two-factor authentication for these users. Note that EspoCRM's own 2FA is not compatible with OIDC sign-in, so confirm the second factor model if your organization signs in through an identity provider.

Limit API user permissions

If other systems read payments or payment requests through the REST API, create a dedicated API user with only the entity and field permissions it needs. EspoCRM supports API key, HMAC and basic authentication for API users. HMAC is the most secure option in the documentation, and basic authentication is not recommended. Review API user roles after each change to the Sales Pack or to the payment entities.

Restrict access by IP address

Where sales staff sign in from known networks, IP restrictions reduce the exposure of the admin interface, while the webhook endpoint must stay open to Stripe. Limit administrative access by network and keep the webhook route reachable only as needed. Confirm how your reverse proxy passes the client address through, since an incorrect forwarding setup can make restrictions ineffective.

Shorten sessions and block admin recovery

The security documentation recommends limiting auth token lifetime and disabling password recovery for admin accounts. Shorter sessions reduce the window in which a stolen browser session can create payment requests. Pair these settings with a documented break-glass procedure, so that a locked-out administrator can recover access without weakening the policy for everyone else.

Testing Stripe webhooks when EspoCRM runs behind a firewall

A firewalled or local EspoCRM instance cannot receive Stripe webhooks directly, because Stripe sends the checkout.session events from its own servers to a public address. Without a route from Stripe to the instance, a paid payment request will never move to Paid automatically, so the webhook path must be proven before any customer sees a payment link. The Stripe integration docs suggest two approaches: the Stripe CLI, which forwards events from your Stripe test account to a local endpoint, and a tunnel service, which gives the local instance a temporary public URL that Stripe can call. Choose one per test environment and record which one you used, because the signing secret that EspoCRM checks belongs to that delivery path.

Run the first tests in Stripe test mode with test API keys only, and confirm that the webhook endpoint in EspoCRM points to the path the docs specify, /api/v1/Stripe/webhook on your host. Then create a payment request, pay it with a Stripe test card, and check three things: the payment request changes to Paid, the event appears in Stripe's delivery log with a successful response, and the status is not changed twice by duplicate events. Repeat the test for a failed or expired session, because the integration handles the async failure and expiry events as well as successful completion. Ask the team that owns the instance to confirm which Stripe account and API keys are configured in each environment, since mixing test and live keys is the most common cause of confusing results.

Moving to production means replacing the test route with a public, TLS-protected endpoint that Stripe can reach, and registering the live webhook in the live Stripe account with the same four events. Before go-live, plan a rollback: keep the previous Stripe configuration documented, decide who may disable the live webhook or revert keys, and define how payment requests created during a failed cutover will be reconciled against Stripe's records. Confirm your firewall, reverse proxy and any IP restrictions allow Stripe's delivery traffic to reach the endpoint, because a restriction that works for users may block webhooks. Treat the first live payment as a supervised test, and check the delivery log and the EspoCRM record together before opening the process to customers.

Common failures when payments do not update in EspoCRM

This table lists the failure points that most often leave a Stripe payment request unpaid in EspoCRM, with the likely cause and fix for each. Work through the rows in order, since the first three checks (Sales Pack, version and reachability) rule out the most common causes before you inspect Stripe events or keys.

SymptomLikely causeFix
Stripe integration missing or not workingThe Sales Pack extension is not installed, so the Stripe integration cannot runInstall the Sales Pack extension, then confirm the Stripe integration settings are saved and enabled
Integration unavailable or unexpected behaviorEspoCRM is older than 9.1, the minimum version the Stripe integration requiresUpgrade to EspoCRM 9.1 or later, planning the upgrade with your extensions and PHP version in mind
Payment stays unpaid after the customer paysThe instance is on a private network or localhost, so Stripe cannot send webhook callsMake the instance reachable over HTTPS from the internet, or test with the Stripe CLI or a tunnel service
Webhook deliveries fail in StripeThe endpoint URL uses the wrong host or path instead of the documented webhook pathSet the endpoint to using your public host name
Events never reach EspoCRMThe Stripe webhook does not subscribe to the four checkout session events the integration usesSubscribe to checkout.session.async_payment_failed, async_payment_succeeded, completed and expired
Stripe shows failed deliveries with timeouts or blocked requestsA firewall, WAF or reverse proxy blocks or rewrites POST requests to the webhook pathAllow POST requests to the webhook path from Stripe, then check proxy and WAF logs for blocked calls
Webhook signature or key errorsTest-mode and live-mode keys or webhook secrets are mixed up in the EspoCRM settingsUse keys and the signing secret from the same Stripe mode, and repeat a test payment after correcting them
Payment completes in Stripe but the request stays openThe event was not received, was rejected, or the request was not linked to the Stripe checkout sessionCheck Stripe event delivery logs first, then confirm the payment request matches the checkout session before retesting

Questions teams ask before connecting Stripe to EspoCRM

What does a Stripe connection to EspoCRM cost, and what drives the effort?

Cost depends on the written scope, not on a list price. Effort is driven by where the EspoCRM instance is hosted, how it is exposed to the internet, how many payment flows you need, and how much testing the team requires. The official Stripe integration requires the Sales Pack extension and EspoCRM 9.1 or later, so the first cost question is whether your instance already meets those prerequisites. Ask any partner to split the quote into one-time work (configuration, webhook setup, testing) and any recurring work (monitoring, upgrades, support). Each payment flow you add, such as payment requests for different products or currencies, adds configuration and test cases.

How long does setting up Stripe payments in EspoCRM take?

No duration is documented for this integration, so treat any timeline as something to agree in writing. The main duration drivers are whether the instance is already on EspoCRM 9.1 or later with the Sales Pack installed, whether the host is reachable by Stripe at a stable public address, how many payment channels and methods you configure, and how long your finance and compliance reviewers take to approve test results. Teams that already run EspoCRM on their own servers usually move faster than teams that must first upgrade or expose a new host.

What must our team provide before a partner can start?

Plan to provide a Stripe account with API access that your finance team controls, administrator access to the EspoCRM instance and the Sales Pack extension, and a public HTTPS host that Stripe can reach for webhooks. You will also need test data: sample accounts, contacts, products and a test payment request that finance agrees on. Confirm who holds the Stripe API keys and webhook signing details, and where they will be stored. Missing any of these items usually delays testing more than the configuration itself.

Can an internal administrator set up Stripe payments without outside help?

An experienced EspoCRM administrator can likely do the configuration alone if the instance meets the prerequisites and the team can reach Stripe from a public host. The documented steps cover installing the Sales Pack, configuring the Stripe integration, registering the webhook endpoint, and testing. The harder parts are usually network exposure for a self-hosted instance, testing behind a firewall, and verifying that payment status changes are correct before go-live. Teams without an administrator who has done webhook testing before often find an outside review useful for the final check.

Does the Stripe integration cover subscriptions or refunds?

The documented scope is one-time payments. Subscriptions and refunds are not described in the EspoCRM Stripe integration documentation, so do not assume they are covered. Ask the EspoCRM documentation or your partner to confirm exactly which Stripe events and payment flows are supported in your version before you design your process. If your business needs recurring billing or refund handling, plan those as separate requirements, with their own scope, testing and finance sign-off.

What does Stripe need to reach our EspoCRM instance, and what is the risk?

Stripe sends webhook events to your instance, so the EspoCRM host must be reachable from the internet on an HTTPS address. The documented endpoint receives events for checkout session completion, async payment success, async payment failure and session expiry, and a paid payment request is then marked as Paid automatically. The security risk is that the endpoint is public. Review network exposure, restrict access where possible, keep the instance patched, and confirm how webhook signatures are verified in your setup. For testing from a private network, the documentation suggests the Stripe CLI or a tunnel service.

What should we ask for in a quote for this integration?

Ask for a written scope that names the EspoCRM version, the Sales Pack version, the hosting model and the payment channels and methods in scope. Request a breakdown of configuration, webhook endpoint setup, network and TLS review, test plan with cases for each webhook event, and handover documentation. Ask who performs and who signs off each test, how payment requests are verified in a staging environment, what happens if Stripe events are missed, and what ongoing support or upgrade work is excluded. DeployOpen plans and delivers engagements under a written, fixed scope, so the quote follows from that document.

How DeployOpen scopes and delivers the Stripe integration

DeployOpen plans, implements, tests and documents self-hosted open-source platforms inside your own infrastructure. For EspoCRM and Stripe payments integration, we start from a written scope that fixes which payment flows, users and Stripe settings are in play, then build and verify the webhook path in your environment.

How we scope

  • Confirm your EspoCRM version, hosting model and whether the instance is reachable from Stripe before work starts
  • Agree in writing which payment channels, payment methods and payment request flows the engagement covers
  • Document the Sales Pack and EspoCRM version prerequisites, plus the Stripe account settings and roles each team will use

How we build

  • Install and configure the Sales Pack and Stripe integration, then set the webhook endpoint for your host
  • Test the four checkout session events and confirm that a paid payment request moves to Paid automatically
  • Use the Stripe CLI or a tunnel service for a local test environment when the production host sits behind a firewall

How we hand over

  • Deliver configuration notes covering API keys, webhook secrets, payment request layouts and user permissions
  • Provide a test record showing each event path, including failed, expired and asynchronous payment outcomes
  • Walk your administrators through reconciling payment statuses and rotating credentials on a schedule you set

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after handover
  • Plan Stripe and EspoCRM upgrades against the Sales Pack compatibility you confirm for each release
  • Ask for a written quote based on the agreed scope, since DeployOpen does not publish a price list

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.