亚马逊灵活支付异常:呼叫者输入异常:无效签名


Amazon Flexible Payments Exception: Caller Input Exception: Invalid Signature

我正在尝试使用PHP API来实现亚马逊的灵活支付。

以下是我发送付款请求的PHP代码片段:

<?php
$string_to_sign = 'GET
authorize.payments-sandbox.amazon.com
/cobranded-ui/actions/start
SignatureMethod=HmacSHA256&SignatureVersion=2&callerKey=my_access_key&callerReference=YourCallerReference&paymentReason=donation&pipelineName=SingleUse&returnUrl=http%3A%2F%2Fproblemio.com&transactionAmount=4.0';
$encoded_string_to_sign = URLEncode(Base64_Encode(hash_hmac('sha256', $string_to_sign, 'my_secret_key')));
$amazon_request_sandbox = 'https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start?SignatureVersion=2&returnUrl='.$return_url.'&paymentReason='.$payment_reason.'&callerReference=YourCallerReference&callerKey='.$my_access_key_id.'&transactionAmount=4.0&pipelineName=SingleUse&SignatureMethod=HmacSHA256&Signature='.$encoded_string_to_sign;
// When it goes to the url, it gets the invalid signature error
header('Location: '.$amazon_request_sandbox); 
?>

这似乎遵循了他们的指示,但我无法克服那个错误。

谢谢!!

<?php
$method = 'GET';
$host   = 'authorize.payments-sandbox.amazon.com';
$path   = '/cobranded-ui/actions/start';
$params = array( 
    'signatureMethod'  => 'HmacSHA256',
    'signatureVersion' => '2',
    'currencyCode'     => 'USD',
    'callerKey' => 'Your_Key_ID',
    'callerReference'  => 'YourCallerReference',
    'paymentReason'    => 'donation',
    'pipelineName'     => 'SingleUse',
    'returnUrl'        => 'http://yourcallback.com',
    'transactionAmount'=> '5',
    'version'          => '2009-01-09',
);

$params = array_map('rawurlencode', $params);

$paramStringArray = array();
foreach($params as $key => $value){
    $paramStringArray[] = $key . '=' . $value;
}


$paramString = implode('&', $paramStringArray);
$string_to_sign = $method . "'n"
        . $host . "'n"
        . $path  . "'n"
        . $paramString;
    
$signature = base64_encode(hash_hmac(
    'sha256',
    $string_to_sign,
    'Your_Super_Secret_Key',
    true
));

$amazon_request_sandbox = "https://{$host}{$path}?" . $paramString .
    '&signature=' . rawurlencode($signature);
header('Location: '.$amazon_request_sandbox); 
?>

好吧。。。使用下面代码中的结构,我终于通过上面的代码弄清楚了这一切。在形成签名/URL时,有三件事需要注意。。。

  1. 似乎参数";transactionAmount;对于有效的联合品牌UI管道来说是必要的,尽管没有具体的说明暗指这个问题。

  2. 如果您的任何参数中都有空格,并且您尝试在除最新(5.4)版本的PHP之外的所有版本中使用html_build_query(),那么您将得到一个具有"+"标记空格而不是"%"20〃;这正是亚马逊所喜欢的。我上面的代码通过在整个参数数组上实现rawurlencode()来解决这个问题。

  3. 参数的排序在签名的构造中是至关重要的。键(而不是值)需要按不区分大小写的字母顺序排列。还值得注意的是,尽管文档中对API做了规定,但在为签名创建查询字符串时,必须同时存在与号(&)和等于号(=)。

例如:

签名查询字符串:callerKey=11111111111&currencyCode=美元&signatureVersion=2

我注意到的其他一些事情

在PHP SDK(2010-8-28)中包含的示例代码中;paymentReason";文件中的属性";CBUISingleUsePipelineSample.php";被列为";哈利波特1-5 DVD套装";。由于这个属性中有空格,它抛出了一个一直令人讨厌的";无效签名";尝试访问生成的链接时出错,因为html_build_query()用于生成URL的查询字符串。为了解决这个问题;"CBUIPipeline.php";,并在constructUrl()方法中查找以下行。。。

$queryString = http_build_query($parameters, '', '&');

替换为:

$queryString = str_replace('+', '%20', http_build_query($parameters, '', '&'));

这将解决旧版本PHP(<5.4)的空间编码问题;enc_type";您可以设置的标志。

最后的事情最后

这是我在StackOverflow上的第一篇帖子,所以如果我违反了协议,不要杀了我。希望它能有所帮助!

试试这段代码:

<?php
$method = 'GET';
$host   = 'authorize.payments-sandbox.amazon.com';
$path   = '/cobranded-ui/actions/start';
$params = array(
    'SignatureMethod'  => 'HmacSHA256'
    'SignatureVersion' => 2,
    'callerKey'        => 'my_access_key',
    'callerReference'  => 'YourCallerReference',
    'paymentReason'    => 'donation',
    'pipelineName'     => 'SingleUse',
    'returnUrl'        => 'http://problemio.com&transactionAmount=4.0',
);
$string_to_sign = $method . "'n"
    . $host . "'n"
    . $path . "'n"
    . http_build_query($params);
$signature = base64_encode(hash_hmac(
    'sha256',
    $string_to_sign,
    'my_secret_key'
));
$params['Signature'] = $signature;
$amazon_request_sandbox = "https://{$host}{$path}?" . http_build_query($params);
header('Location: ' . $amazon_request_sandbox);

所以我做了一些改变:

  • PHP的http_build_query()来构建查询字符串(确保正确编码)
  • 尝试重复使用vars与重复工作(更容易发现错误等)
  • 显式'n-可能您的编辑器输入了'r'r'n

HTH