OpenReceive 0.4.25 makes checkout faster. A checkout's back-to-back requests now share one wallet scan instead of running one each (all engines), and the PHP engine reuses its relay connection and keeps prices between requests: on the trial wallet's public relay, a PHP checkout reload went from 14 s to 2 s. <Checkout fetch> lets a React app whose sign-in is a bearer token, such as plain supabase-js, authorize every checkout request. Flask and NestJS get quickstarts, agent directions and starters, and both pass agent trials, as does Supabase. A new guide covers checkout in mobile apps. Upgrade if you run the PHP engine, Laravel or WordPress, or a React app signed in with a bearer token.
Optional swaps let payers use USDT, USDC, SOL and ETH; a configured swap provider converts them to BTC over Lightning in the merchant's connected wallet. Asset and network availability depends on the provider.
- Fixed (all engines): the reconcile gate's interval now also runs from the
end of the last pass, not only from its claim. A pass slower than the
interval used to leave the gate open when it ended, so every request in a
checkout's back-to-back burst ran a wallet scan of its own. On the PHP
checkout a scan took about 3 s, so each click cost 3–4 s and a reload took
15 s. The gate row stores
finished_at; older engines ignore it. The gate only gets stricter: it still refuses every scan the old rule refused, and a refused request answers from the host's row without waiting. So the wallet and its relay see fewer scans, about half as many under steady traffic. A payment can take up to one scan longer to show as paid. - Fixed (PHP): a reconcile pass reuses one relay connection for its history
pages instead of a TLS handshake per page (about 0.4 s each). A mint
(
make_invoice) still opens its own connection. - Added (PHP):
Servicetakes an optionalsharedCache(OpenReceive\Support\SharedCache) that keeps the BTC price and the swap provider's currency list and rates between requests. PHP builds the engine for every request, so each route used to fetch them again (0.5–1.5 s).openreceive/laravelpasses the app's default cache store and the WordPress plugin its transients. Measured on the trial wallet's public relay with the engine rebuilt per request, a reload went from five scans (14 s) to one (2 s). - Added (React):
<Checkout fetch>, the fetch every checkout request goes through: prepare and create, the status poll, and the swap quote, start, status and refund calls, in create and snapshot mode alike. An app whose sign-in is a bearer token kept in the browser (plain supabase-js keeps it in localStorage) passes a fetch that adds theAuthorizationheader, and itsauthorizesees the same user on every call. The old prop,createFetch, covered only prepare and create, so the poll and the swap calls went out with cookies alone and such an app'sauthorizerefused them.createFetchstill works, now covers every request too, and is deprecated.useCheckoutandCheckoutProvidertake the samefetchfor the poll and the refund calls. The Supabase guide shows the token route. The custom element and the Vue, Svelte and Angular wrappers keep using the page's own fetch. - Added (docs): Flask is a directions target. /guides/quickstart-flask
replaces the Flask recipe (/guides/flask-recipe redirects to it), and
/agent-directions/flask.md hands it to a coding agent, with Flask on
openreceive.org/integrations. Flask still has no adapter package: the app
copies one file from the quickstart,
openreceive_flask.py, a Blueprint over the engine. The quickstart keeps Flask-WTF's CSRF protection on the payment routes (the checkout sendsX-CSRFToken), serves the checkout's script and stylesheet from the installedopenreceivepackage, and names the objectopenreceive doctor --app app:openreceivereads. examples/flask-starter is the quickstart as a one-product shop, and the agent trials gain a Flask 3.1 shop (npm run trial -- --platform flask). The trials' live buyer now sends Flask-WTF'scsrf_tokenform field. Three agent trials in a row passed on these directions, two with Codex and one with Cursor, so /integrations/flask shows Tested. - Added (docs): a NestJS quickstart (/guides/quickstart-nestjs), agent
directions for NestJS, and an /integrations/nestjs page. A Nest app mounts
@openreceive/expresswithapp.use()inmain.ts, withapp.useBodyParser("json")right before it: Nest adds its own JSON parser only when the app starts listening, after anythingmain.tsmounts, so without that line every checkout request failed with a 500. Nest's guards do not run for middleware, soauthorizemakes the guard's check itself. The hooks reach the app's services and its TypeORMDataSourcethroughapp.get(). - Added (examples): examples/nestjs-starter, a one-product NestJS 12 shop on Postgres with TypeORM migrations, sessions and Handlebars views, built on the published packages. Checked in Docker against a test wallet: an order gets a Lightning invoice, another browser is refused, and a paid invoice marks the order paid.
- Added (docs): a guide for mobile apps (/guides/mobile-apps). The app opens a checkout page on its own server in a browser tab, through a one-time link the server turns into a cookie for that order, and asks its server whether the order is paid; the wallet code never ships in the app. A table says what the App Store and Google Play allow by kind of purchase, and where digital goods may link out to the web (US, EU, Japan, Brazil) and at what commission, from the stores' own pages as of October 2026. It has snippets for Expo, Flutter, Swift and Kotlin. The Node, Fastify, Next.js, FastAPI, Django, Rails, PHP and Laravel directions link it.
- Added (docs): Supabase is a Tested platform, and the Supabase guide says
what is tested and what is not. Coding agents following the Express
directions added checkout to an Express shop whose data is in a real
Supabase project, reached through Supavisor's transaction pooler with
Supabase's certificate: 3 of 3 runs passed on 0.4.24. Each created
OpenReceive's tables, closed them to Supabase's Data API, issued a real
invoice, refused a stranger and marked a paid order paid.
/platforms/supabase is published. The agent trials gain
--platform supabase, which runs on a real project named in the repo-root .env, empties its public schema before each run, keeps the database password out of reports and fails a run that shows it to the agent. - Changed (docs): the Lovable guide says what is tested and what is not. The route runs in CI as a Cloudflare Worker against Supabase's database and PostgREST 14, the storage has run against a real Supabase project, and coding agents pass the guide's prompt on a shop built with Lovable's build setup. Lovable's own agent, Lovable Cloud and its migration approval are not tested, and the guide asks for an issue when Lovable does something it does not describe. Step 1 links Lovable's Secrets docs.
- Fixed (examples): the Next.js and Express starters' order pages say "Paid,
thank you." as soon as the checkout shows the payment received. The status
line came from the server render alone, so it said "Awaiting payment" under
a settled checkout until a reload. The Next.js page refreshes on
onSettled;onPaidhas already marked the order paid by then. The Express page updates the line onopenreceive-settled. An order page opened after the order is paid shows only the paid status. It used to show the checkout too, which said "Could not start checkout." becauseamountForhas no price for a paid order. A payment made on the page keeps its checkout and receipt. - Security updates in the lockfiles: rbsecp256k1 6.0.2, which allows
rubyzip 3.7.0 (the root and Rails demo bundles), and puma 8.0.2 in the Rails
trial shop, whose Gemfile now asks for
puma >= 5.0asrails newwrites it. rbsecp256k1 6.0.2 builds libsecp256k1 v0.8.0 from bitcoin-core's release archive, checked against a pinned SHA-256. The Rails demo's bundler-audit ignore for the rubyzip advisory is gone. Apps onopenreceive-railstake the same fix withbundle update rbsecp256k1; the gems already allow it. - Tests (trials): a NestJS 12 trial shop (
npm run trial -- --platform nestjs): TypeORM on Postgres, express-session sessions and server-rendered views. Three agent trials in a row passed on the NestJS directions, so /integrations/nestjs shows Tested. - Tests (trials): the live check makes four
payments/checkcalls in a row and fails when more than one of them ran a wallet scan (live_one_scan_back_to_back). The evidence lists each call's time.