Подписанный URL-адрес для google-ковша не соответствует сигнатуре

Мне трудно работать с хранилищем Google.

Поэтому я пытаюсь сделать подписанный URL-адрес , уже имею идентификатор клиента (который является адресом электронной почты) и закрытый ключ (как описано здесь ), поэтому:

ШАГ 1: постройте строку

function googleBuildConfigurationString($method, $expiration, $file, array $options = []) { $allowedMethods = ['GET', 'HEAD', 'PUT', 'DELETE']; // initialize $method = strtoupper($method); $contentType = $options['Content_Type']; $contentMd5 = $options['Content_MD5'] ? base64_encode($options['Content_MD5']) : ''; $headers = $options['Canonicalized_Extension_Headers'] ? $options['Canonicalized_Extension_Headers'] . PHP_EOL : ''; $file = $file ? $file : $options['Canonicalized_Resource']; // validate if(array_search($method, $allowedMethods) === false) { throw new RuntimeException("Method '{$method}' is not allowed"); } if(!$expiration) { throw new RuntimeException("An expiration date should be provided."); } return <<<TXT {$method} {$contentMd5} {$contentType} {$expiration} {$headers}{$file} TXT; } 

Пока что так хорошо (я думаю), повторяя вывод, он похож на примеры, поэтому теперь подписать строку

ШАГ 2. Подписывая строку Initialy, я использовал openssl_public_encrypt , после поиска нашел, что у google-api-php-client есть Google_Signer_P12 (который фактически использует openssl_sign ), поэтому метод выглядит так:

 function googleSignString($certificatePath, $stringToSign) { return (new Google_Signer_P12( file_get_contents($certificatePath), 'notasecret' ))->sign($stringToSign); } 

И здесь я не уверен, правильно ли это его подписание, наконец, создавая окончательный URL-адрес

ШАГ 3: создание URL-адреса

 function googleBuildSignedUrl($serviceEmail, $file, $expiration, $signature) { return "http://storage.googleapis.com{$file}" . "?GoogleAccessId={$serviceEmail}" . "&Expires={$expiration}" . "&Signature=" . urlencode($signature); } 

Но откроется URL-адрес в браузере:

 <Error> <Code>SignatureDoesNotMatch</Code> <Message> The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method. </Message> <StringToSign>GET 1437470250 /example/video.mp4</StringToSign> </Error> 

Я добавил сущность с окончательным сценарием, чтобы было легче читать

Итак, любая идея, что я делаю неправильно?

Solutions Collecting From Web of "Подписанный URL-адрес для google-ковша не соответствует сигнатуре"

Я нашел решение, была ошибка с датой истечения срока действия, в которой я делал:

 $expiration = (new DateTime())->modify('+3h')->getTimestamp(); 

Поэтому я изменил h на hours так что теперь он работает, например:

 $expiration = (new DateTime())->modify('+3hours')->getTimestamp(); 

Но это не совсем решило, фактическая недостающая часть заключается в том, что для параметра Google_Signer_P12::sign() требуется, чтобы он был закодирован на base64, который указан в документах google:

Google Cloud Storage ожидает кодировку Base64 в своих API.

Однако я (ошибочно), хотя Google_Signer_P12::sign() уже сделал бы это, поэтому, когда я понял, что это необходимо, я изменил метод знака на:

 function googleSignString($certificatePath, $stringToSign) { return base64_encode((new Google_Signer_P12( file_get_contents($certificatePath), 'notasecret' ))->sign($stringToSign)); } 

И он работает сейчас !!!

Я также обновил суть для всех, кто хочет ее использовать 🙂