在过去的 6 个小时里,我一直在尝试按照亚马逊的说明在 node.js 中签署简单支付按钮表单。我无法接受签名,并且我已经尝试了令人困惑的指令的每一种排列方式。谁能帮我摆脱困境?
我得到的错误是
输入参数签名无效
这是我的程序
var params={
"returnUrl": "[confidential]",
"ipnUrl": "[confidential]",
"processImmediate": "1",
"accessKey" :"[AWS key]",
"collectShippingAddress" :"0",
"isDonationWidget" :"0",
"amazonPaymentsAccountId" :"[the button generator creates this but there is no mention in the docs]",
"referenceId" :ref,
"cobrandingStyle" :"logo",
"immediateReturn" :"1",
"amount" :"USD "+amount,
"description" : desc,
"abandonUrl" :"[confidential]",
"signatureMethod": "HmacSHA256", //docs not clear if signatureMethod and signatureVersion should be included, but I've tried all permutations and can't get it to work
"signatureVersion" :"2"
}
//Docs say it should confirm to
/*
StringToSign = HTTPVerb + "\n" +
ValueOfHostHeaderInLowercase + "\n" +
HTTPRequestURI + "\n" +
CanonicalizedQueryString <from the preceding step>
*/
//sort parameters (natural byte order)
var p=_.pairs(params);
var psorted=_.sortBy(p, function(p) { return p[0];});
//start to construct the form
var input='';
for(var i=0; i<psorted.length;i++) {
input+="<input type='hidden' name='"+psorted[i][0]+"' value='"+psorted[i][1]+"'>";
}
//prepare the string to be signed
var qstring='POST'+'\n';
qstring+='https://authorize.payments.amazon.com'+'\n';
qstring+='/pba/paypipeline'+'\n';
for(var i=0; i<psorted.length;i++) {
psorted[i][0]=encodeURI(psorted[i][0]);
psorted[i][1]=encodeURI(psorted[i][1]);
qstring+=psorted[i][0]+'='+psorted[i][1];
if (i<psorted.length-1) {qstring+='&';}
};
console.log(qstring+'\n\n');
var sig=crypto.createHmac("SHA256", "[AWS Secret Key") 6
.update(qstring)
.digest('base64');
input+="<input type='hidden' name='signature' value='"+sig+"'>"; //doesn't matter whether or not i url encode this
console.log(input);
将参数转换为
POST
authorize.payments.amazon.com
/pba/paypipeline
abandonUrl=XXXX&accessKey=XXXXX&amazonPaymentsAccountId=XXXXXX&amount=USD%203&cobrandingStyle=logo&collectShippingAddress=0&description=sadasdd&immediateReturn=1&ipnUrl=XXXXXx&isDonationWidget=0&processImmediate=1&referenceId=324324&returnUrl=XXXXXXXX&signatureMethod=HmacSHA256&signatureVersion=2
我将输出连接并粘贴到此表单以进行测试
<form action="https://authorize.payments.amazon.com/pba/paypipeline" method="POST">
<input type='hidden' name='abandonUrl' value='[confidential]'>
<input type='hidden' name='accessKey' value='[confidential]'>
<input type='hidden' name='amazonPaymentsAccountId' value='[confidential]'>
<input type='hidden' name='amount' value='USD 3'>
<input type='hidden' name='cobrandingStyle' value='logo'>
<input type='hidden' name='collectShippingAddress' value='0'>
<input type='hidden' name='description' value='sadasdd'>
<input type='hidden' name='immediateReturn' value='1'>
<input type='hidden' name='ipnUrl' value='[confidential]'>
<input type='hidden' name='isDonationWidget' value='0'>
<input type='hidden' name='processImmediate' value='1'>
<input type='hidden' name='referenceId' value='324324'>
<input type='hidden' name='returnUrl' value='[confidential]'>
<input type='hidden' name='signatureMethod' value='HmacSHA256'>
<input type='hidden' name='signatureVersion' value='2'>
<input type='hidden' name='signature' value='fHSA+p37r5ooOJOUnjYBdhNFe/pAEg/KunAEOudUvGs='>
<input type="submit">
</form>
这是亚马逊文档
http://docs.aws.amazon.com/AmazonSimplePay/latest/ASPAdvancedUserGuide/Sig2CreateSignature.html
如何生成签名
创建签名
创建稍后在此过程中需要的规范化查询字符串:
使用自然字节顺序按参数名称对 UTF-8 查询字符串组件进行排序。
参数可以来自 GET URI 或 POST 正文(当 Content-Type 为 application/x-www-form-urlencoded 时)。
URL 根据以下规则对参数名称和值进行编码:
不要对 RFC 3986 定义的任何非保留字符进行 URL 编码。
这些非保留字符是 AZ、az、0-9、连字符 (-)、下划线 (_)、句点 (.) 和波浪号 (~)。
百分比使用 %XY 对所有其他字符进行编码,其中 X 和 Y 是十六进制字符 0-9 和大写 AF。
百分比编码扩展的 UTF-8 字符,格式为 %XY%ZA....
百分比将空格字符编码为 %20(而不是 +,就像常见的编码方案那样)。
Note 目前所有 AWS 服务参数名称都使用非保留字符,因此您不需要对它们进行编码。但是,您可能希望包含代码来处理使用保留字符的参数名称,以备将来使用。使用等号 ( = )(ASCII 字符 61)将编码参数名称与其编码值分开,即使参数值为空。
使用与号 ( & ) 分隔名称-值对(ASCII 代码 38)。
根据以下伪语法创建要签名的字符串(“\n”表示 ASCII 换行符)。
StringToSign = HTTPVerb + "\n" + ValueOfHostHeaderInLowercase + "\n" + HTTPRequestURI + "\n" + CanonicalizedQueryString HTTPRequestURI 组件是 URI 的 HTTP 绝对路径组件,直到但不包括查询字符串。如果 HTTPRequestURI 为空,请使用正斜杠 ( / )。
使用您刚刚创建的字符串、您的秘密访问密钥作为密钥以及 SHA256 或 SHA1 作为哈希算法来计算符合 RFC 2104 的 HMAC。
如需更多信息,请访问http://www.ietf.org/rfc/rfc2104.txt。
将结果值转换为 base64。
使用结果值作为 Signature 请求参数的值。
重要 您在请求中发送的最终签名必须按照 RFC 3986 中的规定进行 URL 编码(有关更多信息,请访问 http://www.ietf.org/rfc/rfc3986.txt)。如果您的工具包 URL 对您的最终请求进行编码,那么它会处理所需的签名 URL 编码。如果您的工具包没有对最终请求进行 URL 编码,请确保在将签名包含在请求中之前对签名进行 URL 编码。最重要的是,确保签名仅被 URL 编码一次。一个常见的错误是在签名形成期间手动对其进行 URL 编码,然后在工具包 URL 对整个请求进行编码时再次对其进行编码。有关创建按钮的高级流程的信息,请参阅动态创建按钮表单。
在以下示例中,已插入新行以使示例更易于阅读。显式 '\n' 用于需要换行的地方。
以下是使用 POST 的 Amazon Simple Pay 请求示例。
以下是前面示例中用于 StringToSign 的字符串示例。
POST\n authorize.payments-sandbox.amazon.com\n /pba/paypipeline\n SignatureMethod=HmacSHA256 &SignatureVersion=2 &accessKey=YourCallerKey &amount=USD%201.1 &cobrandingStyle=logo &description=Test%20Widget &immediateReturn=0 &ipnUrl=http%3A %2F%2Fyourwebsite.com%2Fipn &processImmediate=1 &referenceId=YourReferenceId &returnUrl=http%3A%2F%2Fyourwebsite.com%2Freturn.html 有关生成签名的更多示例,请参阅附录:示例代码。
有关正确签署按钮表单的信息,请参阅如何正确签署按钮表单。