Andrew Newby
Andrew Newby

Reputation: 5197

PayPal API returning 500 IS Error when trying to get transaction

I'm trying to work out why my Curl request is not working for the PayPal API. I have the following query working fine to get the auth token:

sub get_token {

    my $curl = WWW::Curl::Easy->new();
    my $fh   = 'README';

    $curl->setopt(CURLOPT_HEADER,0); # dont want the headers, or they will break the json reading!
    $curl->setopt(CURLOPT_URL,"https://".$config->{$config->{mode}}->{transaction_endpoint}."/v1/oauth2/token");
    $curl->setopt(CURLOPT_POSTFIELDS,"grant_type=client_credentials");
    $curl->setopt(CURLOPT_USERPWD, $config->{$config->{mode}}->{system_client_id}.":".$config->{$config->{mode}}->{system_secret});
    $curl->setopt(CURLOPT_SSL_VERIFYPEER,0);
    $curl->setopt(CURLOPT_SSL_VERIFYHOST,0);
    $curl->setopt('CURLOPT_RETURNTRANSFER',1);
    $curl->setopt(CURLOPT_POST,1);

    my $response_body;

    open(my $fh, '>', \$response_body);
    $curl->setopt(CURLOPT_WRITEDATA, $fh);
    $curl->setopt(CURLOPT_VERBOSE,0);
    my $retcode = $curl->perform();

    if ($retcode != 0) {
        warn "An error happened: ", $curl->strerror($retcode), " ($retcode)\n";
        warn "errbuf: ", $curl->errbuf;
    }

    my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
    use JSON;
    my $json_vals = decode_json($response_body);

    return $json_vals->{access_token};
}

..but then when I try and use the same logic below to get the transaction, it fails with a 500 IS Error:

sub get_proper_trans_id {

    my $token = get_token($_[0]);

    print $IN->header( 'utf8' );

    my $curl = WWW::Curl::Easy->new();
    my $fh   = 'README';

    my @headers = ("Authorization: Bearer $token","Content-Type: application/json; charset=utf-8");

    print qq|Getting: https://$config->{$config->{mode}}->{transaction_endpoint}/v1/payments/payment/$_[0] \n|;

    $curl->setopt(CURLOPT_HTTPHEADER,\@headers);
    $curl->setopt(CURLOPT_HEADER,1);
    $curl->setopt(CURLOPT_URL,"https://$config->{$config->{mode}}->{transaction_endpoint}/v1/payments/payment/$_[0]");
    $curl->setopt(CURLOPT_SSL_VERIFYPEER,0);
    $curl->setopt(CURLOPT_SSL_VERIFYHOST,0);
    $curl->setopt('CURLOPT_RETURNTRANSFER',1);
    $curl->setopt(CURLOPT_POST,1);

    my $response_body;

    open(my $fh, '>', \$response_body);
    $curl->setopt(CURLOPT_WRITEDATA, $fh);
    $curl->setopt(CURLOPT_VERBOSE,1);
    my $retcode = $curl->perform();

    if ($retcode != 0) {
        warn "An error happened: ", $curl->strerror($retcode), " ($retcode)\n";
        warn "errbuf: ", $curl->errbuf;
    }

    my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);

}

The value of $_[0] being passed into get_proper_trans_id() is the PAY-xxxx transaction ID passed back from the PayPal-Checkout.JS system.

If I run this curl command manually, it works:

curl https://$config->{$config->{mode}}->{transaction_endpoint}/v1/payments/payment/$_[0] -H "Content-Type: application/json; charset=utf-8" -H "Authorization: Bearer $token"

The problem is that I'm having utf8 issues with that method, so I'm trying to find a module that will do the job for me.

Here is the output of the curl (with debugging and headers);

* Hostname was NOT found in DNS cache
*   Trying 173.0.82.78...
* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / AES256-SHA256
* Server certificate:
*        subject: C=US; ST=California; L=San Jose; O=PayPal, Inc.; OU=PayPal Production; CN=api.sandbox.paypal.com
*        start date: 2016-01-13 00:00:00 GMT
*        expire date: 2018-01-13 23:59:59 GMT
*        issuer: C=US; O=Symantec Corporation; OU=Symantec Trust Network; CN=Symantec Class 3 Secure Server CA - G4
*        SSL certificate verify ok.
> POST /v1/payments/payment/PAY-6KY19646FF321593HLCVRQSY HTTP/1.1
Host: api.sandbox.paypal.com
Accept: */*
Authorization: Bearer MY_TOKEN_HERE
Content-Type: application/json; charset=utf-8
Expect: 100-continue

< HTTP/1.1 500 Internal Server Error
< Date: Tue, 21 Feb 2017 06:38:03 GMT
* Server Apache is not blacklisted
< Server: Apache
< paypal-debug-id: 217b14fc80976
< Connection: close
< X-SLR-RETRY: 500
< X-SLR-RETRY-API: /v1/payments/payment/{id}
< Connection: close
< Paypal-Debug-Id: 217b14fc80976
< Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dplatformapiserv%26TIME%3D1273015128%26HTTP_X_PP_AZ_LOCATOR%3D; Expires=Tue, 21 Feb 2017 07:08:03 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
< Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
< Vary: Authorization
< Content-Length: 196
< Content-Type: text/xml;charset=UTF-8
<
* Closing connection 0
GOT:

"HTTP/1.1 500 Internal Server Error
Date: Tue, 21 Feb 2017 06:38:03 GMT
Server: Apache
paypal-debug-id: 217b14fc80976
Connection: close
X-SLR-RETRY: 500
X-SLR-RETRY-API: /v1/payments/payment/{id}
Connection: close
Paypal-Debug-Id: 217b14fc80976
Set-Cookie: X-PP-SILOVER=name%3DSANDBOX3.API.1%26silo_version%3D1880%26app%3Dplatformapiserv%26TIME%3D1273015128%26HTTP_X_PP_AZ_LOCATOR%3D; Expires=Tue, 21 Feb 2017 07:08:03 GMT; domain=.paypal.com; path=/; Secure; HttpOnly
Set-Cookie: X-PP-SILOVER=; Expires=Thu, 01 Jan 1970 00:00:01 GMT
Vary: Authorization
Content-Length: 196
Content-Type: text/xml;charset=UTF-8

<ns1:XMLFault xmlns:ns1="http://cxf.apache.org/bindings/xformat"><ns1:faultstring xmlns:ns1="http://cxf.apache.org/bindings/xformat">java.lang.NullPointerException</ns1:faultstring></ns1:XMLFault>"

What am I missing? Thanks!

Upvotes: 1

Views: 175

Answers (1)

Andrew Newby
Andrew Newby

Reputation: 5197

Ok, I just got a reply from the PayPal Tech's. It would seem that this particular function needs a GET instead of POST:

I see you are trying to use a POST where you need to use a GET (the REST API flow needs a GET for you to be able to get transaction details. GET https://api.sandbox.paypal.com/v1/payments/payment/ Can you try changing it for a GET? I hope this sorts it.

...and sure enough, that fixed it :)

For anyone wondering how I made that change, I just commented out:

$curl->setopt(CURLOPT_POST,1);

curl defaults to GET when sending requests.

Upvotes: 1

Related Questions