PaymentProvider
Driver di pagamento: Code, Capabilities, CreatePayment, ParseWebhook, Refund. Vedi
Driver di pagamento.
Le interfacce del pacchetto pkg/ext sono le uniche API Go stabili per chi estende il core: cambiarle è un
cambiamento incompatibile. Tutto ciò che sta in internal/ può cambiare senza preavviso. pkg/ext non importa
nulla di internal/, quindi un’estensione dipende solo da tipi pubblici.
type Extensions struct { PaymentProviders []PaymentProvider // aggiunti a "manual" e "stripe"; stesso Code = sostituisce FiscalDrivers []FiscalDriver // aggiunti a "none" EventSinks []EventSink // ricevono ogni evento dopo l'outbox (almeno una volta) ConcessionData ConcessionDataProvider // perimetro, immagini, scadenze della concessione TenantResolver TenantResolver // stabilimento da host/header (domini personalizzati) AuthProviders []AuthProvider // accesso esterno, es. OIDC Notifiers []Notifier // canali oltre l'email: SMS, WhatsApp BotProtection BotProtection // challenge invisibile sulle creazioni pubbliche EventBus EventBus // bus in tempo reale, es. PostgreSQL LISTEN/NOTIFY HTTPRoutes func(r chi.Router) // rotte aggiuntive (non su /api/admin/v1, /api/public/v1, /admin, /b) AdminUIPlugins []UIPluginManifest // voci di menu e pagine nel pannello}Il binario ufficiale usa le sole implementazioni del core. Per aggiungere le tue, compila un tuo main che le
registra:
package main
import ( "context" "log"
"github.com/coste360/arenile/internal/app" "github.com/coste360/arenile/internal/config" "github.com/coste360/arenile/pkg/ext"
"example.com/arenile-satispay")
func main() { cfg, err := config.FromEnv() if err != nil { log.Fatal(err) } a, err := app.New(cfg, app.WithExtensions(ext.Extensions{ PaymentProviders: []ext.PaymentProvider{satispay.New()}, })) if err != nil { log.Fatal(err) } defer a.Close() if err := a.Run(context.Background()); err != nil { log.Fatal(err) }}PaymentProvider
Driver di pagamento: Code, Capabilities, CreatePayment, ParseWebhook, Refund. Vedi
Driver di pagamento.
FiscalDriver
Emissione dei documenti commerciali: Code, Issue, Void, Status. Le righe derivano dallo snapshot del
prezzo (importi lordi, aliquote in punti base: 2200 = 22%).
EventSink
Name, Handle(ctx, Event): riceve ogni evento di dominio dopo l’outbox. Deve essere idempotente sull’id.
EventBus
Publish, Subscribe: sostituisce il bus in memoria del tempo reale, per più istanze in parallelo.
Notifier
Channel, Send: nuovi canali di notifica accanto all’email.
AuthProvider
Code, DisplayName, BeginLogin, CompleteLogin: accesso con un identity provider esterno.
TenantResolver
ResolveSlug(r): risolve lo stabilimento della pagina pubblica dal dominio (es. prenota.lido-a.it).
ConcessionDataProvider
Lookup(ctx, ref): dati della concessione demaniale da fonti esterne.
BotProtection
ClientConfig, Verify: challenge invisibile senza servizi imposti.
UIPluginManifest
Voci di menu (etichette per lingua, italiano obbligatorio) e un URL di pagina caricata in un’area dedicata del pannello.
type Event struct { ID string `json:"id"` // "evt_<uuidv7>" Type string `json:"type"` // es. "booking.confirmed" EstablishmentID string `json:"establishment_id"` OccurredAt time.Time `json:"occurred_at"` Data json.RawMessage `json:"data"` // payload versionato Version int `json:"version"`}L’elenco dei tipi è in Eventi e webhook in uscita.
int64 in centesimi, mai float.EventSink lento non blocca il core, ma deve gestire da sé i propri tentativi e l’idempotenza.