Skip to main content

Odoo integration

Connect Stripe Payments and Subscriptions to Odoo

Three different problems get called "Stripe integration": taking a payment, running a subscription lifecycle, and making the accounting agree afterwards. They fail in different ways, so this page treats them separately.

  • Checkout
  • Recurring billing
  • Webhooks
  • Refunds
  • Reconciliation

Reviewed by Bhavesh Selarka, COO & Co-Founder, Heliconia Solutions · Odoo 16 Functional Certification · Odoo Partner · Updated

Proof

Recurring billing in productionSubscription lifecycle automatedOdoo Community and EnterpriseWebhook-driven, idempotent

Clients

Businesses that run on what we built

  • Ladder Logix
  • Avasar Agency
  • Aria Jewellers
  • Freiburger Bund
  • Jo Ann's
  • Opsio
  • LittleQ

The short answer

What Does a Stripe and Odoo Integration Cover?

Stripe owns the card, the payment method and the money movement. Odoo owns the customer, the order, the subscription state and the ledger. The integration is a webhook-driven flow in one direction (Stripe tells Odoo what happened) and an API call in the other (Odoo asks Stripe to charge). Everything hard about it is in the third part: making the two agree at the end of the month.

Odoo ships payment provider support, and for a simple online checkout that is often enough. You'll need a real integration when the payment has to drive something else: activate an account, extend an expiry date, release a delivery, post a specific journal entry, or start a dunning sequence.

That is the work we have done twice. WaveContact takes recurring payments on Stripe against membership plans held in Odoo. MEP Emart runs a full subscription lifecycle on Odoo 14 Community where Stripe billing drives database activation, expiry, renewals, reminders and plan upgrades.

The first decision

Which System Owns What

Agree this before writing code. Most Stripe integration bugs are really disagreements about a row in this table.

Which System Owns What
ObjectSystem of recordDirectionConflict rule
Card and payment methodStripeNever leaves StripeOdoo stores a token reference only, never card data
Customer identityOdooOdoo to Stripe on first chargeOdoo partner id is the key, and the Stripe customer carries it in metadata
Price and plan definitionOdooOdoo to StripeA plan changed only in Stripe is a plan that will drift. Change it in Odoo
Payment outcomeStripeStripe to Odoo by webhookThe webhook is the truth. A UI redirect is a hint, not a confirmation
Subscription stateOdooBoth, reconciledOdoo decides what access the state grants, Stripe decides whether money arrived
RefundsWherever it was issuedBothEither way it ends as a credit note in Odoo. Never only in Stripe
Invoice and ledger entryOdooOdoo onlyStripe invoices are not accounting records for your books

The row people skip is the fourth. Treating the browser redirect as confirmation, instead of the webhook, is the single most common cause of orders that are paid in Stripe and unpaid in Odoo.

The lifecycle

From Checkout to Reconciled Ledger

Three flows, kept separate on purpose: capture, subscription lifecycle, and accounting.

  1. Step 01

    Capture: intent

    Odoo creates the order and asks Stripe for a payment intent with the amount, currency and metadata that ties it back to the Odoo record.

    • Odoo to Stripe
  2. Step 02

    Capture: authorisation

    The customer pays. Strong customer authentication happens in Stripe, which is exactly where it should happen and why the browser cannot be trusted with the result.

    • Stripe
  3. Step 03

    Capture: confirmation

    Stripe sends a webhook. Odoo verifies the signature, looks up the record by metadata, marks the payment and moves the order on. Idempotent, so a repeated delivery changes nothing.

    • Webhook
  4. Step 04

    Subscription: billing cycle

    On a schedule, the plan bills. Success advances the period. Failure starts retries, and the Odoo subscription state follows, which is what actually gates access.

    • Stripe + Odoo
  5. Step 05

    Subscription: change and cancel

    Upgrades, interval changes and cancellations decided in Odoo, applied to Stripe, and confirmed back by webhook. MEP Emart lets customers do this themselves.

    • Odoo to Stripe
  6. Step 06

    Consequence

    This is where the value is. Payment received means: activate the database, extend the expiry, release the order, send the confirmation. Payment failed means the opposite, on a defined timetable.

    • Custom
  7. Step 07

    Accounting

    Invoice and payment posted in Odoo, fees recorded, payouts matched against the bank statement. Stripe settles net of fees, so gross and net have to be handled deliberately.

    • Accounting

Stripe pays out in batches, net of fees, days after the transactions. If nobody designs for that, the bank reconciliation is manual forever.

Which pattern

Native Provider, Community Module or Custom Integration?

Try them in this order. We will tell you when the built-in option covers your case.

Native Provider, Community Module or Custom Integration?
Your needApproachWhy
One-off online payments on an Odoo website or portalOdoo's built-in Stripe providerConfiguration, not a project. Use it
Recurring billing, standard terms, EnterpriseSubscriptions app with the providerCovered, as long as nothing outside Odoo depends on the payment
Recurring billing on CommunityCustomWhat we built for MEP Emart: the lifecycle, not just the charge
Payment must trigger provisioning, access or fulfilmentCustomThe consequence is the integration. That logic is yours
Payments from a custom frontend or mobile appCustom API layerWaveContact bills through Odoo behind a web frontend and a Flutter app
Fee and payout reconciliation into the ledgerCustom, with accounting agreementGross, fees and payout timing have to be modelled, not assumed

Failure handling

What Makes It Survive a Bad Day

  • Signature verification on every webhook, rejecting anything unsigned or replayed outside the tolerance window
  • Idempotent handlers keyed on the Stripe event id, because at-least-once delivery means duplicates are normal, not exceptional
  • A queue with retry and backoff, so a brief Odoo outage doesn't lose a payment confirmation
  • A scheduled catch-up that pulls recent Stripe events and fills gaps, because a webhook you never received can't be retried by anyone
  • Idempotency keys on outbound charge requests, so a timeout never becomes a double charge
  • Daily reconciliation of Stripe payments against Odoo records, reporting differences before finance finds them
  • Alerting on failed webhook processing and on queue depth, with a named person who receives it

Security boundary

Credentials, Data and What We Do Not Touch

  1. 01

    Card data never reaches Odoo or our code. Stripe holds the payment method and Odoo holds a token reference, which is what keeps your PCI scope small.

  2. 02

    API keys live in the server environment, never in the database or a module, and restricted keys are used where Stripe supports them.

  3. 03

    Webhook endpoints are signature-verified and rate-limited, and they do exactly one thing: enqueue a verified event.

  4. 04

    Access to the Stripe dashboard stays yours. We ask for the least access that lets us build and debug.

  5. 05

    Audit trail: every inbound event and outbound call logged with its identifier, so a disputed payment can be traced end to end.

  6. 06

    We are not a payment institution and we do not advise on PCI scope or financial licensing. Where your setup raises those questions, they go to your compliance adviser.

How we run it

Implementation Sequence

  1. Assessment

    Odoo version and edition, what triggers a payment, what a payment must trigger, currencies, volumes and whether subscriptions are involved.

  2. Ownership and mapping

    The matrix above filled in, plus the product and plan mapping between Odoo and Stripe.

  3. Build in test mode

    Full flow against Stripe test keys, including the awkward paths: failed card, retry, refund, duplicate webhook, expired subscription.

  4. Reconciliation first

    The daily comparison job is built before go-live, not after the first month-end discrepancy.

  5. Controlled go-live

    Live keys, a small volume first, webhooks monitored, with a rollback path that does not strand a paid customer.

  6. First cycle support

    We stay close through the first full billing cycle and the first payout reconciliation.

Evidence

Stripe and Odoo in Production

Two subscription businesses, one on Community and one behind web and mobile clients.

Stripe and Odoo in Production
ProjectIndustryOdooKey capabilitiesTechnology
MEP EmartSaaS: AI solutions & digital transformationOdoo 14 CommunityStripe · Odoo Website & customer portal · Email (SMTP)Odoo 14 Community · Python · PostgreSQL
WaveContactSaaS: digital business cardsOdooDigital Business Card Management · Contact Management · Profile Management · Subscription ManagementOdoo · Python · PostgreSQL · GraphQL · Flutter

Integration assessment

Request an Integration Assessment

Send us your Odoo version and edition, where payments start, what a successful payment has to trigger, your currencies and volumes, and whether you already use a connector. You get the ownership matrix filled in and an honest answer on whether the built-in provider covers you.

  • Data ownership matrix completed for your setup
  • Capture, subscription and reconciliation flows mapped separately
  • Built-in provider, Subscriptions app or custom, with the reasoning
  • Failure-handling plan: webhooks, retries, catch-up and reconciliation
  • Accounting treatment of fees and payouts, agreed with your finance team

Request the assessment

What clients say

In Their Words

Questions

Stripe and Odoo Questions, Answered Directly

Bhavesh Selarka

COO & Co-Founder, Heliconia Solutions

Not answered here? Ask Bhavesh directly, the person who reviewed this page, not a sales queue. Odoo 16 Functional Certification.

Ask a question

Does Odoo support Stripe out of the box?

Yes, as a payment provider for online payments on the Odoo website and portal, and that covers a straightforward checkout without any development.

You need an integration when the payment has to drive something beyond marking an order paid: provisioning, access, fulfilment or a specific accounting treatment.

Can we run subscriptions on Odoo Community with Stripe?

Yes. MEP Emart runs online recurring plans on Stripe and offline annual plans, with automated activation and expiry, renewals, reminders, plan upgrades and customer self-service, entirely on Odoo 14 Community.

Read the project

What happens if a webhook never arrives?

A scheduled catch-up job pulls recent events from Stripe and processes anything missing, and the daily reconciliation reports what still doesn't match. Don't rely on webhook delivery alone, or orders end up paid in one system and unpaid in the other.

How do Stripe fees appear in the accounts?

Deliberately, because Stripe pays out net of fees on its own schedule. We agree the treatment with your finance team up front: gross revenue, fee expense and the payout matched against the bank line. Getting it wrong means a bank reconciliation nobody can close.

The finance side

Can customers pay from our app rather than the Odoo website?

Yes. WaveContact takes subscription payments behind a web frontend and a Flutter mobile app, with Odoo holding the memberships, orders and store. The app talks to your API, and the card still never touches your systems.

Flutter app development

Is card data ever stored in Odoo?

No. Stripe holds the payment method and Odoo holds a token reference. That boundary is deliberate: it keeps card data out of your database and your PCI scope small, and anyone proposing otherwise isn't solving your problem, they're creating one.

Next step

Make the Payment Trigger the Right Thing

Tell us what a successful payment has to cause in your business, and what a failed one has to stop. That is the integration. We will scope it and tell you if Odoo already does it.