國家網路遊戲防沉迷實名認證系統 接入核心工具

全村的希望發表於2021-03-09

1. AntiAddictionService 防沉迷系統 業務程式碼

<?php


namespace App\Services;


use GuzzleHttp\Client;

class AntiAddictionService
{
    private $app_id = '';
    private $secret_key = '';
    private $biz_id = '';

    /**
     * AntiAddictionService constructor.
     * @param $app_id
     * @param $secret_key
     * @param $biz_id
     */
    public function __construct($app_id, $secret_key, $biz_id) {
        $this->app_id = $app_id;
        $this->secret_key = $secret_key;
        $this->biz_id = $biz_id;
    }

    /**
     * 實名認證介面
     * @param $ai
     * @param $name
     * @param $id_num
     */
    public function checkIdCard($ai, $name, $id_num, $test_code = '') {
        $client = new Client();
        $body = [
            'ai' => $ai,
            'name' => $name,
            'idNum' => $id_num
        ];
        $uri = 'https://api.wlc.nppa.gov.cn/idcard/authentication/check';
//        $uri = 'https://wlc.nppa.gov.cn/test/authentication/check';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/authentication/check/'.$test_code;
        }
        $header = $this->getHeader($body, []);
        try {
            $response  = $client->request('POST', $uri, [
                'headers' => $header['header'],
                'json' => $header['encrypted_body'],
                'timeout' => 5
            ]);
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
            \Log::error("Anti Addiction - checkIdCard: ". $e->getMessage());
            return false;
        }

        $content = $response->getBody()->getContents();
        \Log::info("Anti Addiction - checkIdCard: ".$content);
        return json_decode($content, true);
    }

    /**
     * 實名認證結果查詢
     * @param $ai
     */
    public function queryIdCard($ai, $test_code = '') {
        $client = new Client();
        $query_params = [
            'ai' => $ai
        ];
        $header = $this->getHeader([], $query_params);
        $uri = 'http://api2.wlc.nppa.gov.cn/idcard/authentication/query';
//        $uri = 'https://wlc.nppa.gov.cn/test/authentication/query';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/authentication/query/'.$test_code;
        }
        try {
            $response  = $client->request('GET', $uri, [
                'headers' => $header['header'],
                'query' => $query_params,
                'timeout' => 5
            ]);
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
            \Log::error("Anti Addiction - queryIdCard: ". $e->getMessage());
            return false;
        }

        $content = $response->getBody()->getContents();
        \Log::info("Anti Addiction - queryIdCard: ".$content);

        return json_decode($content, true);
    }

    /**
     * 上報遊戲使用者上下線行為資料
     * @param $collections
     * @return mixed
     */
    public function reportLogInOut($collections, $test_code = '') {
        $client = new Client();

        $header = $this->getHeader(['collections' => $collections], []);
        $uri = 'http://api2.wlc.nppa.gov.cn/behavior/collection/loginout';
//        $uri = 'https://wlc.nppa.gov.cn/test/collection/loginout';
        if($test_code) {
            $uri = 'https://wlc.nppa.gov.cn/test/collection/loginout/'.$test_code;
        }
        try {
            $response  = $client->request('POST', $uri, [
                'headers' => $header['header'],
                'json' => $header['encrypted_body'],
                'timeout' => 5
            ]);
        } catch (\GuzzleHttp\Exception\GuzzleException $e) {
            \Log::error("Anti Addiction - reportLogInOut: ". $e->getMessage());
            return false;
        }

        $content = $response->getBody()->getContents();
        \Log::info("Anti Addiction - reportLogInOut: ".$content);
        return json_decode($content, true);
    }


    /**
     * 對請求報文體進行加密
     * @param $body
     * @return string
     */
    private function bodyEncrypt($body)
    {
        \Log::info("Anti Addiction - Encrypt Before:" .json_encode($body));
        $key = hex2bin($this->secret_key);
        $cipher = "aes-128-gcm";
        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = openssl_random_pseudo_bytes($ivlen);

        $tag = null;
        $encrypt = openssl_encrypt(json_encode($body), $cipher, $key, OPENSSL_RAW_DATA,$iv,$tag);
        $str = bin2hex($iv) .  bin2hex($encrypt) . bin2hex($tag);
        $after = base64_encode(hex2bin($str));
        \Log::info("Anti Addiction - Encrypt After:" .$after);
        return $after;
    }

    /**
     * 介面簽名
     * @param $body
     * @param $query_params
     */
    private function sign($body, $query_params, $timestamps)
    {
        if(!empty($body)) {
            $encrypted_body = json_encode(['data' => $this->bodyEncrypt($body)]);
        } else {
            $encrypted_body = '';
        }

        \Log::info("Anti Addiction - Encrpyted Body:".$encrypted_body);

        $sys_params = [
            'appId' => $this->app_id,
            'bizId' => $this->biz_id,
            'timestamps' => $timestamps
        ];
        $final_params = array_merge($sys_params, $query_params);
        ksort($final_params);

        $str_params = '';
        foreach ($final_params as $k => $v) {
            $str_params .= $k.$v;
        }
        $str_params .= $encrypted_body;
        $str_params = $this->secret_key.$str_params;

        \Log::info("Anti Addiction - Sign Before:".$str_params);
        $hash = hash('sha256', $str_params);

        \Log::info("Anti Addiction - Sign After:".$hash);
        return [
            'sign' => $hash,
            'encrypted_body' => json_decode($encrypted_body, true)
        ];
    }


    /**
     * 請求頭構建
     * @param $body
     * @param $query_params
     * @return array
     */
    private function getHeader($body, $query_params) {
        list($msec, $sec) = explode(' ', microtime());
        $timestamps = sprintf('%d', (floatval($msec) + floatval($sec)) * 1000);

        $sign_data = $this->sign($body, $query_params, $timestamps);
        $header = [
            'Content-Type' => 'application/json;charset=utf-8',
            'appId' => $this->app_id,
            'bizId' => $this->biz_id,
            'timestamps' => $timestamps,
            'sign' => $sign_data['sign']
        ];



        \Log::info("Anti Addiction - Header:". json_encode($header));

        return [
            'header' => $header,
            'encrypted_body' => $sign_data['encrypted_body']
        ];

    }


}

2. 防沉迷系統介面測試 testcase01~08 命令

<?php

namespace App\Console\Commands;

use App\Services\AntiAddictionService;
use Illuminate\Console\Command;

class AntiAddictionTest extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'anti_addiction:test {--code= : 測試碼} {--method= : 測試用例} {--bizId= : 遊戲備案識別碼}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '國家防沉迷系統介面測試';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    protected $service = null;

    public function __construct()
    {
        parent::__construct();

    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->service = new AntiAddictionService(env('ANTI_ADDICTION_APP_ID'), env('ANTI_ADDICTION_SECRET_KEY'), $this->option('bizId'));
        $method = $this->option('method');
        $this->$method();


    }

    // 實名認證介面 - 認證成功
    private function testcase01() {
        $this->service->checkIdCard('100000000000000001', '某一一', '110000190101010001', $this->option('code'));
    }

    // 實名認證介面 - 認證中
    private function testcase02() {
        $this->service->checkIdCard('200000000000000001', '某二一', '110000190201010009', $this->option('code'));
    }

    // 實名認證介面 - 認證失敗
    private function testcase03() {
        $this->service->checkIdCard('300000000000000001', '某三一', '440682200001011111', $this->option('code'));
    }

    // 實名認證結果查詢介面 - 認證成功
    private function testcase04() {
        $this->service->queryIdCard('100000000000000001', $this->option('code'));
    }

    // 實名認證結果查詢介面 - 認證中
    private function testcase05() {
        $this->service->queryIdCard('200000000000000001', $this->option('code'));
    }

    // 實名認證結果查詢介面 - 認證失敗
    private function testcase06() {
        $this->service->queryIdCard('300000000000000001', $this->option('code'));
    }

    // 遊戲使用者行為資料上報介面 - 模擬“遊客模式”下游戲使用者行為資料上報場景
    private function testcase07() {
        $this->service->reportLogInOut([
            [
                'no' => 1,
                'si' => '888',
                'bt' => 0,
                'ot' => time(),
                'ct' => 2,
                'di' => '666',
            ]
        ], $this->option('code'));
    }

    // 遊戲使用者行為資料上報介面 - 模擬“已認證”下游戲使用者行為資料上報場景
    private function testcase08() {
        $this->service->reportLogInOut([
            [
                'no' => 1,
                'si' => '888',
                'bt' => 0,
                'ot' => time(),
                'ct' => 0,
                'pi' => '1fffbjzos82bs9cnyj1dna7d6d29zg4esnh99u',
            ]
        ], $this->option('code'));
    }
}

歡迎加入QQ群:789235512 參與系統接入討論與分享

本作品採用《CC 協議》,轉載必須註明作者和本文連結
劉曉峰

相關文章