ursellicosimo94/certificati-inps

该项目的目的是验证INPS病假证明的有效性,并获取所有必要的信息。

1.0.0 2024-09-12 16:12 UTC

This package is auto-updated.

Last update: 2024-09-12 16:22:56 UTC


README

该项目的目的是验证INPS病假证明的有效性,并获取所有必要的信息。为此,使用了INPS网站页面(链接)。

由于没有真正的API,该项目使用正常的HTTP调用到上述链接的网站,并分析响应的body以提取证书数据。

如何使用包

这个小教程附有实际示例,旨在帮助您实现自己的算法。具体来说,为了恢复一个或多个证书的数据,您至少需要两个步骤:

  1. 前端页面显示验证码并让用户输入解决方案,以及可能的税务编码和相应的疾病协议号
  2. 结果页面/结果展示

步骤1

从实际的角度来看,您的前端需要联系后端页面,该后端页面将执行静态的getCaptcha方法,该方法仅模拟访问INPS网站页面,以获取会话cookie和要解决的验证码的base64编码。

$pre_auth = Certificato::getCaptcha();

在上面的示例中,$pre_auth 将是一个包含2个键的关联数组,键的类型为?string

  • sessionId:INPS网站的会话cookie(将在第二步中用于验证验证码)
  • captcha:要解决的验证码的png的base64编码,将展示给用户以供输入解决方案,最简单的方式是通过图像标签显示
    <img src='data:image/png;base64, <!-- Base64 data -->' />

步骤2

一旦收集到验证码和税务编码以及相应的员工puk,只需创建一个端点,将所有这些信息(包括获得的sessionId和验证码的base64编码)发送到该端点即可。假设我们有一个如下结构的数组,我们可以编写如下代码

$array_esempio = [
    // array associativo dei codici dove la chiave è il codice fiscale del dipendente
    'BCDFGH94A22X123X' => [ 
        '123456789', // Ogni elemento della chiave associativa è un numero di protocollo da verificare
        '987654321',
    ], 
    //...
];

// session ID ricevuto con lo step 1
$sessionId = '0000AB9pIzL5kQL2Af5pnR1kG2n:16k7d6azz';

// codice captcha risolto dall'utente
$captcha = 'gr3df'; 

/**
 * flag per stabilire se il pdf deve essere scaricato o no, consiglio se non vi serve il pdf,
 * per velocizzare l'algoritmo e per non intasare i sistemi INPS non scaricatelo.
 */
$pdf = false;

$protocolli_validi = [];
$protocolli_non_validi = [];
$verifiche_fallite = [];

foreach ($array_esempio as $codice_fiscale => $protocolli){

    foreach( $protocolli as $protocollo){
        
        try{
            $certificato = new Certificato(
                $sessionId,
                $captcha,
                $codice_fiscale,
                $protocollo,
                $pdf
            );

            /**
             * Se arrivi qui il download del certificato è riuscito!
             * Ora puoi:
             *  - Accedere alle varie proprietà dell'oggetto,
             *  - Trasformare il certificato in un array associativo (se non ti interessa rimanere in un contesto oggetto)
             *  - Puoi usare l'oggetto come stringa (la sua rappresentazione stringa sarà il numero di protocollo)
             *  - Potrai accedere alla sua proprietà pdf (se nella costruzione dell'oggetto $pdf era true)
             */
            
            $protocolli_validi[] = $certificato;
            
        } catch ( Exception $e ){
            // Se ottenete un codice eccezione da 500 in su ci sono stati problemi sul sito INPS
            if( $e->getCode() >= 500 ){
                if(empty($verifiche_fallite[$codice_fiscale])){
                    $verifiche_fallite[$codice_fiscale] = [];
                }

                $verifiche_fallite[$codice_fiscale][] = $protocollo;
                continue;
            }

            // Se invece il codice è sotto i 500 allora uno degli input era errato (codice fiscale, protocollo, captcha o sessione)
            if(empty($protocolli_non_validi[$codice_fiscale])){
                $protocolli_non_validi[$codice_fiscale] = [];
            }

            $protocolli_non_validi[$codice_fiscale][] = $protocollo;
        } finally {
            /** 
             * NOTA BENE
             * 
             * so che può allungare di molto i tempi di risposta ma
             * fare troppe chiamate al sito inps può essere controproducente:
             *  - potrebbe bloccarvi vedendo il vostro come un tentativo di attacco
             *  - potrebbe voler adottare delle politiche di sicurezza più ferree
             *  - potrebbe aggiornare il sistema rendendo questo pacchetto completamente inutilizzabile
             * 
             * Per il bene di tutti i programmatori italiani, per i motivi sopra descritti,
             * non fare chiamate senza un delay di almeno 500 ms
             * 
             * Attenzione:
             * Ricordate che il return del try o del catch viene eseguito SEMPRE dopo il finally e
             * se ci sono dei return sia nel try (o nel catch) che nel finally, viene restituito sempre
             * e comunque quello del finally, tenetelo presente se usate il return in uno di questi tre punti.
             */
            sleep(1);
        }

    }

}

/**
 * A questo punto del codice avete i tre array popolati con i dati precedenti in base all'esito che le operazioni hanno avuto.
 * Potete quindi:
 *  - Implementare una logica di retry per gli elementi in $verifiche_fallite (sito INPS KO) ma vi consiglio di aspettare almeno 15/30 minuti
 *  - Segnalare all'utente quali numeri di protocollo non sono validi ($protocolli_non_validi), in modo che possa richiedere quelli corretti
 *  - Inserire le malattie nei vostri database sfruttando i dati scaricati del certificato ($protocolli_validi).
 */

注意:有时INPS网站会连续几天都无法访问,对此没有解决办法。此外,这种导入/控制证书的方法不是官方的,但是我所知道的唯一一种几乎可以自动执行检查的方法。此外,由于这不是官方的API,而是基于HTML正常前端页面的API模拟,因此如果证书页面的HTML结构或认证系统发生微小变化,该系统可能无法正常工作或根本无法工作。因此,我的建议是将其用作简单的疾病协议号验证工具,以及自动下载和存档PDF的方式(如果公司需要)。另一种更手动但肯定更安全、更稳定的方法是使用公司的登录凭证访问INPS系统,下载员工的疾病报告XLS / CSV文件,作为将数据导入您的系统或进行数据验证的工具。

容器

该项目包含Docker文件,以便在测试和开发中有一个“标准”环境。

有关创建和启动项目的方法,请参阅

docker compose up --build -d
docker exec -it certificati-malattia-inps-certificati-inps-1 /bin/zsh