Download Latest Version OpenReceive v0.4.33 source code.zip (14.5 MB)
Home / v0.4.33
Name Modified Size InfoDownloads / Week
Parent folder
openreceive-docs-0.4.33.tar.gz < 5 hours ago 3.0 MB
openreceive-odoo-0.4.33.zip < 5 hours ago 505.4 kB
openreceive-0.4.33-py3-none-any.whl < 5 hours ago 1.4 MB
openreceive-0.4.33.tar.gz < 5 hours ago 1.3 MB
openreceive-fossbilling-0.4.33.zip < 5 hours ago 2.4 MB
openreceive-fossbilling-module-0.4.33.zip < 5 hours ago 2.4 MB
openreceive-paymenter-0.4.33.zip < 5 hours ago 2.4 MB
openreceive-prestashop-0.4.33.zip < 5 hours ago 2.4 MB
openreceive-wordpress-0.4.33.zip < 5 hours ago 3.4 MB
standalone-checkout-0.4.33.tar.gz < 5 hours ago 833.4 kB
openreceive-0.4.33.gem < 5 hours ago 341.5 kB
openreceive-rails-0.4.33.gem < 5 hours ago 53.2 kB
openreceive-server-0.4.33.gem < 5 hours ago 57.3 kB
openreceive-vendure-0.4.33.tgz < 5 hours ago 12.7 kB
openreceive-vue-0.4.33.tgz < 5 hours ago 4.8 kB
openreceive-express-0.4.33.tgz < 5 hours ago 6.2 kB
openreceive-fastify-0.4.33.tgz < 5 hours ago 6.1 kB
openreceive-http-0.4.33.tgz < 5 hours ago 54.3 kB
openreceive-medusa-0.4.33.tgz < 5 hours ago 8.4 kB
openreceive-next-0.4.33.tgz < 5 hours ago 5.0 kB
openreceive-node-0.4.33.tgz < 5 hours ago 376.4 kB
openreceive-provider-data-0.4.33.tgz < 5 hours ago 256.9 kB
openreceive-react-0.4.33.tgz < 5 hours ago 58.0 kB
openreceive-svelte-0.4.33.tgz < 5 hours ago 4.7 kB
openreceive-0.4.33.tgz < 5 hours ago 2.5 kB
openreceive-angular-0.4.33.tgz < 5 hours ago 11.1 kB
openreceive-browser-0.4.33.tgz < 5 hours ago 156.9 kB
openreceive-core-0.4.33.tgz < 5 hours ago 37.4 kB
openreceive-elements-0.4.33.tgz < 5 hours ago 887.4 kB
OpenReceive v0.4.33 source code.tar.gz < 5 hours ago 12.4 MB
OpenReceive v0.4.33 source code.zip < 5 hours ago 14.5 MB
README.md < 5 hours ago 23.5 kB
Totals: 32 Items   49.1 MB 0

OpenReceive 0.4.33 makes setup checks honest and recovery more dependable. doctor now proves the wallet accepts your code instead of only reading what the wallet publishes. A shop restarted during a relay outage now starts on every engine, a checkout reopened for a paid order opens on its receipt, and the PHP engine no longer loses a wallet reply too large for one network read, which could leave paid orders unpaid. Each wallet's tutorial now leads with Copy invoice and then shows every step at once.

Breaking: openWallet and everything around it are removed from the Browser, React, Vue, Svelte and Angular packages, because Cash App cancels an invoice opened from a link. See the first entry below.

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.

  • Removed (Browser, React, Vue, Svelte, Angular): breaking. openWallet, OpenWalletOptions, the controller's and useCheckout's openWallet(), the open option, React's OpenWalletButton and components.OpenWalletButton, classNames.openWalletButton, the onOpenWallet handler, checkoutLabels.openWallet and the openreceive-open-wallet event. Cash App cancels an invoice opened from a link and pays the same invoice scanned or pasted, so a wallet button fails for every payer using Cash App. Show the QR code and Copy invoice. Agent directions now say not to build one.
  • Fixed (all languages): doctor now fails when the wallet will not accept the code. A wallet publishes its methods for anyone to read, so a code with a wrong secret could pass and then fail every checkout. Doctor now sends one signed request, reading one history row, and names a refused or silent wallet. In PHP, a $walletCheck closure should return the Service it builds to get this.
  • Fixed (checkout): a browser that refuses the clipboard no longer strands the payer in a wallet's tutorial. The copy falls back to the browser's older copy command, and if that is refused too, the steps open and step 1 becomes the invoice, selected, to copy by hand.
  • Fixed (swaps): the Total on a swap screen is the order's own price even when the attempt comes back from the server without its quote. It could show the provider's valuation instead, a different figure from the one the payer saw.
  • Fixed (Easy Digital Downloads): a failed save no longer shows "Settings updated." beside the reason it was not saved.
  • Fixed (PHP): doctor no longer prints a NUL byte for an anonymous Host, which made tools such as grep treat its output as binary.
  • Docs: the Rails, Laravel and plain PHP guides give the Alpine packages. Debian's package names do not exist there.
  • Fixed (WooCommerce, Easy Digital Downloads): a payment that arrives on an order the merchant already cancelled or revoked now adds a note to that order. The order stays as the merchant left it, but nothing used to say the money had arrived.
  • Fixed (Easy Digital Downloads): fifty revoked orders holding a completion marker no longer stop the repair pass from reaching later paid orders.
  • Fixed (PHP): a wallet reply too large for one network read no longer fails the whole reconcile pass. PHP's websocket reader gave up with "Empty read" when a frame arrived in pieces, so once a wallet's page of twenty recent transactions grew large enough, every pass failed and paid orders stayed unpaid. Affects WordPress, Laravel, plain PHP and the PHP billing panels.
  • Fixed (PHP): a relay that drops the connection during a request no longer prints a PHP warning into the checkout's response. On a host with display_errors on, the warning went out ahead of the headers, so the payer's browser got a 200 with broken JSON instead of the error it could retry.
  • Fixed (Python, PHP, Ruby): a wallet-reported failed or expired invoice no longer closes while a wallet scan is still running. If a later page of that scan failed, the row stayed closed even though the scan had not completed. Only a settled payment is committed as it is found, as in JavaScript.
  • Fixed (Node): a relay that cannot be reached now reads as the wallet being unavailable on bundled hosts too. Next's bundler renames the SDK's error classes, so the payer saw "Failed to connect to wss://..." and a 502. Failed publishes and reply timeouts are now classified the same way on every bundler.
  • Changed (agent directions): a project's own rules now win over the directions, so an agent asks and waits when one forbids a step such as running migrations. Shops with no bundler are told to use renderTransactionDetailsHtml, because the standalone file has no createTransactionDetails and one bad import stops the whole checkout page.
  • Changed (Rails): openreceive-rails now requires nwc-ruby ~> 0.5. Each connection's encryption key is derived in OpenSSL instead of pure Ruby, about 58x faster, and the ecdsa gem is no longer installed. A Ruby whose OpenSSL cannot use secp256k1, as in FIPS mode, cannot use 0.5.
  • Changed (provider data): Cash App is now first in the Lightning wallet list, above Rizful, so its copy-and-paste walkthrough is the first one payers see.
  • Changed (Browser, React, Vue, Svelte, Angular): a wallet's pay tutorial is now one dialog with numbered steps. Step 1 is a large Copy invoice button at the top whenever there is an invoice, and the wallet's steps stay greyed out until it has worked. Then every step shows at once with its screenshot, because a payer on one phone can't flip between the page and the wallet for each step. checkoutLabels loses tutorialIntroPrefix, tutorialIntroCopy, tutorialCopiedContinue, tutorialExit and tutorialNext, and OPENRECEIVE_PAYMENT_WIZARD_ATTRIBUTES loses providerTutorialIndex.
  • Changed (Odoo): the Lightning invoice memo is now only the order reference. It also carried the Odoo company name, which every payer's wallet app saw.
  • Fixed (all engines, checkout): a checkout reopened for an order that is already paid now opens on its receipt. POST /checkouts/prepare used to answer the price and the payment methods, so a payer on another device was offered to pay again, and the method they picked answered an error. Prepare now answers a paid object for a paid reference, without asking the host for a price, and the checkout shows the receipt and fires its settled event. POST /checkouts and POST /swaps now refuse a paid reference with 409 before asking for a price, so a host whose amountFor returns null for paid orders no longer turns it into 404 "Unknown reference.". Reported in issue [#122].
  • Fixed (Python): the wallet-history pages of one reconcile pass now share one relay connection instead of opening one each, so a checkout costs two connections, not three to six. With every relay handshake delayed by 3.24 s, a FastAPI checkout answered in about 8.3 s instead of 12 s. The connection belongs to one thread and closes when the pass ends. Only list_transactions shares it: make_invoice always opens its own.
  • Fixed (React): <Checkout checkout={...}> with a snapshot from prepareCheckout now mints when the payer picks Bitcoin. It showed a wallet list with no invoice and no QR, because a snapshot with no payer invoice ran as an already-minted checkout. It now runs as create mode, as the element does.
  • Added (Node): openreceive doctor --scan-build <dir> searches a production build, source maps included, for the NWC_URI and LSC_URI_* codes in the environment and env files. It prints only the code's name and the relative file, never any part of a value, and exits 1 on a hit.
  • Fixed (Node, PHP): a new invoice's first wallet check no longer waits for the older invoices' slower pace. When only invoices older than five minutes were pending, the checkout's own reconcile pass ran just before the new row existed and set a 12 s interval, and later claims kept the larger of that and their own, so a payment could take about 16 s to show as paid. Each claim now uses the interval for what is pending at that moment (3 s while any invoice is under two minutes old), as Ruby and Python already did. Node reads the pending list before claiming, and a request with nothing pending no longer writes to the gate. Custom repositories: Node no longer passes intervalSeconds to checkpointReconcileGate.
  • Changed (Node): the ready promise on createStack, @openreceive/express and @openreceive/next rejects only for what trying again cannot fix: no NWC code, a malformed one, or a wallet that can spend. A relay that did not answer at start now resolves it, so await ready before listen() no longer stops a shop during a relay outage. Checkouts answer a retryable 503 and the next request after a short wait checks again, as on Python and Ruby. ready therefore does not prove the wallet answered; run openreceive doctor for that. ConfigError has a new retryable field.
  • Changed (checkout): a shop that only takes Lightning no longer tells the payer to "Choose how you want to pay." above its one button.
  • Changed (checkout): the "Keep this order id" note no longer calls the id "the way back to this payment", which shops that tie an order to the browser could not honor from another one. It now says the shop can find the payment with it, and that the link brings the payer back on this browser.
  • Added (WordPress): wp openreceive test-invoice --new --amount=20.00 sets the Easy Digital Downloads test order's amount, as the Paymenter, FOSSBilling and PrestaShop commands do. The EDD directions use it, so the test order is large enough for every payment method.
  • Changed (WordPress): the plugin's short description names ETH and SOL.
  • Docs (agent directions): the top of each file says how to save the directions and read them in parts when a tool cuts long output.
  • Fixed (Vue): a Nuxt or Vite app without TypeScript, or with TypeScript 7, now builds with @openreceive/vue. The package shipped Checkout.vue as source, and its props name an imported type (defineProps<WrapperCheckoutComponentProps>()), so the shop's own Vue compiler had to resolve that type across packages with TypeScript. In all three Nuxt agent trials docker compose up -d --build stopped at "[@vue/compiler-sfc] Failed to load TypeScript, which is required for resolving imported types"; with TypeScript 7 installed it stopped at "No fs option provided to compileScript", and the shop never started. Agents got past it only by pinning or removing TypeScript, or by copying the component into the app. The package build now compiles the component itself: @openreceive/vue/checkout.vue is plain JavaScript with runtime props and a render function, so any Vue 3.4+ build (Vite, Nuxt, webpack with vue-loader) imports it like any other module, with or without TypeScript. The import path, the props and their defaults, styles.css and the TypeScript types are unchanged. The optional typescript peer is gone.
  • Fixed (Python): a FastAPI or Flask shop restarted while its wallet's relay refused connections now starts. The wallet check at start-up raised WalletPreflightError ("could not read wallet info …"), so Uvicorn logged "Application startup failed. Exiting." and gunicorn's worker exited with code 3, and the shop stayed down although the relay was back seconds later. Now a relay that refuses, drops or does not answer the check does not stop the start: the service logs one line, checkouts answer 503 WALLET_UNAVAILABLE, retryable, "The payment service is not available. Please try again shortly.", and the first checkout after a short wait checks the wallet again and is served if it answers. The wait starts at 1 s and doubles after each failure, up to 60 s; there is no timer or thread, so an idle process makes no wallet calls. A code that is wrong still stops the start: a malformed code, a wallet that does not advertise make_invoice and list_transactions or speaks no supported encryption, and a spend-capable wallet without the override. A later check that finds such a wallet refuses it the same way and takes no payments. Django, which builds the service on the first request, now follows the same schedule instead of checking again on every request. openreceive reconcile still exits 1 when it cannot reach the wallet, OPENRECEIVE_PREFLIGHT=1 manage.py check still reports it as openreceive.E002, and the openreceive notifications worker subscribes only once the check passes. Found by the agent trials' new restart check.
  • Fixed (Ruby): the same for the Rails engine and openreceive-server. A production boot with the relay refusing connections raised WalletPreflightError (NwcRuby::NotSentError: not sent: relay … failed before the request was written) from the engine's eager preflight, and the app never answered. It now boots and behaves as above. bin/rails openreceive:doctor still reports the relay as FAILED, and bin/rails openreceive:notifications subscribes once the check passes.
  • Fixed (Ruby): a relay that accepts the connection and never answers costs a Rails checkout 12 s before its 503, not 30 s. The engine built its nwc-ruby client with the gem's default budget of 30 s per call, which covers the info fetch, the relay handshake and the wallet's reply. It now passes 12 s (OpenReceive::NwcRubyReceiveClient::REQUEST_TIMEOUT_SECONDS), which still leaves a slow wallet room: relay handshakes measured 0.6 to 3.2 s, and the wallet's make_invoice reply takes a few seconds more. Python gives up at 10 s, Node at 8 s and PHP at about 6 s. OpenReceive::NwcRubyReceiveClient.from_uri builds the same client for a Rack host.
  • Fixed (Node, Python, Ruby): the start-up error for a relay that could not be reached no longer says "Use a receive-only NWC connection advertising make_invoice and list_transactions", which sent operators after a code that was never checked. Node's createOpenReceive now rejects with WALLET_PREFLIGHT_FAILED, "OpenReceive could not reach the wallet's relay at start-up (Failed to connect to wss://…).", and a hint that the code was not checked; the stack's boot line still adds when it tries again. Python and Ruby log "wallet.unreachable: OpenReceive could not reach the wallet's relay at start-up (…). The first checkout after 1 s tries again." The receive-only advice stays on real capability failures.
  • Fixed (Node): a wallet relay that accepts the connection and then never answers (or refuses new connections while the app runs) now reaches the buyer as 503 WALLET_UNAVAILABLE, retryable, so the checkout shows its payer sentence and Try again. It answered 502 OTHER, not retryable, with "Failed to connect to wss://…" as the text: @getalby/sdk throws Nip47NetworkError with code OTHER and never sets the error's name, so the engine now reads the error's class. SDK reply and publish timeouts are TIMEOUT the same way. Found by the agent trials' new chaos phase.
  • Fixed (Node): a relay handshake slower than 3 s no longer fails the checkout. @getalby/sdk's connection pool gave a relay connection 3 s and every request waits on the one its subscription opened; from a shop container, one of eight handshakes to Rizful's relay took 3.24 s. The engine now gives it 8 s. A relay that refuses still fails at once. The PHP engine got the same fix in 0.4.32.
  • Fixed (Python, PHP, Ruby): a swap the provider refuses no longer shows the buyer "Internal server error.". When the provider said no to an order, POST /openreceive/swaps answered 500 INTERNAL and the payer read that text; now it answers 502 INTERNAL "The swap provider refused this request.", the Node engine's answer. A provider 429 or outage on that call, or on swap status and refunds, is 503 INTERNAL, retryable, with "The swap provider is rate limited. Please try again shortly." or "The swap provider is temporarily unreachable. Please try again shortly." The provider's own words go to the shop's log as a warning. The WordPress, PrestaShop, FOSSBilling and Paymenter plugins bundle the PHP engine and carry the fix, as do the Django, FastAPI, Flask and Rails mounts.
  • Fixed (Python, PHP, Ruby): a buyer who presses Try again on a swap a few times no longer ends at "Internal server error.". Each try spends the process's own budget of provider calls, so the third or fourth press within a minute was refused before it reached the provider, as a 500. It is now the same retryable 503 "The swap provider is rate limited. Please try again shortly." that a provider 429 gives, and the budget refills after a minute.
  • Fixed (Django): a checkout right after the shop starts with the wallet relay down answers OpenReceive's JSON 503 WALLET_UNAVAILABLE, retryable, "The payment service is not available. Please try again shortly.", like the Node mounts. It answered Django's own HTML "Server Error (500)" page, which the checkout cannot read, and nothing was logged. The same holds for a missing or malformed NWC_URI. The cause goes to the log, redacted, and a later request tries again (on the schedule above for a relay that is down).
  • Fixed (Django): with DEBUG = True, Django's error page no longer prints NWC_URI, LSC_URI_PRIMARY and LSC_URI_BACKUP in full. manage.py runserver copies the environment into request.META, and Django's filter hides only names with API, AUTH, TOKEN, KEY, SECRET, PASS or SIGNATURE in them. The app now installs openreceive.django.debug.OpenReceiveExceptionReporterFilter as DEFAULT_EXCEPTION_REPORTER_FILTER when the project has not set its own; it also hides the NWC and LSC names and any value holding a nostr+walletconnect: or lightning+swapconnect: code. A project with its own filter gets system check warning openreceive.W003 while DEBUG is on until that filter subclasses OpenReceive's.
  • Fixed (Django): manage.py openreceive_install prints "RATE_LIMITING": True under "Recommended for public web shops", not False, and says to set it to False for point-of-sale and to put a trusted-proxy middleware first behind a reverse proxy. It no longer prints export NWC_URI=<receive-only NWC code>, a code on a shell line: it says to write NWC_URI into the project's .env with a file editor and load that file (django-environ, or Compose's env_file), or to set it in the server's environment.

  • Fixed (Rails): an unexpected error inside OpenReceive's routes now leaves a line in the Rails log, "[openreceive] unexpected <class> (request_id=…) at <file:line>", as it did without Rails. With Rails.error present the engine reported only there, and a default app subscribes nothing to it, so the log showed "Completed 500 Internal Server Error" and nothing else. The report to Rails.error is unchanged; neither carries the error's message.

  • Fixed (Node): an onPaid that throws on every retry is now visible in the shop's log. The opportunistic reconcile warned only "One or more settlement transactions failed; pending attempts will be retried.", so a shop whose orders never turned paid gave its developer nothing to go on. The warning now ends with "Cause:" and the first three failures, redacted like every other OpenReceive log line. In the trial that found it, the agent wrote paidAt into a Postgres TIMESTAMPTZ column.
  • Docs (Node): paidAt in onPaid is Unix seconds; its type and the ORM guide now say so and show to_timestamp($1) (Postgres) and FROM_UNIXTIME(?) (MySQL) for a timestamp column.
  • Docs (agent directions), from the 2026-11-08 trial reviews: SvelteKit 3 takes the shop's origin from paths.origin, set from ORIGIN at build time, never a literal host:port and never a widened CSRF check. The Next.js quickstart's rateLimiting and trustProxyIpHeader are commented out: only behind Vercel or a proxy that replaces x-forwarded-for. FastAPI's doctor runs without dotenv run, inside the container under Compose. The PrestaShop and FOSSBilling closings hand over a whole crontab entry. Node guest cookies are signed with the app's own secret, never a wallet or swap code, and a swap's payment_hash stays on the order row. A line about coming back to pay or for a refund shows only while the order is unpaid.

  • Changed (checkout): the paid screen's badge reads "Paid" (and "Expired"), not the engine's "settled", and the waiting screen says "Keep this page open while we confirm your payment." instead of "… while we verify settlement.". The data-state attribute still carries settled and expired for hosts and stylesheets. Every reviewer of the 2026-11-08 trial round read "settled" on a payer's screen as jargon.

  • Fixed (checkout): a payer whose browser does not own the order no longer reads the server's text for the developer. A PrestaShop trial's payer saw "Not authorized for this action. The application's authorize hook denied it; if this is unexpected, check that the payer's session reaches the checkout routes." under "Could not start checkout.", and a field error ("payment_hash is required.") or a 409's "The selected payment attempt is not a reusable pending checkout." could reach the screen the same way. The element and React (and the Vue, Svelte and Angular wrappers, through the element) now pick the payer's sentence by error code and status, on the "Could not start checkout." screen, beside the invoice's Try again and in the swap address panel: a 403 or 401 reads "This payment can only be opened from the browser or account that placed the order. If you placed it here, reload the page and try again."; a 404 "This order could not be found. Check the link, or open it from the browser or account that placed the order."; a 409 "This payment changed while the page was open. Reload the page and try again."; a bad request, a server bug or a code the checkout does not know "Something went wrong with this payment. Please try again."; a retryable 5xx or a proxy's 502/503/504 "The payment service did not answer in time. Please try again.". The sentences the engines write for the payer are kept: the exchange-rate and swap-provider sentences, the 429 text (host-configurable), and the PrestaShop and FOSSBilling "security token" refusal. A failure that never reached a server ("Failed to fetch") shows the screen's own "Please try again." sentence. The original text and code still go to onError and the openreceive-error event, and a reworded failure logs one checkout.error.reworded warning to the console with error_code, status and error_message. payerErrorMessage takes the same rules, and an optional third argument for that warning. The agent trials' payer walk now fails a screen that names the authorize hook, the payer's session, the checkout routes, a wire field name or a bare error code such as FORBIDDEN.

  • Docs (Python): the install guides now say Python 3.10 to 3.13. On 3.14 the install stops with "Failed to build coincurve", because that library has no 3.14 build yet. The guides used to say "3.10 or newer".

Source: README.md, updated 2026-11-09