我一直在尝试使用 ColdFusion 实现 Amazon Seller Central API 以获取订单详细信息。API 响应是一个错误,指出
" 我们计算的请求签名与您提供的签名不匹配。请检查您的 AWS Secret Access Key 和签名方法。有关详细信息,请参阅服务文档。"
代码:
<cfcomponent displayname="AmazonOrderDetails">
<cfoutput>
<cfset variables.timeStamp = getIsoTimeString(now())>
<cffunction name="getOrderDetails" access="remote" returntype="any">
<cfhttp url="https://mws.amazonservices.com/Orders/2013-09-01" method="POST">
<cfhttpparam name="AWSAccessKeyId" type="url" value="XXXXXXXXXXXXX">
<cfhttpparam name="Action" type="url" value="ListOrders">
<cfhttpparam name="Marketplace" type="url" value="XXXXXXXXXXXXXX">
<cfhttpparam name="Merchant" type="url" value="XXXXXXXXXXXXX">
<cfhttpparam name="SignatureMethod" type="url" value="HmacSHA256">
<cfhttpparam name="SignatureVersion" type="url" value="2">
<cfhttpparam name="Signature" type="url" value="#generateSignature()#">
<cfhttpparam name="Timestamp" type="url" value="#variables.timeStamp#">
<cfhttpparam name="Version" type="url" value="2013-09-01">
<cfhttpparam name="CreatedAfter" type="url" value="#getIsoTimeString(dateAdd("m", -1, now()))#">
</cfhttp>
<cfdump var="#cfhttp.Filecontent#">
</cffunction>
<cffunction name="HMAC_SHA256" returntype="string" access="private" output="false">
<cfargument name="Data" type="string" required="true" />
<cfargument name="Key" type="string" required="true" />
<cfargument name="Bits" type="numeric" required="false" default="256" />
<cfset local.i = 0 />
<cfset local.HexData = "" />
<cfset local.HexKey = "" />
<cfset local.KeyLen = 0 />
<cfset local.KeyI = "" />
<cfset local.KeyO = "" />
<cfset local.HexData = BinaryEncode(CharsetDecode(Arguments.data, "iso-8859-1"), "hex") />
<cfset local.HexKey = BinaryEncode(CharsetDecode(Arguments.key, "iso-8859-1"), "hex") />
<cfset local.KeyLen = Len(local.HexKey)/2 />
<cfif local.KeyLen gt 64>
<cfset local.HexKey = Hash(CharsetEncode(BinaryDecode(local.HexKey, "hex"), "iso-8859-1"), "SHA-256", "iso-8859-1") />
<cfset local.KeyLen = Len(local.HexKey)/2 />
</cfif>
<cfloop index="i" from="1" to="#KeyLen#">
<cfset local.KeyI = local.KeyI & Right("0"&FormatBaseN(BitXor(InputBaseN(Mid(local.HexKey,2*i-
1,2),16),InputBaseN("36",16)),16),2) />
<cfset local.KeyO = local.KeyO & Right("0"&FormatBaseN(BitXor(InputBaseN(Mid(local.HexKey,2*i-
1,2),16),InputBaseN("5c",16)),16),2) />
</cfloop>
<cfset local.KeyI = local.KeyI & RepeatString("36",64-local.KeyLen) />
<cfset local.KeyO = local.KeyO & RepeatString("5c",64-local.KeyLen) />
<cfset local.HexKey = Hash(CharsetEncode(BinaryDecode(local.KeyI&local.HexData, "hex"), "iso-8859-1"), "SHA-256", "iso-8859-1")
/>
<cfset local.HexKey = Hash(CharsetEncode(BinaryDecode(local.KeyO&local.HexKey, "hex"), "iso-8859-1"), "SHA-256", "iso-8859-1") />
<cfreturn Left(local.HexKey,arguments.Bits/4) />
</cffunction>
<cffunction name="getIsoTimeString" returntype="Any" access="private">
<cfargument name="datetime" type="date" required="true">
<cfset local.convertToUTC = true>
<cfif local.convertToUTC >
<cfset local.datetime = dateConvert( "local2utc", arguments.datetime )>
<cfreturn(
dateFormat( local.datetime, "yyyy-mm-dd" )&"T"&timeFormat( local.datetime, "HH:mm:ss" )&"Z"
)>
</cfif>
</cffunction>
<cffunction name="generateSignature" returntype="String" access="private">
<cfset local.secret_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
<cfset parameters = structNew() >
<cfset parameters["xxxxxxxxxxxxxxxxxxxx"] = "UserID">
<cfset parameters["1.0"] = "Version">
<cfset parameters["ListOrders"] = "Action">
<cfset parameters["#variables.timeStamp#"] = "Timestamp">
<cfset local.strtohash = "" >
<cfloop list="#ArrayToList(StructSort(parameters, "text", "asc"))#" index="key" >
<cfset local.strtohash = local.strtohash & #parameters[key]# & "=" & #URLEncodedFormat(key)# & "&" >
</cfloop>
<cfset local.strtohash = RemoveChars(local.strtohash, len(local.strtohash), 1)>
<cfset local.strtohash = Replace(local.strtohash, "%2D", "-", "All")>
<cfset local.strtohash = Replace(local.strtohash, "%2E", ".", "All")>
<cfset local.signature="#LCase(toBase64(HMAC_SHA256(local.strtohash, local.secret_key)))#">
<cfreturn local.signature>
</cffunction>
</cfoutput>
</cfcomponent>