Implementazione di un proxy

Molti aspetti implementativi dipendono più dalla normativa che da nostre scelte progettuali, in questa pagina si evidenziano gli uni e le altre.

Requisiti funzionali

Sono requisiti che dipendono da nostre scelte implementative, possono cambiare man mano che evolviamo la piattaforma, per supportare nuovi casi d'uso (pagamento dei dovuti) oppure perché ci accorgiamo che abbiamo commesso qualche errore nella progettazione.

  1. Gestione di pagamenti spontanei

  2. Gestione di pagamenti con bilancio

  3. Gestione della notifica dello stato del pagamento da parte dell'IdP - se disponibile - o del polling se non è disponibile la notifica

  4. Se è implementato il polling, questo deve avvenire con un back-off esponenziale che assicuri alcuni check nel giro di pochi minuti e poi si diradi fino a un massimo di un check al giorno fino alla scadenza del pagamento o 1 anno se la scadenza è inferiore.

  5. Gestione delle configurazioni a livello di Tenant e di Servizio

Requisiti normativi

Requisiti per l'ambiente di produzione

  • Sappiamo che in molti topic ci sono diversi eventi mal formati, per vari errori e assenza di uno schema registry, quindi è necessario validare gli eventi in input e opzionalmente in output (lo fanno le nostre prime implementazioni in python, ma è un requisito?)

  • Ci aspettiamo che se di dovesse aggiornare il formato dell'evento nel topic payments gestiremo eventi anche in parallelo con versioni distinte, quindi ogni proxy deve Interpretare solo gli eventi che riportano il formato più recente dell'evento nel topic payments: event_version: 2.0

  • Integrarsi con sentry per la gestione degli errori

  • Esporre metriche di monitoraggio in formato prometheus, in particolare:

    • counter sul numero di pagamenti creati

    • counter sul numero di errori durante il processamento di pagamenti, differenziando gli errori interni (errori di formato dati in ingresso o validazione) da errori esterni (errori di dialogo con l'IdP)

    • latenza delle chiamate fatte all'IdP

    Di seguito la tabella contenente le specifiche di ogni metrica

Metrica
Labels
Descrizione

oc_payment_validation_errors_total

cluster, env, app_name

la metrica deve misurare gli errori di validazione sull'evento letto (es. l'importo è una stringa invece che un float)

oc_api_requests_total

cluster, env, method, app_name, status_code

la metrica deve monitorare le chiamate http indicandone lo status code

oc_payment_success_events_total

cluster, env, app_name

la metrica deve misurare solo gli eventi per cui il proxy ha una configurazione e che stati processati con successo

oc_payment_failed_events_total

cluster, env, app_name

la metrica deve misurare gli eventi di pagamento validi di cui però è fallito il processing per qualsiasi motivo (escluso il caso in cui non esiste una configurazione per esso)

oc_payment_provider_errors_total

cluster, env, app_name

la metrica deve misurare gli eventi di pagamento validi di cui però è fallito il processing a causa di un errore sul provider

oc_payment_internal_errors_total

cluster, env, app_name

la metrica deve misurare gli eventi di pagamento validi di cui però è fallito il processing per errori interni al codice

oc_payment_provider_latency_bucket

cluster, env, app_name

istogramma che mostra la distribuzione di latenza delle risposte del provider

Inoltre il servizio deve rispettare gli standard della piattaforma in particolare per quanto riguarda la gestione dello storage: non possiamo avere vendor-lockin sulle tecnologie, quindi dobbiamo essere compatibili con file-system posix tradizionale, NFS share e almeno i due cloud-storage più diffusi S3 e Azure Blob.

Documentazione API di Esempio - Swagger

Get Status

get

Get Service Status

Responses
200

Successful Response

application/problem+json
get
/status

Get Online Url

get
Path parameters
payment_idstringRequired
Responses
200

Successful Response

application/json
Responseany
get
/online-payment/{payment_id}

No content

Get Notice Url

get
Path parameters
payment_idstringRequired
Query parameters
offline_urlstringRequired
Responses
200

Successful Response

application/json
Responseany
get
/notice/{payment_id}

No content

Get Receipt Url

get
Path parameters
payment_idstringRequired
Responses
200

Successful Response

application/json
Responseany
get
/receipt/{payment_id}

No content

Check For Updates

get
Path parameters
payment_idstringRequired
Responses
200

Successful Response

application/json
Responseany
get
/update/{payment_id}

No content

Get Landing Url

get
Path parameters
payment_idanyRequired
Query parameters
idSessionstringOptional
esitostringOptionalDefault: OK
Responses
200

Successful Response

application/json
Responseany
get
/landing/{payment_id}

No content

Register Payment

patch
Path parameters
payment_idanyRequired
Body
statusundefined · enumRequired

An enumeration.

Possible values:
Responses
200

Successful Response

application/json
Responseany
patch
/payments/{payment_id}

No content

Get Tenant Form Schema

get
Responses
200

Successful Response

application/json
Responseany
get
/tenants/schema

No content

Get Tenant Configuration

get
Path parameters
tenant_idstring · uuidRequired
Responses
200

Successful Response

application/json
get
/tenants/{tenant_id}

Update Tenant Configuration

put
Path parameters
tenant_idstring · uuidRequired
Body
namestringRequired
IPA_codestringRequired
tax_identification_numberstringOptional
passwordstringRequired
cart_passwordstringOptionalDefault: ""
application_codestringOptionalDefault: ""
activebooleanRequired
enable_checkoutbooleanOptionalDefault: false
Responses
200

Successful Response

application/json
Responseany
put
/tenants/{tenant_id}

No content

Update Existing Tenant Configuration

patch
Path parameters
tenant_idstring · uuidRequired
Body
object · NewConfigurationOptional
Responses
200

Successful Response

application/json
Responseany
patch
/tenants/{tenant_id}

No content

Delete Tenant

delete
Path parameters
tenant_idstring · uuidRequired
Responses
200

Successful Response

application/json
Responseany
delete
/tenants/{tenant_id}

No content

Save Tenant Configuration

post
Body
namestringRequired
IPA_codestringRequired
tax_identification_numberstringOptional
passwordstringRequired
cart_passwordstringOptionalDefault: ""
application_codestringOptionalDefault: ""
activebooleanRequired
enable_checkoutbooleanOptionalDefault: false
idstring · uuidRequired
Responses
200

Successful Response

application/json
Responseany
post
/tenants

No content

Get Service Form Schema

get
Responses
200

Successful Response

application/json
Responseany
get
/configs/schema

No content

Get Payment Configurations List

get
Query parameters
config_idsstring · uuid[]Optional

Lista id delle configurazioni di pagamento

Responses
200

Successful Response

application/json
get
/configs

Save Payment Configuration

post
Body
tenant_idstring · uuidRequired
activebooleanRequired
idstring · uuidOptional
Responses
200

Successful Response

application/json
Responseany
post
/configs

No content

Get Payment Configuration

get
Path parameters
config_idstring · uuidRequired
Responses
200

Successful Response

application/json
get
/configs/{config_id}

Update Payment Configuration

put
Path parameters
config_idstring · uuidRequired
Body
tenant_idstring · uuidRequired
activebooleanRequired
Responses
200

Successful Response

application/json
Responseany
put
/configs/{config_id}

No content

Delete Service

delete
Path parameters
config_idstring · uuidRequired
Responses
200

Successful Response

application/json
Responseany
delete
/configs/{config_id}

No content

Update Existing Payment Configuration

patch
Path parameters
config_idstring · uuidRequired
Body
object · NewConfigurationOptional
Responses
200

Successful Response

application/json
Responseany
patch
/configs/{config_id}

No content

Update User Dues

post
Body
tax_identification_numberstringRequired
user_idstringRequired
tenant_idstringRequired
job_idstringRequired
Responses
200

Successful Response

application/json
Responseany
post
/update-user-dues

No content

Esempi di proxy da cui si può prendere spunto

EFIL: http://gitlab.com/opencontent/stanza-del-cittadino/efil-payment-proxy

IRIS: http://gitlab.com/opencontent/stanza-del-cittadino/iris-payment-proxy

MYPAY: http://gitlab.com/opencontent/stanza-del-cittadino/mypay-payment-proxy

PMPAY: http://gitlab.com/opencontent/stanza-del-cittadino/pmpay-payment-proxy

Questi proxy condividono alcune scelte implementative grazie a un apposito python-sdk sviluppato in parallelo ai proxy stessi:

  • le configurazioni sono salvate su disco locale o s3 secondo un albero ben definito tenant->servizio

  • i singoli pagamenti vengono salvati su storage fino a che il pagamento è pendente, così da poter fare il polling in autonomia.

Altri riferimenti utili

Last updated

Was this helpful?