Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message
integrate-openreceive
integrate-openreceive
openreceive/laravel
claude-code
checkout
payments
laravel
bitcoin
Lightning
payment-gateway
self-hosted
USDT
stablecoin
USDC
nostr
nwc
bitcoin-payments

Integrate OpenReceive Bitcoin Lightning checkout and optional USDT, USDC, SOL, and ETH swaps. Use for Node.js, Express, Fastify, Next.js, NestJS, SvelteKit, Nuxt, Astro, React Router, TanStack Start, Rails, Python, Django, FastAPI, Flask, Laravel, plain PHP, WordPress/WooCommerce, Easy Digital Downloads, Paymenter, FOSSBilling, PrestaShop, Odoo, Medusa, Vendure, Lovable, Bolt, Supabase, React, Vue, Svelte, Angular, or plain HTML applications, mobile apps (React Native, Expo, Flutter, Swift, Kotlin) through their server, or connecting BTCPay Server to a receive-only NWC wallet. A configured swap provider converts these payments to BTC over Lightning in the merchant's connected wallet; asset and network availability depends on the provider.

Install
php artisan boost:add-skill openreceive/laravel

Save this content to: .claude/skills/integrate-openreceive/SKILL.md

# Integrate OpenReceive

OpenReceive is a payment library that runs inside the application you are
editing. It mounts HTTP routes there, issues Lightning invoices against a
wallet the merchant already controls, and calls back into your code when one
settles. There is no OpenReceive account and no API key; funds land directly in
the merchant's wallet. The one required credential is a **receive-only NWC
code** (`NWC_URI`).

Optional swaps let customers pay with USDT, USDC, SOL, and ETH. A configured
swap provider converts these payments to BTC over Lightning in the merchant's
connected wallet; asset and network availability depends on the provider.

## Pick the stack, then follow its directions

1. Identify the server stack of the application you are in.
2. Open the matching reference — it is complete (quickstart inlined) and needs
   no network access:
   - Node, Express: [references/node.md](references/node.md)
   - Node, Fastify: [references/fastify.md](references/fastify.md)
   - Node, Next.js App Router: [references/next.md](references/next.md)
   - Node, NestJS (Express platform): [references/nestjs.md](references/nestjs.md)
   - Node, SvelteKit (adapter-node): [references/sveltekit.md](references/sveltekit.md)
   - Node, Nuxt (Nitro node-server): [references/nuxt.md](references/nuxt.md)
   - Node, Astro (@astrojs/node): [references/astro.md](references/astro.md)
   - Node, React Router (framework mode): [references/react-router.md](references/react-router.md)
   - Node, TanStack Start on your own server:
     [references/tanstack-start.md](references/tanstack-start.md) — on Lovable,
     use the Lovable reference below instead.
   - Rails: [references/rails.md](references/rails.md)
   - Python, FastAPI: [references/fastapi.md](references/fastapi.md)
   - Plain PHP: [references/php.md](references/php.md)
   - Django: [references/django.md](references/django.md)
   - Flask: [references/flask.md](references/flask.md) — a one-file Blueprint
     copied from the quickstart; there is no `openreceive.flask` package.
   - Laravel: [references/laravel.md](references/laravel.md)
   - WordPress + WooCommerce: [references/woocommerce.md](references/woocommerce.md) — the packaged gateway and merchant settings.
   - WordPress + Easy Digital Downloads: [references/edd.md](references/edd.md) — the same
     WordPress.org plugin, its EDD gateway and WP-CLI setup.
   - Paymenter: [references/paymenter.md](references/paymenter.md) — a gateway
     extension from the GitHub release, configured with artisan commands; no
     Composer or npm packages.
   - FOSSBilling: [references/fossbilling.md](references/fossbilling.md) — a
     module and payment gateway from the GitHub release, configured with
     console commands; no Composer or npm packages.
   - PrestaShop: [references/prestashop.md](references/prestashop.md) — a
     payment module from the GitHub release, configured with bin/console
     commands; no Composer or npm packages.
   - Odoo: [references/odoo.md](references/odoo.md) — a payment provider module
     from the GitHub release and the `openreceive` package from PyPI,
     configured with `odoo openreceive` commands.
   - Medusa: [references/medusa.md](references/medusa.md) — the
     `@openreceive/medusa` plugin and payment provider in the Medusa server,
     and the React checkout in the storefront; no hooks to write.
   - Vendure: [references/vendure.md](references/vendure.md) — the
     `@openreceive/vendure` plugin and payment method handler in the Vendure
     server, and the React checkout in the storefront; no hooks to write.
   - Lovable (TanStack Start on Cloudflare Workers, with Supabase):
     [references/lovable.md](references/lovable.md) — no terminal; codes are
     Lovable secrets and payments go through Supabase's HTTPS API.
   - Bolt (a Vite React app with Bolt Database or Supabase, and Supabase
     Edge Functions as server functions):
     [references/bolt.md](references/bolt.md) — codes are Bolt secrets; one
     server function serves the payment routes, and the page sends the
     buyer's Supabase token.
   - A mobile app (React Native or Expo, Flutter, Swift, Kotlin):
     [references/mobile.md](references/mobile.md) — OpenReceive goes on the
     app's server, through that server's reference; the app opens its checkout
     page in a browser tab.
   - BTCPay Server: [references/btcpay.md](references/btcpay.md) — a plugin,
     configured in BTCPay's store UI or Greenfield API; no application code,
     no npm packages, no gem. The rest of this file is about the library.
3. Follow its **Step 0** first: before writing code or searching the machine,
   ask the user for the receive-only NWC code (then the swap URI), one question
   per message, and store each pasted code in the project's env file yourself.
   Never print the value; never invent a placeholder.

Install, per adapter — Express: `npm install @openreceive/express @openreceive/react`;
Fastify: `npm install @openreceive/fastify @openreceive/react`; Next.js:
`npm install @openreceive/next @openreceive/react`; NestJS:
`npm install @openreceive/express @openreceive/http @openreceive/react`;
SvelteKit, Nuxt, Astro, React Router and TanStack Start: `npm install @openreceive/http pg`
plus the UI package. Swap the UI package (`vue`,
`svelte`, `angular`, `elements`) for the frontend the app already has. Install
(Rails): `bundle add openreceive-rails`.
Django: `pip install "openreceive[django]"`; FastAPI:
`pip install "openreceive[fastapi]"`; Flask: `pip install "openreceive[sqlalchemy]"`; Laravel: `composer require openreceive/laravel`;
plain PHP: `composer require openreceive/openreceive nyholm/psr7 nyholm/psr7-server`.

## The three server objects

| Object | Built with | Talks to |
| --- | --- | --- |
| Wallet client | `createOpenReceive()` | the merchant's wallet — mints invoices, reads settlement, holds the NWC code |
| Host | `createHost()` | your database — your hooks plus the `openreceive_payments` table |
| HTTP routes | `openReceiveExpress()` / `openReceiveFastify()` / `openReceiveNext()` / the Rails engine | the browser — mounted at `/openreceive` by default |

The quickstart's one-factory form (`openReceiveExpress({ wallet, storage,
amountFor, authorize })`) builds all three; compose them separately only for a
shared wallet client or a custom repository. The checkout UI
(`<Checkout reference={...} prefix="/openreceive" />`) is the optional fourth
piece.

## The host contract: authorize, amountFor, onPaid

Your application keeps orders, users, prices, and fulfillment. Three hooks are
the entire bridge — wire them to the models this app already has, never to
copied demo models:

- `amountFor(reference)` — the authoritative price, read from your own data.
  Return `{ currency, value, description }` with `value` a **decimal string**
  (never a float, never payer input), or `null` when there is nothing to pay
  for. The `reference` is your order id: one per thing you fulfill, created
  before checkout, kept across retries, never reused.
- `authorize({ action, request, resource })` — your own access check, run on
  every request. `resource.reference` is a claim the payer made, not proof;
  read a real session.
- `onPaid({ reference, paidAt, query })` — fulfillment, run once per reference
  inside the settlement transaction, only for the first settled attempt. Use
  the provided `query`, not your ORM's other connection, and guard the
  transition (`UPDATE … WHERE state = 'awaiting_payment'`).

## 409 is a state, not a failure

The library serializes attempts per reference. A create that returns **409
CONFLICT** is normal checkout flow: the reference already settled, or an unpaid
checkout for that payment method is already in progress. Surface it as order
state; do not retry-loop it, and do not build an idempotency store around it —
that serialization is the library's job. (A hook failure while persisting an
attempt is a **503 retryable**, deliberately distinct.)

## Amounts on the deposit panel

`swap.deposit_amount` is the ONLY amount a payer is ever told to send, in the
pay-in token. `swap.fee.pay_in_fiat` / `payout_fiat` are fiat valuations that
explain the spread (why the deposit exceeds the cart total); they are not
instructions. For a stablecoin pegged to the fee currency (USDT, USDC) the
packaged checkout expresses the breakdown in the token and never renders
`pay_in_fiat` — "$50.03" under "50.05 USDC" reads as the same number with a
typo. A custom UI gets the same rule from `createSwapFeeBreakdown(fee, swap)`;
pass the swap, not just the fee.

## Secrets

`NWC_URI` and `LSC_URI_*` are server-only. Never put them in browser code,
logs, assets, or tests. Boot fails closed if the NWC code advertises spend
methods such as `pay_invoice` — mint a receive-only code
(https://openreceive.org/get_a_nwc_code_to_receive_payments) instead of
overriding.

## Database tables

Generate the two tables in the host's existing database:

| Stack | Generate and apply |
| --- | --- |
| Node | `npx openreceive scaffold payments --orm <orm>`, then the app's normal migration command |
| Rails | `bin/rails generate openreceive:install && bin/rails db:migrate` |
| Django | `manage.py openreceive_install <app> && manage.py migrate` |
| FastAPI | `openreceive scaffold payments --alembic --dialect <db>` (or `--sql`), then apply through the app's migration workflow |
| Laravel | `php artisan openreceive:install && php artisan migrate` |
| Plain PHP | Use `OpenReceive\Storage\PaymentsSchema::statements($dialect)` in the host's migration workflow, as in the PHP reference |

These emit `openreceive_payments` + `openreceive_meta`. The tables sit beside
your models — no relations to them, no separate database, no Redis. WordPress
and BTCPay manage installation through their plugins; follow their references.

## Verify, and test without a real wallet

| Stack | Doctor | Test seam |
| --- | --- | --- |
| Node | `npx openreceive doctor` | `client` on `createOpenReceive` (`preflight`, `makeInvoice`, `listTransactions`), plus `StaticPriceProvider` |
| Rails | `bin/rails openreceive:doctor` | `config.nwc_client`, `config.swap_providers`, `config.price_provider` |
| Django | `manage.py openreceive_doctor` | `OPENRECEIVE["SERVICE"]`, a factory returning a `Service` built on `openreceive.testing` fakes |
| FastAPI | `openreceive doctor --app main:app` | `nwc_client`, `price_provider`, `swap_providers` on `openreceive_router`, using `openreceive.testing` fakes |
| Laravel | `php artisan openreceive:doctor` | Bind `ReceiveNwcClient`, `PriceProvider`, and `OpenReceiveServiceProvider::SWAP_PROVIDERS` in the container |
| Plain PHP | `php bin/doctor` (host script calling `$engine->doctor()`) | Build `Service` with `OpenReceive\Testing\FakeWallet`, `FakeSwapProvider`, and `OpenReceive\Rates\StaticPriceProvider` |
| WordPress | `wp openreceive doctor`, then `wp openreceive test-invoice <order id>` for a real invoice | Repository development: the documented Docker `compose.testkit.yml` override |
| BTCPay | Follow the plugin reference's connection and checkout checks | Use the plugin's Docker test setup in its reference |

The routes, persistence, reconciliation, and fulfillment hooks then run the
production paths. Details: https://openreceive.org/guides/host-testing.md

## Deeper documentation

Fetch on demand — each URL is raw markdown:
https://openreceive.org/guides/authorization.md ·
https://openreceive.org/guides/storage.md ·
https://openreceive.org/guides/api-reference.md ·
https://openreceive.org/guides/security.md ·
https://openreceive.org/openapi.yaml (the normative HTTP contract) ·
https://openreceive.org/llms.txt (the full index)

Integrate OpenReceive

OpenReceive is a payment library that runs inside the application you are editing. It mounts HTTP routes there, issues Lightning invoices against a wallet the merchant already controls, and calls back into your code when one settles. There is no OpenReceive account and no API key; funds land directly in the merchant's wallet. The one required credential is a receive-only NWC code (NWC_URI).

Optional swaps let customers pay with USDT, USDC, SOL, and ETH. A configured swap provider converts these payments to BTC over Lightning in the merchant's connected wallet; asset and network availability depends on the provider.

Pick the stack, then follow its directions

  1. Identify the server stack of the application you are in.
  2. Open the matching reference — it is complete (quickstart inlined) and needs no network access:
  3. Follow its Step 0 first: before writing code or searching the machine, ask the user for the receive-only NWC code (then the swap URI), one question per message, and store each pasted code in the project's env file yourself. Never print the value; never invent a placeholder.

Install, per adapter — Express: npm install @openreceive/express @openreceive/react; Fastify: npm install @openreceive/fastify @openreceive/react; Next.js: npm install @openreceive/next @openreceive/react; NestJS: npm install @openreceive/express @openreceive/http @openreceive/react; SvelteKit, Nuxt, Astro, React Router and TanStack Start: npm install @openreceive/http pg plus the UI package. Swap the UI package (vue, svelte, angular, elements) for the frontend the app already has. Install (Rails): bundle add openreceive-rails. Django: pip install "openreceive[django]"; FastAPI: pip install "openreceive[fastapi]"; Flask: pip install "openreceive[sqlalchemy]"; Laravel: composer require openreceive/laravel; plain PHP: composer require openreceive/openreceive nyholm/psr7 nyholm/psr7-server.

The three server objects

Object Built with Talks to
Wallet client createOpenReceive() the merchant's wallet — mints invoices, reads settlement, holds the NWC code
Host createHost() your database — your hooks plus the openreceive_payments table
HTTP routes openReceiveExpress() / openReceiveFastify() / openReceiveNext() / the Rails engine the browser — mounted at /openreceive by default

The quickstart's one-factory form (openReceiveExpress({ wallet, storage, amountFor, authorize })) builds all three; compose them separately only for a shared wallet client or a custom repository. The checkout UI (<Checkout reference={...} prefix="/openreceive" />) is the optional fourth piece.

The host contract: authorize, amountFor, onPaid

Your application keeps orders, users, prices, and fulfillment. Three hooks are the entire bridge — wire them to the models this app already has, never to copied demo models:

  • amountFor(reference) — the authoritative price, read from your own data. Return { currency, value, description } with value a decimal string (never a float, never payer input), or null when there is nothing to pay for. The reference is your order id: one per thing you fulfill, created before checkout, kept across retries, never reused.
  • authorize({ action, request, resource }) — your own access check, run on every request. resource.reference is a claim the payer made, not proof; read a real session.
  • onPaid({ reference, paidAt, query }) — fulfillment, run once per reference inside the settlement transaction, only for the first settled attempt. Use the provided query, not your ORM's other connection, and guard the transition (UPDATE … WHERE state = 'awaiting_payment').

409 is a state, not a failure

The library serializes attempts per reference. A create that returns 409 CONFLICT is normal checkout flow: the reference already settled, or an unpaid checkout for that payment method is already in progress. Surface it as order state; do not retry-loop it, and do not build an idempotency store around it — that serialization is the library's job. (A hook failure while persisting an attempt is a 503 retryable, deliberately distinct.)

Amounts on the deposit panel

swap.deposit_amount is the ONLY amount a payer is ever told to send, in the pay-in token. swap.fee.pay_in_fiat / payout_fiat are fiat valuations that explain the spread (why the deposit exceeds the cart total); they are not instructions. For a stablecoin pegged to the fee currency (USDT, USDC) the packaged checkout expresses the breakdown in the token and never renders pay_in_fiat — "$50.03" under "50.05 USDC" reads as the same number with a typo. A custom UI gets the same rule from createSwapFeeBreakdown(fee, swap); pass the swap, not just the fee.

Secrets

NWC_URI and LSC_URI_* are server-only. Never put them in browser code, logs, assets, or tests. Boot fails closed if the NWC code advertises spend methods such as pay_invoice — mint a receive-only code (https://openreceive.org/get_a_nwc_code_to_receive_payments) instead of overriding.

Database tables

Generate the two tables in the host's existing database:

Stack Generate and apply
Node npx openreceive scaffold payments --orm <orm>, then the app's normal migration command
Rails bin/rails generate openreceive:install && bin/rails db:migrate
Django manage.py openreceive_install <app> && manage.py migrate
FastAPI openreceive scaffold payments --alembic --dialect <db> (or --sql), then apply through the app's migration workflow
Laravel php artisan openreceive:install && php artisan migrate
Plain PHP Use OpenReceive\Storage\PaymentsSchema::statements($dialect) in the host's migration workflow, as in the PHP reference

These emit openreceive_payments + openreceive_meta. The tables sit beside your models — no relations to them, no separate database, no Redis. WordPress and BTCPay manage installation through their plugins; follow their references.

Verify, and test without a real wallet

Stack Doctor Test seam
Node npx openreceive doctor client on createOpenReceive (preflight, makeInvoice, listTransactions), plus StaticPriceProvider
Rails bin/rails openreceive:doctor config.nwc_client, config.swap_providers, config.price_provider
Django manage.py openreceive_doctor OPENRECEIVE["SERVICE"], a factory returning a Service built on openreceive.testing fakes
FastAPI openreceive doctor --app main:app nwc_client, price_provider, swap_providers on openreceive_router, using openreceive.testing fakes
Laravel php artisan openreceive:doctor Bind ReceiveNwcClient, PriceProvider, and OpenReceiveServiceProvider::SWAP_PROVIDERS in the container
Plain PHP php bin/doctor (host script calling $engine->doctor()) Build Service with OpenReceive\Testing\FakeWallet, FakeSwapProvider, and OpenReceive\Rates\StaticPriceProvider
WordPress wp openreceive doctor, then wp openreceive test-invoice <order id> for a real invoice Repository development: the documented Docker compose.testkit.yml override
BTCPay Follow the plugin reference's connection and checkout checks Use the plugin's Docker test setup in its reference

The routes, persistence, reconciliation, and fulfillment hooks then run the production paths. Details: https://openreceive.org/guides/host-testing.md

Deeper documentation

Fetch on demand — each URL is raw markdown: https://openreceive.org/guides/authorization.md · https://openreceive.org/guides/storage.md · https://openreceive.org/guides/api-reference.md · https://openreceive.org/guides/security.md · https://openreceive.org/openapi.yaml (the normative HTTP contract) · https://openreceive.org/llms.txt (the full index)

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core