diff --git a/README.md b/README.md index 15748c7..43ab768 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ Events includes a shareable ticket scanner, which can be used to register attend 1. Create an event\ ![create event](https://i.imgur.com/dadK1dp.jpg) 2. Fill out the event information: - - event name - wallet (normally there's only one) - event information @@ -34,7 +33,6 @@ Events includes a shareable ticket scanner, which can be used to register attend 3. Share the event registration link\ ![event ticket](https://imgur.com/AQWUOBY.jpg) - - ticket example\ ![ticket example](https://i.imgur.com/trAVSLd.jpg) @@ -44,6 +42,31 @@ Events includes a shareable ticket scanner, which can be used to register attend 4. Use the built-in ticket scanner to validate registered, and paid, attendees\ ![ticket scanner](https://i.imgur.com/zrm9202.jpg) +## Guest checkout, card payments and email delivery (aio fork) + +- **Identity.** `POST /events/api/v1/tickets/{event_id}` accepts either an + LNbits `user_id` or a guest `name` + `email`; a `user_id` ticket may also + carry an `email` so logged-in buyers get their ticket mailed. +- **Payment methods.** `extra.payment_methods` (`lightning`, `fiat`) lists the + rails an event accepts; an empty list keeps the legacy rule (Lightning always, + fiat when `allow_fiat`). The effective list is published on the NIP-52 event + as `tickets_payment_methods` and enforced at purchase. +- **Return to the calling app.** A client may send `frontend_url` (its app + root, e.g. `https://app.example/events`). Its origin must be one of + `LNBITS_CORS_ALLOWED_ORIGINS`, the LNbits base URL or + `LNBITS_CUSTOM_FRONTEND_URL`, otherwise the request is refused. Under that + root the extension builds the Stripe `success_url` + (`/events/{event_id}?checkout=success&tickets=`), `cancel_url` + (`/events/{event_id}?checkout=cancelled`) and the emailed ticket link + (`/events/ticket/{ticket_id}`). Absent, the LNbits host is used as before. +- **Stripe session.** The buyer's email is passed as `customer_email` + (prefilled and locked on the hosted page); the line item is named after the + event; `event_id`, `quantity` and `ticket_ids` ride along as metadata. +- **Email.** Multipart text + HTML with the ticket QR embedded from + `GET /events/api/v1/qr/{ticket_id}` (PNG, branded with the instance QR logo). + `POST /events/api/v1/tickets/{ticket_id}/resend-email` returns a + `TicketResendResult` with per-channel outcome. + ## Powered by LNbits [LNbits](https://lnbits.com) is a free and open-source lightning accounts system. diff --git a/config.json b/config.json index 02272e3..330240f 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { "id": "events", - "version": "1.6.1-aio.7", + "version": "1.6.1-aio.8", "name": "Events", "repo": "https://git.atitlan.io/aiolabs/events", "short_description": "Sell and register event tickets", diff --git a/docs/upstream-candidates.md b/docs/upstream-candidates.md new file mode 100644 index 0000000..b3246c2 --- /dev/null +++ b/docs/upstream-candidates.md @@ -0,0 +1,17 @@ +# Upstream PR candidates + +Running log of fork features that are shaped so they could be offered to +`lnbits/events` (or `lnbits/lnbits`). Add a row whenever a change lands here +in an upstream-compatible form; strike it when the PR merges upstream. + +| Feature | Where | Upstream target | Readiness | +| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| `frontend_url` + origin allow-list + `?checkout=` return contract | `views_api.py` `_resolve_frontend_root`, `api_ticket_create` | lnbits/events | after the #33 rebase, as a small PR | +| Ticket ids minted before the invoice so `success_url` can carry them | `api_ticket_create` | lnbits/events | ships with the above | +| `extra.checkout` (success/cancel URL, `customer_email`, line item, metadata) on fiat purchases | `api_ticket_create` | lnbits/events (needs lnbits `StripeCheckoutOptions.cancel_url`/`customer_email`, PR'd from aiolabs/lnbits) | with the lnbits patch | +| `extra.payment_methods` per event + `tickets_payment_methods` NIP-52 tag | `models.py`, `nostr_publisher.py` | lnbits/events (v2 PR #64 introduces the same field) | offer as review input on #64 | +| `asyncio.to_thread` around the smtplib send | `services.py` `_send_ticket_email_notification` | lnbits/events | trivial, standalone | +| QR logo overlay in `make_qr_png` (instance `lnbits_qr_logo`) | `views_api.py` | lnbits/events | standalone | +| Multi-ticket purchase as N rows on one `payment_hash` | `api_ticket_create`, `crud.py` | lnbits/events | overlaps v2 baskets; review input on #64 | +| Free tickets without minting an invoice | `_issue_free_tickets` | lnbits/events | small, standalone | +| NIP-52 publishing + approval workflow | `nostr_*.py`, `views_api.py` | lnbits/events #46 | open; rebase onto v1.6.8 |