Dashboard Overview
Ricevute Oggi
-
Tasso Successo
-
Terminali Attivi
-
Totale Oggi
-
Sessioni Redis (trx:*)
-
Totale Ricevute
-
Logs Terminali
-
- righeRedis 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 enabledSessioni 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
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
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
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
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.
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
- Sostituisci
YOUR_API_KEY_HEREcon 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();
}
- Non hardcodare l'API Key! Usa
BuildConfigo Android Keystore - Ferma il polling quando l'app va in background (
onPause) - Gestisci gli errori di rete con retry automatico
- Usa un
WorkManagerper polling in background affidabile
Partners Registrati
| ID | Partner | Username | 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
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
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
App Versions Manager Auto-Update System
Versioni Totali
0
Versione Attiva
-
Installazioni 7gg
0
Success Rate
-
Lista Versioni App
Caricamento versioni...
Crea Nuova Versione
Upload APK File
Drag & Drop APK File
oppure clicca per selezionare
Nuovo Deploy
Push Update
Invia notifica FORCE_UPDATE via WebSocket
Deployments Attivi
| Versione | Tipo | Target | Data | Note | Azioni |
|---|---|---|---|---|---|
| Caricamento... | |||||
Adozione Versioni (ultimi 7gg)
Success Rate Installazioni
Carica una nuova versione APK
- Vai sul tab "Upload & Deploy" qui sopra
- Trascina il file APK nell'area grigia (oppure click per selezionare)
- 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
- Click su "Upload & Create Version"
- Attendi il completamento - vedrai la barra di progresso
/opt/serverPOS/apk-files/ e salvato nel database!
Attiva la nuova versione
- Torna sul tab "Versioni"
- Trova la tua versione appena caricata nella lista
- Click sul pulsante verde "Attiva"
Invia notifica push ai terminali
Opzione A: Broadcast a TUTTI i terminali
- Tab "Versioni" → Click su "Push Update" sulla versione attiva
- Lascia vuoto il campo "Terminal ID" (o scrivi "ALL")
- Scegli se rendere l'aggiornamento "Mandatory" (obbligatorio)
- Click "Send Push"
Opzione B: Target singolo terminale
- Tab "Versioni" → Click su "Push Update"
- Inserisci il Terminal ID specifico (es:
90011005) - Scegli se "Mandatory"
- Click "Send Push"
{
"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.
- Tab "Deployments" → Click "Add Deployment"
- Compila:
- Version: Seleziona versione 2.0
- Terminal ID:
90011005(lascia vuoto Merchant ID) - Enabled: ✅
- Ripeti per gli altri 2 terminali
- 🎯 Terminal-specific (più alta)
- 🏪 Merchant-specific (media)
- 🌍 Global (fallback - versione attiva)
Rollback a versione precedente
- Tab "Versioni" → Trova la versione VECCHIA (es: 1.0.0)
- Click "Attiva"
- (Opzionale) Click "Push Update" per forzare il downgrade
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