# Un pagamento in dettaglio

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2FgAgdGIctaTPbvim25VCC%2FScreenshot%202023-10-26%20alle%2017.17.51.png?alt=media&#x26;token=c566864a-bf61-4f36-879c-d0268f56d607" alt=""><figcaption></figcaption></figure>

### Premessa

Essendo il sistema in questione costruito su un'architettura a eventi, è fondamentale che il `payment proxy` controlli la versione dell'evento Payment (campo `event_version`) prima di processarlo e dichiari con quale versione dell'evento quest'ultimo è compatibile. L'evento qui descritto ha versione `2.0`.

### Step 1

L'utente compila e invia la pratica, la quale viene inserita come evento nel topic `applications`&#x20;

Un esempio di evento è il seguente, si faccia particolare attenzione al blocco `payment_data`:

{% code fullWidth="false" %}

```json
{
  "app_version": "2.6.0-rc.7",
  "attachments": [],
  "authentication": {
    "authentication_method": "cps/cns",
    "certificate": "DQpSZXN1bHQgZ29lcyBoZXJlLi4uDQpCYXNlNjQNCg0KQmFzZTY0IGlzIGEgZ2VuZXJpYyB0ZXJtIGZvciBhIG51bWJlciBvZiBzaW1pbGFyIGVuY29kaW5nIHNjaGVtZXMgdGhhdCBlbmNvZGUgYmluYXJ5IGRhdGEgYnkgdHJlYXRpbmcgaXQgbnVtZXJpY2FsbHkgYW5kIHRyYW5zbGF0aW5nIGl0IGludG8gYSBiYXNlIDY0IHJlcHJlc2VudGF0aW9uLiBUaGUgQmFzZTY0IHRlcm0gb3JpZ2luYXRlcyBmcm9tIGEgc3BlY2lmaWMgTUlNRSBjb250ZW50IHRyYW5zZmVyIGVuY29kaW5nLg==",
    "certificate_issuer": "FAKE_issuerdn",
    "certificate_subject": "FAKE_subjectdn",
    "instant": "2000-01-01T00-00Z",
    "session_id": "abc123abc123abc123abc123abc123abc123abc123",
    "session_index": "abc123abc123abc123abc123abc123abc123abc123",
    "spid_code": null,
    "spid_level": null
  },
  "backoffice_data": null,
  "compiled_modules": [],
  "created_at": "2022-12-06T17:43:42+01:00",
  "creation_time": 1670345022,
  "data": {
    "applicant.data.Born.data.natoAIl": "1976-09-01T00:00:00+02:00",
    "applicant.data.Born.data.place_of_birth": "Ponte di Piave",
    "applicant.data.address.data.address": "Via Gramsci, 1",
    "applicant.data.address.data.county": "PI",
    "applicant.data.address.data.house_number": "",
    "applicant.data.address.data.municipality": "Bugliano",
    "applicant.data.address.data.postal_code": "56056",
    "applicant.data.completename.data.name": "Vittorino",
    "applicant.data.completename.data.surname": "Coliandro",
    "applicant.data.email_address": "raffaele.luccisano@opencontent.it",
    "applicant.data.fiscal_code.data.fiscal_code": "CLNVTR76P01G822Q",
    "applicant.data.gender.data.gender": "maschio",
    "payment_amount": "1,34"
  },
  "event_created_at": "2022-12-06T17:43:51+01:00",
  "event_id": "01e86cd4-8263-4ac0-a229-8cada5916eae",
  "event_version": 2,
  "flow_changed_at": "2022-12-06T17:43:51+01:00",
  "id": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e",
  "integrations": [],
  "latest_status_change_at": "2022-12-06T17:43:51+01:00",
  "latest_status_change_time": 1670345031,
  "links": [],
  "meetings": [],
  "outcome": null,
  "outcome_attachments": [],
  "outcome_file": null,
  "outcome_motivation": null,
  "outcome_protocol_document_id": null,
  "outcome_protocol_number": null,
  "outcome_protocol_numbers": null,
  "outcome_protocol_time": null,
  "outcome_protocolled_at": null,
  "path": "/applications",
  "payment_data": {
    "amount": "1.34",
    "expire_at": "2023-03-06T17:43:51+01:00",
    "landing": {
      "method": "GET",
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/detail"
    },
    "notify": {
      "method": "POST",
      "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/payment"
    },
    "reason": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e - CLNVTR76P01G822Q",
    "split": []
  },
  "payment_type": "efil",
  "protocol_document_id": null,
  "protocol_folder_code": null,
  "protocol_folder_number": null,
  "protocol_number": null,
  "protocol_numbers": [],
  "protocol_time": null,
  "protocolled_at": null,
  "service": "pagamento-immediato-efil",
  "service_group_name": null,
  "service_id": "daa0f528-b582-4d1c-9691-e226ac443424",
  "service_name": "Pagamento immediato EFIL",
  "source_type": "http",
  "status": "1500",
  "status_name": "status_payment_pending",
  "subject": null,
  "submission_time": null,
  "submitted_at": null,
  "tenant": "60e35f02-1509-408c-b101-3b1a28109329",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "timestamp": "2022-12-06T16:43:51.829146577Z",
  "user": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "user_compilation_notes": null,
  "user_name": "Vittorino Coliandro",
  "x-forwarded-for": "172.31.73.11"
}
```

{% endcode %}

### Step 2

Il **payment** **dispatcher** legge l'evento della pratica dal topic `applications`, e dopo aver controllato mediante query su `KSQLDB` che il pagamento per tale pratica non sia già stato creato, estrae da esso i dati del pagamento, successivamente li riversa in un nuovo evento di tipo `Payment` e lo inserisce nel topic `payments` in stato `CREATION_PENDING`, indicando come chiave dell'evento il valore del campo `service_id`. Da qui in poi **solo** il proxy si occuperà di scrivere sul topic `payments`.

```json
{
  "id": "2cc87ee5-3f57-4f20-a703-e6718c21b95b",
  "user_id": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "daa0f528-b582-4d1c-9691-e226ac443424",
  "created_at": "2022-12-06T17:43:52+01:00",
  "updated_at": "2022-12-06T17:43:52+01:00",
  "status": "CREATION_PENDING",
  "reason": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e - CLNVTR76P01G822Q",
  "remote_id": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e",
  "payment": {
    "transaction_id": null,
    "paid_at": null,
    "expire_at": "2023-03-06T17:43:51+01:00",
    "amount": 1.34,
    "currency": "EUR",
    "notice_code": null,
    "iud": "2cc87ee53f574f20a703e6718c21b95b",
    "iuv": null,
    "receiver": null,
    "due_type": null,
    "pagopa_category": "9/12129/TS",
    "document": null,
    "split": []
  },
  "links": {
    "online_payment_begin": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/detail",
      "last_opened_at": null,
      "method": "GET"
    },
    "offline_payment": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "receipt": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": null,
      "last_check_at": null,
      "next_check_at": null,
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": null
    },
    "cancel": {
      "url": null
      "last_opened_at": null,
      "method": null
    }    
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "CLNVTR76P01G822Q",
    "name": "Vittorino",
    "family_name": "Coliandro",
    "street_name": "Via Gramsci, 1",
    "building_number": "",
    "postal_code": "56056",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "raffaele.luccisano@opencontent.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": "c3ecf316-ca76-4bf3-ab72-26b941a5ce4f",
  "event_version": "2.0",
  "event_created_at": "2022-12-06T17:43:52+01:00",
  "app_id": "payment-dispatcher:1.1.3"
}
```

### Step 3

Il proxy legge dal topic `payments` e, se ha una configurazione attiva per quel pagamento (quindi se l'evento letto ha un `tenant_id` e un `service_id` per cui ha una configurazione salvata nello storage del proxy), crea una posizione debitoria sull'Intermediario di riferimento.&#x20;

### Step 3 - Marca da Bollo Digitale

È possibile che la configurazione relativa al pagamento letto dal topic `payments` abbia configurato al suo interno una marca da bollo digitale. In tal caso, sarà necessario, per ogni marca da bollo digitale, inserire come minimo le seguenti informazioni all'interno del payload da inviare all'intermediario di pagamento con cui ci si sta integrando (in base a poi all'intermediario potrebbero essere necessari altri campi):

1. Il taglio della marca da bollo o l'importo inserito nella configurazione (per ora l'unico importo supportato è quello da 16 €)
2. La provincia di residenza del pagatore, la quale si trova nel campo `payer.country_subdivision` dell'evento payment
3. L'hash del documento informatico o della segnatura di protocollo cui è associata la marca da bollo digitale (per semplicità il documento in questione sarà il json dell'evento letto dal topic `payments`)
4. Il valore del campo `reason` letto dall'evento nel topic `payments` o, in assenza di questo, la causale della marca da bollo inserita nella configurazione

Successivamente, sarà necessario:

* Valorizzare il campo `payment.amount` l'importo della marca da bollo inserita in configurazione&#x20;
* Valorizzare il campo `payment.due_type` con il tipo di dovuto inserito nella configurazione
* Valorizzare il campo `payment.pagopa_category` con il valore della tassonomia di pagoPA contenuta nella configurazione (se presente)
* Valorizzare il campo `payment.document.hash` contenente l'hash del documento informatico o della segnatura di protocollo cui è associata la marca da bollo digitale

### Step 3 - Bilancio fisso

ATTENZIONE: questa struttura sarà presente **solo** sugli eventi payment con `event_version` valorizzato a `2.0` , sarà necessario dunque controllare la versione dell'evento prima di processarlo&#x20;

In alcuni casi è possibile che il pagamento che il proxy deve processare presenti un bilancio fisso, ovvero un bilancio i cui importi per ogni voce sono già predeterminati a priori in fase di configurazione del servizio. In tal caso il campo `split`, quando letto dal proxy per la prima volta, si presenterà come un array vuoto `[]`, il proxy dunque:

1. Leggerà il campo `service_id` e reperirà nel mediante esso la configurazione del servizio dentro il quale ci sono le informazioni del bilancio.
2. Utilizzerà le informazioni ricavate per popolare il payload di creazione della posizione debitoria sull'intermediario di riferimento e per arricchire l'evento appena letto con i dati del bilancio.

#### **Esempio**

Nel proxy è configurato per il servizio **A** il seguente bilancio

```json
{
  "split": [
    {
      "split_id": "c_1",
      "split_type": "Tipo c1",
      "split_code": "Codice c1",
      "split_description": "Descrizione c1",
      "split_amount": "16.00",
      "split_budget_chapter": "Capitolo di bilancio c1",
      "split_assessment": "Accertamento c1"
    },
    {
      "split_id": "c_2",
      "split_type": "Tipo c2",
      "split_code": "Codice c2",
      "split_description": "Descrizione c12",
      "split_assessment": "0.50",
      "split_budget_chapter": "Capitolo di bilancio c2",
      "split_assessment": "Accertamento c2"
    }
  ]
}
```

Il bilancio da utilizzare per arricchire il campo `split` del pagamento sarà:

```json
{
  "split": [
    {
      "code": "c_1",
      "amount": "16.00",
      "meta": {
        "split_type": "Tipo c1",
        "split_code": "Codice c1",
        "split_description": "Descrizione c1",
        "split_budget_chapter": "Capitolo di bilancio c1",
        "split_assessment": "Accertamento c1"
      }
    },
    {
      "code": "c_2",
      "amount": "0.50",
      "meta": {
        "split_type": "Tipo c2",
        "split_code": "Codice c2",
        "split_description": "Descrizione c12",
        "split_budget_chapter": "Capitolo di bilancio c2",
        "split_assessment": "Accertamento c2"
      }
    }
  ]
}
```

### Step 3 - Bilancio variabile

In alcuni casi è possibile che il pagamento che il proxy deve processare presenti un bilancio variabile, ovvero un bilancio i cui importi per ogni voce vengono determinati dinamicamente a seconda del cittadino. In tal caso il campo `split` , quando letto dal proxy per la prima volta, si presenterà con un payload così strutturato

<pre class="language-json"><code class="lang-json"><strong>[
</strong><strong>  {
</strong>    "code": "c_1",
    "amount" : "14.00",
    "meta": {}
  },
  {
    "code": "c_2",
    "amount" : "2.50",
    "meta": {}
  }
]
</code></pre>

oppure così nel caso in cui il cittadino sia esentato dal pagamento di una certa voce del bilancio

```json
[
  {
    "code": "c_1",
    "amount" : null,
    "meta": {}
  },
  {
    "code": "c_2",
    "amount" : "0.50",
    "meta": {}
  }
]
```

dove il campo `code` indica un identificativo interno della voce di bilancio determinato in fase di configurazione del servizio, e il campo `amount` indica l'importo per ogni voce di bilancio. Nel caso in cui il valore di `amount` sia `null` significa che quella riga deve essere eliminata in fase di creazione del pagamento sul gateway. Il proxy dunque:

1. Leggerà il campo `service_id` e reperirà mediante esso la configurazione del servizio dentro il quale ci sono le informazioni del bilancio.
2. Per ogni voce di bilancio ricavata dalla configurazione del servizio verrà sostituito l'importo con quello letto nel campo `split` del pagamento
3. Utilizzerà le informazioni ricavate per popolare il payload di creazione della posizione debitoria sull'intermediario di riferimento e per arricchire l'evento appena letto con i dati del bilancio.

#### **Esempio 1**

Nel proxy è configurato per il servizio **A** il seguente bilancio

```json
{
  "split": [
    {
      "split_id": "c_1",
      "split_type": "Tipo c1",
      "split_code": "Codice c1",
      "split_description": "Descrizione c1",
      "split_amount": "16.00",
      "split_budget_chapter": "Capitolo di bilancio c1",
      "split_assessment": "Accertamento c1"
    },
    {
      "split_id": "c_2",
      "split_type": "Tipo c2",
      "split_code": "Codice c2",
      "split_description": "Descrizione c12",
      "split_assessment": "0.50",
      "split_budget_chapter": "Capitolo di bilancio c2",
      "split_assessment": "Accertamento c2"
    }
  ]
}
```

Nel messaggio del topic payments il campo `split` è valorizzato a

```json
[
  {
    "code": "c_1",
    "amount" : "14.00",
    "meta": {}
  },
  {
    "code": "c_2",
    "amount" : "2.50",
    "meta": {}
  }
]
```

Il bilancio da utilizzare per arricchire il campo `split` del pagamento sarà:

```json
{
  "split": [
    {
      "code": "c_1",
      "amount": "14.00",
      "meta": {
        "split_type": "Tipo c1",
        "split_code": "Codice c1",
        "split_description": "Descrizione c1",
        "split_budget_chapter": "Capitolo di bilancio c1",
        "split_assessment": "Accertamento c1"
      }
    },
    {
      "code": "c_2",
      "amount": "2.50",
      "meta": {
        "split_type": "Tipo c2",
        "split_code": "Codice c2",
        "split_description": "Descrizione c12",
        "split_budget_chapter": "Capitolo di bilancio c2",
        "split_assessment": "Accertamento c2"
      }
    }
  ]
}
```

#### **Esempio 2**

Nel proxy è configurato per il servizio **a** il seguente bilancio

```json
{
  "split": [
    {
      "split_id": "c_1",
      "split_type": "Tipo c1",
      "split_code": "Codice c1",
      "split_description": "Descrizione c1",
      "split_amount": "16.00",
      "split_budget_chapter": "Capitolo di bilancio c1",
      "split_assessment": "Accertamento c1"
    },
    {
      "split_id": "c_2",
      "split_type": "Tipo c2",
      "split_code": "Codice c2",
      "split_description": "Descrizione c12",
      "split_assessment": "0.50",
      "split_budget_chapter": "Capitolo di bilancio c2",
      "split_assessment": "Accertamento c2"
    }
  ]
}
```

Nel messaggio del topic `payments` il campo `split` è valorizzato a

```json
[
  {
    "code": "c_1",
    "amount" : null,
    "meta": {}
  },
  {
    "code": "c_2",
    "amount" : "0.50",
    "meta": {}
  }
]
```

Il bilancio da utilizzare per arricchire il campo `split` del pagamento sarà:

```json
{
  "split": [
    {
      "code": "c_2",
      "amount": "0.50",
      "meta": {
        "split_type": "Tipo c2",
        "split_code": "Codice c2",
        "split_description": "Descrizione c12",
        "split_budget_chapter": "Capitolo di bilancio c2",
        "split_assessment": "Accertamento c2"
      }
    }
  ]
}
```

### Step 4

In caso di risposta positiva:

1. Il pagamento viene passato in stato `PAYMENT_PENDING` modificando il campo `status`,&#x20;
2. Vengono compilate le informazioni del bilancio nel campo `split` (se presenti),&#x20;
3. Viene compilata l'url per pagare online (`links.online_payment_begin.url`), la quale è data dalla concatenazione della variabile d'ambiente `EXTERNAL_API_URL` alla stringa `/online-payment/{payment_id}`&#x20;
4. Viene compilata l'url di ritorno dal pagamento (`links.online_payment_landing.url`), la quale è data dalla concatenazione della variabile d'ambiente `EXTERNAL_API_URL` alla stringa `/landing/{payment_id}`&#x20;
5. Viene compilata l'url per pagare offline (`links.offline_payment.url`), la quale è è data dalla concatenazione della variabile d'ambiente `EXTERNAL_API_URL` alla stringa `/offline-payment/{payment_id}` &#x20;
6. Viene compilata l'url della ricevuta di pagamento (`links.receipt.url`), la quale è data dalla concatenazione della variabile d'ambiente `EXTERNAL_API_URL` alla stringa `/receipt/{payment_id}`&#x20;
7. Viene compilata l'url per richiedere l'aggiornamento del pagamento (`links.update.url`), la quale è data dalla concatenazione della variabile d'ambiente `INTERNAL_API_URL` alla stringa `/update/{payment_id}`
   1. Nota: a differenza dell'altre url, questa viene valorizzata utilizzando una variabile d'ambiente separata in quanto deve essere possibile chiamarla pubblicamente, questo perchè è compito del solo `payments-poller` richiedere periodicamente l'aggiornamento del pagamento.
8. Viene compilata l'url per forzare l'annullamento di un pagamento (`links.cancel.url`), la quale è data dalla concatenazione della variabile d'ambiente `EXTERNAL_API_URL` alla stringa `/payments/{payment_id}` . Viene inoltre compilato il metodo con cui chiamare la url (`links.cancel.method`) con il valore `PATCH`.
9. Viene segnato il timestamp di aggiornamento dell'evento di pagamento (`updated_at`)
10. Viene infine salvato il pagamento sullo storage e scritto il corrispondente evento aggiornato sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`.

```json
{
  "id": "2cc87ee5-3f57-4f20-a703-e6718c21b95b",
  "user_id": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "daa0f528-b582-4d1c-9691-e226ac443424",
  "created_at": "2022-12-06T17:43:52+01:00",
  "updated_at": "2022-12-06T17:43:53+01:00",
  "status": "PAYMENT_PENDING",
  "reason": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e - CLNVTR76P01G822Q",
  "remote_id": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e",
  "payment": {
    "transaction_id": null,
    "paid_at": null,
    "expire_at": "2023-03-06T17:43:51+01:00",
    "amount": 1.34,
    "currency": "EUR",
    "notice_code": "302872234000000343",
    "iud": "2cc87ee53f574f20a703e6718c21b95b",
    "iuv": "02872234000000343",
    "receiver": null,
    "due_type": "TARI",
    "pagopa_category": "9/12129/TS",
    "document": null,
    "split": []
  },
  "links": {
    "online_payment_begin": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/online-payment/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/detail",
      "last_opened_at": null,
      "method": "GET"
    },
    "offline_payment": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/notice/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "receipt": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/receipt/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": "http://efil-proxy-qa.boat-backplane.opencontent.io/update/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_check_at": null,
      "next_check_at": "2022-12-06T17:43:53+01:00",
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": "PATCH"
    },
    "cancel": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/payments/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "PATCH"
    } 
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "CLNVTR76P01G822Q",
    "name": "Vittorino",
    "family_name": "Coliandro",
    "street_name": "Via Gramsci, 1",
    "building_number": "",
    "postal_code": "56056",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "raffaele.luccisano@opencontent.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": "aa716d45-f56c-4b38-8c62-668a48818a04",
  "event_version": "2.0",
  "event_created_at": "2022-12-06T17:43:53+01:00",
  "app_id": "efil-payment-proxy-qa:1.2.2"
}
```

In caso di risposta negativa, il pagamento viene passato in stato `CREATION_FAILED`, viene salvato il pagamento sullo storage e viene scritto l'evento aggiornato sul topic `payments`

```json
{
  "id": "7037158b-f990-46d9-9377-1392adb81186",
  "user_id": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "b2c33452-a741-4841-acc1-69a2c007e398",
  "created_at": "2022-11-22T17:39:38+01:00",
  "updated_at": "2022-11-22T17:39:38+01:00",
  "status": "CREATION_FAILED",
  "reason": "84a4bc4b-6eaf-4ea2-b4bc-0c4d73b05c6c - CLNVTR76P01G822Q",
  "remote_id": "84a4bc4b-6eaf-4ea2-b4bc-0c4d73b05c6c",
  "payment": {
    "transaction_id": null,
    "paid_at": null,
    "expire_at": "2023-02-20T17:39:37+01:00",
    "amount": 1,
    "currency": "EUR",
    "notice_code": null,
    "iud": "7037158bf99046d993771392adb81186",
    "iuv": null,
    "receiver": null,
    "due_type": null,
    "pagopa_category": null,
    "document": null,
    "split": []
  },
  "links": {
    "online_payment_begin": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/84a4bc4b-6eaf-4ea2-b4bc-0c4d73b05c6c/detail",
      "last_opened_at": null,
      "method": "GET"
    },
    "offline_payment": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "receipt": {
      "url": null,
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/84a4bc4b-6eaf-4ea2-b4bc-0c4d73b05c6c/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": null,
      "last_check_at": null,
      "next_check_at": null,
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": "PATCH"
    },
    "cancel": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/payments/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "PATCH"
    }
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "CLNVTR76P01G822Q",
    "name": "Vittorino",
    "family_name": "Coliandro",
    "street_name": "Via Gramsci, 1",
    "building_number": "",
    "postal_code": "56056",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "raffaele.luccisano@opencontent.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": "8b3452d8-bd5d-4380-b8a6-7e4f551b09d8",
  "event_version": "2.0",
  "event_created_at": "2022-11-22T17:39:39+01:00",
  "app_id": "pmpay-payment-proxy:1.0.0-rc.2"
}
```

Nel core intanto, la UI del cittadino monitora lo stato del pagamento interrogando una tabella su `KSQLDB` creata a partire dal topic payments, e se in stato `PAYMENT_PENDING`, vengono mostrate all'utente le opzioni per pagare

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2FDOQFZDz4fQ8NspGZiDDA%2Fimage.png?alt=media&#x26;token=94157e9e-0d1a-469a-b2da-d832d40ef904" alt=""><figcaption></figcaption></figure>

### Step 4 - "Paga online"

1. Verra richiamata l'url `{EXTERNAL_API_URL}/online-payment/{payment_id}` servita dal proxy
2. Il proxy richiederà all'intermediario di pagamento il link per pagare
3. Sarà segnato il timestamp di apertura del link (`links.online_payment_begin.last_opened_at`)
4. Sarà segnato il timestamp di aggiornamento dell'evento (`updated_at`)&#x20;
5. Il pagamento verrà salvato sullo storage
6. L'evento aggiornato verrà scritto sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`
7. Verrà restituito il link ritornato allo step 2 mediante il quale l'utente verrà rediretto al portale dell'intermediario
8. Al termine della procedura di pagamento, l'utente verrà fatto ritornare sul dettaglio della pratica mediante l'url di landing specificata in fase di creazione della posizione debitoria (`links.online_payment_landing.url`) allo [step 5](#step-5),  a questa url andrà aggiunto in query string un parametro `payment` da valorizzare con `OK` o `KO` a seconda dell'esito del pagamento
9. Contemporaneamente, essendo che si passa per il proxy, verrà segnato il timestamp in cui l'utente ha aperto il link di ritorno  (`links.online_payment_landing.last_opened_at`)
10. Il pagamento verrà portato in stato `PAYMENT_STARTED`
11. Sarà segnato il timestamp di aggiornamento dell'evento (`updated_at`)&#x20;
12. Il pagamento verrà salvato sullo storage&#x20;
13. L'evento aggiornato verrà scritto sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`.&#x20;

```json
{
  "id": "2cc87ee5-3f57-4f20-a703-e6718c21b95b",
  "user_id": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "daa0f528-b582-4d1c-9691-e226ac443424",
  "created_at": "2022-12-06T17:43:52+01:00",
  "updated_at": "2022-12-06T17:44:51+01:00",
  "status": "PAYMENT_STARTED",
  "reason": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e - CLNVTR76P01G822Q",
  "remote_id": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e",
  "payment": {
    "transaction_id": "7b32b299-67db-4f84-9419-f61962c3e202",
    "paid_at": null,
    "expire_at": "2023-03-06T17:43:51+01:00",
    "amount": 1.34,
    "currency": "EUR",
    "notice_code": "302872234000000343",
    "iud": "2cc87ee53f574f20a703e6718c21b95b",
    "iuv": "02872234000000343",
    "receiver": null,
    "due_type": "TARI",
    "pagopa_category": "9/12129/TS",
    "document": null,
    "split": []
  },
  "links": {
    "online_payment_begin": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/online-payment/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": "2022-12-06T17:43:56+01:00",
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/detail",
      "last_opened_at": "2022-12-06T17:44:51+01:00",
      "method": "GET"
    },
    "offline_payment": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/notice/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "receipt": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/receipt/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": "http://efil-proxy-qa.boat-backplane.opencontent.io/update/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_check_at": null,
      "next_check_at": "2022-12-06T17:43:53+01:00",
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": "PATCH"
    },
    "cancel": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/payments/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "PATCH"
    } 
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "CLNVTR76P01G822Q",
    "name": "Vittorino",
    "family_name": "Coliandro",
    "street_name": "Via Gramsci, 1",
    "building_number": "",
    "postal_code": "56056",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "raffaele.luccisano@opencontent.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": "dcd203c7-a6e8-4084-b09b-f700e8fa94d8",
  "event_version": "2.0",
  "event_created_at": "2022-12-06T17:44:51+01:00",
  "app_id": "efil-payment-proxy-qa:1.2.2"
}
```

### Step 4 - "Paga offline"

1. Verra richiamata l'url `{EXTERNAL_API_URL}/offline-payment/{payment_id}` servita dal proxy
2. Il proxy richiederà all'intermediario di pagamento il pdf dell'avviso di pagamento
3. Sarà segnato il timestamp di apertura del link (`links.offline_payment.last_opened_at`)
4. Sarà segnato il timestamp di aggiornamento dell'evento (`updated_at`)&#x20;
5. Il pagamento verrà salvato sullo storage
6. L'evento aggiornato verrà scritto sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`
7. Verrà eseguito il download del pdf ritornato allo step 1

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2FHy1LLveptCJ37UeLIvR2%2Fimage.png?alt=media&#x26;token=d0f730d4-a0f7-48f8-9ede-e3d18d5e433b" alt=""><figcaption><p>Esempio di avviso di pagamento generato</p></figcaption></figure>

### Step 4 - Annulla pagamento

È possibile che l'operatore abbia necessità di annullare un pagamento mediante l'opzione di registrazione del pagamento, ciò può accadere ad esempio se il cittadino, dopo aver creato il pagamento, decide di non concluderlo, e di pagare invece mediante altri canali creando un nuovo pagamento diverso da quello presente sulla piattaforma. Per evitare quindi di lasciare il pagamento pendente per un tempo indefinito, e per permettere l'avanzamento della pratica all'interno della quale è stato creato tale pagamento, sarà possibile annullare quest'ultimo.&#x20;

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2FEMED4ej7c3gKspw2117X%2Fimage.png?alt=media&#x26;token=1e950c87-019a-4ff0-89ee-93d7d2c15af9" alt=""><figcaption></figcaption></figure>

Gli step sono i seguenti:

1. Verra richiamata l'url  `PATCH {EXTERNAL_API_URL}/payments/{payment_id}` servita dal proxy con payload `{"status": "CANCELED"}`
2. Il proxy, dopo aver letto il pagamento dallo storage, segnerà il campo `status` a `CANCELED`
3. Sarà segnato il timestamp di apertura del link (`links.offline_payment.last_opened_at`)
4. Sarà segnato il timestamp di aggiornamento dell'evento (`updated_at`)&#x20;
5. Il pagamento verrà salvato sullo storage
6. L'evento aggiornato verrà scritto sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`

### Step 4 - Dovuti importati da fonte esterna all'Area personale

In alcuni casi è possibile che i pagamenti non siano generati a partire dall'area personale, ma siano invece importati da una fonte esterna. In questo caso gli eventi relativi a tali pagamenti saranno inseriti nel topic `payments` già in status `PAYMENT_PENDING` e conterranno al loro interno tutte le informazioni che il proxy normalmente inserisce quando fa passare un pagamento generato dall'area personale dallo status `CREATION_PENDING` allo status `PAYMENT_PENDING`.&#x20;

In tal caso tuttavia, questi pagamenti non saranno presenti sullo storage del proxy, dal momento che questa è un'operazione che normalmente farebbe il proxy. Di conseguenza, nel momento in cui dovesse venir letto un evento in stato `PAYMENT_PENDING`, ci fosse una configurazione attiva per quest'ultimo (ciò si determina controllando che ci sia sullo storage una configurazione con `tenant_id` e `service_id` equivalenti a quelli contenuti nel pagamento) ma non esistesse sullo storage, bisogna semplicemente salvare il pagamento sullo storage.

Nel core intanto, questo tipo di dovuti saranno mostrati nella sezione "Pagamenti" insieme a tutti i pagamenti (importati e non) generati dal cittadino, i dati qui presenti sono estratti mediante interrogazione di una tabella su `KSQLDB` creata a partire dal topic payments.

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2FObIpoQnFc9sD3KJLP1Bw%2Fimage.png?alt=media&#x26;token=9442d770-c964-4ed3-badc-c703c8a6465b" alt=""><figcaption></figcaption></figure>

Cliccando su "Vedi dettaglio" si andrà sul dettaglio dello specifico pagamento dove saranno mostrate le opzioni per pagare (online, offline)

<figure><img src="https://2402436129-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNwAiDeLoMPCkkp1BdSbI%2Fuploads%2F4iTpBaxmstvMq5HVBxkz%2Fimage.png?alt=media&#x26;token=94ad2731-0148-49f3-b80b-adff39213ef6" alt=""><figcaption></figcaption></figure>

### Step 5

Il **payments poller** nel frattempo:&#x20;

1. Interroga la tabella `PAYMENTS_DETAIL` per ottenere lo stato dei pagamenti, e se questi sono in stato `PAYMENT_PENDING` o `PAYMENT_STARTED`, eseguirà una chiamata http all'url `{INTERNAL_API_URL}/update/{payment_id}` servita dal proxy (quella di aggiornamento menzionata allo [step 5](#step-5))
2. Il proxy a sua volta recupera dallo storage il pagamento, interroga l'intermediario di riferimento per verificare lo stato del pagamento, e in caso lo aggiorna in stato `COMPLETE` o `PAYMENT_STARTED` (questa casistica può verificarsi nel caso in cui l'utente paghi ma poi chiuda il browser anziche cliccare sul bottone contenente la landing url)
   1. Se il pagamento viene portato in stato `COMPLETE` , si dovrà salvare, se presente come informazione ritornata dall'intemediario di riferimento, il timestamp di avvenuto pagamento (`payment.paid_at`), e l'id della transazione (`payment.transaction_id`)
3. &#x20;Il proxy segna il timestamp in cui è stato aperto il link di aggiornamento (`links.update.last_opened_at`)
4. Il proxy segna il timestamp di aggiornamento del pagamento (`updated_at`)
5. Il proxy salva il pagamento sullo storage e lo scrive sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id`.

**Logica di polling**&#x20;

Più passa il tempo, più è probabile che il pagamento non venga eseguito dall'utente, di conseguenza ad ogni chiamata del poller verso il proxy, viene incrementato l'intervallo di tempo tra una chiamata e l'altra, ciò viene fatto in base al campo `links.update.next_check_at.`

Nello specifico il polling avviene con al seguente logica:

1. **Condizione iniziale**:\
   Se il campo `last_check_at` è nullo (non è stato effettuato alcun controllo in precedenza), la funzione termina immediatamente senza aggiornare il prossimo controllo.
2. **Checkpoint temporali**:\
   La funzione utilizza diversi checkpoint per classificare il tempo trascorso dalla creazione della risorsa:
   1. **5 minuti**
   2. **15 minuti**
   3. **7 giorni**
   4. **30 giorni**
   5. **365 giorni**

Ciascun intervallo ha una frequenza di controllo associata:

* **Fino a 5 minuti**: Controlli ogni **1 minuto**.
* **Fino a 15 minuti**: Controlli ogni **5 minuti**.
* **Fino a 7 giorni**: Controlli ogni **ora**.
* **Fino a 30 giorni**: Controlli ogni **6 ore**.
* **Fino a 365 giorni**: Controlli settimanali, sempre alla fine della settimana corrente.
* **Oltre 365 giorni**: La risorsa è considerata scaduta, lo stato è impostato su `STATUS_EXPIRED` e il prossimo controllo è disabilitato (`next_check_at` impostato a `None`).
* **Impostazione del prossimo controllo**:\
  Se determinato, il `next_check` è aggiornato al valore calcolato
* **Aggiornamento dello stato**:\
  Se il tempo dalla creazione supera i 365 giorni, lo stato della risorsa viene aggiornato a `STATUS_EXPIRED`.

**Nota 2**: non tutti i proxy aggiornano i pagamenti mediante update, alcuni vengono aggiornati predisponendo un'apposita API che l'intermediario di pagamento PagoPA chiama inviando la notifica di completamento del pagamento. Questa viene quindi elaborata dal proxy il quale aggiorna il pagamento portandolo in stato `COMPLETE`, segna il timestamp di aggiornamento del pagamento (`updated_at`), lo salva sullo storage e lo scrive sul topic `payments`, indicando come chiave dell'evento il valore del campo `service_id` .

```json
{
  "id": "2cc87ee5-3f57-4f20-a703-e6718c21b95b",
  "user_id": "1c340b05-0808-4dbe-ad12-81ebbf3b6abf",
  "type": "PAGOPA",
  "tenant_id": "60e35f02-1509-408c-b101-3b1a28109329",
  "service_id": "daa0f528-b582-4d1c-9691-e226ac443424",
  "created_at": "2022-12-06T17:43:52+01:00",
  "updated_at": "2022-12-07T09:47:35+01:00",
  "status": "COMPLETE",
  "reason": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e - CLNVTR76P01G822Q",
  "remote_id": "a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e",
  "payment": {
    "transaction_id": "7b32b299-67db-4f84-9419-f61962c3e202",
    "paid_at": null,
    "expire_at": "2023-03-06T17:43:51+01:00",
    "amount": 1.34,
    "currency": "EUR",
    "notice_code": "302872234000000343",
    "iud": "2cc87ee53f574f20a703e6718c21b95b",
    "iuv": "02872234000000343",
    "receiver": null,
    "due_type": "TARI",
    "pagopa_category": "9/12129/TS",
    "document": null,
    "split": []
  },
  "links": {
    "online_payment_begin": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/online-payment/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": "2022-12-06T17:43:56+01:00",
      "method": "GET"
    },
    "online_payment_landing": {
      "url": "https://servizi.comune.bugliano.pi.it/x/it/pratiche/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/detail",
      "last_opened_at": "2022-12-06T17:44:51+01:00",
      "method": "GET"
    },
    "offline_payment": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/notice/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "receipt": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/receipt/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "GET"
    },
    "notify": [
      {
        "url": "https://servizi.comune.bugliano.pi.it/x/api/applications/a1bbcafb-ee78-4cd1-9b8e-7ddeb434d84e/payment",
        "method": "POST",
        "sent_at": null
      }
    ],
    "update": {
      "url": "http://efil-proxy-qa.boat-backplane.opencontent.io/update/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_check_at": "2022-12-07T09:47:35+01:00",
      "next_check_at": "2022-12-07T10:47:35+01:00",
      "method": "GET"
    },
    "confirm": {
      "url": null,
      "last_opened_at": null,
      "method": "PATCH"
    },
    "cancel": {
      "url": "https://efil-proxy-qa.boat.opencontent.io/payments/2cc87ee5-3f57-4f20-a703-e6718c21b95b",
      "last_opened_at": null,
      "method": "PATCH"
    } 
  },
  "payer": {
    "type": "human",
    "tax_identification_number": "CLNVTR76P01G822Q",
    "name": "Vittorino",
    "family_name": "Coliandro",
    "street_name": "Via Gramsci, 1",
    "building_number": "",
    "postal_code": "56056",
    "town_name": "Bugliano",
    "country_subdivision": "PI",
    "country": "IT",
    "email": "raffaele.luccisano@opencontent.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": "1a745224-37bb-4843-a85f-3011764395a6",
  "event_version": "2.0",
  "event_created_at": "2022-12-07T09:47:35+01:00",
  "app_id": "efil-payment-proxy-qa:1.2.2"
}
```

Il **payment updater** monitora lo stato dei pagamenti leggendo dal topic `payments`, e contestualmente aggiorna lo stato della pratica, se il pagamento è in stato`PAYMENT_STARTED`, aggiorna lo stato della pratica a "In attesa dell'esito di pagamento", se invece il pagamento è in stato `COMPLETE`, aggiorna lo stato della pratica a "Accettata" se il pagamento è posticipato, o Inviata se il pagamento è immediato.

### TABELLA STATI PAGAMENTO

Gli stati per i quali passa un pagamento durante il suo ciclo di vita sono riassunti nella seguente tabella

<table><thead><tr><th width="267.3333333333333">STATO PAGAMENTO</th><th>DESCRIZIONE</th><th>NOTE</th></tr></thead><tbody><tr><td><code>CREATION_PENDING</code></td><td>pagamento in attesa di essere creato sul provider di riferimento</td><td></td></tr><tr><td><code>CREATION_FAILED</code></td><td>pagamento di cui è fallita la creazione sul provider di riferimento</td><td></td></tr><tr><td><code>PAYMENT_PENDING</code></td><td>pagamento creato sul provider di riferimento e in attesa di essere eseguito dall'utente</td><td></td></tr><tr><td><code>PAYMENT_STARTED</code></td><td>procedura di pagamento iniziata dall'utente</td><td></td></tr><tr><td><code>COMPLETE</code></td><td>pagamento completato a seguito di conferma dal provider di riferimento</td><td></td></tr><tr><td><code>PAYMENT_FAILED</code></td><td>pagamento fallito a causa di scadenza del termine ultimo entro cui doveva essere eseguito</td><td>nei proxy sviluppati questo stato non è quasi mai stato utilizzato</td></tr><tr><td><code>CANCELED</code></td><td>pagamento annullato forzatamente da un operatore</td><td></td></tr></tbody></table>

### REQUISITI

Tutti i proxy devono:

* Validare gli eventi in input e output
* Integrazione con sentry
* Healthcheck
* Esporre metriche di monitoraggio in formato prometheus
