orgNo = $company['orgNo']; $this->appKey = $company['appKey']; $this->privateKey = $this->loadPrivateKey($company['privateKey']); $this->publicKey = $this->loadPublicKey($company['publicKey']); $this->platformPublicKey = $this->loadPublicKey($company['platformPublicKey']); } protected function loadPrivateKey($base64PrivateKey) { $privateKey = "-----BEGIN PRIVATE KEY-----\n" . chunk_split($base64PrivateKey, 64, "\n") . "-----END PRIVATE KEY-----\n"; $key = openssl_pkey_get_private($privateKey); if ($key === false) { throw new \Exception('Invalid private key: ' . openssl_error_string()); } return $key; } protected function loadPublicKey($base64PublicKey) { $publicKey = "-----BEGIN PUBLIC KEY-----\n" . chunk_split($base64PublicKey, 64, "\n") . "-----END PUBLIC KEY-----\n"; $key = openssl_pkey_get_public($publicKey); if ($key === false) { throw new \Exception('Invalid public key: ' . openssl_error_string()); } return $key; } public function sign($data) { openssl_sign($data, $signature, $this->privateKey, OPENSSL_ALGO_SHA256); return base64_encode($signature); } public function verifySign($data, $signature) { $decodedSignature = base64_decode($signature); return openssl_verify($data, $decodedSignature, $this->platformPublicKey, OPENSSL_ALGO_SHA256); } public function encryptData($data, $key) { $encryptedData = openssl_encrypt($data, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING); return base64_encode($encryptedData); } public function decryptData($data, $key) { $decodedData = base64_decode($data); return openssl_decrypt($decodedData, 'AES-256-ECB', $key, OPENSSL_PKCS1_PADDING); } public function encryptKey($key) { openssl_public_encrypt($key, $encryptedKey, $this->platformPublicKey, OPENSSL_PKCS1_PADDING); return base64_encode($encryptedKey); } public function decryptKey($encryptedKey) { $decodedKey = base64_decode($encryptedKey); if ($decodedKey === false) { throw new \Exception('Base64 decoding failed.'); } $decrypted = ''; $result = openssl_public_decrypt($decodedKey, $decrypted, $this->platformPublicKey, OPENSSL_PKCS1_PADDING); if ($result === false) { throw new \Exception('Decryption failed: ' . openssl_error_string()); } return $decrypted; } public function generateKey() { return openssl_random_pseudo_bytes(32); } public function prepareRequest($header, $body) { $header = [ 'version' => config('crypto.app_version'), 'appKey' => $this->appKey, 'method' => $header['method'] ?? '', 'requestId' => $this->appKey.$this->generateUniqueString(30), ]; $bodyJson = json_encode($body); $signData = "version={$header['version']}&appKey={$header['appKey']}&method={$header['method']}&requestId={$header['requestId']}&body={$bodyJson}"; $signature = $this->sign($signData); $header['sign'] = $signature; $key = $this->generateKey(); $encryptedBody = $this->encryptData($bodyJson, $key); $encryptedKey = $this->encryptKey($key); return [ 'header' => $header, 'encryptData' => [ 'key' => $encryptedKey, 'data' => $encryptedBody, ], ]; } public function processResponse($response) { if(!isset($response['encryptData']['key'])){ return ''; } $encryptedKey = $response['encryptData']['key']; $encryptedData = $response['encryptData']['data']; $header = $response['header']; $key = $this->decryptKey($encryptedKey); $data = $this->decryptData($encryptedData, $key); $body = json_decode($data, true); return $body; // 判断响应中是否有签名 if(empty($header['sign']??'')){ return $body; } $header['appKey'] = $header['appkey'] ?? $header['appKey']; $header['requestId'] = $header['requestid'] ?? $header['requestId']; $signData = "version={$header['version']}&appKey={$header['appKey']}&method={$header['method']}&requestId={$header['requestId']}&body=" . json_encode($body); $isValid = $this->verifySign($signData, $header['sign']); if ($isValid) { return $body; } else { throw new \Exception("Invalid signature"); } } /** * 生成唯一字符串 * * @param int $length 字符串长度,不能超过128 * @return string 生成的唯一字符串 */ public function generateUniqueString($length = 100) { // 确保长度不超过100 if ($length > 100) { $length = 100; } // 生成基于时间的唯一ID $uniqueId = uniqid('', true); // 可选字符集,可以根据需要修改 $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $charactersLength = strlen($characters); $randomString = ''; // 使用时间戳的微秒部分增加随机性 $microtime = microtime(); $randomSeed = substr($microtime, strpos($microtime, ' ') + 1); // 将随机种子转换为整数 $seed = crc32($randomSeed); // 设置随机种子 srand($seed); // 生成随机字符串 for ($i = 0; $i < $length - strlen($uniqueId); $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } // 结合唯一ID和随机字符串 $result = substr($uniqueId, 0, $length - strlen($randomString)) . $randomString; return $result; } }