2016-07-26 117 views
0

我想从我的应用程序内部实现itemLookup从亚马逊的API。我已经看过早期版本的Swift的文档,但他们似乎不再工作,但我有它的工作到一定程度。亚马逊签名创建

我从Javascript移植的代码作为this post

描述这是我迄今为止:

func callAmazon(){ 

     let amazonAccessID = "XXXXXX" 
     let secretKey = "XXXXXXXXX" 
     let associateTag = "XXXXX" 

     var parameters = [String](); 

     let timestamp = ISO8601FormatStringFromDate(NSDate()) 

     parameters.append("AWSAccessKeyId=" + amazonAccessID); 
     parameters.append("Keywords=" + "boots"); 
     parameters.append("Operation=ItemSearch"); 
     parameters.append("Service=AWSECommerceService"); 
     parameters.append("Timestamp=" + (timestamp as String)); 
     parameters.append("Version=2013-08-01"); 
     parameters.append("AssociateTag=" + associateTag); 

     parameters.sortInPlace {$0 < $1} 
     let paramString = parameters.joinWithSeparator("&") 

     let method = NSMutableURLRequest().HTTPMethod 

     let signingKey = "\(method)\n" + "webservices.amazon.com\n" + "/onca/xml\n" + paramString 

     let signature = sha256(signingKey, secretKey: secretKey) 

     let finalString = signature.encodeURIComponent() 

     let amazonUrl = "http://webservices.amazon.com/onca/xml?" + paramString + "&Signature=" + finalString! 

     print("AmazonURL!!! : ", amazonUrl) 


    Alamofire.request(.GET, amazonUrl, parameters: nil).response { 
     (request, response, data, error) in 
      let xml = SHXMLParser().parseData(data!) 
      print(xml)// output the FilmID element. 
    } 


} 

func sha256(StringToSign : String, secretKey : String) -> String{ 

    var hex = StringToSign.hmac(.SHA256, key: secretKey) 
    let hexData = hex.dataUsingEncoding(NSUTF8StringEncoding) 
    let finalString = hexData?.base64EncodedStringWithOptions(.Encoding64CharacterLineLength) 

    return finalString! 

} 

这是输出。

[ItemSearchErrorResponse: { 
Error =  { 
    Code = SignatureDoesNotMatch; 
    Message = "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."; 
}; 
RequestId = "3d560ce4-a862-4792-953d-c0119cd0478b"; 
xmlns = "http://ecs.amazonaws.com/doc/2013-08-01/"; 
}] 

因此,我如何创建我的签名显然有问题,任何人都可以引导我在正确的方向?

+0

你好贾里德,请张贴正确的答案,因为我也面临同样的问题。 –

+1

这是这个问题的解决方案 [amazon-signature-creation-solution-in-swift-3](https://stackoverflow.com/questions/46400364/amazon-signature-creation-solution-in-swift-3 ) –

回答

3

亚马逊签名生成

下面是签名创建用于AWS的soloution。

这里是swift中AWS签名创建问题的解决方案。 我已经创建了AWS请求参数。并用HMAC算法对其进行编码。

通过传递产品ID调用callAmazon方法,并在响应中您将收到您必须解析的xml响应。 试试这个例子: -

static func callAmazon(asinId: String){ 
    // provide your AmazonAccessID, SecretKey and AssociateTag 
    let amazonAccessID = "xxxxxxx" 
    let secretKey = "xxxxxxx" 
    let associateTag = "xxxxx" 

    var parameters = [String](); 

    let timestamp = Date().iso8601.encodeURIComponent()! 

    parameters.append("AWSAccessKeyId=" + amazonAccessID) 
    parameters.append("Operation=ItemLookup") 
    parameters.append("Service=AWSECommerceService") 
    parameters.append("Timestamp=" + (timestamp as String)) 
    parameters.append("AssociateTag=" + associateTag) 
    parameters.append("ResponseGroup="+"Offers") 
    parameters.append("ItemId="+asinId) 
    parameters.append("IdType=ASIN") 

    parameters.sort {$0 < $1} 
    let paramString = parameters.joined(separator: "&") 

    let method = NSMutableURLRequest().httpMethod 

    let signingKey = "\(method)\n" + "webservices.amazon.com\n" + "/onca/xml\n" + paramString 

    let signature = signingKey.hmac(algorithm: .SHA256, key: secretKey) 

    let finalString = signature.encodeURIComponent() 

    let amazonUrl = "http://webservices.amazon.com/onca/xml?" + paramString + "&Signature=" + finalString! 

    print("AmazonURL!!! :", amazonUrl) 


    AppNetworking.serviceRequestPrice(endPoint: amazonUrl, success: { (data) in 

     if let data = data{ 

      print(String(data: data, encoding: .utf8) ?? "CANNOT CONVERT") 
     } 

    }) { (error) in 
     print(error) 
    } 

    } 

extension HMACAlgorithm{ 

func toCCHmacAlgorithm() -> CCHmacAlgorithm { 
    var result: Int = 0 
    switch self { 

    case .MD5: 
     result = kCCHmacAlgMD5 
    case .SHA1: 
     result = kCCHmacAlgSHA1 
    case .SHA224: 
     result = kCCHmacAlgSHA224 
    case .SHA256: 
     result = kCCHmacAlgSHA256 
    case .SHA384: 
     result = kCCHmacAlgSHA384 
    case .SHA512: 
     result = kCCHmacAlgSHA512 
    } 
    return CCHmacAlgorithm(result) 
} 

func digest_Length() -> Int { 

    var result: CInt = 0 
    switch self { 
    case .MD5: 
     result = CC_MD5_DIGEST_LENGTH 
    case .SHA1: 
     result = CC_SHA1_DIGEST_LENGTH 
    case .SHA224: 
     result = CC_SHA224_DIGEST_LENGTH 
    case .SHA256: 
     result = CC_SHA256_DIGEST_LENGTH 
    case .SHA384: 
     result = CC_SHA384_DIGEST_LENGTH 
    case .SHA512: 
     result = CC_SHA512_DIGEST_LENGTH 
    } 
    return Int(result) 
}} 

extension String { 
// returning encoded signature 
func hmac(algorithm: HMACAlgorithm, key: String) -> String { 
    let cKey = key.cString(using: String.Encoding.utf8) 
    let cData = self.cString(using: String.Encoding.utf8) 
    var result = [CUnsignedChar](repeating: 0, count: Int(algorithm.digest_Length())) 
    CCHmac(algorithm.toCCHmacAlgorithm(), cKey!, Int(strlen(cKey!)), cData!, Int(strlen(cData!)), &result) 
    let hmacData:NSData = NSData(bytes: result, length: (Int(algorithm.digestLength()))) 

    let hmacBase64 = hmacData.base64EncodedData(options: NSData.Base64EncodingOptions.lineLength64Characters) 

    return String(data: hmacBase64, encoding: String.Encoding.utf8)! 
} } 

extension String { 
// returning encoded url string 
func encodeURIComponent() -> String? { 
    let characterSet = NSMutableCharacterSet.alphanumeric() 
    characterSet.addCharacters(in: "-_.!~*'()") 

    return self.addingPercentEncoding(withAllowedCharacters: characterSet as CharacterSet) 
}} 

extension Formatter { 
// returning iso dateformater 
static let iso8601: DateFormatter = { 
    let formatter = DateFormatter() 
    formatter.calendar = Calendar(identifier: .iso8601) 
    formatter.locale = Locale(identifier: "en_US_POSIX") 
    formatter.timeZone = TimeZone(secondsFromGMT: 0) 
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 
    //"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"//"yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" 
    return formatter 
}() } 

extension Date { 
// returning iso date 
var iso8601: String { 
    return Formatter.iso8601.string(from: self) 
}} 
+0

谢谢!我实际上在几个月前解决了,但接受帮助别人。 :) –

1

我可以看到的一件事是你的标题不是由\n结束。

+1

固定 - (时间戳为字符串)+“\ n” –

+0

如果我帮助了您,请将答案标记为已接受。 – eMKa

+0

不,那不是解决办法,我实际上都是自己想出来的,整个星期都带着我。无论哪种方式,我会给你的赏金,因为你试图帮助。 :) –