<?php
namespace App\Lib;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class HSM
{
   protected static $baseurl="http://223.70.139.221:2018";
   protected static $keyIndex=1;
   protected static $encAlg="SM4/CBC/PKCS5Padding";
   protected static $iv="31323334353637383132333435363738";

   //protected static $iv="34323456472345912309463212857392";//正式


   //加密
   public static function HsmEncrypt($or_str){
       $str = bin2hex($or_str);
       $url= self::$baseurl."/api/hsm/sym/symEncryptInternalForKEK";
       $data=[
           "keyIndex"=>self::$keyIndex,
           "encAlg"=>self::$encAlg,
           "iv"=>self::$iv,
           "plainData"=>$str
       ];
       $data=json_encode($data);
       $encryptStr=self::post($url,$data,$or_str);

       $r_data=json_decode($encryptStr, true);
      // dd($r_data);
       if($r_data['status']==0){
           return ['status'=>true,'data'=>$r_data['body']['cipherData']];
       }else{
           return ['status'=>false];
       }
   }
    //解密
    public static function HsmDecrypt($str){
        $url= self::$baseurl."/api/hsm/sym/symDecryptInternalForKEK";
        $data=[
            "keyIndex"=>self::$keyIndex,
            "encAlg"=>self::$encAlg,
            "iv"=>self::$iv,
            "cipherData"=>$str
        ];
        $data=json_encode($data);
        $encryptStr=self::post($url,$data);

         $r_data=json_decode($encryptStr, true);
         if($r_data && $r_data['status']==0){
             return ['status'=>true,'data'=>hex2bin($r_data['body']['plain'])];
         }else{
             return ['status'=>false];
         }
     }
    //计算 HMAC
    public static function Hmac($or_str)
    {
        $str = bin2hex($or_str);
        $url= self::$baseurl."/api/hsm/digest/macInternal";
        $data=[
            "keyIndex"=>self::$keyIndex,
            "macAlg"=>'HMac-SM3',
            "plainData"=>$str
        ];
        $data=json_encode($data);
        $encryptStr=self::post($url,$data);

        $r_data=json_decode($encryptStr, true);
        if($r_data['status']==0){
            return ['status'=>true,'data'=>$r_data['body']['mac']];
        }else{
            return ['status'=>false];
        }
    }
    public function post($url, $data_string,$or_str='')
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);              // 添加超时：最大执行时间30秒
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 10);       // 添加超时：连接超时10秒
        curl_setopt($curl, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json; charset=utf-8',
            'Content-Length: ' . strlen($data_string)
        ]);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);
        $r = curl_exec($curl);

        // 检查curl错误
        if (curl_errno($curl)) {
            $error_msg = curl_error($curl);
            $error_code = curl_errno($curl);
            curl_close($curl);

            // 记录到Laravel日志
            Log::error('HSM curl请求失败', [
                'url' => $url,
                'error_code' => $error_code,
                'error_msg' => $error_msg,
                'request_data' => $or_str,
                'post_data_preview' => substr($data_string, 0, 500)
            ]);

            // 返回错误信息
            return json_encode(['status' => 1, 'message' => 'curl错误: ' . $error_msg]);
        }

        curl_close($curl);

        date_default_timezone_set('PRC');
        $table_name='zz_request_log_' . date('ym');
        $formatted_date= date("Y-m-d H:i:s");

        try {
            DB::table($table_name)->insert([
                'request_ip'=>'',
                'response_data'=>json_encode($r, JSON_UNESCAPED_UNICODE),
                'header_data'=>'',
                'post_data'=>$or_str.'/'.$data_string,
                'get_data'=>'',
                'request_url'=>$url,
                'create_time' => $formatted_date,
                'update_time' => $formatted_date
            ]);
        } catch (\Throwable $e) {
            // 数据库日志记录失败不影响主流程，只记录到Laravel日志
            Log::error('HSM数据库日志记录失败', [
                'error' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'url' => $url
            ]);
        }

        return $r;
    }
}
