記錄一下自己專案中的坑, 如有不對之處希望大家指正。
在之前公司專案工作中,經常對接海外的支付,常常用到guzzlehttp 用作介面請求的依賴包,由於沒有查閱文件和程式碼,捕獲異常處理的不正確, 導致重複支付的現象。
try {
$result = $client->request('post', $url, $options);
} catch (\Throwable $throwable) {
//donging something
return false;
}
最開始的時候簡單的這樣捕獲異常,以為這樣的異常都是請求失敗,但是後面由於重複支付的問題,檢視了guzzlehttp的程式碼,發現他們設定了處理請求的中介軟體,程式碼如下:
public static function httpErrors()
{
return function (callable $handler) {
return function ($request, array $options) use ($handler) {
if (empty($options['http_errors'])) {
return $handler($request, $options);
}
return $handler($request, $options)->then(
function (ResponseInterface $response) use ($request, $handler) {
$code = $response->getStatusCode();
if ($code < 400) {
return $response;
}
throw RequestException::create($request, $response);
});
};
};
}
由於上面的可以看出,guzzlehttp 根據請求的httpcode 做了不同的響應,只正常返回<=400以下的響應,其餘的都丟擲的異常,主要是倆類異常4XX 和5XX的異常類,程式碼如下:
$level = (int) floor($response->getStatusCode() / 100);
if ($level === 4) {
$label = 'Client error';
$className = ClientException::class;
} elseif ($level === 5) {
$label = 'Server error';
$className = ServerException::class;
} else {
$label = 'Unsuccessful request';
$className = __CLASS__;
}
所以最後我在請求異常處理裡面根據不同的異常類分別處理, 這樣就可以分別判斷請求狀態,哪些可以重試,哪些支付不能重試。避免了類似5XX 的服務端的錯誤,在專案中進行了支付重試,修改後程式碼如下:
try {
$result = $client->request('post', $url, $options);
} catch (\Throwable $throwable) {
if ($throwable instanceof ClientException) {
//doing something
return ...
}
if ($throwable instanceof ServerException) {
//doing something
return ...
}
//doing something
return false;
}
以上是我記錄guzzlehttp 的異常捕獲遇到的坑,如有錯誤請大家指正
本作品採用《CC 協議》,轉載必須註明作者和本文連結