In questa sezione viene descritto in dettaglio il json del pagamento e la definizione dettagliata dei campi
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
id
UUID
user_id
UUID
type
string(50)
Ogni proxy deve implementare un tipo di pagamento. Se per esempio, il proxy in questione gestisce pagamenti pagopa allora il campo va validato verificando che esso sia valorizzato a PAGOPA
. In caso contrario si scarta l'evento e si emette un log di errore.
tenant_id
UUID
service_id
UUID
created_at
Datetime
ISO8601
updated_at
Datetime
ISO8601
status
Enum
Valori permessi: CREATION_PENDING CREATION_FAILED PAYMENT_PENDING PAYMENT_STARTED PAYMENT_CONFIRMED PAYMENT_FAILED NOTIFICATION_PENDING
COMPLETE EXPIRED
reason
string(140)
Causale del pagamento. Non può eccedere i 140 caratteri.
remote_id
UUID
payment
PaymentData
links
Links
payer
Payer
event_id
UUID
event_version
string(10)
L'attuale versione dell'evento deve essere "1.0". Ogni proxy deve validare la versione dell'evento in modo da sapere se processarlo o meno.
event_created_at
Datetime
ISO8601
app_id
string(100)
Valorizzarlo nel formato <nome-proxy>:<versione-proxy>
Es.
iris-payment-proxy:1.3.0
transaction_id
string(255)
Fornito dall'intermediario di pagamento. La lunghezza dunque può essere variabile
paid_at
Datetime
ISO8601
expire_at
Datetime
ISO8601 E' già valorizzato a priori, quindi non viene gestito dal proxy
amount
float
E' già valorizzato a priori, quindi non viene gestito dal proxy
currency
string(3)
ISO4217
notice_code
string(50)
iud
string(50)
iuv
string(50)
split
jsonArray
online_payment_begin
UrlData
online_payment_landing
UrlData
offline_payment
UrlData
receipt
UrlData
notify
List[Notify]
update
Update
url
string
last_opened_at
Datetime
ISO8601
method
Enum
Valori permessi: GET POST
url
string
method
Enum
Valori permessi: GET POST
sent_at
Datetime
ISO8601
url
string
last_check_at
Datetime
ISO8601
next_check_at
Datetime
ISO8601
method
Enum
Valori permessi: GET POST
type
Enum
Valori permessi: human legal
tax_identification_number
string(255)
name
string(255)
family_name
string(255)
street_name
string(255)
building_number
string(255)
postal_code
string(255)
town_name
string(255)
country_subdivision
string(2)
ISO 3166-2
country
string(2)
ISO 3166-1 alpha-2
email
string(255)
NOTA 1: per gli sviluppatori python è stata definita una libreria a cui fare riferimento per la validazione del nuovo evento, è consultabile qui.
NOTA 2: per gli sviluppatori python, il repository da cui prendere spunto per applicare le modifiche riportate in questa sezione e in quelle successive è consultabile qui.
Con la versione 2.0 aggiornata del pagamento sono stati aggiunti nuovi campi che arricchiscono la descrizione del pagamento, in particolare i campi sono:
type
: serve a distinguere tra un pagamento ordinario e una marca da bollo digitale, può avere PAGOPA
o STAMP
come valori
receiver
: definisce il beneficiario del pagamento, non è un campo obbligatorio ma può essere utilizzato nel caso di pagamenti con beneficiario differente dall'ente su cui viene creato il pagamento. Se viene valorizzato è obbligatorio valorizzare i campi receiver.tax_identification_number
e receiver.name
due_type
: indica la categorizzazione del dovuto sull'intermediario di pagamento, e viene valorizzato dalla configurazione del pagamento
pagopa_category
: indica la categorizzazione del dovuto su pagoPA, e viene valorizzato dalla configurazione del pagamento
document
: è un campo che serve a descrivere il documento su cui viene apposta la marca da bollo digitale, se viene valorizzato è obbligatorio valorizzare il campo document.hash
.
split
: con la versione 2.0 dell'evento, questo campo, che viene alimentato dal bilancio contenuto nella configurazione del pagamento, avrà un tipo ben definito, composto da
split.code
: indica l'identificativo della voce di bilancio
split.amount
: indica l'importo della voce di bilancio
split.meta
: oggetto contenente il resto dei campi presenti nella voce di bilancio
links.confirm
: è un campo che serve a contenere l'API per forzare il completamento di un pagamento, per il momento tutti i proxy mancano di questa API, ma il campo è stato aggiunto per utilizzi futuri.
links.cancel
: è un campo che serve a contenere l'API per forzare l'annullamento di un pagamento.
debtor
: in aggiunta al payer
è stato aggiunto un campo equivalente debtor
, e serve a distinguere tra il debitore e il pagatore di un pagamento, ad esempio è possibile che un cittadino paghi per conto di terzi e in questo caso e debitore e pagatore sono distinti. Per ora non viene valorizzato né utilizzato.
Punti aperti
Determinazione delle URL di ritorno: Come si gestiscono le URL di ritorno? È possibile utilizzare l'indirizzo del proxy per gestire i redirect?
Gestione dell'happy path del pagamento: Come gestire il percorso ideale del pagamento e cosa accade se l'utente chiude la pagina di pagamento e poi ritorna?
Compilazione e invio pratica: L'utente compila la pratica per il servizio e invia la richiesta al Core.
Verifica pagamenti: Il Core verifica se, nella fase attuale della pratica, è necessario effettuare dei pagamenti (es. pagamento anticipato o posticipato).
Creazione pagamenti: Il Core invia i dettagli al servizio di pagamento, che restituisce gli identificativi dei pagamenti creati. Questo passaggio è fondamentale, poiché il Core deve salvare i dettagli dei pagamenti all'interno della pratica, assicurandosi che siano coerenti con il flusso (anticipato o posticipato).
Restituzione della pratica: Una volta ottenuti gli ID dei pagamenti, il Core restituisce all'utente l'intera pratica aggiornata con gli identificativi.
Gestione degli errori nella creazione dei pagamenti:
Cosa accade se la creazione di un pagamento fallisce?
Il personale dell'ufficio preposto dovrebbe essere notificato in caso di fallimento.
Stato "Creation Pending": Quando un pagamento viene creato, si ottiene comunque un ID associato al pagamento, ma questo potrebbe essere in stato di "creation pending".
Politiche di retry: Si potrebbe considerare l'implementazione di politiche di retry, ma è necessario consultare il Product Manager (PM) per decidere la miglior esperienza utente (UX).
Ipotesi: Al secondo o terzo tentativo di retry (o dopo un timeout di 10 secondi), potremmo mostrare un messaggio d'errore all'utente, suggerendo di riprovare o di avvisare l'assistenza (es. con un link "Clicca qui e avvisa"). Questo sarebbe un errore a livello ERROR.
Errore di configurazione: Se si verifica un errore di configurazione errata, è possibile fare affidamento sui messaggi restituiti dall'intermediario. In questo caso, si può evitare il retry e notificare direttamente il responsabile (es. Lorello). Questo tipo di errore potrebbe essere classificato come FATAL.
Il sequence diagram sopra riportato rappresenta il flusso di creazione e gestione dei pagamenti in un'applicazione, con particolare attenzione al retry in caso di fallimento e alla gestione dello stato del pagamento. Il flusso si svolge come segue:
Inizio del processo: L'utente invia la pratica e il Core richiama il Payment Dispatcher API per creare il pagamento. Se la creazione ha successo, si procede, altrimenti si ritenta fino a 3 volte.
Attesa di aggiornamenti dal Read Model: Quando la creazione del pagamento va a buon fine, il Core si mette in attesa di aggiornamenti dal Read Model.
Retry gestito dal Retry Orchestrator: Se il Read Model restituisce lo stato CREATION_FAILED
, il Core delega il processo di retry al Retry Orchestrator, che gestisce i retry tramite Kafka. Il Retry Orchestrator tenterà di risolvere il problema creando il pagamento sull'intermediario esterno.
Risultati del Retry Orchestrator:
Se il retry riesce, il Retry Orchestrator segnalerà il successo al Core, che mostrerà all'utente lo stato PAYMENT_PENDING
per procedere con il pagamento.
Se i retry falliscono, l'utente riceverà un alert di errore.
Conclusione: L'utente vedrà le informazioni di pagamento in caso di successo o un messaggio d'errore in caso di fallimento, dopo aver superato il numero massimo di tentativi.
Gestione di pagamenti parziali: Se due pagamenti vanno a buon fine e uno fallisce, come dovrebbe comportarsi il frontend? Attualmente, il processo di checkout potrebbe risultare incompleto.
Invio degli ID di pagamento: Durante il checkout, il sistema riceve tutti gli ID dei pagamenti che devono essere completati in un’unica operazione.
Il sequence diagram sopra riportato rappresenta il flusso di creazione e gestione dei pagamenti posticipati in fase approvazione della pratica da parte dell'operatore. Il flusso si svolge come segue:
Creazione delle configurazioni: L'utente modifica e invia le configurazioni, che vengono temporaneamente salvate tramite il Payment Proxy. Se fallisce, l'errore viene mostrato all'utente.
Creazione del pagamento tramite Payment Dispatcher: Il Core invia la richiesta di creazione pagamento al Payment Dispatcher API. Se fallisce, viene avviato un retry per un massimo di 3 tentativi. Se dopo 3 tentativi non riesce, viene mostrato un errore all'utente.
Attesa di aggiornamenti dal Read Model: Quando la creazione del pagamento va a buon fine, il Core si mette in attesa di aggiornamenti dal Read Model, che monitora lo stato del pagamento.
Stato CREATION_FAILED
e Retry Orchestrator:
Se il Read Model restituisce lo stato CREATION_FAILED
, il Core delega il retry al Retry Orchestrator, che gestisce i retry attraverso i topic di Kafka.
Se il Retry Orchestrator completa con successo la creazione, il Read Model aggiorna lo stato del pagamento, e l'utente può procedere con il pagamento (PAYMENT_PENDING
).
Se anche il Retry Orchestrator fallisce dopo vari tentativi, viene restituito un errore al Core e un alert viene mostrato all'utente.
Output finale: Se il pagamento va a buon fine (PAYMENT_PENDING
), l'utente riceve le informazioni per procedere con il pagamento. In caso di errore persistente, viene mostrato un alert.
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
Campo | Tipo | Obbligatorio | Validazione |
---|---|---|---|
id
UUID
user_id
UUID
type
string(50)
Ogni proxy deve implementare un tipo di pagamento. Se per esempio, il proxy in questione gestisce pagamenti pagopa allora il campo va validato verificando che esso sia valorizzato a PAGOPA
. In caso contrario si scarta l'evento e si emette un log di errore.
tenant_id
UUID
service_id
UUID
created_at
Datetime
ISO8601
updated_at
Datetime
ISO8601
status
Enum
Valori permessi: CREATION_PENDING CREATION_FAILED PAYMENT_PENDING PAYMENT_STARTED PAYMENT_CONFIRMED PAYMENT_FAILED NOTIFICATION_PENDING
COMPLETE EXPIRED
reason
string(140)
Causale del pagamento. Non può eccedere i 140 caratteri.
remote_id
UUID
payment
PaymentData
links
Links
payer
Payer
Soggetto Versante
debtor
Debtor
Soggetto Pagatore
event_id
UUID
event_version
string(10)
L'attuale versione dell'evento deve essere "1.0". Ogni proxy deve validare la versione dell'evento in modo da sapere se processarlo o meno.
event_created_at
Datetime
ISO8601
app_id
string(100)
Valorizzarlo nel formato <nome-proxy>:<versione-proxy>
Es.
iris-payment-proxy:1.3.0
type
Enum
Valori permessi:
PAGOPA
nel caso in cui si tratto di un dovuto standard
STAMP
nel caso in cui si tratta di un dovuto di tipo marca da bollo digitale
transaction_id
string(255)
Fornito dall'intermediario di pagamento. La lunghezza dunque può essere variabile
paid_at
Datetime
ISO8601
expire_at
Datetime
ISO8601 E' già valorizzato a priori, quindi non viene gestito dal proxy
amount
float
E' già valorizzato a priori, quindi non viene gestito dal proxy
reason
string(140)
Causale del pagamento. Non può eccedere i 140 caratteri.
currency
string(3)
ISO4217
notice_code
string(50)
iud
string(50)
iuv
string(50)
receiver
Receiver
Destinatario o beneficiario del versamento/dovuto
due_type
string(256)
Tipo di dovuto secondo la classificazione dell'intermediario di riferiemento
pagopa_category
string(12)
Tipo di dovuto secondo la tassonomia ufficiale di pagoPA
document
Document
Contiene le informazioni riguardanti il documento informatico o la segnatura di protocollo cui è associata la marca da bollo digitale
split
List[PaymentDataSplit]
tax_identification_number
string(255)
name
string(255)
iban
string(34)
ISO 13616 (obbligatorio solo dal secondo beneficiario in poi)
street_name
string(255)
building_number
string(255)
postal_code
string(255)
town_name
string(255)
country_subdivision
string(2)
ISO 3166-2
country
string(2)
ISO 3166-1 alpha-2
id
UUID
Identificativo del documento
ref
string
Url per scaricare il documento
hash
string
Hash digest del documento informatico
code
string(50)
amount
float
meta
json
online_payment_begin
UrlData
online_payment_landing
UrlData
offline_payment
UrlData
receipt
UrlData
notify
List[Notify]
update
Update
confirm
UrlData
cancel
UrlData
url
string
last_opened_at
Datetime
ISO8601
method
Enum
Valori permessi:
GET
POST
PUT
PATCH
DELETE
url
string
method
Enum
Valori permessi: GET POST
sent_at
Datetime
ISO8601
url
string
last_check_at
Datetime
ISO8601
next_check_at
Datetime
ISO8601
method
Enum
Valori permessi: GET POST
type
Enum
Valori permessi: human legal
tax_identification_number
string(255)
name
string(255)
family_name
string(255)
street_name
string(255)
building_number
string(255)
postal_code
string(255)
town_name
string(255)
country_subdivision
string(2)
ISO 3166-2
country
string(2)
ISO 3166-1 alpha-2
email
string(255)
type
Enum
Valori permessi: human legal
tax_identification_number
string(255)
name
string(255)
family_name
string(255)
street_name
string(255)
building_number
string(255)
postal_code
string(255)
town_name
string(255)
country_subdivision
string(2)
ISO 3166-2
country
string(2)
ISO 3166-1 alpha-2
email
string(255)