Laravel 5 catching 400 response from PayPal API

2019-07-13 01:37发布

问题:

I asked a very specific question located here: Laravel 5 catching PayPal PHP API 400 errors on localhost:8000

As nobody could help I want to make it a more open question about catching a 400 error from the PayPal API.

I am making requests to PayPal, when a successful request is made everything works perfectly and I get a lovely response object, which I can work with and action accordingly.

When for instance incorrect card details are entered Laravel throws a 400 error and fails to catch the error for me to action accordingly.

Snippet:

try {
    // ### Create Payment
    // Create a payment by posting to the APIService
    // using a valid ApiContext
    // The return object contains the status;

    $payment->create($this->_apiContext);

//will not catch here :( throws Laravel 400 error! want to redirect with message!
} catch (\PPConnectionException $ex) {
    return Redirect::back()->withErrors([$ex->getMessage() . PHP_EOL]);
}

//if we get an approved payment ! This fires perfectly when succesful!!! woo!!
if($payment->state == 'approved') {
    //if success we hit here fine!!!
} else {
    //won't get here, dies before catch.
}

Here is the error in Laravel debug mode:

When I look in the PayPal API sandbox logs I should be getting a nice object so I can action accordingly.

{
    "status": 400,
    "duration_time": 60,
    "body": {
        "message": "Invalid request. See details.",
        "information_link": "https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR",
        "details": [
            {
                "field": "payer.funding_instruments[0].credit_card.number",
                "issue": "Value is invalid."
            }
        ],
        "name": "VALIDATION_ERROR",
        "debug_id": "XXXXXXXXXXXXXX"
    },
    "additional_properties": {},
    "header": {
        "Date": "Thu, 25 May 2017 14:44:43 GMT",
        "paypal-debug-id": "2f88f18d519c3",
        "APPLICATION_ID": "APP-XXXXXXXXXXXX",
        "Content-Language": "*",
        "CALLER_ACCT_NUM": "XXXXXXXXXXXXX"
    }
}

If any Laravel wizard can help you would be my hero.

Nick.

回答1:

Right guys,

It would appear that Laravel's default Exception method was interfering with the PayPal API PayPalConnectionException. So I modified the code to catch general Exception errors only as it contained all required error objects. The \ before Exception was critical! as it needs the correct namespace (in my case anyway, your application may be different).

try {
    // ### Create Payment
    // Create a payment by posting to the APIService
    // using a valid ApiContext
    // The return object contains the status;
    $payment->create($this->_apiContext);

} catch (\Exception $ex) {
    return Redirect::back()->withErrors([$ex->getData()])->withInput(Input::all());
}

This link that @rchatburn posted was highly useful, the application always seemed to catch at the point \Exception and NOT \PayPalConnectionException once I had everything namespaced correctly.

In my investigations I came across app/Exceptions/Handler.php. Here you can extend the render method to grab a PayPalConnectionException and handle the errors uniquely to that specific exception . See code:

//Be sure to include the exception you want at the top of the file
use PayPal\Exception\PayPalConnectionException;//pull in paypal error exception to work with

public function render($request, Exception $e)
{
    //check the specific exception
    if ($e instanceof PayPalConnectionException) {
        //return with errors and with at the form data
        return Redirect::back()->withErrors($e->getData())->withInput(Input::all());
    }

    return parent::render($request, $e);
} 

Either work great, but for me it felt neater to just change the catch method to a lookout for a general Exception, where I am testing if a payment was successful.

Hope this helps anyone facing similar issues :D!!!

Nick.