4

我的卷曲超出了我的深度。我想将 PayMill 集成到我的网站(用 Perl 编写)。Paymill 还没有 Perl 库,所以我需要通过 curl 连接到它们。

我已经完成了前端 JS Paymill 的集成,并从 PayMill 收到了一个支付令牌。

我现在需要将从 Paymill 收到的令牌传递到我的后端,并使用 curl 要求 PayMill 完成交易并向用户收费。在这一点上,我被困住了。

要进行交易,PayMill 文档说我必须执行以下操作:

curl https://api.paymill.de/v2/transactions \
-u b94a7550bd908877cbae5d3cf0dc4b74: \
-d "amount=4200" \
-d "currency=EUR" \
-d "token=098f6bcd4621d373cade4e832627b4f6" \
-d "description=Test Transaction"

我相信 -u 是验证我的请求的 Paymill 密钥,尽管此处的文档不清楚。

我已经查看了 WWW::Curl::Easy、Net:Curl::Easy 和 LWP::Curl,但是这些方法的文档中没有任何内容让我很清楚如何形成上面的查询。

我已经尝试过(并不真正相信它会起作用),只是如上所述在 perl 中编码一个字符串;

my $request = '-u ' . $private_key . " ";
foreach my $key (keys %$params_in) {
    $request .= '-d "' . lc($key) .'='.$params_in->{$key} . ' ';
}

然后将 $request 传递给我的 curl 尝试,如下所示;

my $curl = WWW::Curl::Easy->new;
$curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER(), 1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_URL(), $paymill_server);
$curl->setopt(WWW::Curl::Easy::CURLOPT_POST(), 1);
$curl->setopt(WWW::Curl::Easy::CURLOPT_POSTFIELDS(), $request);

my $response;
$curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA(), \$response);

my $retcode = $curl->perform;

但是,由于访问被拒绝错误而失败,我认为这是因为 Paymill 没有找到我的密钥,因为我弄乱了 Curl(假设 -u 应该是 secret_key)。

我觉得我在这里遗漏了一些明显的东西。

有人可以指出我正确的方向,重新如何做到这一点?谢谢

更新

很好的答案,谢谢大家的帮助,它现在正在工作。我最终选择了 Matthias 的解决方案,最终完成交易的完整解决方案如下所示;

use LWP::UserAgent;
use MIME::Base64;
use JSON::XS;

my $ua = LWP::UserAgent->new;
$ua->default_header(Authorization => "Basic " . encode_base64(private_key));

my $response = $ua->post(https://api.paymill.de:443/v2/transactions , $params );
if ( $response->is_success ) {
    my $obj = eval { decode_json $response->content } || {};
    etc
}
4

3 回答 3

4

与其他答案一样,建议最好的方法是使用 LWP::UserAgent 来执行请求。

编辑:由于 PAYMILL 一段时间以来一直在发送挑战响应,因此我更新了代码。

由于 Paymill 不符合 RFC 2616,第 14.47 节(API 不发送质询响应)LWP::UserAgent 和类似的在发送带有凭据的第二个请求时失败。解决方案是“强制” LWP::UserAgent 通过将凭据添加为标头来发送第一个请求的凭据:

use LWP::UserAgent;
use MIME::Base64;

my $ua = LWP::UserAgent->new;
# Use the following line no longer:
# $ua->default_header(Authorization => "Basic " . encode_base64("your PRIVATE key"))
$ua->credentials('api.paymill.de:443', '', 'YOUR PRIVATE KEY');

# Dumping only
use Data::Dumper;
print Dumper($ua->get("https://api.paymill.de:443/v2/clients"));

披露:我在 Paymill 工作。

于 2013-01-10T09:38:31.563 回答
2

我不知道用户/密码和您的令牌的身份验证部分是否正确,因为我不知道“领域”应该是什么。不过,还是试试LWP吧。不是我不喜欢Curl,我只是不知道,但我确实知道LWP。

use strict; use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new;
$ua->credentials(
  'api.paymill.de:80',
  'Realm?',
  'b94a7550bd908877cbae5d3cf0dc4b74'
);
my $response = $ua->post(
  ' https://api.paymill.de/v2/transactions',
  {
    amount      => "4200",
    currency    => "EUR",
    token       => "098f6bcd4621d373cade4e832627b4f6",
    description => "Test Transaction",
  }
);
if ( $response->is_success ) {
  print $response->decoded_content;    # or whatever
} else {
  die $response->status_line;
}

编辑:我在Paymill 文档中阅读了一些内容。它说:

验证

例子

% 卷曲https://api.paymill.de/v2/clients \ -u e73fa5e7b87620585b5ea5d73c4d23bb:

要在 Paymill API 上进行身份验证,您需要测试或真实账户的私钥。您必须使用 http 基本访问身份验证。您的密钥必须设置为用户名。不需要密码,您也不必插入密码。但是,如果您愿意,可以随意插入任意字符串。

笔记

Please keep your private keys secure and don’t pass them to anybody. These private keys have extreme secure information for

处理您商店的交易。您的所有请求都必须通过 https 进行。将以另一种方式发出的请求将失败。这是出于提交数据的安全原因。

还有一个指向http://en.wikipedia.org/wiki/HTTP_Secure-u的链接,我相信它几乎可以清除这部分内容。

于 2013-01-09T15:55:21.923 回答
2

您可以使用LWP::Protocol::Net::Curl将 LWP 和 libcurl有机地集成在一起。检查这个:

#!/usr/bin/env perl
use common::sense;

use Data::Printer;
use JSON::XS;
use LWP::Protocol::Net::Curl verbose => 1;
use LWP::UserAgent;

# create user agent
my $ua = LWP::UserAgent->new;

# POST request
my $res = $ua->post(
    'https://b94a7550bd908877cbae5d3cf0dc4b74:@api.paymill.de/v2/transactions',
    'Accept-Encoding' => 'gzip',
    Content => {
        amount      => 4200,
        currency    => 'EUR',
        token       => '098f6bcd4621d373cade4e832627b4f6',
        description => 'Test Transaction',
    },
);

# parse received data
my $obj = eval { decode_json $res->content } // {};

# output
p $obj;

输出:

* About to connect() to api.paymill.de port 443 (#0)
*   Trying 62.138.241.3...
* Connected to api.paymill.de (62.138.241.3) port 443 (#0)
* Connected to api.paymill.de (62.138.241.3) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* SSL connection using RC4-SHA
* Server certificate:
*    subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.paymill.de
*    start date: 2012-07
*    expire date: 2013-10
*    subjectAltName: api.paymill.de matched
*    issuer: C=GB; S
*    SSL certificate verify ok.
* Server auth using Basic with user 'b94a7550bd908877cbae5d3cf0dc4b74'
> POST /v2/transactions HTTP/1.1
Authorization: Basic Yjk0YTc1NTBiZDkwODg3N2NiYWU1ZDNjZjBkYzRiNzQ6
User-Agent: libwww-perl/6.04 libcurl/7.28.0 OpenSSL/1.0.0e zlib/1.2.3.4 libidn/1.22 libssh2/1.2.8
Host: api.paymill.de
Accept: */*
Accept-Encoding: gzip
Content-Length: 92
Content-Type: application/x-www-form-urlencoded

* upload completely sent off: 92 out of 92 bytes
< HTTP/1.1 200 OK
< Server: nginx
< Date: Wed, 09 Jan 2013 17:22:54 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: close
< Set-Cookie: PHPSESSID=rmdo5a8c6u107gma28lotmmn24; path=/
< Expires: Thu, 19 Nov 1981 08:52:00 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< X-Server: hrtt-frn5-de13
< 
* Closing connection #0
Printing in line 28 of paymill.pl:
\ {
    data   {
        amount             4200,
        client             {
            created_at     1357752174,
            description    undef,
            email          undef,
            id             "client_85cb0bfc837f31c81015",
            payment        [],
            subscription   undef,
            updated_at     1357752174
        },
        created_at         1357752174,
        currency           "EUR",
        description        "Test Transaction",
        id                 "tran_c672daa0538e2a04e919",
        livemode           false,
        origin_amount      4200,
        payment            {
            card_holder    undef,
            card_type      "visa",
            client         "client_85cb0bfc837f31c81015",
            country        undef,
            created_at     1357752174,
            expire_month   12,
            expire_year    2014,
            id             "pay_2732689f44928301c769",
            last4          1111,
            type           "creditcard",
            updated_at     1357752174
        },
        preauthorization   undef,
        refunds            undef,
        status             "closed",
        updated_at         1357752174
    },
    mode   "test"
}
于 2013-01-09T17:24:39.470 回答