> For the complete documentation index, see [llms.txt](https://docs.opencityitalia.it/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.opencityitalia.it/stanza-del-cittadino/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-con-intermediari-di-pagamento-pagopa/il-pagamento/versione-2.0.md).

# Versione 2.0

## Aggiornamenti principali rispetto alla versione 1.0

**NOTA 1**: per gli sviluppatori python è stata definita una libreria a cui fare riferimento per la validazione del nuovo evento, è consultabile [qui](https://docs.opencityitalia.it/installazione-e-manutenzione/integrazioni/pagamenti).

**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](https://docs.opencityitalia.it/installazione-e-manutenzione/integrazioni/pagamenti).

### Arricchimento della descrizione del pagamento

Con la versione 2.0 aggiornata del pagamento sono stati aggiunti nuovi campi che arricchiscono la descrizione del pagamento, in particolare i campi sono:

* `payment.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, E' obbligatorio valorizzare almeno i campi `receiver.tax_identification_number` e `receiver.name`
* `due_type`: indica la categorizzazione del dovuto (o il tipo di dovuto) sull'intermediario di pagamento, e viene valorizzato dalla configurazione del pagamento. (NB: nella configurazione del pagamento questo campo ha nomi diversi a seconda del proxy, può essere `kind` o `management_id` o `debt_type` ecc.)
* `pagopa_category`: indica la categorizzazione del dovuto su pagoPA, e viene valorizzato dalla configurazione del pagamento, precisamente dal campo `collection_data`
* `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` il quale indica l'hash con codifica sha256 del json del pagamento (es. `sha256(payment.json().encode("utf-8")).hexdigest()`).
* `split`: con la versione 2.0 dell'evento, questo campo, che viene alimentato dal bilancio contenuto nella configurazione del pagamento (NB: non tutti gli intermediari hanno questa feature, quindi in alcuni casi non sarà necessario valorizzarlo), 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.

#### Nota 1

Alcuni dei campi che vengono popolati in fase di creazione del pagamento sull'intermediario si leggevano solo dall'evento payment. Con l'upgrade delle API (i cui aggiornamenti sono consultabili [qui](/stanza-del-cittadino/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-con-intermediari-di-pagamento-pagopa/configurazione-tenant-e-servizi/api-v2.md)), questi campi potrebbero non essere valorizzati nell'evento, in tal caso, vanno letti invece dalla configurazione inserita via API. I campi in questione sono:

* `reason`
* `payment.amount`
* `payment.expire_at`
* `payment.receiver`

In sintesi quindi: se questi campi sono valorizzati nell'evento payment, allora li si legge da lì, altrimenti li si legge dalla configurazione inserita via API.

#### Nota 2

L'upgrade alle versioni 2 dell'Evento di Pagamento e delle API di Configurazione è stato intrapreso per ottenere un maggiore disaccoppiamento del mondo dei pagamenti dalla "stanza". Questa transizione comporta necessariamente un aggiornamento delle strutture e, di conseguenza, delle **URL** precedentemente utilizzate (come `online`, `offline`, `receipt`, `update`).

**Obiettivo:**

Il punto principale dell'aggiornamento degli URL è garantire la **sincronizzazione dei dati** e prevenire che gli eventi che sono stati scritti utilizzando gli URL della versione precedente smettano di funzionare.

**Meccanismo di Aggiornamento:**

Per gestire la modifica degli URL nel passaggio alla versione 2 delle API, è stato implementato il seguente processo di allineamento:

1. **Variazione degli URL:** Con l'upgrade alla versione 2 delle API, è confermato che gli URL subiranno un cambiamento.
2. **Attivazione dell'Aggiornamento:** L'aggiornamento degli URL viene innescato quando il **poller** richiede una sincronizzazione dei dati.
3. **Strumento di Aggiornamento:** Gli URL vengono aggiornati utilizzando specificamente l'**API di update**.
4. **Risultato e Sincronizzazione:** Questo processo è fondamentale per assicurare che le URL siano **allineate** e che i dati risultino correttamente **sincronizzati**

## JSON Evento Pagamento

```json
{
  "id": "68dada78-2398-4a11-b80a-98aaede3371c",
  "user_id": "5b00796e-ef10-4c98-b9f5-b0f7ffd7a17d",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "b21c4429-95e4-45d5-930f-44eb74136625",
  "created_at": "2023-06-06T11:59:11+02:00",
  "updated_at": "2023-06-12T00:10:16+02:00",
  "status": "PAYMENT_STARTED",
  "reason": "79501b2a-c9ad-41f8-a9e7-a885f2d570a2 - BNRMHL75C06G702B",
  "remote_id": "79501b2a-c9ad-41f8-a9e7-a885f2d570a2",
  "payment": {
    "type": "PAGOPA",
    "transaction_id": null,
    "paid_at": null,
    "expire_at": "2023-09-04T11:59:05+02:00",
    "amount": 1.34,
    "currency": "EUR",
    "notice_code": "001550000000024427",
    "iud": "68dada7823984a11b80a98aaede3371c",
    "iuv": "550000000024427",
    "receiver": {
      "tax_identification_number": "777777777",
      "name": "Comune di BlaBla",
      "iban": "IT60X0542811101000000123456",
      "address": "Via Del Campo",
      "building_number": "12",
      "postal_code": "38022",
      "town_name": "Roma",
      "country_subdivision": "RM",
      "country": "IT",
    },
    "due_type": "TARI",
    "pagopa_category": "9/12129/TS",
    "document": null,
    "split": [
      {
        "code": "c_1",
        "amount": 1.00,
        "meta": {}
      },
      {
        "code": "c_2",
        "amount": 0.34,
        "meta": {}
      }
    ]
  },
  "links": {
    "online_payment_begin": {
      "url": "https://iris-proxy-qa.boat.opencontent.io/online-payment/68dada78-2398-4a11-b80a-98aaede3371c?gw=https://iristest.rete.toscana.it/gateway/PaymentAuthentication?token=1686045553436001U132&expire_at=2023-06-06T12:13:13",
      "last_opened_at": "2023-06-06T11:59:26+02:00",
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune-qa.bugliano.pi.it/lang/it/pratiche/79501b2a-c9ad-41f8-a9e7-a885f2d570a2/detail",
      "last_opened_at": "2023-06-06T11:59:57+02:00",
      "method": "GET"
    },
    "offline_payment": {
      "url": "https://iris-proxy-qa.boat.opencontent.io/notice/68dada78-2398-4a11-b80a-98aaede3371c",
      "last_opened_at": "2023-06-06T11:59:20+02:00",
      "method": "GET"
    },
    "receipt": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune-qa.bugliano.pi.it/lang/api/applications/79501b2a-c9ad-41f8-a9e7-a885f2d570a2/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": "http://iris-proxy-qa.boat-backplane.opencontent.io/update/68dada78-2398-4a11-b80a-98aaede3371c",
      "last_check_at": "2023-06-12T00:10:16+02:00",
      "next_check_at": "2023-06-12T01:10:16+02:00",
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": "PATCH"
    },
    "cancel": {
      "url": "https://api.qa.stanzadelcittadino.it/payment-proxy/mypay-trentino/payments/5f2c4be0-effb-47a9-a6dc-a972043580f3",
      "last_opened_at": null,
      "method": "PATCH"
    }
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "BNRMHL75C06G702B",
    "name": "Michelangelo",
    "family_name": "Buonarroti",
    "street_name": "Cesare Battisti",
    "building_number": "",
    "postal_code": "38010",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "lorenzo.bertoli@opencitylabs.it"
  },
  "debtor": {
    "type": "human",
    "tax_identification_number": "BNRMHL75C06G702B",
    "name": "Michelangelo",
    "family_name": "Buonarroti",
    "street_name": "Cesare Battisti",
    "building_number": "",
    "postal_code": "38010",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "lorenzo.bertoli@opencitylabs.it"
  },
  "event_id": "e0b25e33-9d38-4781-823a-ed04753aea01",
  "event_version": "2.0",
  "event_created_at": "2023-06-12T00:10:16+02:00",
  "app_id": "iris-payment-proxy-qa:1.2.8"
}
```

### Validazione campi

#### Payment

<table><thead><tr><th width="222">Campo</th><th width="171">Tipo</th><th width="128" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>user_id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>type</code></td><td>string(50)</td><td>true</td><td>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 <code>PAGOPA</code>. In caso contrario si scarta l'evento e si emette un log di errore.</td></tr><tr><td><code>tenant_id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>service_id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>created_at</code></td><td>Datetime</td><td>true</td><td>ISO8601</td></tr><tr><td><code>updated_at</code></td><td>Datetime</td><td>true</td><td>ISO8601</td></tr><tr><td><code>status</code></td><td>Enum</td><td>true</td><td><p><strong>Valori permessi:</strong><br>CREATION_PENDING CREATION_FAILED<br>PAYMENT_PENDING<br>PAYMENT_STARTED PAYMENT_CONFIRMED<br>PAYMENT_FAILED<br>NOTIFICATION_PENDING</p><p>COMPLETE<br>EXPIRED</p></td></tr><tr><td><code>reason</code></td><td>string(140)</td><td>true</td><td>Causale del pagamento. Non può eccedere i 140 caratteri.</td></tr><tr><td><code>remote_id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>payment</code></td><td>PaymentData</td><td>true</td><td></td></tr><tr><td><code>links</code></td><td>Links</td><td>true</td><td></td></tr><tr><td><code>payer</code></td><td>Payer</td><td>true</td><td>Soggetto Versante</td></tr><tr><td><code>debtor</code></td><td>Debtor</td><td>false</td><td>Soggetto Pagatore</td></tr><tr><td><code>event_id</code></td><td>UUID</td><td>true</td><td></td></tr><tr><td><code>event_version</code></td><td>string(10)</td><td>true</td><td>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.</td></tr><tr><td><code>event_created_at</code></td><td>Datetime</td><td>true</td><td>ISO8601</td></tr><tr><td><code>app_id</code></td><td>string(100)</td><td>true</td><td>Valorizzarlo nel formato <code>&#x3C;nome-proxy>:&#x3C;versione-proxy></code><br>Es.<br><code>iris-payment-proxy:1.3.0</code></td></tr></tbody></table>

#### PaymentData

<table><thead><tr><th width="204">Campo</th><th width="226">Tipo</th><th width="135" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>type</code></td><td>Enum</td><td>false</td><td><strong>Valori permessi:</strong><br><code>PAGOPA</code> nel caso in cui si tratto di un dovuto standard<br><code>STAMP</code> nel caso in cui si tratta di un dovuto di tipo marca da bollo digitale</td></tr><tr><td><code>transaction_id</code></td><td>string(255)</td><td>false</td><td>Fornito dall'intermediario di pagamento. La lunghezza dunque può essere variabile</td></tr><tr><td><code>paid_at</code></td><td>Datetime</td><td>false</td><td>ISO8601</td></tr><tr><td><code>expire_at</code></td><td>Datetime</td><td>true</td><td>ISO8601<br><br>E' già valorizzato a priori, quindi non viene gestito dal proxy</td></tr><tr><td><code>amount</code></td><td>float</td><td>true</td><td>E' già valorizzato a priori, quindi non viene gestito dal proxy</td></tr><tr><td><code>reason</code></td><td>string(140)</td><td>false</td><td>Causale del pagamento. Non può eccedere i 140 caratteri.</td></tr><tr><td><code>currency</code></td><td>string(3)</td><td>true</td><td>ISO4217</td></tr><tr><td><code>notice_code</code></td><td>string(50)</td><td>false</td><td></td></tr><tr><td><code>iud</code></td><td>string(50)</td><td>true</td><td>è il valore del campo <code>id</code> del pagamento in formato esadecimale<br>Es.<br>id: <code>4a263efb-300b-437a-ab50-116fa9aff8a7</code><br>iud: <code>4a263efb30</code>0b-437aab50116fa9aff8a7</td></tr><tr><td><code>iuv</code></td><td>string(50)</td><td>false</td><td></td></tr><tr><td><code>receiver</code></td><td>Receiver</td><td>false</td><td>Destinatario o beneficiario del versamento/dovuto</td></tr><tr><td><code>due_type</code></td><td>string(256)</td><td>false</td><td>Tipo di dovuto secondo la classificazione dell'intermediario di riferiemento</td></tr><tr><td><code>pagopa_category</code></td><td>string(12)</td><td>false</td><td>Tipo di dovuto secondo la <a href="https://api.opencityitalia.it/datasets/pagopa">tassonomia</a> ufficiale di pagoPA</td></tr><tr><td><code>document</code></td><td>Document</td><td>false</td><td>Contiene le informazioni riguardanti il documento informatico o la segnatura di protocollo cui è associata la marca da bollo digitale</td></tr><tr><td><code>split</code></td><td>List[PaymentDataSplit]</td><td>false</td><td></td></tr></tbody></table>

#### Receiver

<table><thead><tr><th width="306">Campo</th><th width="143">Tipo</th><th width="126" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>tax_identification_number</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>name</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>iban</code></td><td>string(34)</td><td>false</td><td>ISO 13616</td></tr><tr><td><code>street_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>building_number</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>postal_code</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>town_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>country_subdivision</code></td><td>string(2)</td><td>false</td><td>ISO 3166-2</td></tr><tr><td><code>country</code></td><td>string(2)</td><td>false</td><td>ISO 3166-1 alpha-2</td></tr></tbody></table>

#### Document

<table><thead><tr><th>Campo</th><th>Tipo</th><th data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>id</code></td><td>UUID</td><td>false</td><td>Identificativo del documento</td></tr><tr><td><code>ref</code></td><td>string</td><td>false</td><td>Url per scaricare il documento</td></tr><tr><td><code>hash</code></td><td>string</td><td>true</td><td>Hash digest del documento informatico</td></tr></tbody></table>

#### PaymentDataSplit

<table><thead><tr><th width="200">Campo</th><th>Tipo</th><th data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td>code</td><td>string(50)</td><td>true</td><td></td></tr><tr><td>amount</td><td>float</td><td>false</td><td></td></tr><tr><td>meta</td><td>json</td><td>false</td><td></td></tr></tbody></table>

#### Links

<table><thead><tr><th width="277">Campo</th><th width="201">Tipo</th><th data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>online_payment_begin</code></td><td>UrlData</td><td>true</td><td></td></tr><tr><td><code>online_payment_landing</code></td><td>UrlData</td><td>true</td><td></td></tr><tr><td><code>offline_payment</code></td><td>UrlData</td><td>true</td><td></td></tr><tr><td><code>receipt</code></td><td>UrlData</td><td>true</td><td></td></tr><tr><td><code>notify</code></td><td>List[Notify]</td><td>false</td><td></td></tr><tr><td><code>update</code></td><td>Update</td><td>true</td><td></td></tr><tr><td>confirm</td><td>UrlData</td><td>true</td><td></td></tr><tr><td>cancel</td><td>UrlData</td><td>true</td><td></td></tr></tbody></table>

#### UrlData

<table><thead><tr><th>Campo</th><th>Tipo</th><th width="170" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>false</td><td></td></tr><tr><td><code>last_opened_at</code></td><td>Datetime</td><td>false</td><td>ISO8601</td></tr><tr><td><code>method</code></td><td>Enum</td><td>false</td><td><strong>Valori permessi:</strong><br><code>GET</code><br><code>POST</code><br><code>PUT</code><br><code>PATCH</code><br><code>DELETE</code></td></tr></tbody></table>

#### Notify

<table><thead><tr><th>Campo</th><th>Tipo</th><th width="138" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>false</td><td></td></tr><tr><td><code>method</code></td><td>Enum</td><td>false</td><td><strong>Valori permessi:</strong><br>GET<br>POST</td></tr><tr><td><code>sent_at</code></td><td>Datetime</td><td>false</td><td>ISO8601</td></tr></tbody></table>

#### Update

<table><thead><tr><th>Campo</th><th>Tipo</th><th width="154" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>url</code></td><td>string</td><td>false</td><td></td></tr><tr><td><code>last_check_at</code></td><td>Datetime</td><td>false</td><td>ISO8601</td></tr><tr><td><code>next_check_at</code></td><td>Datetime</td><td>false</td><td>ISO8601</td></tr><tr><td><code>method</code></td><td>Enum</td><td>false</td><td><strong>Valori permessi:</strong><br>GET<br>POST</td></tr></tbody></table>

#### Payer

<table><thead><tr><th width="306">Campo</th><th width="143">Tipo</th><th width="131" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>type</code></td><td>Enum</td><td>true</td><td><strong>Valori permessi:</strong><br>human<br>legal</td></tr><tr><td><code>tax_identification_number</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>name</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>family_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>street_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>building_number</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>postal_code</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>town_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>country_subdivision</code></td><td>string(2)</td><td>false</td><td>ISO 3166-2</td></tr><tr><td><code>country</code></td><td>string(2)</td><td>false</td><td>ISO 3166-1 alpha-2</td></tr><tr><td><code>email</code></td><td>string(255)</td><td>false</td><td></td></tr></tbody></table>

#### Debtor

<table><thead><tr><th width="306">Campo</th><th width="143">Tipo</th><th width="123" data-type="checkbox">Obbligatorio</th><th>Validazione</th></tr></thead><tbody><tr><td><code>type</code></td><td>Enum</td><td>true</td><td><strong>Valori permessi:</strong><br>human<br>legal</td></tr><tr><td><code>tax_identification_number</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>name</code></td><td>string(255)</td><td>true</td><td></td></tr><tr><td><code>family_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>street_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>building_number</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>postal_code</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>town_name</code></td><td>string(255)</td><td>false</td><td></td></tr><tr><td><code>country_subdivision</code></td><td>string(2)</td><td>false</td><td>ISO 3166-2</td></tr><tr><td><code>country</code></td><td>string(2)</td><td>false</td><td>ISO 3166-1 alpha-2</td></tr><tr><td><code>email</code></td><td>string(255)</td><td>false</td><td></td></tr></tbody></table>

## Flussi

Punti aperti

1. **Determinazione delle URL di ritorno**: Come si gestiscono le URL di ritorno? È possibile utilizzare l'indirizzo del proxy per gestire i redirect?
2. **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?

### Configurazione Pagamento

#### Happy Path

```mermaid
sequenceDiagram
    participant Admin(frontend)
    participant Core
    participant Payment Proxy

    Admin(frontend)->>Core: Configura 1-5 pagamenti sul servizio
    Core->>Payment Proxy: Inserisce 1-5 configurazioni di pagamento (/configs)
    Payment Proxy-->>Core: Restituisce configurazioni di pagamento
    Core->>Core: Salva identificativi delle configurazioni e la fase in cui necessario attivare il pagamento
    Core-->>Admin: Conferma configurazioni inserite
```

#### Error Path

```mermaid
sequenceDiagram
    participant Admin as Admin (frontend)
    participant Core
    participant Payment Proxy

    Admin->>Core: Configura 1-5 pagamenti sul servizio
    Core->>Payment Proxy: Inserisce 1-5 configurazioni di pagamento (/configs)
    
    alt Configurazioni inserite con successo
        Payment Proxy-->>Core: Restituisce configurazioni di pagamento
        Core->>Core: Salva identificativi delle configurazioni e la fase del pagamento
        Core-->>Admin: Conferma configurazioni inserite
    else Errore nell'inserimento della configurazione
        Payment Proxy-->>Core: Restituisce json di errore
        Core-->>Admin: Mostra alert di errore
    end
```

### Compilazione Pratica

1. **Compilazione e invio pratica**: L'utente compila la pratica per il servizio e invia la richiesta al Core.
2. **Verifica pagamenti**: Il Core verifica se, nella fase attuale della pratica, è necessario effettuare dei pagamenti (es. pagamento anticipato o posticipato).
3. **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).
4. **Restituzione della pratica**: Una volta ottenuti gli ID dei pagamenti, il Core restituisce all'utente l'intera pratica aggiornata con gli identificativi.

#### Punti aperti:

**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**.

#### Happy Path

```mermaid
sequenceDiagram
    participant U as User(frontend)
    participant Core
    participant PDAPI as Payment Dispatcher API
    participant RM as Read Model
    participant Payment Proxy
    participant Checkout pagoPA API
    participant pagoPA

    U->>Core: Compila pratica per il servizio
    U->>Core: Invia pratica
    Core->>PDAPI: Richiede creazione pagamenti
    PDAPI-->>Core: Restituisce gli id dei pagamenti creati
    Core-->>U: Restituisce l'intera pratica con gli id dei pagamenti creati
    Note over Core, PDAPI: quest'interazione serve in quanto la stanza (core) <br>deve salvare il pagamento nel punto corretto <br>del flusso della pratica (pagamento anticipato/posticipato)

    U->>RM: attendo aggiornamenti sui pagamenti
    RM-->>U: stato pagamento
    U->>Checkout pagoPA API: Invia id dei pagamenti creati (/payment)
    Checkout pagoPA API-->>U: Restituisce link carrello pagoPA
```

#### Error Path - Creazione Pagamenti

```mermaid
sequenceDiagram
    participant U as User (frontend)
    participant Core
    participant PDAPI as Payment Dispatcher API
    participant RM as Read Model
    participant Payment Proxy
    participant Retry Orchestrator

    U->>Core: Compila pratica per il servizio
    U->>Core: Invia pratica
    
    loop Per ogni configurazione valida
        loop Retry creazione pagamento su Payment Dispatcher (max 3 tentativi)
            Core->>PDAPI: Richiede creazione pagamento (/payment)
            alt Creazione riuscita
                PDAPI-->>Core: Restituisce id pagamento creato
            else Creazione fallita o nessuna risposta
                PDAPI-->>Core: Restituisce errore
                Core->>Core: Incrementa il contatore dei tentativi
            end
        end
    end

    Core-->>U: Restituisce l'intera pratica con gli id dei pagamenti creati
    Note over Core, PDAPI: quest'interazione serve in quanto la stanza (core) <br>deve salvare il pagamento nel punto corretto <br>del flusso della pratica (pagamento anticipato/posticipato)

    alt Creazione riuscita
        Core->>RM: Attende aggiornamenti dal Read Model
        loop Controllo stato pagamento
            RM-->>Core: Restituisce stato del pagamento
            alt Stato CREATION_FAILED
                Core->>Retry Orchestrator: Delego retry al Retry Orchestrator
                Retry Orchestrator->>Kafka: Gestisce retry attraverso i topic di Kafka
                alt Retry completato con successo
                    Kafka-->>Retry Orchestrator: Creazione riuscita
                    Retry Orchestrator-->>Core: Pagamento creato
                    Core->>RM: Attende nuovi aggiornamenti dal Read Model
                    RM-->>Core: Stato pagamento aggiornato (PAYMENT_PENDING)
                    Core-->>U: Mostra informazioni pagamento
                else Retry fallito
                    Retry Orchestrator-->>Core: Restituisce errore dopo vari tentativi
                    Core-->>U: Mostra alert di errore
                end
            else Stato PAYMENT_PENDING
                Core-->>U: Mostra informazioni pagamento
            end
        end
    else Superato numero massimo di tentativi
        Core-->>U: Mostra alert di errore
    end
```

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:

1. **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.
2. **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**.
3. **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.
4. **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.
5. **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.

#### Error Path - Creazione Carrello Pagamenti

* **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.

```mermaid
sequenceDiagram
    participant U as User (frontend)
    participant Checkout as Checkout pagoPA API
    participant pagoPA

    U->>Checkout: Invia id dei pagamenti creati (/payment)
    alt Creazione link carrello riuscita
        Checkout-->>U: Restituisce link carrello pagoPA
    else Errore nella creazione del carrello
        Checkout-->>U: Mostra errore di creazione carrello
    end
    
    Note over U, pagoPA: L'utente viene reindirizzato alla pagina di pagoPA

```

### Creazione pagamento posticipato da operatore

```mermaid
sequenceDiagram
    participant U as User (frontend)
    participant Core
    participant PDAPI as Payment Dispatcher API
    participant RM as Read Model
    participant Payment Proxy
    participant Retry Orchestrator

    U->>Core: Modifica configurazioni di pagamento
    loop Per ogni configurazione (max 5)
        Core->>Payment Proxy: Crea configurazioni temporanee (/configs)
        alt Configurazione creata con successo
            Payment Proxy-->>Core: Restituisce configurazione
        else Errore nella configurazione
            Payment Proxy-->>Core: Restituisce errore
            Core-->>U: Mostra errore e richiede correzione
        end
    end

    loop Per ogni configurazione valida
        loop Retry creazione pagamento su Payment Dispatcher (max 3 tentativi)
            Core->>PDAPI: Richiede creazione pagamento (/payment)
            alt Creazione riuscita
                PDAPI-->>Core: Restituisce id pagamento creato
            else Creazione fallita o nessuna risposta
                PDAPI-->>Core: Restituisce errore
                Core->>Core: Incrementa il contatore dei tentativi
            end
        end
    end

    alt Creazione riuscita
        Core->>RM: Attende aggiornamenti dal Read Model
        loop Controllo stato pagamento
            RM-->>Core: Restituisce stato del pagamento
            alt Stato CREATION_FAILED
                Core->>Retry Orchestrator: Delego retry al Retry Orchestrator
                Retry Orchestrator->>Kafka: Gestisce retry attraverso i topic di Kafka
                alt Retry completato con successo
                    Kafka-->>Retry Orchestrator: Creazione riuscita
                    Retry Orchestrator-->>Core: Pagamento creato
                    Core->>RM: Attende nuovi aggiornamenti dal Read Model
                    RM-->>Core: Stato pagamento aggiornato (PAYMENT_PENDING)
                    Core-->>U: Mostra informazioni pagamento
                else Retry fallito
                    Retry Orchestrator-->>Core: Restituisce errore dopo vari tentativi
                    Core-->>U: Mostra alert di errore
                end
            else Stato PAYMENT_PENDING
                Core-->>U: Mostra informazioni pagamento
            end
        end
    else Superato numero massimo di tentativi
        Core-->>U: Mostra alert di errore
    end
```

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:

1. **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.
2. **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.
3. **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.
4. **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.
5. **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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.opencityitalia.it/stanza-del-cittadino/sviluppatori-e-partner-tecnologici/integrazioni/integrazione-con-intermediari-di-pagamento-pagopa/il-pagamento/versione-2.0.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
