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”);に変更します。

最後に仕様としてアマゾンは検索結果を全部返します。

仮に検索に一致した商品がない場合でも少しでも引っかかる「まったく違う商品」を返すので、そこを気をつける必要アリです。

contact us お問い合わせ

Contact お問い合わせ・ご相談

Webサービス・システム開発の
ご相談はお気軽にご連絡ください。

Recruit 求人へのご応募

サニージェムでは現在、プロジェクトの推進を
担う仲間を募集しています。