Back to Blog

May 25, 2026

Odoo Fixes a Stripe Bug That Silently Cancelled Restaurant Payments When Customers Left No Tip

A flaw in Odoo's POS restaurant Stripe integration meant that when customers selected a 0% tip, the pre-authorized payment was never captured — leaving it pending until Stripe automatically voided it days later, costing restaurants real revenue.

Flow diagram showing how a zero-tip Stripe payment in Odoo POS was left uncaptured and eventually voided, versus the fixed path that forces capture

Here’s a scenario that was quietly costing restaurants money: a customer finishes their meal, pays with a credit card through a Stripe terminal, reaches the tip screen, and selects 0%. A perfectly normal interaction. Except the payment never actually settled. The charge sat in a pending state on the customer’s card, and after seven days, Stripe automatically voided it. The restaurant served the meal, the customer walked out thinking they’d paid, and the money never arrived.

This wasn’t a Stripe problem. It was a gap in how Odoo’s POS restaurant module handled the interaction between deferred payment capture and the tipping workflow.

How Deferred Capture Creates the Problem

When a restaurant enables “tip after payment” in Odoo POS, the system uses Stripe’s deferred capture flow. Instead of charging the card immediately, it pre-authorizes the meal amount and holds the funds. This lets the customer add a tip on the next screen, and then the system captures the final amount (meal + tip) in a single charge.

The capture step is critical. Stripe requires an explicit API call to convert a pre-authorization into an actual charge. Without that call, the hold expires and the funds release back to the customer’s account. The capture was wired to the tip validation logic — when the customer confirms their tip, the system captures the total. But the code path assumed that a tip would always be a positive number.

Zero Is a Valid Tip. The Code Didn’t Agree.

When a customer tapped 0% or entered $0 as their tip, the validation function parsed the amount and found… nothing actionable. No tip amount to add to the base price, so no reason to trigger a capture. The system moved on to the next order, leaving the pre-authorized payment in limbo.

Stripe’s rules are clear: uncaptured authorizations are automatically voided after a set period (typically seven days for card-present transactions). The restaurant’s POS showed the order as completed. The daily report looked normal. But the actual fund transfer never happened.

The insidious part is the timing. The void happens days later, long after the shift ended and the receipts were filed. Unless someone was cross-referencing POS reports against Stripe’s dashboard daily — which almost nobody does — the lost charges blended into the background noise of restaurant accounting.

The Fix: Capture on Zero, Not Just on Positive

The solution is straightforward but had to be placed precisely. The tip validation function now checks whether the tip amount is zero or unparseable. When it is, the system detects the Stripe payment method on the current order and manually triggers a capture for the pre-authorized amount. The meal total gets charged at face value, no tip added, and the payment settles normally.

After the capture fires, the standard tip validation continues as before — closing the tip screen, advancing to the next order, and recording the transaction. The customer’s experience doesn’t change. The restaurant’s bank account does.

Who Was Affected

The bug specifically hit restaurants running three conditions simultaneously: Odoo POS, Stripe as the payment terminal provider, and the “tip after payment” feature enabled. Restaurants using other payment processors weren’t affected because the deferred capture flow is Stripe-specific. Restaurants with tipping disabled also weren’t affected because the payment captures immediately at the standard checkout screen.

The financial impact scaled with the frequency of zero-tip transactions. A fine-dining restaurant where most customers tip generously might see the issue once a week. A casual counter-service spot where takeout orders routinely skip the tip — that’s a different story. Some operators may have been losing several transactions per day without realizing it.

A Reminder About Payment Integration Testing

Payment bugs are uniquely dangerous because they fail silently. A broken feature throws an error. A broken payment flow processes the order, prints the receipt, and reports success — it just doesn’t move the money. The feedback loop between “this looks like it worked” and “the money never arrived” can be days or weeks long.

For any business running POS with Stripe integration, the fix rolls out with the latest update. No configuration change needed. But the incident is a good reminder to periodically reconcile POS reports against the payment processor’s transaction log — especially when deferred capture workflows are involved. The edge cases that slip through testing tend to be exactly the ones where a valid input (zero, null, empty string) triggers an unexpected code path.

Ready to experience Odoo AI?

Join hundreds of teams using DearERP to customize Odoo in minutes, not weeks. Plans start at $29/month.