Add configurable LNbits invoice memos and pubkey metadata

Read INVOICE_MEMO_YEARLY and INVOICE_MEMO_LIFETIME from the environment
and pass the user pubkey in LNbits payment extra for invoice creation.
This commit is contained in:
2026-05-06 19:52:07 +00:00
parent fe2b95258d
commit 43d78862e3
5 changed files with 33 additions and 24 deletions

View File

@@ -20,6 +20,8 @@ LNBITS_INVOICE_KEY=your-lnbits-invoice-read-key
PRICE_YEARLY_SATS=1000 PRICE_YEARLY_SATS=1000
PRICE_LIFETIME_SATS=10000 PRICE_LIFETIME_SATS=10000
INVOICE_EXPIRY_MINUTES=30 INVOICE_EXPIRY_MINUTES=30
INVOICE_MEMO_YEARLY=Noderunners Relay yearly Access
INVOICE_MEMO_LIFETIME=Noderunners Relay lifetime Access
# --- Nostr --- # --- Nostr ---
RELAYS=wss://relay.azzamo.net,wss://nostr.azzamo.net,wss://wot.azzamo.net RELAYS=wss://relay.azzamo.net,wss://nostr.azzamo.net,wss://wot.azzamo.net

View File

@@ -102,6 +102,8 @@ func run() error {
YearlySats: cfg.Lightning.PriceYearlySats, YearlySats: cfg.Lightning.PriceYearlySats,
LifetimeSats: cfg.Lightning.PriceLifetimeSats, LifetimeSats: cfg.Lightning.PriceLifetimeSats,
ExpiryMins: cfg.Lightning.InvoiceExpiryMins, ExpiryMins: cfg.Lightning.InvoiceExpiryMins,
MemoYearly: cfg.Lightning.InvoiceMemoYearly,
MemoLifetime: cfg.Lightning.InvoiceMemoLifetime,
}, cfg.Domain) }, cfg.Domain)
} }

View File

@@ -16,6 +16,8 @@ type LightningConfig struct {
PriceYearlySats int64 PriceYearlySats int64
PriceLifetimeSats int64 PriceLifetimeSats int64
InvoiceExpiryMins int InvoiceExpiryMins int
InvoiceMemoYearly string
InvoiceMemoLifetime string
} }
type NostrConfig struct { type NostrConfig struct {
@@ -83,6 +85,8 @@ func Load() (*Config, error) {
PriceYearlySats: int64(envInt("PRICE_YEARLY_SATS", 1000)), PriceYearlySats: int64(envInt("PRICE_YEARLY_SATS", 1000)),
PriceLifetimeSats: int64(envInt("PRICE_LIFETIME_SATS", 10000)), PriceLifetimeSats: int64(envInt("PRICE_LIFETIME_SATS", 10000)),
InvoiceExpiryMins: envInt("INVOICE_EXPIRY_MINUTES", 30), InvoiceExpiryMins: envInt("INVOICE_EXPIRY_MINUTES", 30),
InvoiceMemoYearly: env("INVOICE_MEMO_YEARLY", "Noderunners Relay yearly Access"),
InvoiceMemoLifetime: env("INVOICE_MEMO_LIFETIME", "Noderunners Relay lifetime Access"),
}, },
Nostr: NostrConfig{ Nostr: NostrConfig{
Relays: csv(env("RELAYS", "")), Relays: csv(env("RELAYS", "")),

View File

@@ -30,6 +30,7 @@ type createReq struct {
Amount int64 `json:"amount"` Amount int64 `json:"amount"`
Memo string `json:"memo"` Memo string `json:"memo"`
Expiry int `json:"expiry,omitempty"` Expiry int `json:"expiry,omitempty"`
Extra map[string]string `json:"extra,omitempty"`
} }
type createResp struct { type createResp struct {
@@ -47,8 +48,8 @@ type statusResp struct {
} `json:"details"` } `json:"details"`
} }
func (c *LNbitsClient) Create(ctx context.Context, amountSats int64, memo string, expirySecs int) (string, string, error) { func (c *LNbitsClient) Create(ctx context.Context, amountSats int64, memo string, expirySecs int, extra map[string]string) (string, string, error) {
body, err := json.Marshal(createReq{Out: false, Amount: amountSats, Memo: memo, Expiry: expirySecs}) body, err := json.Marshal(createReq{Out: false, Amount: amountSats, Memo: memo, Expiry: expirySecs, Extra: extra})
if err != nil { if err != nil {
return "", "", err return "", "", err
} }

View File

@@ -20,6 +20,8 @@ type Pricing struct {
YearlySats int64 YearlySats int64
LifetimeSats int64 LifetimeSats int64
ExpiryMins int ExpiryMins int
MemoYearly string
MemoLifetime string
} }
type Service struct { type Service struct {
@@ -131,17 +133,15 @@ func (s *Service) Create(ctx context.Context, req CreateRequest) (*PendingInvoic
} }
amount := s.pricing.YearlySats * int64(req.Years) amount := s.pricing.YearlySats * int64(req.Years)
memo := s.pricing.MemoYearly
if req.SubscriptionType == user.SubLifetime { if req.SubscriptionType == user.SubLifetime {
amount = s.pricing.LifetimeSats amount = s.pricing.LifetimeSats
} memo = s.pricing.MemoLifetime
memo := fmt.Sprintf("%s@%s", username, s.domain)
if isRenewal {
memo = "renewal: " + memo
} }
expirySecs := s.pricing.ExpiryMins * 60 expirySecs := s.pricing.ExpiryMins * 60
hash, request, err := s.lnbits.Create(ctx, amount, memo, expirySecs) extra := map[string]string{"pubkey": req.Pubkey}
hash, request, err := s.lnbits.Create(ctx, amount, memo, expirySecs, extra)
if err != nil { if err != nil {
return nil, err return nil, err
} }