Perl哈希到oauth签名

时间:2017-08-08 12:55:47

标签: perl hash oauth

我找到了一个如何制作oauth签名的示例,但是遇到了多维哈希的问题。我的哈希看起来像使用Data :: Dumper来显示我的名为%request的哈希:

$VAR1 = { 'Invoice' => { 'Line' => [ { 'Id' => '1', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2267' }, 'UnitPrice' => '10.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 1 }, { 'Id' => '2', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2292' }, 'UnitPrice' => '20.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 2 }, { 'Id' => '3', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2285' }, 'UnitPrice' => '30.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 3 } ], 'DocNumber' => '90210', 'CustomerRef' => \{ 'name' => 'Amazon.com', 'value' => 1 } } };

进行签名的示例涉及将上面的%request hash加入到字符串中:

my $string = join('&',map {$_ . '=' . uri_escape($request{$_})} sort keys %request);

但是这会产生以下不一致的用作签名:

Invoice=HASH%280x7f254c17b540%29

如何处理此哈希以创建我需要传递到我的oauth签名字符串的字符串?

示例脚本运行正常,使用以下内容构造oauth签名:

my $hmac = Digest::HMAC_SHA1->new($e->{params}{qbo_consumer_secret} . '&' . $e->{params}{qbo_access_token_secret});
$hmac->add('GET&' . uri_escape('https://sandbox-quickbooks.api.intuit.com/v3/company/' . $company_id . '/query') . '&' . uri_escape('oauth_consumer_key=' . $consumer_key . '&oauth_nonce=' . $nonce . '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' . $time . '&oauth_token=' . $access_token . '&oauth_version=1.0' . '&' . join('&',map {$_ . '=' . uri_escape($params{$_})} sort keys %params)));

与我的尝试相比:

my $hmac = Digest::HMAC_SHA1->new($e->{params}{qbo_consumer_secret} . '&' . $e->{params}{qbo_access_token_secret});
$hmac->add('POST&' . uri_escape($server) . '&' . uri_escape('oauth_consumer_key=' . $e->{params}{qbo_consumer_key}) . '&oauth_nonce=' . $nonce . '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' . $time . '&oauth_token=' . $e->{params}{qbo_access_token} . '&oauth_version=1.0' . '&' . join('&',map {$_ . '=' . uri_escape($request{$_})} sort keys %request));

然后请求包含此授权标头:

my $req = HTTP::Request->new(POST => $server);
$req->header(Authorization =>
    'OAuth oauth_consumer_key="' . $e->{qbo_consumer_key}
    . '",oauth_nonce="' . $nonce
    . '",oauth_signature="' . encode_base64($hmac->digest)
    . '",oauth_signature_method="HMAC-SHA1'
    . '",oauth_timestamp="' . time();
    . '",oauth_token="' . $e->{qbo_access_token}
    . '",oauth_version="1.0'
    . '"');
$req->content( \%request );

此外,尝试将散列转换为json导致'无法编码对标量的引用'。我尝试这个简单的测试脚本:

#!/usr/bin/perl

use strict;
use warnings;
use JSON;

my %hash = { 'Invoice' => { 'Line' => [ { 'Id' => '1', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2267' }, 'UnitPrice' => '10.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 1 }, { 'Id' => '2', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2292' }, 'UnitPrice' => '20.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 2 }, { 'Id' => '3', 'SalesItemLineDetail' => { 'ItemRef' => { 'value' => 'SKM2285' }, 'UnitPrice' => '30.00' }, 'DetailType' => 'SalesItemLineDetail', 'LineNum' => 3 } ], 'DocNumber' => '90210', 'CustomerRef' => \{ 'name' => 'Amazon.com', 'value' => 1 } } };

my $js = encode_json \%hash;
print "$js\n";

下面产生此错误,我的哈希值有问题吗?

Reference found where even-sized list expected at testjson.pl line 8.
{"HASH(0x8db5f3c)":null}

1 个答案:

答案 0 :(得分:0)

首先,如果你阅读了JSON模块文档,它就会清楚地说明encode方法只需要一个标量,所以传递一个哈希不会起作用。当您将类似的哈希值传递给函数时,它会获取每个键和值并单独传递它们。

my %hash=("a" => 1,"b" => 2);
my_func(%hash);
# The above function call is the same as the one below
my_func("b",2,"a",1);

它传递的每个键/值配对的顺序是随机的,因为您通常会使用哈希找到它。它甚至会引发错误,告诉您如何使用它,或者至少在我尝试测试您的代码时已安装的版本。

相反,你真正想要做的就是像这样传入hashref

$json->encode(\%request);

返回的值是您需要传递给$req->content()并在签名中使用的值。我不知道Quickbooks API的任何内容,无法知道您是按原样传递JSON数据还是将其用作CGI参数的值。它应该是我希望在他们的文档中告诉你的东西。