<?php
/**
 * 知岁OS 第三方对接 SDK — PHP 版
 *
 * 使用前请确保：
 * 1. 已在知岁OS后台注册服务商，获取 uuid 和 secretkey
 * 2. PHP >= 7.1 且启用 openssl 扩展
 */

class ZsosClient
{
    private $baseUrl;
    private $uuid;
    private $secretKey; // hex 编码的密钥

    public function __construct(string $baseUrl, string $uuid, string $secretKey)
    {
        $this->baseUrl = rtrim($baseUrl, '/');
        $this->uuid = $uuid;
        $this->secretKey = $secretKey;
    }

    /**
     * 消费数据 token，获取解密后的院校应用数据
     *
     * @param string $token 用户通过知岁OS小程序获取的接口数据token
     * @return array 解密后的原始数据
     * @throws Exception
     */
    public function useToken(string $token): array
    {
        $plaintext = $this->uuid . $token;
        $encrypted = $this->aes256GcmEncrypt($plaintext);

        $response = $this->post('/api/open/useToken', [
            'uuid' => $this->uuid,
            'data' => $encrypted,
        ]);

        if (!isset($response['code']) || $response['code'] !== 1) {
            throw new Exception($response['msg'] ?? '请求失败');
        }

        $decrypted = $this->aes256GcmDecrypt($response['data']);
        return json_decode($decrypted, true);
    }

    /**
     * AES-256-GCM 加密
     *
     * @param string $plaintext 明文
     * @return string Base64(IV + TAG + CipherText)
     */
    private function aes256GcmEncrypt(string $plaintext): string
    {
        $method = 'aes-256-gcm';
        $key = hex2bin($this->secretKey);
        $ivLen = openssl_cipher_iv_length($method);
        $iv = openssl_random_pseudo_bytes($ivLen);

        $tag = '';
        $ciphertext = openssl_encrypt(
            $plaintext,
            $method,
            $key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag,
            '',
            16
        );

        if ($ciphertext === false) {
            throw new Exception('AES-256-GCM 加密失败: ' . openssl_error_string());
        }

        return base64_encode($iv . $tag . $ciphertext);
    }

    /**
     * AES-256-GCM 解密
     *
     * @param string $encoded Base64(IV + TAG + CipherText)
     * @return string 明文
     */
    private function aes256GcmDecrypt(string $encoded): string
    {
        $method = 'aes-256-gcm';
        $key = hex2bin($this->secretKey);
        $ivLen = openssl_cipher_iv_length($method);

        $decoded = base64_decode($encoded);
        $iv = substr($decoded, 0, $ivLen);
        $tag = substr($decoded, $ivLen, 16);
        $ciphertext = substr($decoded, $ivLen + 16);

        $decrypted = openssl_decrypt(
            $ciphertext,
            $method,
            $key,
            OPENSSL_RAW_DATA,
            $iv,
            $tag
        );

        if ($decrypted === false) {
            throw new Exception('AES-256-GCM 解密失败: ' . openssl_error_string());
        }

        return $decrypted;
    }

    /**
     * 发送 POST 请求
     */
    private function post(string $uri, array $data = []): array
    {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $this->baseUrl . $uri,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query($data),
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/x-www-form-urlencoded',
            ],
        ]);

        $response = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);

        if ($error) {
            throw new Exception("HTTP 请求失败: {$error}");
        }

        $result = json_decode($response, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception("JSON 解析失败: " . json_last_error_msg());
        }

        return $result;
    }
}
