Возникли проблемы с созданием подписи Amazon AWS с помощью PHP

Я пытался сделать HTTP-запрос POST к API службы AGCOD amazon, я следовал все шаги по созданию подписи и все хешированные ключи соответствовали инструкциям здесь, но я все равно получил "Токен безопасности, включенный в запрос, недействителен". ОШИБКА.

<?php
define('PARTNER_ID','Test');
define('ACCESS_KEY','fake-aws-key');
define('SECRET_KEY','fake-secret-key');
define('TIME_STAMP_ISO_8601',date('Ymd\THisO'));
//define('TIME_STAMP_ISO_8601','20140205T171524Z');
//define('TIME_STAMP','20140205');
define('TIME_STAMP',date('Ymd'));
define('REGION_CODE','us-east-1');
define('SERVICE_NAME','AGCODService');


$secretKey = 'AWS4'.SECRET_KEY;

$hashedDateKey = hash_hmac('sha256', TIME_STAMP, $secretKey, true);//41b8dd5e0d1716ba90401d46b58b12d500accdd2ea9c2b22a2d275946c9d978e

$hashedRegionKey = hash_hmac('sha256', REGION_CODE, $hashedDateKey, true);//7b47360ce7afbe1b839e0b0e55834df99979a5414bc7f846b17c9374d230d45d

$hashedServiceKey = hash_hmac('sha256', SERVICE_NAME , $hashedRegionKey, true);//68136b0a64b2d01c8934370288b46500243645e468f521503e0d1fa73526d409

$signingKey = hash_hmac('sha256', 'aws4_request', $hashedServiceKey,true);//27cb9f5b991c2933f5faae716e99bd50c66a45811b1424128269312bdd570dff

$payload = "<CreateGiftCardRequest><creationRequestId>Test001</creationRequestId><partnerId>Test</partnerId><value><currencyCode>USD</currencyCode><amount>10</amount></value></CreateGiftCardRequest>";

$hashedPayload = hash('sha256',$payload);//50bf24a091a7463bb4a2661f93a7299c94774bc81f9fddf02af2925922b869dc

$CanonicalRequestStr = "POST\n/CreateGiftCard\n\naccept:charset=UTF-8\ncontent-type:charset=UTF-8\nhost:agcod-v2-gamma.amazon.com\nx-amz-date:".TIME_STAMP_ISO_8601."\nx-amz-target:com.amazonaws.agcod.AGCODService.CreateGiftCard\n\naccept;content-type;host;x-amz-date;x-amz-target\n".$hashedPayload;

$hashedCanonicalRequest = hash('sha256',$CanonicalRequestStr);//7d9f2765e4f23e85d3dce4ae264dac4f784c152f3746aff45ac7f3afd7fad649

$str2Sign = "AWS4-HMAC-SHA256\n".TIME_STAMP_ISO_8601."\n".TIME_STAMP."/".REGION_CODE."/".SERVICE_NAME."/aws4_request\n".$hashedCanonicalRequest;

$signature = hash_hmac('sha256', $str2Sign, $signingKey);//e32110cf663ed86460621dff12bb1139afe29d015584d208df09f149fa1b69d1

$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,'https://agcod-v2-gamma.amazon.com/CreateGiftCard');
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTPS);
//curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'accept:charset=UTF-8',
'content-type:charset=UTF-8',
'host:agcod-v2-gamma.amazon.com',
'x-amz-date:'.TIME_STAMP_ISO_8601,
'x-amz-target:com.amazonaws.agcod.AGCODService.CreateGiftCard',
'Authorization:AWS4-HMAC-SHA256 Credential='.ACCESS_KEY.'/'.TIME_STAMP.'/us-east-1/AGCODService/aws4_request, SignedHeaders=accept;content-type;host;x-amz-date;x-amz-target,Signature='.$signature,
));
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

$return = curl_exec($ch);

$return_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

curl_close($ch);

var_dump($return_code);
?>

person JohnnyChenFromCN    schedule 29.07.2014    source источник
comment
любой, кто знает, как решить эту проблему, пожалуйста, помогите мне... я ценю любое ваше предложение, потому что я застрял в этой проблеме более 2 дней T_T   -  person JohnnyChenFromCN    schedule 29.07.2014


Ответы (1)


SDK AWS для PHP имеет реализацию SignatureV4. Для AGCOD не включен PHP-клиент, так как это не сервис AWS, но сервис DynamoDB работает очень похоже на то, как работает AGCOD. Мне удалось взломать клиент DynamoDB, чтобы вместо этого отправлять запросы в AGCOD.

<?php

require 'vendor/autoload.php'; // If installed via Composer.

// Instantiate DynamoDB client, but overwrite a bunch of the settings
// to work with the AGCOD service
$client = \Aws\DynamoDb\DynamoDbClient::factory([
    'base_url' => 'https://agcod-v2-gamma.amazon.com',
    'key' => 'AWS_ACCESS_KEY_ID',
    'secret' => 'AWS_SECRET_ACCESS_KEY',
    'region' => 'us-east-1',
    'signature' => 'v4',
    'signature.service' => 'AGCODService',
    'signature.region' => 'us-east-1',
]);

// Add wire logger for debugging
$client->addSubscriber(\Guzzle\Plugin\Log\LogPlugin::getDebugPlugin());

$body = <<<JSON
{"requestId": "Awssb0327141418PM", "partnerId": "Awssb", "utcStartDate":
"2014-03-27T00:10:10Z", "utcEndDate": "2014-03-27T23:59:59Z", "pageIndex": 0,
"pageSize": 200, "showNoOps": "true"}
JSON;

try {
    // Use underlying Guzzle feature to send request,
    // to skip some of the DynamoDB-specific logic.
    $response = $client->put('GetGiftCardActivityPage', [
        'x-amz-target' => 'com.amazonaws.agcod.AGCODService.GetGiftCardActivityPage',
        'accept'       => 'application/json'
    ], $body)->send();
} catch (\Aws\Common\Exception\ServiceResponseException $e) {
    echo $e; // This exception class has a __toString() method.
}

Обратите внимание, если это сильно поможет, но его можно использовать в качестве отправной точки, если вы решите выбрать код из AWS SDK для PHP.

person Jeremy Lindblom    schedule 30.07.2014
comment
большое спасибо Джереми! ваш код очень полезен!! - person JohnnyChenFromCN; 30.07.2014