Closed davidalvarez305 closed 2 years ago
Hey, I know this doesn't belong here but I'm not sure where else to ask this question. In trying to request PAAPI5 from Go using very similar code as to the one used in this library, I keep receiving this error message:
"The request has not been correctly signed. If you are using an AWS SDK, requests are signed for you automatically; otherwise, go to https://webservices.amazon.com/paapi5/documentation/sending-request.html#signing."
Would you be able to help me figure out exactly what I'm doing wrong? If not, I apologize for the inconvinience:
func makeHash(hash hash.Hash, b []byte) []byte { hash.Reset() hash.Write(b) return hash.Sum(nil) } func buildCanonicalString(method, uri, query, signedHeaders, canonicalHeaders, payloadHash string) string { return strings.Join([]string{ method, uri, query, canonicalHeaders, signedHeaders, payloadHash, }, "\n") } func buildStringToSign(date, credentialScope, canonicalRequest string) string { return strings.Join([]string{ "AWS4-HMAC-SHA256", date, credentialScope, hex.EncodeToString(makeHash(sha256.New(), []byte(canonicalRequest))), }, "\n") } func buildSignature(strToSign string, sig string) (string, error) { return hex.EncodeToString(HMACSHA256([]byte(sig), []byte(strToSign))), nil } func HMACSHA256(key []byte, data []byte) []byte { hash := hmac.New(sha256.New, key) hash.Write(data) return hash.Sum(nil) } func SearchPaapi5Items(keyword string) []AmazonSearchResultsPage { var products []AmazonSearchResultsPage resources := []string{ "Images.Primary.Medium", "ItemInfo.Title", "Offers.Listings.Price", "ItemInfo.ByLineInfo", "ItemInfo.Features", "ItemInfo.ProductInfo"} d := AmazonPaapi5RequestBody{ Marketplace: "www.amazon.com", PartnerType: "Associates", PartnerTag: os.Getenv("AMAZON_PARTNER_TAG"), Keywords: keyword, SearchIndex: "All", ItemCount: 10, Resources: resources, } body, e := json.Marshal(d) if e != nil { return products } method := "POST" service := "ProductAdvertisingAPI" url := "https://webservices.amazon.com/paapi5/searchitems" host := "webservices.amazon.com" region := os.Getenv("AWS_REGION") contentType := "application/json; charset=UTF-8" amazonTarget := "com.amazon.paapi5.v1.ProductAdvertisingAPIv1.SearchItems" contentEncoding := "amz-1.0" t := time.Now() amazonDate := strftime.Format(t, "%Y%m%d") xAmazonDate := strftime.Format(t, "%Y%m%dT%H%M%SZ") canonicalUri := "/paapi5/searchitems" canonicalQuerystring := "" canonicalHeaders := "content-type:" + contentType + "\n" + "host:" + host + "\n" + "x-amz-date:" + xAmazonDate + "\n" + "x-amz-target:" + amazonTarget + "\n" + "content-encoding:" + contentEncoding credentialScope := amazonDate + "/" + region + "/" + service + "/" + "aws4_request" signedHeaders := "content-type;host;x-amz-date;x-amz-target;content-encoding" kSecret := os.Getenv("AWS_SECRET_ACCESS_KEY") kDate := hex.EncodeToString(HMACSHA256([]byte("AWS4"+kSecret), []byte(amazonDate))) kRegion := hex.EncodeToString(HMACSHA256([]byte(kDate), []byte(region))) kService := hex.EncodeToString(HMACSHA256([]byte(kRegion), []byte(service))) signingKey := hex.EncodeToString(HMACSHA256([]byte(kService), []byte("aws4_request"))) canonicalRequest := buildCanonicalString(method, canonicalUri, canonicalQuerystring, signedHeaders, canonicalHeaders, hex.EncodeToString(makeHash(sha256.New(), []byte(body)))) stringToSign := buildStringToSign(xAmazonDate, credentialScope, canonicalRequest) signature, err := buildSignature(stringToSign, signingKey) if err != nil { fmt.Println("Error while building signature.") } authorizationHeader := "AWS4-HMAC-SHA256" + " Credential=" + os.Getenv("AWS_ACCESS_KEY_ID") + "/" + credentialScope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature client := &http.Client{} req, err := http.NewRequest(method, url, bytes.NewBuffer(body)) if err != nil { fmt.Println("Request failed: ", err) return products } req.Header.Set("content-type", contentType) req.Header.Set("host", host) req.Header.Set("x-amz-date", xAmazonDate) req.Header.Set("x-amz-target", amazonTarget) req.Header.Set("content-encoding", contentEncoding) req.Header.Set("Authorization", authorizationHeader) resp, err := client.Do(req) if err != nil { fmt.Println("Error while fetching Amazon SERP", err) return products } defer resp.Body.Close() respDump, err := httputil.DumpResponse(resp, true) if err != nil { log.Fatal(err) } fmt.Printf("RESPONSE:\n%s", string(respDump)) return products }
The problem was that my function is using EST instead of UTC time. Sorry!
Hey, I know this doesn't belong here but I'm not sure where else to ask this question. In trying to request PAAPI5 from Go using very similar code as to the one used in this library, I keep receiving this error message:
"The request has not been correctly signed. If you are using an AWS SDK, requests are signed for you automatically; otherwise, go to https://webservices.amazon.com/paapi5/documentation/sending-request.html#signing."
Would you be able to help me figure out exactly what I'm doing wrong? If not, I apologize for the inconvinience: