Dashboard Overview

Ricevute Oggi

-

Tasso Successo

-

Terminali Attivi

-

Totale Oggi

-

Sessioni Redis (trx:*)

-

Totale Ricevute

-

Logs Terminali

-

- righe
Redis Cache

-

-
Redis Cache Info
Host: - Mode: -
Totale Chiavi: - Memoria Usata: -
Logs Storage: - Terminali con Logs: -
Transazioni per Metodo
Status Transazioni
Transazioni per Ora (Oggi)

Terminali Attivi

Lista Terminali
Terminal ID Status Live Last Seen Totale Ricevute Oggi Ultima Attività Azioni
Caricamento...

Gestione Ricevute

Ultime Ricevute
ID Terminal ID UUID Importo Metodo Esito Transaction ID Data/Ora
Caricamento...

Redis Cache Management

Redis LOCAL

-

Checking...
Redis REMOTE

-

Checking...
Cluster Mode

-

Dual-publish enabled
Sessioni Attive

-

Sessioni Redis
Terminal ID TTL (secondi) Ha Dati
Caricamento...

Monitoraggio WebSocket

Connessioni Attive

-

Terminali Connessi

-

Messaggi Inviati

-

Connessioni Totali

-

Dati Trasmessi

-

-
Sessioni Attive
Session ID Terminal ID Managed Terminals Server IP Client Durata Ultimo Ping Status
Caricamento...

ZVT ECR Listener

Protocollo ZVT (A32.de v1.3.41)
Listener TCP per integrazione con casse (ECR) che supportano il protocollo ZVT standard tedesco.
Autenticazione: Password ZVT deve essere il Terminal ID (8 cifre numeriche).
Stato Listener

-

-
ECR Connessi

-

Max: -
Totale Connessioni

-

Comandi Processati

-

Sessioni ECR Attive
Terminal ID Indirizzo Remoto Autenticato Connesso Da Ultima Attività
Caricamento...
Configurazione
Le modifiche alla configurazione richiedono il riavvio dell'applicazione. Modificare il file application.properties.
Parametro Valore Descrizione
serverpos.zvt.enabled - Abilita/Disabilita listener ZVT
serverpos.zvt.port - Porta TCP (standard: 40007)
serverpos.zvt.timeout-seconds 300 Timeout operazioni di pagamento
serverpos.zvt.max-connections - Massime connessioni simultanee
serverpos.zvt.logging.level DEBUG Livello di logging
Comandi ZVT Supportati
CCRC Comando Descrizione Mappatura ServerPOS
04 0F Registration Registrazione ECR (richiesta password = Terminal ID) Autenticazione
06 00 Authorization Richiesta pagamento → Comando "payment" via WebSocket/Polling
06 01 Pre-Authorization Pre-autorizzazione → Comando "preauth"
06 30 Reversal Storno ultima operazione → Comando "reversal"
06 31 Refund Rimborso → Comando "refund"
06 50 End-of-Day Chiusura giornaliera → Comando "endofday"
05 00 Status Enquiry Richiesta stato terminale Status OK

Ingenico ECR Listener

Protocollo Ingenico ECR Proto 17 v3.4
Listener TCP per integrazione con casse (ECR) che supportano il protocollo Ingenico EMV Proto 17.
Formato Messaggio: STX + Dati + ETX + LRC (XOR checksum con base 0x7F).
Stato Listener

-

-
ECR Connessi

-

Max: -
Totale Connessioni

-

Comandi Processati

-

Sessioni ECR Attive
Terminal ID Indirizzo Remoto Connesso Da Ultima Attività Ultimo Comando Azioni
Caricamento...
Configurazione
Le modifiche alla configurazione richiedono il riavvio dell'applicazione. Modificare il file application.properties.
Parametro Valore Descrizione
serverpos.ingenico.enabled - Abilita/Disabilita listener Ingenico
serverpos.ingenico.port - Porta TCP (standard: 11000)
serverpos.ingenico.timeout-seconds 300 Timeout operazioni di pagamento
serverpos.ingenico.reversal-timeout-seconds 180 Timeout operazioni di storno
serverpos.ingenico.max-connections - Massime connessioni simultanee
serverpos.ingenico.logging.level DEBUG Livello di logging
Comandi Ingenico Proto 17 Supportati
Codice Comando Descrizione Mappatura ServerPOS
P Payment Richiesta pagamento standard → Comando "payment" via WebSocket/Polling
X Payment Extended Pagamento con dati estesi → Comando "payment" (esteso)
M Payment + Cashback Pagamento con prelievo contante → Comando "payment" con cashback
A Credit Accredito (rimborso) → Comando "refund"
S Reversal Storno ultima operazione → Comando "reversal"
Q Reversal Retroactive Storno retroattivo → Comando "reversal" retroattivo
C Closure Chiusura giornaliera → Comando "endofday"
T Totals Richiesta totali Report totali
H Print Last Stampa ultima transazione Recupero ultima ricevuta
D Print Duplicate Stampa duplicato Recupero duplicato ricevuta
s Status Enquiry Richiesta stato terminale Status operativo

Manutenzione Database

Pulizia Ricevute Vecchie

Elimina ricevute più vecchie di N giorni per liberare spazio.

giorni
Informazioni Database
Totale Ricevute: -
Ricevute Oggi: -
Terminali Unici: -

Gestione Partners API

Esempi di Utilizzo API
1. Invia Pagamento al Terminale
# POST /api/send-data - Invia pagamento al terminale con API Key
curl -X POST https://ricevute.payglobe.it/serverpos/api/send-data \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "terminalId": "90011004",
    "uuid": "payment-12345",
    "data": {
      "amount": 1050,
      "currency": "EUR",
      "paymentMethod": "CARD"
    }
  }'

# Risposta attesa:
# HTTP 200 OK
# {"status":"ok","message":"Payment sent successfully"}
2. Ottieni Stato Pagamento (Polling)
# GET /api/v1/{terminalId}/get - Controlla se ci sono pagamenti pendenti
curl -X GET https://ricevute.payglobe.it/serverpos/api/v1/90011004/get

# Risposta 1: Nessun pagamento in coda
# HTTP 204 No Content
# (corpo vuoto)

# Risposta 2: Pagamento presente
# HTTP 200 OK
# {
#   "status": "ok",
#   "data": {
#     "received": {
#       "uuid": "payment-12345",        // ID univoco transazione
#       "amount": 1050,                 // Importo in centesimi (10.50 EUR)
#       "currency": "EUR",              // Valuta
#       "paymentMethod": "CARD",        // Metodo: CARD, SATISPAY, VOUCHER
#       "timestamp": "2025-10-09T12:00:00Z"
#     },
#     "terminalID": "90011004"          // Terminale destinatario
#   },
#   "error": null
# }

# ⚠️ IMPORTANTE: Il pagamento viene RIMOSSO da Redis dopo il primo GET
# Successive richieste torneranno 204 No Content
3. Autenticazione con Basic Auth (Legacy)
# Stesso endpoint con Basic Auth invece di API Key
curl -X POST https://ricevute.payglobe.it/serverpos/api/send-data \
  -u username:password \
  -H "Content-Type: application/json" \
  -d '{
    "terminalId": "90011004",
    "uuid": "payment-12345",
    "data": {...}
  }'

# L'endpoint GET non richiede autenticazione (pubblico)
curl -X GET https://ricevute.payglobe.it/serverpos/api/v1/90011004/get
Note:
  • Sostituisci YOUR_API_KEY_HERE con l'API Key generata dal pulsante "Genera"
  • L'endpoint /get è pubblico e non richiede autenticazione
  • Il pagamento viene rimosso da Redis dopo il primo GET (TTL 60 secondi)
OpenAPI 3.0 Specification (per import in Postman/Swagger)
openapi: 3.0.0
info:
  title: ServerPOS API
  version: 1.0.0
  description: API per invio pagamenti a terminali POS

servers:
  - url: https://ricevute.payglobe.it/serverpos

# Definizione metodi di autenticazione
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: API Key generata dal Dashboard Admin

    BasicAuth:
      type: http
      scheme: basic
      description: Username e password del partner

paths:
  /api/send-data:
    post:
      summary: Invia pagamento a terminale
      description: Endpoint per inviare dati di pagamento al terminale POS
      tags:
        - Payments

      # Supporta entrambi i metodi di autenticazione
      security:
        - ApiKeyAuth: []
        - BasicAuth: []

      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - terminalId
                - uuid
                - data
              properties:
                terminalId:
                  type: string
                  example: "90011004"
                  description: ID del terminale destinatario
                uuid:
                  type: string
                  example: "payment-12345"
                  description: ID univoco transazione
                data:
                  type: object
                  description: Dati del pagamento
                  properties:
                    amount:
                      type: integer
                      example: 1050
                      description: Importo in centesimi (1050 = 10.50 EUR)
                    currency:
                      type: string
                      example: "EUR"
                      description: Codice valuta ISO 4217
                    paymentMethod:
                      type: string
                      enum: [CARD, SATISPAY, VOUCHER]
                      description: Metodo di pagamento

      responses:
        '200':
          description: Pagamento inviato con successo
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
                  message:
                    type: string
                    example: "Payment sent successfully"

        '401':
          description: Autenticazione fallita
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "error"
                  error:
                    type: string
                    example: "Unauthorized"

  /api/v1/{terminalId}/get:
    get:
      summary: Ottieni stato pagamento (Polling)
      description: |
        Controlla se ci sono pagamenti pendenti per il terminale.

        **Comportamento:**
        - Ritorna `204 No Content` se non ci sono pagamenti in coda
        - Ritorna `200 OK` con JSON se c'è un pagamento
        - **IMPORTANTE:** Il pagamento viene rimosso dopo il primo GET

        **Nota:** Questo endpoint è pubblico e non richiede autenticazione.
      tags:
        - Polling

      parameters:
        - name: terminalId
          in: path
          required: true
          schema:
            type: string
            example: "90011004"
          description: ID del terminale POS

      responses:
        '200':
          description: Pagamento presente
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
                    description: Stato della richiesta
                  data:
                    type: object
                    properties:
                      received:
                        type: object
                        description: Dati del pagamento ricevuto
                        properties:
                          uuid:
                            type: string
                            example: "payment-12345"
                            description: ID univoco transazione
                          amount:
                            type: integer
                            example: 1050
                            description: Importo in centesimi (1050 = 10.50 EUR)
                          currency:
                            type: string
                            example: "EUR"
                            description: Codice valuta ISO 4217
                          paymentMethod:
                            type: string
                            example: "CARD"
                            enum: [CARD, SATISPAY, VOUCHER]
                            description: |
                              Metodo di pagamento:
                              - CARD: Carta di credito/debito
                              - SATISPAY: Pagamento Satispay
                              - VOUCHER: Buoni pasto elettronici
                          timestamp:
                            type: string
                            format: date-time
                            example: "2025-10-09T12:00:00Z"
                            description: Data e ora ricezione pagamento (ISO 8601)
                      terminalID:
                        type: string
                        example: "90011004"
                        description: ID terminale destinatario
                  error:
                    type: string
                    nullable: true
                    example: null
                    description: Messaggio errore (null se successo)

        '204':
          description: |
            Nessun pagamento in coda

            Corpo della risposta vuoto. Il client dovrebbe riprovare
            periodicamente (ogni 3 secondi consigliato).
1. Client Completo Java/Android
import okhttp3.*;
import org.json.JSONObject;
import android.os.Handler;
import android.util.Log;

public class ServerPosClient {

    private static final String BASE_URL = "https://ricevute.payglobe.it/serverpos";
    private static final String API_KEY = "YOUR_API_KEY_HERE";
    private static final int POLLING_INTERVAL_MS = 3000; // 3 secondi

    private final OkHttpClient client = new OkHttpClient();
    private final Handler pollingHandler = new Handler();
    private boolean isPolling = false;

    // ============= INVIA PAGAMENTO =============
    public void sendPayment(String terminalId, String uuid, JSONObject data) {
        try {
            // Costruisci JSON payload
            JSONObject payload = new JSONObject();
            payload.put("terminalId", terminalId);
            payload.put("uuid", uuid);
            payload.put("data", data);

            // Crea richiesta HTTP
            RequestBody body = RequestBody.create(
                payload.toString(),
                MediaType.parse("application/json")
            );

            Request request = new Request.Builder()
                .url(BASE_URL + "/api/send-data")
                .addHeader("X-API-Key", API_KEY)
                .post(body)
                .build();

            // Esegui chiamata
            try (Response response = client.newCall(request).execute()) {
                if (response.isSuccessful()) {
                    String responseBody = response.body().string();
                    Log.d("ServerPOS", "Payment sent: " + responseBody);
                } else {
                    Log.e("ServerPOS", "Send failed: " + response.code());
                }
            }

        } catch (Exception e) {
            Log.e("ServerPOS", "Exception: " + e.getMessage());
        }
    }

    // ============= CONTROLLA STATO (POLLING) =============
    public void checkPaymentStatus(String terminalId, PaymentCallback callback) {
        try {
            Request request = new Request.Builder()
                .url(BASE_URL + "/api/v1/" + terminalId + "/get")
                .get()
                .build();

            try (Response response = client.newCall(request).execute()) {
                if (response.code() == 204) {
                    // 204 No Content = Nessun pagamento
                    Log.d("ServerPOS", "No payment pending");
                    callback.onNoPayment();

                } else if (response.isSuccessful()) {
                    // 200 OK = Pagamento ricevuto
                    String body = response.body().string();
                    JSONObject json = new JSONObject(body);
                    JSONObject data = json.getJSONObject("data");
                    JSONObject received = data.getJSONObject("received");

                    // Estrai dati pagamento
                    String uuid = received.getString("uuid");
                    int amount = received.getInt("amount");          // Centesimi
                    String currency = received.getString("currency");
                    String method = received.getString("paymentMethod");
                    String timestamp = received.getString("timestamp");

                    Log.d("ServerPOS", String.format(
                        "Payment received: %s - %.2f %s (%s)",
                        uuid, amount / 100.0, currency, method
                    ));

                    callback.onPaymentReceived(uuid, amount, currency, method, timestamp);
                }
            }

        } catch (Exception e) {
            Log.e("ServerPOS", "Check failed: " + e.getMessage());
            callback.onError(e);
        }
    }

    // ============= POLLING AUTOMATICO =============
    public void startPolling(String terminalId, PaymentCallback callback) {
        if (isPolling) return;
        isPolling = true;

        Runnable pollRunnable = new Runnable() {
            @Override
            public void run() {
                if (!isPolling) return;

                checkPaymentStatus(terminalId, callback);

                // Ripeti dopo 3 secondi
                pollingHandler.postDelayed(this, POLLING_INTERVAL_MS);
            }
        };

        pollingHandler.post(pollRunnable);
        Log.d("ServerPOS", "Polling started for terminal: " + terminalId);
    }

    public void stopPolling() {
        isPolling = false;
        pollingHandler.removeCallbacksAndMessages(null);
        Log.d("ServerPOS", "Polling stopped");
    }

    // ============= CALLBACK INTERFACE =============
    public interface PaymentCallback {
        void onPaymentReceived(String uuid, int amount, String currency,
                               String method, String timestamp);
        void onNoPayment();
        void onError(Exception e);
    }
}

// ============= UTILIZZO ESEMPIO =============

// 1. Invia pagamento
ServerPosClient client = new ServerPosClient();

JSONObject paymentData = new JSONObject();
paymentData.put("amount", 1050);  // 10.50 EUR in centesimi
paymentData.put("currency", "EUR");
paymentData.put("paymentMethod", "CARD");

client.sendPayment("90011004", "payment-12345", paymentData);

// 2. Polling automatico per ricevere pagamenti
client.startPolling("90011004", new ServerPosClient.PaymentCallback() {
    @Override
    public void onPaymentReceived(String uuid, int amount, String currency,
                                   String method, String timestamp) {
        // Pagamento ricevuto!
        runOnUiThread(() -> {
            Toast.makeText(this,
                String.format("Ricevuto: %.2f %s", amount/100.0, currency),
                Toast.LENGTH_LONG).show();
        });
    }

    @Override
    public void onNoPayment() {
        // Nessun pagamento in coda (normale)
    }

    @Override
    public void onError(Exception e) {
        Log.e("App", "Errore polling: " + e.getMessage());
    }
});

// 3. Ferma polling quando l'app va in background
@Override
protected void onPause() {
    super.onPause();
    client.stopPolling();
}
Best Practices:
  • Non hardcodare l'API Key! Usa BuildConfig o Android Keystore
  • Ferma il polling quando l'app va in background (onPause)
  • Gestisci gli errori di rete con retry automatico
  • Usa un WorkManager per polling in background affidabile
Partners Registrati
ID Partner Username Email Stato API Key Terminali Creato Azioni
Caricamento...

Logs Terminali

Richiedi Logs da Terminale

Invia comando LOGCAT al terminale Android per richiedere i log in tempo reale.

Visualizza Logs Ricevuti
Logs Ricevuti - Terminal:

Totale logs: 0

Inserisci un Terminal ID per visualizzare i logs

Subscription Rules Whitelist

Aggiungi/Modifica Regola
Terminal ID che verrà autorizzato
Non richiesto per tipo ANY
Regole Configurate
Terminal ID Tipo Valore Stato Note Creato Azioni
Caricamento...
Testa Subscription

Verifica se un terminalId può sottoscrivere un topic specifico

PayGlobe Credentials

Gestione credenziali PayGlobe Payment Links API (sk_test_* / sk_live_*)

Aggiungi/Modifica Credenziale
Identificatore univoco (es: default_test, partner_prod)
PayGlobe Secret Key (sk_test_* per TEST, sk_live_* per PRODUCTION)
Email di default quando il cliente non fornisce la propria email
Default: https://api.payglobe.it/paymentgw
Credenziali Configurate
Nome Environment Secret Key Base URL Stato Note Azioni
Caricamento...

AWS Services S3 Backups & CloudWatch Logs

S3 Backups
Nome File Dimensione Data Storage Azioni
Caricamento...
CloudWatch Logs
Seleziona un log stream per visualizzare i log...

App Versions Manager Auto-Update System

Versioni Totali

0

Versione Attiva

-

Installazioni 7gg

0

Success Rate

-

Lista Versioni App

Caricamento versioni...

Crea Nuova Versione
Numero intero incrementale (es: 1, 2, 3...)
Nome versione visualizzato (es: 1.3.0)
Nome file APK (deve corrispondere al file caricato)
Upload APK File
Drag & Drop APK File

oppure clicca per selezionare

Nuovo Deploy
Push Update

Invia notifica FORCE_UPDATE via WebSocket

Lascia vuoto per broadcast globale
Deployments Attivi
Versione Tipo Target Data Note Azioni
Caricamento...
Adozione Versioni (ultimi 7gg)
Success Rate Installazioni
Benvenuto nel sistema App Auto-Update! Segui questa guida per pubblicare nuove versioni dell'app Android POS.
Carica una nuova versione APK
  1. Vai sul tab "Upload & Deploy" qui sopra
  2. Trascina il file APK nell'area grigia (oppure click per selezionare)
  3. Compila il form:
    • Version Code: Numero intero progressivo (es: 2, 3, 4...) - deve essere maggiore della versione precedente
    • Version Name: Nome versione leggibile (es: 1.0.1, 1.2.0)
    • Mandatory: ✅ seleziona se vuoi forzare l'aggiornamento obbligatorio
    • Min API Level: Solitamente 21 (Android 5.0+)
    • Release Notes: Descrivi cosa c'è di nuovo in questa versione
  4. Click su "Upload & Create Version"
  5. Attendi il completamento - vedrai la barra di progresso
Il file APK sarà caricato su /opt/serverPOS/apk-files/ e salvato nel database!
Attiva la nuova versione
  1. Torna sul tab "Versioni"
  2. Trova la tua versione appena caricata nella lista
  3. Click sul pulsante verde "Attiva"
Importante: Solo UNA versione può essere attiva alla volta! Attivando una nuova versione, quella precedente verrà automaticamente disattivata.
Invia notifica push ai terminali
Opzione A: Broadcast a TUTTI i terminali
  1. Tab "Versioni" → Click su "Push Update" sulla versione attiva
  2. Lascia vuoto il campo "Terminal ID" (o scrivi "ALL")
  3. Scegli se rendere l'aggiornamento "Mandatory" (obbligatorio)
  4. Click "Send Push"

Opzione B: Target singolo terminale
  1. Tab "Versioni" → Click su "Push Update"
  2. Inserisci il Terminal ID specifico (es: 90011005)
  3. Scegli se "Mandatory"
  4. Click "Send Push"
Risultato: Il terminale riceverà un messaggio WebSocket STOMP con l'URL del file APK da scaricare:
{
  "type": "FORCE_UPDATE",
  "versionCode": 2,
  "versionName": "1.0.1",
  "apkUrl": "https://ricevute.payglobe.it/serverpos/api/v1/app/download/pos-app-v1.0.1.apk",
  "mandatory": true
}
Scenario Avanzato: Deployment Selettivo

Use Case: Vuoi testare la versione 2.0 solo su 3 terminali prima del rollout globale.

  1. Tab "Deployments" → Click "Add Deployment"
  2. Compila:
    • Version: Seleziona versione 2.0
    • Terminal ID: 90011005 (lascia vuoto Merchant ID)
    • Enabled:
  3. Ripeti per gli altri 2 terminali
Priorità sistema:
  1. 🎯 Terminal-specific (più alta)
  2. 🏪 Merchant-specific (media)
  3. 🌍 Global (fallback - versione attiva)
Rollback a versione precedente
  1. Tab "Versioni" → Trova la versione VECCHIA (es: 1.0.0)
  2. Click "Attiva"
  3. (Opzionale) Click "Push Update" per forzare il downgrade
Attenzione: Se hai deployment selettivi attivi, devi eliminarli prima del rollback globale!
Monitoring Installazioni

Tab "Analytics" per visualizzare:

  • 📊 Version Distribution: Quanti terminali hanno installato ogni versione
  • Success Rates: Percentuale installazioni riuscite vs fallite
  • ⏱️ Avg Install Duration: Tempo medio di installazione
Best Practices
  • Testa sempre su 1-2 terminali prima del broadcast globale (usa deployment selettivi)
  • Usa "Mandatory" solo per fix critici di sicurezza
  • Incrementa Version Code ad ogni release - non riusare numeri vecchi
  • Scrivi Release Notes chiare - utili per troubleshooting futuro
  • Monitora Analytics dopo ogni deploy - il success rate dovrebbe essere >95%
  • File APK max 50MB per evitare timeout su reti lente