Agile Payment Services
Documentazione tecnica completa per l'integrazione dei microservizi di pagamento, fatturazione elettronica e trasmissione SDI — piattaforma 231 Agile.
Il sistema di pagamento e fatturazione Agile è composto da quattro microservizi coordinati. Ogni componente può essere usato in modo indipendente o come parte del flusso end-to-end acquisto → fattura → SDI.
billing-ms
Abbonamenti, pacchetti onboarding, Stripe Checkout, compliance scheduler settimanale, FatturaPA automatica, impostazioni piattaforma.
payment-ms v2
Multi-provider: Revolut Pay, Open Banking, SEPA Direct Debit, Stripe. Configurazione per-tenant con chiavi cifrate AES-256.
FatturaPA Service
Generazione XML FatturaPA 1.2.2 (TD01, TD04…), validazione schema. Auth: X-API-Key infragruppo.
SDI Service
Trasmissione fatture allo SDI via OpenAPI.it. Polling stato, ricevute AT/MC/NS. Idempotente su numero fattura.
/health e /webhooks/) richiedono autenticazione
dual-header: X-API-Key (tenant API key) + Authorization: Bearer {JWT}.
X-API-Key: lg231-demo-api-key-2026-secure Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json
| Header | Obbligatorio | Descrizione |
|---|---|---|
X-API-Key | REQUIRED | API Key del tenant — identifica e autentica il tenant |
Authorization | REQUIRED | JWT Bearer — contiene user_id, tenant_id, role |
Content-Type | required per POST/PUT | Deve essere application/json |
Stripe-Signature | solo webhook Stripe | Header HMAC inviato automaticamente da Stripe |
X-Cron-Secret | solo cron endpoint | Secret condiviso per proteggere il cron job |
| Servizio | URL Esterno (HTTPS) | Porta Docker |
|---|---|---|
| billing-ms | https://lg231.certisource.it/api/billing/ | 3058 |
| payment-ms v2 | https://[app].certisource.it/api/payment/ | per app |
| FatturaPA Service | https://certisource.it/fattura-service.php | — |
| SDI Service | https://certisource.it/sdi-service.php | — |
GET /health senza autenticazione.
billing-ms:
curl https://lg231.certisource.it/api/billing/healthCheckout Stripe
POST /billing/checkout/{n} — billing-ms crea una Stripe Checkout Session
e restituisce checkout_url. Il frontend redirige il cliente.
Webhook Stripe
POST /billing/webhook — Stripe invia checkout.session.completed.
billing-ms verifica la firma, marca il pacchetto paid, poi chiama automaticamente
generateFattura().
Generazione FatturaPA
POST https://certisource.it/fattura-service.php?action=genera —
billing-ms invia cedente + cessionario + righe. Il servizio ritorna XML FatturaPA 1.2.2
in base64 + hash_sha256.
Salvataggio XML
billing-ms salva fattura_xml, fattura_hash, fattura_numero
e fattura_at nella tabella billing_packages.
Download XML (opzionale)
GET /billing/fattura/{packageId} — restituisce l'XML come file scaricabile
con header Content-Disposition: attachment.
Trasmissione SDI (opzionale)
POST https://certisource.it/sdi-service.php?action=trasmetti —
invia l'XML allo SDI via OpenAPI.it. Risponde con sdi_id per polling stato.
https://lg231.certisource.it/api/billingStato abbonamento del tenant corrente: subscription, pacchetti, scadenze.
curl https://lg231.certisource.it/api/billing/billing/status \ -H "X-API-Key: {API_KEY}" \ -H "Authorization: Bearer {JWT}"
{
"success": true,
"data": {
"subscription": {
"id": 1, "status": "trial",
"trial_ends_at": "2026-05-01T00:00:00Z",
"packages_completed": 2, "packages_total": 8
},
"packages": [ /* array 8 pacchetti */ ],
"days_remaining": 60
}
}
Crea una Stripe Checkout Session per il pacchetto n (1-8) — €150. Ritorna checkout_url a cui redirigere il browser.
curl https://lg231.certisource.it/api/billing/billing/checkout/1 \ -H "X-API-Key: {API_KEY}" \ -H "Authorization: Bearer {JWT}" \ -H "Content-Type: application/json" \ -X POST
{
"success": true,
"data": { "checkout_url": "https://checkout.stripe.com/c/pay/cs_..." }
}
Webhook Stripe. Gestisce checkout.session.completed: marca pacchetto paid e genera FatturaPA automaticamente. Deve rispondere sempre HTTP 200.
https://lg231.certisource.it/api/billing/billing/webhookScarica il file XML FatturaPA del pacchetto. Risponde con Content-Type: application/xml e header Content-Disposition: attachment.
curl -o fattura.xml \ https://lg231.certisource.it/api/billing/billing/fattura/1 \ -H "X-API-Key: {API_KEY}" \ -H "Authorization: Bearer {JWT}"
Legge o aggiorna le impostazioni della piattaforma: dati cedente FatturaPA (P.IVA, indirizzo, regime fiscale…) e IBAN incasso. I valori sono salvati nel DB con priorità su .env.
{
"cedente_piva": "07776161213",
"cedente_nome": "Agile Technology SRL",
"cedente_indirizzo": "Via Roma 1",
"cedente_cap": "80100",
"cedente_comune": "Napoli",
"cedente_provincia": "NA",
"cedente_iban": "IT60X0542811101000000123456",
"cedente_regime": "RF01",
"bonifico_iban": "IT60X0542811101000000123456",
"bonifico_bic": "SELBIT2BXXX",
"bonifico_beneficiario":"231 Agile"
}
{
"fattura_ready": true,
"bonifico_ready": true,
"fattura_api_key_set": true,
"settings": { /* tutte le chiavi con label e source (db|env|empty) */ }
}
Verifica compliance settimanale: sospende tenant che hanno saltato una settimana, scade trial expirate. Da eseguire 1 volta/giorno via cron.
# /etc/cron.d/lg231-billing — ogni giorno alle 08:00 0 8 * * * root curl -s -X POST \ http://127.0.0.1:3058/billing/cron/check-compliance \ -H "X-Cron-Secret: {CRON_SECRET}" \ >> /var/log/lg231-billing-cron.log 2>&1
Restituisce i metodi di pagamento disponibili per il provider configurato del tenant, con label, icone e disponibilità SEPA.
{
"provider": "revolut",
"methods": [
{ "id": "revolut_pay", "label": "Revolut Pay", "recommended": true },
{ "id": "open_banking", "label": "Open Banking", "recommended": false },
{ "id": "sepa_debit", "label": "SEPA Direct Debit", "recommended": false }
]
}
Crea un link di pagamento via Revolut Pay, Open Banking o carta. Ritorna payment_url a cui redirigere il cliente.
{
"amount": 15000, // centesimi (€150.00)
"currency": "EUR",
"description": "Pacchetto Onboarding 231 #3",
"reference": "PKG-2026-003",
"method": "revolut_pay", // revolut_pay | open_banking | card | sepa_debit
"return_url": "https://lg231.certisource.it/#billing"
}
Crea un mandato SEPA Direct Debit. Il cliente firma una volta e i futuri addebiti avvengono automaticamente. Ritorna mandate_url per la firma digitale.
{
"customer_name": "Mario Rossi",
"customer_email": "mario@esempio.it",
"iban": "IT60X0542811101000000123456",
"description": "Abbonamento 231 Agile"
}
{
"mandate_id": "mnd_abc123",
"mandate_url": "https://revolut.com/mandate/sign/...",
"status": "pending_mandate_signature",
"iban_masked": "IT60****3456"
}
Addebita il cliente via SEPA DD su un mandato attivo. Richiede status: active.
{
"amount": 15000,
"currency": "EUR",
"description": "Pacchetto Onboarding #4",
"reference": "PKG-2026-004"
}
Configura il provider di pagamento del tenant. Le API key vengono cifrate con AES-256-CBC prima di essere salvate nel DB.
{
"provider": "revolut", // revolut | stripe
"api_key": "sk_live_...",
"webhook_secret": "whsec_..."
}
Genera XML FatturaPA 1.2.2. Ritorna xml_base64 (file completo in base64) e hash_sha256.
{
"cedente": {
"piva": "07776161213",
"nome": "231 Agile",
"indirizzo": "Via Roma 1",
"cap": "80100",
"comune": "Napoli",
"provincia": "NA",
"regime": "RF01"
},
"cessionario": {
"nome": "TechnoSteel S.r.l.",
"piva": "12345678901",
"indirizzo": "Via Industria 42",
"cap": "20100",
"comune": "Milano",
"provincia": "MI",
"pec": "fatture@technosteel.it"
},
"righe": [{
"descrizione": "231 Agile — Pacchetto Onboarding #1",
"quantita": 1,
"prezzo_unitario": 150.00,
"aliquota_iva": 22
}],
"numero": "FT-2026-0001-01",
"tipo": "TD01",
"formato": "FPR12"
}
{
"xml_base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i...",
"hash_sha256": "a3f4b2c1d9e8f7a6b5c4d3e2f1a0b9c8..."
}
Valida un XML FatturaPA (base64). Risponde con valid: true/false e lista errori.
{ "xml_base64": "PD94bWwg..." }
Trasmette fattura allo SDI via OpenAPI.it. Idempotente su fattura_numero: se già trasmessa restituisce il record esistente.
{
"xml_base64": "PD94bWwg...",
"fattura_numero": "FT-2026-0001-01",
"tenant_code": "lg231"
}
{
"sdi_id": "SDI-2026-001234",
"stato": "inviata", // inviata | AT | MC | NS | errore
"trasmessa_at": "2026-03-01T09:00:00Z"
}
# Database billing DB_HOST=lg231-mysql DB_NAME=lg231_billing_db DB_USER=lg231_user DB_PASS=Lg231Agile2026! AUTH_DB_NAME=lg231_auth_db # JWT (allineato con tutti gli altri ms) JWT_SECRET=0a76926c6fdfb49a60dc70de1b2f13cb... # Stripe live keys STRIPE_SECRET_KEY=sk_live_... STRIPE_WEBHOOK_SECRET=whsec_... STRIPE_PRICE_PACKAGE=price_... # €150 one-time # FatturaPA — CertiSource infragruppo FATTURA_API_KEY=cs_fat_8bce32c3b95fa878... # Dati cedente (fallback .env, meglio DB via admin UI) FATTURA_CEDENTE_PIVA=07776161213 FATTURA_CEDENTE_NOME="231 Agile" FATTURA_CEDENTE_REGIME=RF01 # Cron protection CRON_SECRET=lg231-billing-cron-secret-2026 # URL redirect Stripe SUCCESS_URL=https://lg231.certisource.it/#view-billing?payment=success CANCEL_URL=https://lg231.certisource.it/#view-billing?payment=cancel
.env. Non è necessario modificare file di configurazione.Crea prodotto "Pacchetto Onboarding 231 Agile"
Dashboard Stripe → Products → Add product → One-time price €150.00 → copia price_xxx
Crea Webhook endpoint
Developers → Webhooks → https://lg231.certisource.it/api/billing/billing/webhook
→ events: checkout.session.completed
Aggiorna .env su Hetzner e rebuild
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_PACKAGE
→ docker compose build billing-ms && docker compose up -d billing-ms
{
"success": false,
"error": "Descrizione errore leggibile"
}
| HTTP | Significato | Causa tipica |
|---|---|---|
400 | Bad Request | Body mancante o campi obbligatori assenti |
401 | Unauthorized | X-API-Key non valida o JWT scaduto/invalido |
402 | Payment Required | Abbonamento sospeso o scaduto (auth-ms) |
403 | Forbidden | Ruolo insufficiente (es: non admin) |
404 | Not Found | Risorsa non trovata (es: fattura non ancora generata) |
409 | Conflict | Mandato già esistente per il cliente |
500 | Server Error | Errore PHP, DB non raggiungibile, cURL timeout |