Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form a CURL request to PayMill in Perl

Tags:

curl

perl

paymill

I'm out of my depth with curl. I want to integrate PayMill into my site (which is written in Perl). There isn't a Perl lib for Paymill yet, so I need to connect to them via curl.

I have completed the front end JS Paymill integration, and received a payment token from PayMill.

I now need to pass the token received from Paymill to my backend and use curl to ask PayMill to complete the transaction and charge the user. At this point I'm stuck.

To make a transaction, the PayMill documentation says that I must do the following:

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

I believe -u is the Paymill secret key to authenticate my request although the documentation is not clear here.

I've had a look at WWW::Curl::Easy, Net:Curl::Easy and LWP::Curl, however nothing in the documentation for those methods makes it obvious to me how to form the query above.

I've tried (without really believing it would work), simply encoding a string in perl as described above;

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

And then passing $request to my attempt at curl as follows;

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;

however that fails with an Access Denied error, which I assume is because Paymill is not finding my key because I'm messing up the Curl (assuming -u is supposed to be the secret_key).

I feel I'm missing something obvious here.

Could someone point me in the right direction re how to do this? Thanks

UPDATE

Excellent answers, thanks everyone for your help, it's working now. I went with Matthias's solution in the end and the final complete solution for making a transaction looked as follows;

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
}
like image 634
mark Avatar asked Feb 17 '23 22:02

mark


1 Answers

Like other answers propose the best way would be using LWP::UserAgent for doing the requests.

Edit: Since PAYMILL is sending challenge responses since a while now I updated the code.

Since Paymill doesn't comply with RFC 2616, Section 14.47 (the API isn't sending a challenge response) LWP::UserAgent and similar are failing in sending a second request with the credentials. The solution is to "force" LWP::UserAgent to send the credentials with the first request by adding them as header:

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"));

Disclosure: I work at Paymill.

like image 96
Matthias Dietrich Avatar answered Feb 27 '23 19:02

Matthias Dietrich