cakephp amazon api 商品検索
2021/07/01
題名にcakephpを入れたけど特にcakephpだからやり方変わるとかないです。
amazon apiを使うには申請が通る必要があります。
登録しましたー>使います!ではないです。
登録した?ー>売上上げた?ー>コンテンツ沢山ある?->API_KEYどうぞって流れです。
ということでAPI使うより申請通すほうが大変です。はい。
SDKダウンロードしてやる方法もありましたが、今回はファイル作ってコピーしました。
class AmazonApiController extends Controller
{
public function getAmazonData($item=null)
{
$amazonKeys = Configure::read( 'AmazonKey' );
$searchItemRequest = new SearchItemsRequest ();
$searchItemRequest->PartnerType = "Associates";
$searchItemRequest->PartnerTag = 'hogehogePartnerTag';
$searchItemRequest->Keywords = $item->name;
$searchItemRequest->SearchIndex = "All";
$searchItemReques
->Resource ["Images.Primary.Small","ItemInfo.Title","Offers.Listings.Price"];
$host = "webservices.amazon.co.jp";
$path = "/paapi5/searchitems";
$payload = json_encode ($searchItemRequest);
$awsv4 = new AwsV4 ( 'hogehogeAccessKey', 'hogehogeSecretKey');
$awsv4->setRegionName("us-west-2");
$awsv4->setServiceName("ProductAdvertisingAPI");
$awsv4->setPath ($path);
$awsv4->setPayload ($payload);
$awsv4->setRequestMethod ("POST");
$awsv4->addHeader ('content-encoding', 'amz-1.0');
$awsv4->addHeader ('content-type', 'application/json; charset=utf-8');
$awsv4->addHeader ('host', $host);
$awsv4->addHeader ('x-amz-
target','com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems');
$headers = $awsv4->getHeaders ();
$headerString = "";
foreach ( $headers as $key => $value )
{ $headerString .= $key . ': ' . $value . "\r\n"; }
$params = [
'http' => [
'header' => $headerString,
'method' => 'POST',
'content' => $payload
]
];
$stream = stream_context_create ( $params );
$fp = @fopen ( 'https://'.$host.$path, 'rb', false, $stream );
$response = @stream_get_contents ( $fp );
return $response;
}
}
class SearchItemsRequest {
public $PartnerType;
public $PartnerTag;
public $Keywords;
public $SearchIndex;
public $Resources;
}
class AwsV4 {
private $accessKeyID = null;
private $secretAccessKey = null;
private $path = null;
private $regionName = null;
private $serviceName = null;
private $httpMethodName = null;
private $queryParametes = array ();
private $awsHeaders = array ();
private $payload = "";
private $HMACAlgorithm = "AWS4-HMAC-SHA256";
private $aws4Request = "aws4_request";
private $strSignedHeader = null;
private $xAmzDate = null;
private $currentDate = null;
public function __construct($accessKeyID, $secretAccessKey) {
$this->accessKeyID = $accessKeyID;
$this->secretAccessKey = $secretAccessKey;
$this->xAmzDate = $this->getTimeStamp ();
$this->currentDate = $this->getDate ();
}
function setPath($path) {
$this->path = $path;
}
function setServiceName($serviceName) {
$this->serviceName = $serviceName;
}
function setRegionName($regionName) {
$this->regionName = $regionName;
}
function setPayload($payload) {
$this->payload = $payload;
}
function setRequestMethod($method) {
$this->httpMethodName = $method;
}
function addHeader($headerName, $headerValue) {
$this->awsHeaders [$headerName] = $headerValue;
}
private function prepareCanonicalRequest() {
$canonicalURL = "";
$canonicalURL .= $this->httpMethodName . "\n";
$canonicalURL .= $this->path . "\n" . "\n";
$signedHeaders = '';
foreach ( $this->awsHeaders as $key => $value ) {
$signedHeaders .= $key . ";";
$canonicalURL .= $key . ":" . $value . "\n";
}
$canonicalURL .= "\n";
$this->strSignedHeader = substr ( $signedHeaders, 0, - 1 );
$canonicalURL .= $this->strSignedHeader . "\n";
$canonicalURL .= $this->generateHex ( $this->payload );
return $canonicalURL;
}
private function prepareStringToSign($canonicalURL) {
$stringToSign = '';
$stringToSign .= $this->HMACAlgorithm . "\n";
$stringToSign .= $this->xAmzDate . "\n";
$stringToSign .= $this->currentDate . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "\n";
$stringToSign .= $this->generateHex ( $canonicalURL );
return $stringToSign;
}
private function calculateSignature($stringToSign) {
$signatureKey = $this->getSignatureKey ( $this->secretAccessKey, $this->currentDate, $this->regionName, $this->serviceName );
$signature = hash_hmac ( "sha256", $stringToSign, $signatureKey, true );
$strHexSignature = strtolower ( bin2hex ( $signature ) );
return $strHexSignature;
}
public function getHeaders() {
$this->awsHeaders ['x-amz-date'] = $this->xAmzDate;
ksort ( $this->awsHeaders );
$canonicalURL = $this->prepareCanonicalRequest ();
$stringToSign = $this->prepareStringToSign ( $canonicalURL );
$signature = $this->calculateSignature ( $stringToSign );
if ($signature) {
$this->awsHeaders ['Authorization'] = $this->buildAuthorizationString ( $signature );
return $this->awsHeaders;
}
}
private function buildAuthorizationString($strSignature) {
return $this->HMACAlgorithm . " " . "Credential=" . $this->accessKeyID . "/" . $this->getDate () . "/" . $this->regionName . "/" . $this->serviceName . "/" . $this->aws4Request . "," . "SignedHeaders=" . $this->strSignedHeader .
}
private function generateHex($data) {
return strtolower ( bin2hex ( hash ( "sha256", $data, true ) ) );
}
private function getSignatureKey($key, $date, $regionName, $serviceName) {
$kSecret = "AWS4" . $key;
$kDate = hash_hmac ( "sha256", $date, $kSecret, true );
$kRegion = hash_hmac ( "sha256", $regionName, $kDate, true );
$kService = hash_hmac ( "sha256", $serviceName, $kRegion, true );
$kSigning = hash_hmac ( "sha256", $this->aws4Request, $kService, true );
return $kSigning;
}
private function getTimeStamp() {
return gmdate ( "Ymd\THis\Z" );
}
private function getDate() {
return gmdate ( "Ymd" );
}
}
公式の丸々コピーでは勿論うまくいかないです。
まずリージョンを変更するために、多分公式では$awsv4->setRegionName(“us-east-1”);になっている所を
$awsv4->setRegionName(“us-west-2”);に変更します。
最後に仕様としてアマゾンは検索結果を全部返します。
仮に検索に一致した商品がない場合でも少しでも引っかかる「まったく違う商品」を返すので、そこを気をつける必要アリです。