openreceive 0.4.29 → 0.4.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/openreceive/version.rb +1 -1
- data/skills/integrate-openreceive/SKILL.md +10 -1
- data/skills/integrate-openreceive/references/astro.md +8 -9
- data/skills/integrate-openreceive/references/bolt.md +9 -7
- data/skills/integrate-openreceive/references/btcpay.md +3 -4
- data/skills/integrate-openreceive/references/django.md +2 -3
- data/skills/integrate-openreceive/references/edd.md +4 -5
- data/skills/integrate-openreceive/references/fastapi.md +4 -5
- data/skills/integrate-openreceive/references/fastify.md +4 -5
- data/skills/integrate-openreceive/references/flask.md +2 -3
- data/skills/integrate-openreceive/references/fossbilling.md +7 -8
- data/skills/integrate-openreceive/references/laravel.md +3 -4
- data/skills/integrate-openreceive/references/lovable.md +16 -12
- data/skills/integrate-openreceive/references/medusa.md +12 -5
- data/skills/integrate-openreceive/references/mobile.md +1 -1
- data/skills/integrate-openreceive/references/nestjs.md +2 -3
- data/skills/integrate-openreceive/references/next.md +4 -5
- data/skills/integrate-openreceive/references/node.md +4 -5
- data/skills/integrate-openreceive/references/nuxt.md +9 -10
- data/skills/integrate-openreceive/references/odoo.md +446 -0
- data/skills/integrate-openreceive/references/paymenter.md +5 -6
- data/skills/integrate-openreceive/references/php.md +2 -3
- data/skills/integrate-openreceive/references/prestashop.md +476 -0
- data/skills/integrate-openreceive/references/rails.md +2 -3
- data/skills/integrate-openreceive/references/react-router.md +8 -9
- data/skills/integrate-openreceive/references/sveltekit.md +9 -10
- data/skills/integrate-openreceive/references/tanstack-start.md +14 -11
- data/skills/integrate-openreceive/references/vendure.md +544 -0
- data/skills/integrate-openreceive/references/woocommerce.md +5 -6
- metadata +6 -2
|
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/nestjs/full.md
|
|
|
17
17
|
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
18
|
- Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
19
|
|
|
20
|
-
These directions describe OpenReceive 0.4.
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
21
|
|
|
22
22
|
Add OpenReceive to a NestJS application — the app you are already working in,
|
|
23
23
|
on Nest's default Express platform. You do not need a copy of the OpenReceive
|
|
@@ -447,13 +447,12 @@ enough; drop the `.md` for the same page a person would read.
|
|
|
447
447
|
- https://openreceive.org/guides/api-reference.md — every route, option and error code
|
|
448
448
|
- https://openreceive.org/guides/custom-checkout-route.md — advanced: replacing the shipped adapter's routes with your own
|
|
449
449
|
- https://openreceive.org/guides/react-material-ui-recipe.md — a worked custom UI on a component library
|
|
450
|
+
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
450
451
|
- https://openreceive.org/guides.md — the index, if what you need is not above
|
|
451
452
|
|
|
452
453
|
Questions, or a problem with the library itself:
|
|
453
454
|
https://openreceive.org/contact
|
|
454
455
|
|
|
455
|
-
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
456
|
-
|
|
457
456
|
---
|
|
458
457
|
|
|
459
458
|
## The quickstart, in full
|
|
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/next/full.md
|
|
|
17
17
|
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
18
|
- Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
19
|
|
|
20
|
-
These directions describe OpenReceive 0.4.
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
21
|
|
|
22
22
|
Add OpenReceive to a Next.js App Router application — the app you are already
|
|
23
23
|
working in. You do not need a copy of the OpenReceive source: the packages are
|
|
@@ -438,13 +438,12 @@ enough; drop the `.md` for the same page a person would read.
|
|
|
438
438
|
- https://openreceive.org/guides/react-material-ui-recipe.md — a worked custom UI on a component library
|
|
439
439
|
- https://openreceive.org/guides/tanstack-start-recipe.md — the same handler as a TanStack Start server route, if this app is TanStack Start after all
|
|
440
440
|
- https://openreceive.org/guides/sveltekit-recipe.md, https://openreceive.org/guides/nuxt-recipe.md, https://openreceive.org/guides/astro-recipe.md and https://openreceive.org/guides/react-router-recipe.md — the same handler as a SvelteKit, Nuxt, Astro or React Router route, if this app is one of those
|
|
441
|
+
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
441
442
|
- https://openreceive.org/guides.md — the index, if what you need is not above
|
|
442
443
|
|
|
443
444
|
Questions, or a problem with the library itself:
|
|
444
445
|
https://openreceive.org/contact
|
|
445
446
|
|
|
446
|
-
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
447
|
-
|
|
448
447
|
---
|
|
449
448
|
|
|
450
449
|
## The quickstart, in full
|
|
@@ -473,8 +472,8 @@ stays the same.
|
|
|
473
472
|
| Server | `@openreceive/next`, `@openreceive/express`, `@openreceive/fastify` |
|
|
474
473
|
| Frontend | `@openreceive/react`, `@openreceive/vue`, `@openreceive/svelte`, `@openreceive/angular`, `@openreceive/elements` (plain HTML) |
|
|
475
474
|
|
|
476
|
-
Express: [quickstart
|
|
477
|
-
[quickstart
|
|
475
|
+
Express: [Express quickstart](https://openreceive.org/guides/quickstart-node.md) · Fastify:
|
|
476
|
+
[Fastify quickstart](https://openreceive.org/guides/quickstart-fastify.md). This page is the Next.js one.
|
|
478
477
|
An agent given the Express guide goes wrong on Next.js in three places: Next
|
|
479
478
|
needs no `dotenv`, no `app.use`, and it needs a client component for the
|
|
480
479
|
checkout.
|
|
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/node/full.md
|
|
|
17
17
|
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
18
|
- Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
19
|
|
|
20
|
-
These directions describe OpenReceive 0.4.
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
21
|
|
|
22
22
|
Add OpenReceive to a Node application — the app you are already working in. You
|
|
23
23
|
do not need a copy of the OpenReceive source: the packages are on npm, and the
|
|
@@ -428,13 +428,12 @@ enough; drop the `.md` for the same page a person would read.
|
|
|
428
428
|
- https://openreceive.org/guides/custom-checkout-route.md — advanced: replacing the shipped adapter's routes with your own
|
|
429
429
|
- https://openreceive.org/guides/react-material-ui-recipe.md — a worked custom UI on a component library
|
|
430
430
|
- https://openreceive.org/guides/sveltekit-recipe.md, https://openreceive.org/guides/nuxt-recipe.md, https://openreceive.org/guides/astro-recipe.md and https://openreceive.org/guides/react-router-recipe.md — the same handler as a SvelteKit, Nuxt, Astro or React Router route, if this app is one of those
|
|
431
|
+
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
431
432
|
- https://openreceive.org/guides.md — the index, if what you need is not above
|
|
432
433
|
|
|
433
434
|
Questions, or a problem with the library itself:
|
|
434
435
|
https://openreceive.org/contact
|
|
435
436
|
|
|
436
|
-
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
437
|
-
|
|
438
437
|
---
|
|
439
438
|
|
|
440
439
|
## The quickstart, in full
|
|
@@ -463,8 +462,8 @@ stays the same.
|
|
|
463
462
|
| Server | `@openreceive/express`, `@openreceive/fastify`, `@openreceive/next` |
|
|
464
463
|
| Frontend | `@openreceive/react`, `@openreceive/vue`, `@openreceive/svelte`, `@openreceive/angular`, `@openreceive/elements` (plain HTML) |
|
|
465
464
|
|
|
466
|
-
Fastify: [quickstart
|
|
467
|
-
[quickstart
|
|
465
|
+
Fastify: [Fastify quickstart](https://openreceive.org/guides/quickstart-fastify.md) · Next.js:
|
|
466
|
+
[Next.js quickstart](https://openreceive.org/guides/quickstart-next.md). This page is the Express one.
|
|
468
467
|
|
|
469
468
|
On a fresh project, also install what this guide assumes you already have: the
|
|
470
469
|
framework and an env loader (`npm install express dotenv`). Install your ORM
|
|
@@ -3,7 +3,7 @@ This is the full file; follow it from Step 0.
|
|
|
3
3
|
# OpenReceive agent directions (Nuxt)
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
# READ THIS FIRST: this file is
|
|
6
|
+
# READ THIS FIRST: this file is 34 KB and a summary drops required steps. Download it whole:
|
|
7
7
|
curl -fsSL https://openreceive.org/agent-directions/nuxt/full.md
|
|
8
8
|
# Skip the download only if you already have all of it: pasted, read from disk or fetched raw.
|
|
9
9
|
```
|
|
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/nuxt/full.md
|
|
|
17
17
|
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
18
|
- Start the quickstart only once the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
19
|
|
|
20
|
-
These directions describe OpenReceive 0.4.
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
21
|
|
|
22
22
|
Add OpenReceive to a Nuxt application — the app you are already working in,
|
|
23
23
|
on Nitro's `node-server` preset. OpenReceive ships no Nuxt package: the
|
|
@@ -419,13 +419,12 @@ enough; drop the `.md` for the same page a person would read.
|
|
|
419
419
|
- https://openreceive.org/guides/custom-checkout-route.md — advanced: replacing the shipped adapter's routes with your own
|
|
420
420
|
- https://openreceive.org/guides/react-material-ui-recipe.md — a worked custom UI on a component library
|
|
421
421
|
- https://openreceive.org/guides/quickstart-next.md — each hook explained step by step, on Next.js; they are the same here
|
|
422
|
+
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
422
423
|
- https://openreceive.org/guides.md — the index, if what you need is not above
|
|
423
424
|
|
|
424
425
|
Questions, or a problem with the library itself:
|
|
425
426
|
https://openreceive.org/contact
|
|
426
427
|
|
|
427
|
-
- https://openreceive.org/guides/payment-safety-upgrade.md — coordinated upgrades and reviewed repair of existing attempts
|
|
428
|
-
|
|
429
428
|
---
|
|
430
429
|
|
|
431
430
|
## The quickstart, in full
|
|
@@ -464,7 +463,7 @@ npm install @openreceive/http @openreceive/vue pg
|
|
|
464
463
|
On Node, with Nitro's default `node-server` preset. The wallet connection and
|
|
465
464
|
your database driver need Node, so the route cannot run on an edge runtime.
|
|
466
465
|
The Vercel, Netlify and AWS Lambda presets deploy Node functions: read
|
|
467
|
-
Bitcoin checkout on serverless hosts first. For
|
|
466
|
+
[Bitcoin checkout on serverless hosts](https://openreceive.org/guides/serverless.md) first. For
|
|
468
467
|
Cloudflare Workers, the [TanStack Start recipe](https://openreceive.org/guides/tanstack-start-recipe.md#where-it-runs)
|
|
469
468
|
explains what a Worker needs. This recipe was not run on those hosts.
|
|
470
469
|
|
|
@@ -529,24 +528,24 @@ export default defineEventHandler((event) => handleOpenReceive(event));
|
|
|
529
528
|
Put it in `server/routes/`, not `server/api/`, which would add `/api` to
|
|
530
529
|
the path. `native` is the request's `H3Event`, so `authorize` can check the
|
|
531
530
|
session your app already has: its cookies, or the user your session module
|
|
532
|
-
reads from the event. The Next.js quickstart
|
|
531
|
+
reads from the event. The [Next.js quickstart](https://openreceive.org/guides/quickstart-next.md)
|
|
533
532
|
explains each hook. They are the same here.
|
|
534
533
|
|
|
535
534
|
One stack serves the whole server process. `getRequestIP` returns the socket
|
|
536
535
|
address. Behind your own reverse proxy, `{ xForwardedFor: true }` reads the
|
|
537
536
|
first address in `x-forwarded-for`, which is safe only when that proxy sets
|
|
538
|
-
the header (Rate limiting).
|
|
537
|
+
the header ([Rate limiting](https://openreceive.org/guides/rate-limiting.md)).
|
|
539
538
|
|
|
540
539
|
### Your database
|
|
541
540
|
|
|
542
541
|
`db` is a `pg` Pool, `node:sqlite` or `better-sqlite3`, or one of the
|
|
543
|
-
adapters in Node ORM recipes. With Drizzle, pass
|
|
542
|
+
adapters in [Node ORM recipes](https://openreceive.org/guides/node-orms.md). With Drizzle, pass
|
|
544
543
|
the `pg` Pool underneath it.
|
|
545
544
|
|
|
546
545
|
Create OpenReceive's two tables with your migrations
|
|
547
546
|
(`npx openreceive scaffold payments --orm <your orm>`), or run
|
|
548
547
|
`paymentsSchemaSql("postgres")` from `@openreceive/http` once. It is
|
|
549
|
-
idempotent. See Payment storage.
|
|
548
|
+
idempotent. See [Payment storage](https://openreceive.org/guides/storage.md).
|
|
550
549
|
|
|
551
550
|
### The checkout page
|
|
552
551
|
|
|
@@ -585,7 +584,7 @@ if (error.value) {
|
|
|
585
584
|
The page renders on the server and starts the checkout in the browser. The
|
|
586
585
|
payer picks Bitcoin and gets the invoice. Keep it at the order's own URL: a
|
|
587
586
|
payer with a swap deposit in flight comes back to it
|
|
588
|
-
(Swap refunds).
|
|
587
|
+
([Swap refunds](https://openreceive.org/guides/swap-refunds.md)).
|
|
589
588
|
|
|
590
589
|
### Settings
|
|
591
590
|
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
This is the full file; follow it from Step 0.
|
|
2
|
+
|
|
3
|
+
# OpenReceive agent directions (Odoo)
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
# READ THIS FIRST: this file is 23 KB and a summary drops required steps. Download it whole:
|
|
7
|
+
curl -fsSL https://openreceive.org/agent-directions/odoo/full.md
|
|
8
|
+
# Skip the download only if you already have all of it: pasted, read from disk or fetched raw.
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Step 0 in brief** (Step 0 below has the details):
|
|
12
|
+
|
|
13
|
+
- Before installing or editing anything, ask the user for a receive-only NWC code. One question per message.
|
|
14
|
+
- Next ask for the LSC code. If the user wants stablecoins, USDT, USDC, ETH, SOL or crypto, do not ask yes/no first.
|
|
15
|
+
- The user only pastes codes into this chat. Never ask them to run a command, edit a file or use an admin page.
|
|
16
|
+
- Store each code yourself as Step 2 says. Never put a code in a shell command.
|
|
17
|
+
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
|
+
- Setup is done only when the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
|
+
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
|
+
|
|
22
|
+
Install and configure the OpenReceive payment provider in the Odoo you are
|
|
23
|
+
working in. Preserve its website, customers, products, orders, invoices and
|
|
24
|
+
prices. The module is a ZIP; its Python side is the `openreceive` package from
|
|
25
|
+
PyPI at the same version. Do not install anything else into Odoo, do not
|
|
26
|
+
change Odoo's own files, and do not clone the OpenReceive repository.
|
|
27
|
+
|
|
28
|
+
The one required credential is a receive-only NWC code (Nostr Wallet Connect):
|
|
29
|
+
a string from the merchant's wallet that can create invoices and read their
|
|
30
|
+
status, and cannot spend. A swap provider (an "LSC" code) optionally lets
|
|
31
|
+
customers pay with USDT, USDC, ETH or SOL instead; the provider converts the
|
|
32
|
+
payment to BTC over Lightning in the merchant's connected wallet. Available
|
|
33
|
+
assets and networks depend on the provider.
|
|
34
|
+
|
|
35
|
+
The module needs Odoo 19 or 20. With Odoo's official Docker image, run Odoo's
|
|
36
|
+
commands through the image's entrypoint, which adds the database connection:
|
|
37
|
+
`docker compose exec -T odoo /entrypoint.sh odoo …` (`-T` passes stdin
|
|
38
|
+
through; use the Odoo service's own name). `-d <database>` names the
|
|
39
|
+
database; `docker compose exec -T db psql -U <user> -l` lists them when you
|
|
40
|
+
do not know it. On a server, run `odoo …` (or `odoo-bin …`) as Odoo's own
|
|
41
|
+
user with its config file (`-c`).
|
|
42
|
+
|
|
43
|
+
## Step 0 — ask for the two codes, one question at a time
|
|
44
|
+
|
|
45
|
+
Before anything else, check one thing: whether OpenReceive is already
|
|
46
|
+
installed (`odoo openreceive doctor -d <database>`). If the command exists, it
|
|
47
|
+
prints `NWC_URI: present-redacted` or `missing` (likewise the LSC
|
|
48
|
+
connections), never the values. A code that is already saved is not asked for
|
|
49
|
+
again; if both are saved, skip to Step 3.
|
|
50
|
+
|
|
51
|
+
Otherwise your next action is a question to the user. Do not download the
|
|
52
|
+
module, edit Docker files or search anywhere else before asking it. Do not
|
|
53
|
+
read Odoo's config file, its database, container environments or other
|
|
54
|
+
projects looking for a code: a new install has neither code yet.
|
|
55
|
+
|
|
56
|
+
The user never runs a command and never edits a file. They paste each code
|
|
57
|
+
into this chat; you store it. That is the supported path: do not ask them to
|
|
58
|
+
run the save command themselves, and do not tell them to revoke or replace a
|
|
59
|
+
code because it was pasted here. Ask one question per message.
|
|
60
|
+
|
|
61
|
+
1. **First message — the NWC code, and nothing else.**
|
|
62
|
+
|
|
63
|
+
> To receive payments I need a receive-only wallet code. In Rizful: open
|
|
64
|
+
> the menu, tap NWC, choose Receive-only NWC code, and tap Copy
|
|
65
|
+
> (https://openreceive.org/get_a_nwc_code_to_receive_payments). If you would
|
|
66
|
+
> rather run your own wallet, Alby Hub works too: Connections → Add
|
|
67
|
+
> Connection → Read Only. Paste the code here and I will store it.
|
|
68
|
+
|
|
69
|
+
2. **When they paste it.** If it does not start with `nostr+walletconnect://`,
|
|
70
|
+
ask them to copy the receive-only code again. Otherwise do not repeat it:
|
|
71
|
+
reply only that you have it, then ask the next question. You store it in
|
|
72
|
+
Step 2.
|
|
73
|
+
3. **Second message — swaps.** If the user asked for stablecoins, USDT, USDC,
|
|
74
|
+
ETH, SOL, altcoins or "crypto" (as in "Bitcoin and stablecoin payments"),
|
|
75
|
+
this message IS the walkthrough below: do not skip it, and do not ask yes
|
|
76
|
+
or no first. Otherwise ask whether customers should also be able to pay
|
|
77
|
+
with USDT, USDC, ETH or SOL, then give the walkthrough. The walkthrough:
|
|
78
|
+
|
|
79
|
+
> Go to https://lightning-swap.com, sign in for API keys, create a key, and
|
|
80
|
+
> copy the whole URI (https://openreceive.org/set_up_swap_provider). Paste
|
|
81
|
+
> it here and I will store it — or say "Bitcoin only" and I will continue
|
|
82
|
+
> without it.
|
|
83
|
+
|
|
84
|
+
Mention FixedFloat only if they already use it.
|
|
85
|
+
4. **When they paste it.** If it does not start with
|
|
86
|
+
`lightning+swapconnect://`, ask them to copy it again. Swaps are now on,
|
|
87
|
+
so keep the route back (the swap non-negotiable below).
|
|
88
|
+
|
|
89
|
+
Do not report setup as complete until the NWC code is saved, and the LSC code
|
|
90
|
+
is saved or the user said "Bitcoin only". Never invent a placeholder code.
|
|
91
|
+
|
|
92
|
+
## Step 1 — install the module
|
|
93
|
+
|
|
94
|
+
The `openreceive` Python package must be importable by Odoo's own Python.
|
|
95
|
+
Odoo's official Docker image keeps its packages under the system's package
|
|
96
|
+
manager, so build an image that adds it:
|
|
97
|
+
|
|
98
|
+
1. Put a `Dockerfile` next to the Compose file, with the same tag as the Odoo
|
|
99
|
+
service's `image:` line:
|
|
100
|
+
|
|
101
|
+
```dockerfile
|
|
102
|
+
FROM odoo:<tag>
|
|
103
|
+
USER root
|
|
104
|
+
RUN pip3 install --no-cache-dir --break-system-packages --ignore-installed typing_extensions h11 \
|
|
105
|
+
&& pip3 install --no-cache-dir --break-system-packages openreceive==0.4.31
|
|
106
|
+
USER odoo
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The first line installs two packages beside the system's copies, which pip
|
|
110
|
+
cannot replace; do not add other packages, and do not install
|
|
111
|
+
`cryptography`: Odoo keeps using the system's.
|
|
112
|
+
2. In the Compose file, replace that service's `image:` line with `build: .`
|
|
113
|
+
(the folder that holds the Dockerfile). Change nothing else in the file.
|
|
114
|
+
3. Run `docker compose up -d --build`.
|
|
115
|
+
|
|
116
|
+
On a server, install `openreceive==0.4.31` with the pip of the Python
|
|
117
|
+
that runs Odoo (its virtualenv when it has one). On Odoo.sh, add
|
|
118
|
+
`openreceive==0.4.31` to the repository's `requirements.txt`. If you
|
|
119
|
+
cannot tell which Python runs Odoo, say so and stop.
|
|
120
|
+
|
|
121
|
+
The module is the ZIP attached to this GitHub release, with its folder,
|
|
122
|
+
`payment_openreceive`, at the top. Unzip it into the folder Odoo reads extra
|
|
123
|
+
modules from: with the official image, the host folder mounted at
|
|
124
|
+
`/mnt/extra-addons` (the Compose file's `volumes:` says which); on a server, a
|
|
125
|
+
folder on the config file's `addons_path`. Never install the GitHub
|
|
126
|
+
source-code ZIP or a ZIP from an older release.
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.31/openreceive-odoo-0.4.31.zip
|
|
130
|
+
unzip -oq openreceive-odoo-0.4.31.zip -d <that folder> && rm openreceive-odoo-0.4.31.zip
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Then install it into the database and restart Odoo:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
docker compose exec -T odoo /entrypoint.sh odoo -d <database> -i payment_openreceive --stop-after-init --no-http
|
|
137
|
+
docker compose restart odoo
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Installing creates the module's two tables in Odoo's database, its payment
|
|
141
|
+
provider "OpenReceive" with the payment method "Bitcoin Lightning", a
|
|
142
|
+
scheduled action that records payments made after the customer left, and the
|
|
143
|
+
`odoo openreceive` command. The provider stays hidden from customers until a
|
|
144
|
+
wallet code is saved and Step 2 publishes it. If the install says the
|
|
145
|
+
`openreceive` package is missing, the image or virtualenv from the step above
|
|
146
|
+
is not the one Odoo runs: fix that, do not work around it.
|
|
147
|
+
|
|
148
|
+
## Step 2 — store the codes
|
|
149
|
+
|
|
150
|
+
Store each code yourself, one per command, and never as a shell argument:
|
|
151
|
+
|
|
152
|
+
1. Write the code with your file-editing tool, not a shell command (no
|
|
153
|
+
`echo`, `printf` or heredoc), to a new file outside the Odoo folders, such
|
|
154
|
+
as `/tmp/openreceive-code`.
|
|
155
|
+
2. Run `odoo openreceive configure --nwc-uri=- -d <database> < /tmp/openreceive-code`.
|
|
156
|
+
In Docker: `docker compose exec -T odoo /entrypoint.sh odoo openreceive configure --nwc-uri=- -d <database> < /tmp/openreceive-code`.
|
|
157
|
+
For the LSC code, use `--lsc-uri-primary=-`.
|
|
158
|
+
3. Delete the file (`rm /tmp/openreceive-code`), whether the command passed
|
|
159
|
+
or not.
|
|
160
|
+
|
|
161
|
+
The command asks the wallet first and saves the code, in the module's own
|
|
162
|
+
table, only when the wallet answers as receive-only; a failure saves nothing.
|
|
163
|
+
If it reports spend methods such as `pay_invoice`, ask the user for a
|
|
164
|
+
receive-only code again. Saving the swap code renames the payment method to
|
|
165
|
+
"Bitcoin & stablecoins". Never write a code into Odoo's database, its config
|
|
166
|
+
file or any file in its folders yourself.
|
|
167
|
+
|
|
168
|
+
Then publish the provider, in every company:
|
|
169
|
+
`odoo openreceive configure --enable -d <database>`, and run
|
|
170
|
+
`odoo openreceive doctor -d <database>`. Doctor names any failed check and
|
|
171
|
+
exits nonzero; fix it before going on.
|
|
172
|
+
|
|
173
|
+
## Step 3 — mint a test invoice, then stop
|
|
174
|
+
|
|
175
|
+
Create a small draft payment transaction for a test contact the command
|
|
176
|
+
creates once (`openreceive-test@example.invalid`, with no order, so no
|
|
177
|
+
customer sees it), and mint its Lightning invoice:
|
|
178
|
+
|
|
179
|
+
```sh
|
|
180
|
+
odoo openreceive test-invoice --new -d <database>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
To use a transaction that already exists, pass `--reference <its reference>`
|
|
184
|
+
instead of `--new`. `test-invoice` goes through the same route as the
|
|
185
|
+
checkout page. It prints the amount in sats, the BOLT11 invoice and the
|
|
186
|
+
methods the checkout offers, each swap asset marked available or followed by
|
|
187
|
+
the reason it is not. That reason is the answer; report it. A reason about the
|
|
188
|
+
provider's minimum or maximum is about this amount, not a fault. `test-invoice`
|
|
189
|
+
and `doctor` are the whole check.
|
|
190
|
+
|
|
191
|
+
The checkout page itself belongs to the customer who starts a payment: tell
|
|
192
|
+
the user to try it from the shop, by putting a product in the cart and paying
|
|
193
|
+
with "Bitcoin Lightning" (or "Bitcoin & stablecoins").
|
|
194
|
+
|
|
195
|
+
You cannot pay the invoice: the code is receive-only. Do not pay, settle or
|
|
196
|
+
mark the transaction paid, and do not look for a way to (a wallet control
|
|
197
|
+
port, a test endpoint, another wallet). If the user wants a real settlement
|
|
198
|
+
test, they pay a shop order with their own wallet; afterwards the order is
|
|
199
|
+
confirmed.
|
|
200
|
+
|
|
201
|
+
Setup ends here. Once doctor is clean, your last message starts "Setup is
|
|
202
|
+
finished" and has at most six short lines: the methods the checkout offers
|
|
203
|
+
(Bitcoin, plus USDT, USDC, ETH and SOL when the swap code is saved), and one
|
|
204
|
+
line of what to try in the shop. Do not list each coin's availability, mention
|
|
205
|
+
a minimum, or say a coin will not work: a provider minimum depends on the
|
|
206
|
+
order total, and real orders will differ. Do not list what you changed or
|
|
207
|
+
what doctor checked. Send nothing after it. Do not add containers, services,
|
|
208
|
+
workers or cron jobs: the module's scheduled action runs inside Odoo.
|
|
209
|
+
|
|
210
|
+
## Non-negotiables
|
|
211
|
+
|
|
212
|
+
- Never print, log or commit a code, never put one in a shell argument, and
|
|
213
|
+
never write one into source files, Odoo's config file, the database or
|
|
214
|
+
browser code. Doctor's present/missing is all you report.
|
|
215
|
+
- Do not suggest rotating, revoking or replacing a code because it was pasted
|
|
216
|
+
into this chat; that is the supported path.
|
|
217
|
+
- Work only in this Odoo. Never read or run anything from another project or
|
|
218
|
+
directory on this machine (its `node_modules`, tools or source), for any
|
|
219
|
+
reason. A browser, Playwright, hand-made calls to the checkout's routes,
|
|
220
|
+
database queries and reading the module's source are not part of setup:
|
|
221
|
+
when doctor or `test-invoice` fails, report its output.
|
|
222
|
+
- Receive-only NWC is required. Never get past the preflight with a code that
|
|
223
|
+
can spend.
|
|
224
|
+
- The module owns only its two payment tables and its settings table in
|
|
225
|
+
Odoo's database. Odoo owns customers, orders, invoices, prices and email.
|
|
226
|
+
Do not add an external payment database or custom fulfillment code, and do
|
|
227
|
+
not edit Odoo's own files or modules. The Dockerfile that adds the Python
|
|
228
|
+
package and the one Compose line that builds it are the only deployment
|
|
229
|
+
change.
|
|
230
|
+
- IF SWAPS ARE ON, KEEP THE ROUTE BACK. A deposit that arrives short or late
|
|
231
|
+
becomes refundable, and the customer claims it later from the same
|
|
232
|
+
transaction's checkout page. Keep the module installed while swap payments
|
|
233
|
+
may still need a refund. https://openreceive.org/guides/swap-refunds.md
|
|
234
|
+
- A receive-only wallet cannot send refunds. Refund a settled payment manually
|
|
235
|
+
from the wallet.
|
|
236
|
+
|
|
237
|
+
## Further reading
|
|
238
|
+
|
|
239
|
+
- [Odoo Quickstart](https://openreceive.org/guides/quickstart-odoo.md)
|
|
240
|
+
- [Automated Swaps](https://openreceive.org/guides/automated-swaps.md)
|
|
241
|
+
- [Swap Refunds](https://openreceive.org/guides/swap-refunds.md)
|
|
242
|
+
- [Lightning Swap Connect URI](https://openreceive.org/guides/lightning-swap-connect.md)
|
|
243
|
+
- [Security](https://openreceive.org/guides/security.md)
|
|
244
|
+
- [Price Feeds](https://openreceive.org/guides/price-feeds.md)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## The quickstart, in full
|
|
249
|
+
|
|
250
|
+
Inlined verbatim so this file needs no network access. Steps 0–3 above are the setup and this is their reference: where the two differ, the steps win, and its provider-form screens are only for an Odoo with no shell.
|
|
251
|
+
The page it comes from is https://openreceive.org/guides/quickstart-odoo.
|
|
252
|
+
|
|
253
|
+
## Odoo quickstart
|
|
254
|
+
|
|
255
|
+
[Odoo](https://www.odoo.com) runs shops, sales and invoicing. The OpenReceive
|
|
256
|
+
module adds a payment provider to it: the customer pays an online order, or an
|
|
257
|
+
invoice's payment link, with Bitcoin over Lightning, straight into your own
|
|
258
|
+
wallet, on a checkout page of your own site. With a swap provider, the same
|
|
259
|
+
page also takes USDT, USDC, SOL and ETH, which the provider converts to BTC
|
|
260
|
+
over Lightning into the same wallet.
|
|
261
|
+
|
|
262
|
+
Odoo keeps owning customers, orders, invoices and prices. The module keeps its
|
|
263
|
+
payment attempts in two tables of Odoo's own PostgreSQL database. When a
|
|
264
|
+
payment settles, it marks Odoo's payment transaction done in the same database
|
|
265
|
+
transaction that settles the payment, then runs Odoo's own post-processing:
|
|
266
|
+
the order is confirmed, or the invoice paid, and Odoo sends its emails as it
|
|
267
|
+
does for any other provider.
|
|
268
|
+
|
|
269
|
+
Requirements: Odoo 19 or 20, self-hosted or on Odoo.sh, and the `openreceive`
|
|
270
|
+
Python package at the module's version. Odoo Online cannot install modules, so
|
|
271
|
+
it cannot run this one. A shop that already runs BTCPay Server can use
|
|
272
|
+
[Odoo via BTCPay Server](https://openreceive.org/guides/odoo.md) instead.
|
|
273
|
+
|
|
274
|
+
### Install the module
|
|
275
|
+
|
|
276
|
+
Each GitHub release attaches the module as `openreceive-odoo-<version>.zip`,
|
|
277
|
+
with its folder, `payment_openreceive`, at the top. Unzip it into a folder on
|
|
278
|
+
Odoo's addons path, install the Python package where Odoo's Python finds it,
|
|
279
|
+
restart Odoo, and install **Payment Provider: OpenReceive** under **Apps**, or
|
|
280
|
+
from a terminal:
|
|
281
|
+
|
|
282
|
+
```sh
|
|
283
|
+
cd /path/to/your/addons
|
|
284
|
+
curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.31/openreceive-odoo-0.4.31.zip
|
|
285
|
+
unzip -oq openreceive-odoo-0.4.31.zip && rm openreceive-odoo-0.4.31.zip
|
|
286
|
+
odoo -d <database> -i payment_openreceive --stop-after-init
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
How the Python package gets in depends on how Odoo runs:
|
|
290
|
+
|
|
291
|
+
- **Odoo.sh**: commit the `payment_openreceive` folder to your repository and
|
|
292
|
+
add `openreceive==0.4.31` to the repository's `requirements.txt`.
|
|
293
|
+
- **A source install with a virtualenv**: `pip install openreceive==0.4.31`
|
|
294
|
+
in Odoo's virtualenv.
|
|
295
|
+
- **Odoo's Docker image** or **its Debian package**: see below.
|
|
296
|
+
|
|
297
|
+
Installing the module creates its two tables, its payment provider,
|
|
298
|
+
"OpenReceive", with the payment method buyers pick, "Bitcoin Lightning", and a
|
|
299
|
+
scheduled action that records payments made after the customer left. The
|
|
300
|
+
provider stays hidden from customers until a wallet code is saved and you
|
|
301
|
+
publish it.
|
|
302
|
+
|
|
303
|
+
#### Odoo in Docker
|
|
304
|
+
|
|
305
|
+
Odoo's official image keeps its Python packages under the system's package
|
|
306
|
+
manager. Build your own image on top of it: put this `Dockerfile` next to your
|
|
307
|
+
`compose.yml`, with the same tag as your image,
|
|
308
|
+
|
|
309
|
+
```dockerfile
|
|
310
|
+
FROM odoo:19.0
|
|
311
|
+
USER root
|
|
312
|
+
RUN pip3 install --no-cache-dir --break-system-packages --ignore-installed typing_extensions h11 \
|
|
313
|
+
&& pip3 install --no-cache-dir --break-system-packages openreceive==0.4.31
|
|
314
|
+
USER odoo
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
and in `compose.yml` replace the Odoo service's `image:` line with
|
|
318
|
+
`build: .`, then run `docker compose up -d --build`. The first `pip3` line
|
|
319
|
+
installs two packages beside the system's own copies, which pip cannot
|
|
320
|
+
replace; Odoo keeps using the system's other packages, its `cryptography`
|
|
321
|
+
included. Your database and the module folder you mount at
|
|
322
|
+
`/mnt/extra-addons` stay as they are.
|
|
323
|
+
|
|
324
|
+
Run Odoo's commands through the image's entrypoint, which adds the database
|
|
325
|
+
connection: `docker compose exec odoo /entrypoint.sh odoo <arguments>`. To
|
|
326
|
+
install the module from a terminal:
|
|
327
|
+
|
|
328
|
+
```sh
|
|
329
|
+
docker compose exec odoo /entrypoint.sh odoo -d <database> -i payment_openreceive --stop-after-init --no-http
|
|
330
|
+
docker compose restart odoo
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Configure the wallet
|
|
334
|
+
|
|
335
|
+
You need a receive-only NWC code: a Nostr Wallet Connect code that can create
|
|
336
|
+
invoices and read payments but cannot spend. The module refuses a code that
|
|
337
|
+
can spend.
|
|
338
|
+
|
|
339
|
+
In **Invoicing** (or **Website**) → **Configuration** → **Payment Providers**,
|
|
340
|
+
open **OpenReceive**. Paste the code into **Receive-only NWC code** and save.
|
|
341
|
+
To accept stablecoins too, paste a swap provider code into **Swap provider
|
|
342
|
+
code**. Saving asks the wallet first and keeps the code only when the wallet
|
|
343
|
+
answers as receive-only. The codes go to the module's own table, which no Odoo
|
|
344
|
+
screen lists, and the form never shows them again; it says only whether each
|
|
345
|
+
is saved. Then publish the provider (Odoo 19: State **Enabled**; Odoo 20:
|
|
346
|
+
**Live** and **Published**).
|
|
347
|
+
|
|
348
|
+
From a terminal, pipe each code into `odoo openreceive configure` from your
|
|
349
|
+
secret manager or a protected file. Never type a code as a command argument:
|
|
350
|
+
|
|
351
|
+
```sh
|
|
352
|
+
odoo openreceive configure --nwc-uri=- -d <database> < /secure/path/wallet-code
|
|
353
|
+
odoo openreceive configure --lsc-uri-primary=- -d <database> < /secure/path/swap-code
|
|
354
|
+
odoo openreceive configure --enable -d <database>
|
|
355
|
+
odoo openreceive doctor -d <database>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
In Docker, start each with `docker compose exec -T odoo /entrypoint.sh`; `-T`
|
|
359
|
+
passes the file through. `--enable` publishes the provider in every company.
|
|
360
|
+
Saving a swap code renames the payment method "Bitcoin & stablecoins"; a name
|
|
361
|
+
you gave it yourself stays. Skip the swap code for Bitcoin-only checkout.
|
|
362
|
+
|
|
363
|
+
`doctor` checks the module and the Python package versions, each code as set
|
|
364
|
+
or unset (never its value), the wallet, the tables, the provider in each
|
|
365
|
+
company, the payment method, the checkout's files, the scheduled action, the
|
|
366
|
+
price feed for each company's currency and the swap provider. It exits nonzero
|
|
367
|
+
when a check fails.
|
|
368
|
+
|
|
369
|
+
One wallet serves the whole database: every company's OpenReceive provider
|
|
370
|
+
uses the codes saved last.
|
|
371
|
+
|
|
372
|
+
### Check it
|
|
373
|
+
|
|
374
|
+
Make a Lightning invoice through the same route the checkout page uses, for a
|
|
375
|
+
new $5 test transaction, or for any unpaid OpenReceive transaction by its
|
|
376
|
+
reference:
|
|
377
|
+
|
|
378
|
+
```sh
|
|
379
|
+
odoo openreceive test-invoice --new -d <database>
|
|
380
|
+
odoo openreceive test-invoice --reference S00012-1 -d <database>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`--new` creates a draft payment transaction for a test contact it creates
|
|
384
|
+
once, `openreceive-test@example.invalid`, with no order behind it, so no
|
|
385
|
+
customer sees it. `--amount=` changes the amount, in the company's currency.
|
|
386
|
+
It prints the amount in sats, the Lightning invoice, then each method the
|
|
387
|
+
checkout offers: Bitcoin Lightning, and each swap asset with its network and
|
|
388
|
+
whether it is available for this amount. A small amount is often below a swap
|
|
389
|
+
provider's minimum; that is the amount, not a fault.
|
|
390
|
+
|
|
391
|
+
### How a payment works
|
|
392
|
+
|
|
393
|
+
1. The customer picks OpenReceive on Odoo's payment step, at checkout or on an
|
|
394
|
+
invoice's payment link, and clicks **Pay**. Odoo creates its payment
|
|
395
|
+
transaction and sends the customer to the module's checkout page for it.
|
|
396
|
+
2. The module charges the transaction's amount, in its currency, converted to
|
|
397
|
+
sats at the current BTC price. Only the browser session that started the
|
|
398
|
+
payment can see its checkout page and make or follow its invoice: Odoo
|
|
399
|
+
records that transaction in the session, as its own payment status page
|
|
400
|
+
does.
|
|
401
|
+
3. Once the wallet reports the payment, the module marks the transaction done
|
|
402
|
+
and runs Odoo's post-processing in the same database transaction that
|
|
403
|
+
settles it: the order is confirmed or the invoice paid. Should the
|
|
404
|
+
post-processing fail, the transaction stays done and Odoo's own scheduled
|
|
405
|
+
action finishes it.
|
|
406
|
+
4. The checkout takes the customer to Odoo's payment status page, which takes
|
|
407
|
+
them on to the order's confirmation.
|
|
408
|
+
|
|
409
|
+
The checkout asks the wallet while the page is open. If the customer closes it
|
|
410
|
+
before the payment settles, the module's scheduled action finds the payment
|
|
411
|
+
within a minute. `odoo openreceive reconcile -d <database>` runs one pass by
|
|
412
|
+
hand.
|
|
413
|
+
|
|
414
|
+
A customer who reloads the checkout page gets the same Lightning invoice
|
|
415
|
+
again while it is still valid. Paying again from the order starts a new Odoo
|
|
416
|
+
transaction with its own invoice; the earlier invoice still counts if paid.
|
|
417
|
+
|
|
418
|
+
Odoo's log records each settlement under `odoo.addons.payment_openreceive`.
|
|
419
|
+
|
|
420
|
+
### Refunds and removal
|
|
421
|
+
|
|
422
|
+
The receive-only wallet cannot send refunds. Send a refund from your own
|
|
423
|
+
wallet, then record it in Odoo. A customer whose swap deposit never converted
|
|
424
|
+
reclaims it from the same transaction's checkout page, while the transaction
|
|
425
|
+
is still unpaid. If you turn on swaps, you commit to keeping that path
|
|
426
|
+
available. See [swap refunds](https://openreceive.org/guides/swap-refunds.md).
|
|
427
|
+
|
|
428
|
+
Uninstalling the module deletes the saved codes and keeps the two payment
|
|
429
|
+
tables, which are a record of payments received. Odoo keeps the provider and
|
|
430
|
+
its transactions, as it does for any provider whose module is removed.
|
|
431
|
+
|
|
432
|
+
### Tested, and not tested
|
|
433
|
+
|
|
434
|
+
Tested on 2026-10-19 with Odoo 19 and Odoo 20 from their official Docker
|
|
435
|
+
images, PostgreSQL 17, a test wallet and a test swap provider: install from
|
|
436
|
+
the built ZIP, configure from stdin and from the provider form, the doctor,
|
|
437
|
+
`test-invoice --new`, and a signed-in customer ordering through the shop and
|
|
438
|
+
paying by Lightning and by USDT on Solana in Chromium, after which the sale
|
|
439
|
+
order is confirmed. A payment whose page was closed was recorded by the
|
|
440
|
+
scheduled action. Another customer, a visitor and a request without Odoo's
|
|
441
|
+
CSRF token were refused. The module's own tests run on both series.
|
|
442
|
+
|
|
443
|
+
Not tested: Odoo.sh, Odoo's Debian package, paying an invoice from its
|
|
444
|
+
payment link, multi-company shops, and Odoo 18 or older, which the module does
|
|
445
|
+
not install on. Lightning cannot pull a payment, so
|
|
446
|
+
OpenReceive offers no subscriptions or saved payment tokens.
|
|
@@ -17,7 +17,7 @@ curl -fsSL https://openreceive.org/agent-directions/paymenter/full.md
|
|
|
17
17
|
- Do not suggest rotating or revoking a code because it was pasted here.
|
|
18
18
|
- Setup is done only when the NWC code is saved, and the LSC code is saved or the user said "Bitcoin only".
|
|
19
19
|
|
|
20
|
-
These directions describe OpenReceive 0.4.
|
|
20
|
+
These directions describe OpenReceive 0.4.31.
|
|
21
21
|
|
|
22
22
|
Install and configure the OpenReceive payment gateway in the Paymenter billing
|
|
23
23
|
panel you are working in. Preserve its theme, clients, products, invoices and
|
|
@@ -97,7 +97,7 @@ release. With Paymenter's official Docker image, download and unpack it inside
|
|
|
97
97
|
the container, as the web user:
|
|
98
98
|
|
|
99
99
|
```sh
|
|
100
|
-
docker compose exec -T -u nginx paymenter sh -c 'cd /app/extensions/Gateways && curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.
|
|
100
|
+
docker compose exec -T -u nginx paymenter sh -c 'cd /app/extensions/Gateways && curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.31/openreceive-paymenter-0.4.31.zip && unzip -q openreceive-paymenter-0.4.31.zip && rm openreceive-paymenter-0.4.31.zip'
|
|
101
101
|
docker compose exec -T -u nginx paymenter php artisan app:extension:install gateway OpenReceive
|
|
102
102
|
```
|
|
103
103
|
|
|
@@ -207,7 +207,6 @@ Paymenter's scheduler has never run, say so in one line of that message.
|
|
|
207
207
|
- [Lightning Swap Connect URI](https://openreceive.org/guides/lightning-swap-connect.md)
|
|
208
208
|
- [Security](https://openreceive.org/guides/security.md)
|
|
209
209
|
- [Price Feeds](https://openreceive.org/guides/price-feeds.md)
|
|
210
|
-
- [Payment Safety Upgrade](https://openreceive.org/guides/payment-safety-upgrade.md)
|
|
211
210
|
|
|
212
211
|
---
|
|
213
212
|
|
|
@@ -243,9 +242,9 @@ directory, next to Stripe and PayPal:
|
|
|
243
242
|
|
|
244
243
|
```sh
|
|
245
244
|
cd /var/www/paymenter
|
|
246
|
-
curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.
|
|
247
|
-
unzip -q openreceive-paymenter-0.4.
|
|
248
|
-
rm openreceive-paymenter-0.4.
|
|
245
|
+
curl -fsSLO https://github.com/OpenReceive/openreceive/releases/download/v0.4.31/openreceive-paymenter-0.4.31.zip
|
|
246
|
+
unzip -q openreceive-paymenter-0.4.31.zip -d extensions/Gateways
|
|
247
|
+
rm openreceive-paymenter-0.4.31.zip
|
|
249
248
|
chown -R www-data:www-data extensions/Gateways/OpenReceive
|
|
250
249
|
sudo -u www-data php artisan app:extension:install gateway OpenReceive
|
|
251
250
|
```
|