2013-07-19 11 views
25

podczas moich testów paskowych w witrynie, I zbudował kodu:Catching błędy naszywka z try/catch metody PHP

try { 
     $charge = Stripe_Charge::create(array(
      "amount" => $clientPriceStripe, // amount in cents 
      "currency" => "usd", 
      "customer" => $customer->id, 
      "description" => $description)); 
      $success = 1; 
      $paymentProcessor="Credit card (www.stripe.com)"; 
    } 
    catch (Stripe_InvalidRequestError $a) { 
     // Since it's a decline, Stripe_CardError will be caught 
     $error3 = $a->getMessage(); 
    } 

    catch (Stripe_Error $e) { 
     // Since it's a decline, Stripe_CardError will be caught 
     $error2 = $e->getMessage(); 
     $error = 1; 
    } 
if ($success!=1) 
{ 
    $_SESSION['error3'] = $error3; 
    $_SESSION['error2'] = $error2; 
    header('Location: checkout.php'); 
    exit(); 
} 

Problem polega na tym, że czasami występuje błąd z kartą (nie przechwycony przez argumenty "catch", które mam) i "próba" kończy się niepowodzeniem, a strona natychmiastowo wysyła błąd na ekranie zamiast do "if" i przekierowuje z powrotem do checkout.php.

W jaki sposób powinienem uporządkować obsługę błędów, więc pojawia się błąd i natychmiast przekierowuję z powrotem do checkout.php i wyświetla tam błąd?

Dzięki!


Błąd rzucony:

Fatal error: Uncaught exception 'Stripe_CardError' with message 'Your card was declined.' in ............ 
/lib/Stripe/ApiRequestor.php on line 92 

Odpowiedz

42

Myślę, że jest więcej niż tych wyjątków (Stripe_InvalidRequestError i Stripe_Error), aby złapać.

Poniższy kod pochodzi z Stripe's web site. Prawdopodobnie te dodatkowe wyjątki, których nie brałeś pod uwagę, występują i Twój kod nie powiedzie się czasami.

try { 
    // Use Stripe's bindings... 
} catch(Stripe_CardError $e) { 
    // Since it's a decline, Stripe_CardError will be caught 
    $body = $e->getJsonBody(); 
    $err = $body['error']; 

    print('Status is:' . $e->getHttpStatus() . "\n"); 
    print('Type is:' . $err['type'] . "\n"); 
    print('Code is:' . $err['code'] . "\n"); 
    // param is '' in this case 
    print('Param is:' . $err['param'] . "\n"); 
    print('Message is:' . $err['message'] . "\n"); 
} catch (Stripe_InvalidRequestError $e) { 
    // Invalid parameters were supplied to Stripe's API 
} catch (Stripe_AuthenticationError $e) { 
    // Authentication with Stripe's API failed 
    // (maybe you changed API keys recently) 
} catch (Stripe_ApiConnectionError $e) { 
    // Network communication with Stripe failed 
} catch (Stripe_Error $e) { 
    // Display a very generic error to the user, and maybe send 
    // yourself an email 
} catch (Exception $e) { 
    // Something else happened, completely unrelated to Stripe 
} 

EDIT:

try { 
    $charge = Stripe_Charge::create(array(
    "amount" => $clientPriceStripe, // amount in cents 
    "currency" => "usd", 
    "customer" => $customer->id, 
    "description" => $description)); 
    $success = 1; 
    $paymentProcessor="Credit card (www.stripe.com)"; 
} catch(Stripe_CardError $e) { 
    $error1 = $e->getMessage(); 
} catch (Stripe_InvalidRequestError $e) { 
    // Invalid parameters were supplied to Stripe's API 
    $error2 = $e->getMessage(); 
} catch (Stripe_AuthenticationError $e) { 
    // Authentication with Stripe's API failed 
    $error3 = $e->getMessage(); 
} catch (Stripe_ApiConnectionError $e) { 
    // Network communication with Stripe failed 
    $error4 = $e->getMessage(); 
} catch (Stripe_Error $e) { 
    // Display a very generic error to the user, and maybe send 
    // yourself an email 
    $error5 = $e->getMessage(); 
} catch (Exception $e) { 
    // Something else happened, completely unrelated to Stripe 
    $error6 = $e->getMessage(); 
} 

if ($success!=1) 
{ 
    $_SESSION['error1'] = $error1; 
    $_SESSION['error2'] = $error2; 
    $_SESSION['error3'] = $error3; 
    $_SESSION['error4'] = $error4; 
    $_SESSION['error5'] = $error5; 
    $_SESSION['error6'] = $error6; 
    header('Location: checkout.php'); 
    exit(); 
} 

Teraz będzie można złapać wszystkie możliwe wyjątki i można wyświetlić komunikat o błędzie, jak chcesz. A także błąd $ 6 dotyczy niezwiązanych wyjątków.

+0

dodałem błąd rzucony na ekranie. Pochodzi z jednego z błędów obsługi plików Stripe. Pytanie brzmiałoby, jak sam mógłbym złapać błąd, a następnie przekierować, zamiast rzucać wiadomość od Stripe'a ... – samyb8

+0

Mam już zmodyfikowany kod. Nie uwzględniono wszystkich wyjątków (na przykład ** Stripe_CarError **), więc nie można ich wszystkich przechwycić, aby wyświetlić własny komunikat o błędzie. –

+1

Problem polega na tym, że kod przechodzi przez ApiRequestor.php (plik Stripe'a) i tam się nie udaje i nie przechodzi dalej przez moje "połowy". – samyb8

8

Mogę spóźnić się na to pytanie, ale wpadłem na ten sam problem i znalazłem to.

Wystarczy użyć klasy "Stripe_Error".

use Stripe_Error; 

Po zadeklarowaniu tego, udało mi się złapać błędy z powodzeniem.

+0

Musiałem użyć "use \ Stripe_CardError i użyj \ Stripe_Error". –

55

Jeśli używasz biblioteki Stripe PHP i zostały one przestrzeni nazw (na przykład gdy są one instalowane poprzez kompozytor) można złapać wszystkie wyjątki paskiem:

<?php 
try { 
    // Use a Stripe PHP library method that may throw an exception.... 
    \Stripe\Customer::create($args); 
} catch (\Stripe\Error\Base $e) { 
    // Code to do something with the $e exception object when an error occurs 
    echo($e->getMessage()); 
} catch (Exception $e) { 
    // Catch any other non-Stripe exceptions 
} 
+3

Szkoda, że ​​nie mogłem przegłosować więcej ... – superphonic

+1

Zobacz drugą odpowiedź (http://stackoverflow.com/a/17750537/470749), która odnosi się do dokumentów Stripe (https://stripe.com/docs/api?lang = php # errors), które pokazują różne obiekty błędów do przechwycenia. 'Stripe \ Error \ Base' to za mało. – Ryan

+4

@Ryan wszystkie klasy błędów Stripe dziedziczą po 'Stripe \ Error \ Base', a pierwszy blok' catch' pasuje do wszystkich tych podklas. Dodałem drugie "catch", które jest bardziej niezawodne i obsługuje przypadki, w których wywołanie API Stripe nie zwraca wyjątku Stripe. – leepowers

5

Jest to aktualizacja do drugiego odpowiedź, ale docs zmieniły się bardzo nieznacznie, więc musiałem sukces stosując następujące metody:

try { 
    // Use Stripe's library to make requests... 
} catch(\Stripe\Error\Card $e) { 
    // Since it's a decline, \Stripe\Error\Card will be caught 
    $body = $e->getJsonBody(); 
    $err = $body['error']; 

    print('Status is:' . $e->getHttpStatus() . "\n"); 
    print('Type is:' . $err['type'] . "\n"); 
    print('Code is:' . $err['code'] . "\n"); 
    // param is '' in this case 
    print('Param is:' . $err['param'] . "\n"); 
    print('Message is:' . $err['message'] . "\n"); 
} catch (\Stripe\Error\RateLimit $e) { 
    // Too many requests made to the API too quickly 
} catch (\Stripe\Error\InvalidRequest $e) { 
    // Invalid parameters were supplied to Stripe's API 
} catch (\Stripe\Error\Authentication $e) { 
    // Authentication with Stripe's API failed 
    // (maybe you changed API keys recently) 
} catch (\Stripe\Error\ApiConnection $e) { 
    // Network communication with Stripe failed 
} catch (\Stripe\Error\Base $e) { 
    // Display a very generic error to the user, and maybe send 
    // yourself an email 
} catch (Exception $e) { 
    // Something else happened, completely unrelated to Stripe 
} 

można znaleźć źródło tego w docs paskiem prawo tutaj:

https://stripe.com/docs/api?lang=php#handling-errors

2

Myślę, że wszystko, co naprawdę trzeba sprawdzić, to podstawowa klasa błędów pasków i wyjątek, jeśli nie ma to związku z paskiem. Oto, jak to robię.

/** 
* Config. 
*/ 
require_once(dirname(__FILE__) . '/config.php'); 

// Hit Stripe API. 
try { 
    // Register a Customer. 
    $customer = \Stripe\Customer::create(array(
    'email' => '[email protected]', 
    'source' => $token, 
    'metadata' => array(// Note: You can specify up to 20 keys, with key names up to 40 characters long and values up to 500 characters long. 
     'NAME'   => 'AA', 
     'EMAIL'   => '[email protected]', 
     'ORDER DETAILS' => $order_details, 
    ) 
)); 

    // Charge a customer. 
    $charge = \Stripe\Charge::create(array(
    'customer' => $customer->id, 
    'amount' => 5000, // In cents. 
    'currency' => 'usd' 
)); 



    // If there is an error from Stripe. 
} catch (Stripe\Error\Base $e) { 
    // Code to do something with the $e exception object when an error occurs. 
    echo $e->getMessage(); 

    // DEBUG. 
    $body = $e->getJsonBody(); 
    $err = $body['error']; 
    echo '<br> ——— <br>'; 
    echo '<br>THE ERROR DEFINED — <br>'; 
    echo '— Status is: ' . $e->getHttpStatus() . '<br>'; 
    echo '— Message is: ' . $err['message'] . '<br>'; 
    echo '— Type is: ' . $err['type'] . '<br>'; 
    echo '— Param is: ' . $err['param'] . '<br>'; 
    echo '— Code is: ' . $err['code'] . '<br>'; 
    echo '<br> ——— <br>'; 

// Catch any other non-Stripe exceptions. 
} catch (Exception $e) { 
    $body = $e->getJsonBody(); 
    $err = $body['error']; 
    echo '<br> ——— <br>'; 
    echo '<br>THE ERROR DEFINED — <br>'; 
    echo '— Status is: ' . $e->getHttpStatus() . '<br>'; 
    echo '— Message is: ' . $err['message'] . '<br>'; 
    echo '— Type is: ' . $err['type'] . '<br>'; 
    echo '— Param is: ' . $err['param'] . '<br>'; 
    echo '— Code is: ' . $err['code'] . '<br>'; 
    echo '<br> ——— <br>'; 
} 
+0

'getJsonBody()' i 'getHttpStatus()' są funkcjami paskowymi i nie mają zastosowania przy wychwytywaniu standardowego wyjątku. – xinthose

3

W ten sposób Stripe odnotowuje błędy w 2017 roku. Documentation. Ten fragment wymaga PHP 7.1+

catch(\Stripe\Error\Card | \Stripe\Error\RateLimit | \Stripe\Error\InvalidRequest | \Stripe\Error\Authentication | \Stripe\Error\ApiConnection $e) 
{ 
    $body = $e->getJsonBody(); 
    $err = $body["error"]; 
    $return_array = [ 
     "status" => $e->getHttpStatus(), 
     "type" => $err["type"], 
     "code" => $err["code"], 
     "param" => $err["param"], 
     "message" => $err["message"], 
    ]; 
    $return_str = json_encode($return_array);   
    http_response_code($e->getHttpStatus()); 
    echo $return_str; 
} 

Następnie można złapać błąd w ajax z następującego kodu:

$(document).ajaxError(function ajaxError(event, jqXHR, ajaxSettings, thrownError) { 
    try { 
     var url = ajaxSettings.url; 
     var http_status_code = jqXHR.status; 
     var response = jqXHR.responseText; 
     var message = ""; 
     if (isJson(response)) {  // see here for function: https://stackoverflow.com/a/32278428/4056146 
      message = " " + (JSON.parse(response)).message; 
     } 
     var error_str = ""; 

     // 1. handle HTTP status code 
     switch (http_status_code) { 
      case 0: { 
       error_str = "No Connection. Cannot connect to " + new URL(url).hostname + "."; 
       break; 
      } // No Connection 
      case 400: { 
       error_str = "Bad Request." + message + " Please see help."; 
       break; 
      } // Bad Request 
      case 401: { 
       error_str = "Unauthorized." + message + " Please see help."; 
       break; 
      } // Unauthorized 
      case 402: { 
       error_str = "Request Failed." + message; 
       break; 
      } // Request Failed 
      case 404: { 
       error_str = "Not Found." + message + " Please see help."; 
       break; 
      } // Not Found 
      case 405: { 
       error_str = "Method Not Allowed." + message + " Please see help."; 
       break; 
      } // Method Not Allowed 
      case 409: { 
       error_str = "Conflict." + message + " Please see help."; 
       break; 
      } // Conflict 
      case 429: { 
       error_str = "Too Many Requests." + message + " Please try again later."; 
       break; 
      } // Too Many Requests 
      case 500: { 
       error_str = "Internal Server Error." + message + " Please see help."; 
       break; 
      } // Internal Server Error 
      case 502: { 
       error_str = "Bad Gateway." + message + " Please see help."; 
       break; 
      } // Bad Gateway 
      case 503: { 
       error_str = "Service Unavailable." + message + " Please see help."; 
       break; 
      } // Service Unavailable 
      case 504: { 
       error_str = "Gateway Timeout." + message + " Please see help."; 
       break; 
      } // Gateway Timeout 
      default: { 
       console.error(loc + "http_status_code unhandled >> http_status_code = " + http_status_code); 
       error_str = "Unknown Error." + message + " Please see help."; 
       break; 
      } 
     } 

     // 2. show popup 
     alert(error_str); 
     console.error(arguments.callee.name + " >> http_status_code = " + http_status_code.toString() + "; thrownError = " + thrownError + "; URL = " + url + "; Response = " + response); 

    } 
    catch (e) { 
     console.error(arguments.callee.name + " >> ERROR >> " + e.toString()); 
     alert("Internal Error. Please see help."); 
    } 
});