下载AMZ广告报告

时间:2018-05-24 23:56:25

标签: node.js api express authentication

我有以下应用程序从amazons Sponsored Products API下载productAds

文档:https://advertising.amazon.com/API/docs/reference/reports

当我尝试使用它时,我从请求报告中获得响应,并在s3 Bucket中获取文件。

server is running at localhost:3000
{"reportId":"amzn1.clicPI.v1.p7.5B7EE.d141f-e5-4b-a8-6a4e712","status":"SUCCESS","statusDetails":"Report has been successfully generated","location":"https://advertising-api.amazon.com/v1/reports/amzn1.clsAPI.v1.p7.5B7EE.d151f-e5-4b-a8-699e712/download","fileSize":22}

接下来我尝试下载报告 enter image description here

和休息我得到以下错误:

donwloading <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message><ArgumentName>Authorization</ArgumentName><ArgumentValue>bearer Atza|IwEBIJvCt20TUi122srkN4JCOdUxlBNuLJBrtbIGF9x5QbKG67f-K-0L4RkLzeyouXWy_U_-VscaCe1aFqOJK55X9Mu2X6nwWkAWRyhc6cCMfPjKpyyVjKtPqC8Plme84om1dqtmIqC93yUVc_clHimQqmnl262te2EXyUhYoVQg8hK2nlDG67Iw7xjsLK4rgl3E4RR36DHnZkEOnVQZtfjIkIbcYtsCSAdpRZRazF4FQfpS-jHvMlwuH8TZfY9tRpmBEx5fjJw1WZ14Dejqti23mZ7yt-MjNkUuD-DdPXs3fek1ZJePlHEVzcI2y_WzCnwJnoSVp5a5w1WgNco8YqEGEuLsT9S0dxQRluTiw8f4b4lx2FFFm9jz0K7pqo1Mvs6DZOVCDJzE-xJ_VLlWoE5QDMUAMor4AEQH44_0NWBjJDrYaVvn1vZLCER1uxW4jgr127W5yXaj4y1vj_vADwFq9a3330hAc73EWwL6FFSfoTQZyNc4Fh1d3DXfVHpXFk6cv0bHt4cV_OotGwGHat5fv75VHX5K3al3Xd5-QJv2cTiQ9srY5oqKsdbxptGaxAdrdMQaUlFHhyHEGbwED9xYoCw6-IauN15gvMAei9wz2kzRCA</ArgumentValue><RequestId>BDCE812C4363E9D2</RequestId><HostId>4ixH24mPtMBt+FDnI3rM9UJP95toaNBmmR1v0uQJ5XkyiXbtLEuZ8d+vDI0+gquwhn6/Fkz6/+o=</HostId></Error>

这是应用程序。如何下载报告并正确传递标题?我在PHP中发现了这个具有下载功能的repo:https://github.com/dbrent-amazon/amazon-advertising-api-php/blob/master/AmazonAdvertisingApi/Client.php

const express = require('express')
const app = express();
const request = require('request');
const moment = require('moment');
const fs = require('fs')
const path = require('path')
const config = require('./config')
const auth = require('./helpers/auth');
const cron = require('./helpers/cron');
const con = require('./helpers/database');

const getProfiles = (headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/profiles',
            method: "GET",
            headers: headers
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}

const createReport = (params, recordType, headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/' + recordType + '/report',
            method: "POST",
            headers: headers,
            json: params
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}

const getReport = (reportId, headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/reports/' + reportId,
            method: "GET",
            headers: headers
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}

function download(fileUrl, apiPath, callback) {
    var url = require('url'),
        http = require('http'),
        p = url.parse(fileUrl),
        timeout = 10000;

    var file = fs.createWriteStream(apiPath);

    var timeout_wrapper = function (req) {
        return function () {
            console.log('abort');
            req.abort();
            callback("File transfer timeout!");
        };
    };


    console.log('before');

    var request = http.get(fileUrl).on('response', function (res) {
        console.log('in cb');
        var len = parseInt(res.headers['content-length'], 10);
        var downloaded = 0;

        res.on('data', function (chunk) {
            file.write(chunk);
            downloaded += chunk.length;
            process.stdout.write("Downloading " + (100.0 * downloaded / len).toFixed(2) + "% " + downloaded + " bytes" + isWin ? "\033[0G" : "\r");
            // reset timeout
            clearTimeout(timeoutId);
            timeoutId = setTimeout(fn, timeout);
        }).on('end', function () {
            // clear timeout
            clearTimeout(timeoutId);
            file.end();
            console.log(file_name + ' downloaded to: ' + apiPath);
            callback(null);
        }).on('error', function (err) {
            // clear timeout
            clearTimeout(timeoutId);
            callback(err.message);
        });
    });

    // generate timeout handler
    var fn = timeout_wrapper(request);

    // set initial timeout
    var timeoutId = setTimeout(fn, timeout);
}

const recordType = 'productAds';
const campaignType = 'sponsoredProducts';
const reportDate = moment().format('YYYYMMDD');
const metrics = 'campaignId,sku,currency,attributedConversions1d';

const reportParam = {
    campaignType: campaignType,  
    // segment: "query",
    reportDate: reportDate,      
    metrics: metrics             
}


auth().then(res => {
    const headers = {
        'Content-Type': 'application/json',
        'Authorization': config.token_type + ' ' + res.access_token,
        'Amazon-Advertising-API-Scope': '196354651614',
    }

    // getProfiles(headers).then(res => {})
    const reportId = 'amzn1.clicksAI.1.p.5B057EE.d41f-e5-4a-a8-699e712';
        getReport(reportId, headers).then(res => {
            console.log(res)
            const file = JSON.parse(res);
            // console.log(file.location )
            // download

            request({
                url: file.location,
                method: 'GET',
                headers: {
                    'Authorization': headers.Authorization,
                    'Amazon-Advertising-API-Scope': '196335474',
                    'Allow': 'GET, HEAD, PUT, DELETE'
                }
            }, (err, response, body) => {
                console.log('donwloading', body)
            })
        })

    createReport(reportParam, recordType, headers).then(res => {
        const reportId = 'amzn1.clicksI.v1.p7.5B07EE.d1541f-e5-eb-a68-6996e712';
    })
})


app.listen(3000, function(err) {
    console.log("server is running at localhost:3000");
})

1 个答案:

答案 0 :(得分:0)

这是由于将“ Authorization”标头发送到S3而引起的,它不希望这样做。原因是因为来自API的/ download响应是307重定向,所以您正在使用的客户端使用完整的API标头进行重定向。要解决此问题,请防止客户端遵循重定向并改为从响应的标题解析S3位置。