<?php
declare(strict_types=1);
namespace Modules\Payment\Services;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;
use Illuminate\Http\Client\Response; // Убедитесь, что этот импорт есть
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Modules\Payment\Models\Order;
use RuntimeException;
class YooKassaService
{
private string $shopId;
private string $secretKey;
private string $apiUrl;
private string $currency;
public function __construct()
{
$this->apiUrl = config('payment.yookassa_api_url');
$this->shopId = config('payment.yookassa_shop_id');
$this->secretKey = config('payment.yookassa_secret_key');
$this->currency = config('payment.yookassa_currency');
// *** ВАЖНОЕ ДОБАВЛЕНИЕ ДЛЯ СТАРЫХ СЕРВЕРОВ ***
// Fix for the "Undefined constant CURL_SSLVERSION_TLSv1_2" error
if (!defined('CURL_SSLVERSION_TLSv1_2')) {
define('CURL_SSLVERSION_TLSv1_2', 6);
}
}
/**
* Создание платежа
*/
public function createPayment(Order $order): array
{
$url = $this->apiUrl . '/payments';
$idempotenceKey = uniqid('', true);
// Формирование данных (часть, которую вы не показали, но она должна быть тут)
$data = [
/* ... данные заказа, как в предыдущем ответе ... */
];
try {
$response = Http::withBasicAuth($this->shopId, $this->secretKey)
->retry(3, 100)
->withHeaders([
'Idempotence-Key' => $idempotenceKey,
'Content-Type' => 'application/json',
])
->post($url, $data)
->throw();
return $this->handleResponse($response);
} catch (ConnectionException $e) {
Log::error('YooKassa connection failed', [
'error' => $e->getMessage(),
'url' => $url,
]);
throw new RuntimeException('Не удалось подключиться к YooKassa');
} catch (RequestException $e) {
// Используем оператор объединения с null (??) для безопасного доступа к json()
$error = $e->response?->json() ?? $e->getMessage();
Log::critical('YooKassa API error', [
'error' => $error,
]);
throw new RuntimeException('Ошибка API YooKassa');
}
}
/**
* Проверка статуса платежа
*/
public function getPaymentInfo(string $paymentId): array
{
$url = $this->apiUrl . '/payments/' . $paymentId;
try {
$response = Http::withBasicAuth($this->shopId, $this->secretKey)
->retry(3, 100)
->withHeaders([
'Content-Type' => 'application/json',
])
->get($url)
->throw();
return $this->handleResponse($response);
} catch (ConnectionException $e) {
Log::error('YooKassa connection failed', [
'payment_id' => $paymentId,
'error' => $e->getMessage(),
'url' => $url,
]);
throw new RuntimeException('Не удалось подключиться к API YooKassa');
} catch (RequestException $e) {
$error = $e->response?->json() ?? $e->getMessage();
Log::critical('YooKassa API error', [
'payment_id' => $paymentId,
'error' => $error,
]);
throw new RuntimeException('Ошибка API YooKassa');
}
}
/**
* Обработка ответа
*
* @param Response $response Laravel HTTP Response object
* @return array Decoded JSON response data
*/
private function handleResponse(Response $response): array
{
// Поскольку вы используете ->throw() в вызывающих методах,
// сюда попадают ТОЛЬКО успешные ответы (status 2xx).
// Дополнительная проверка $response->successful() избыточна,
// но безопасна.
if ($response->successful()) {
return $response->json();
}
// Эта часть кода не будет достигнута при использовании ->throw(),
// но остается как хороший запасной вариант:
Log::error('YooKassa API Error (unhandled)', [
'status' => $response->status(),
'error' => $response->json('description'),
]);
throw new RuntimeException('Ошибка API YooKassa');
}
}