added beads and fixes for paddle checkout
This commit is contained in:
@@ -14,13 +14,17 @@ use App\Models\Tenant;
|
||||
use App\Models\User;
|
||||
use App\Services\Checkout\CheckoutAssignmentService;
|
||||
use App\Services\Checkout\CheckoutSessionService;
|
||||
use App\Services\Paddle\Exceptions\PaddleException;
|
||||
use App\Services\Paddle\PaddleTransactionService;
|
||||
use App\Support\CheckoutRoutes;
|
||||
use App\Support\Concerns\PresentsPackages;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Str;
|
||||
use Inertia\Inertia;
|
||||
@@ -250,7 +254,14 @@ class CheckoutController extends Controller
|
||||
public function sessionStatus(
|
||||
CheckoutSessionStatusRequest $request,
|
||||
CheckoutSession $session,
|
||||
CheckoutSessionService $sessions,
|
||||
CheckoutAssignmentService $assignment,
|
||||
PaddleTransactionService $transactions,
|
||||
): JsonResponse {
|
||||
$this->attemptPaddleRecovery($session, $sessions, $assignment, $transactions);
|
||||
|
||||
$session->refresh();
|
||||
|
||||
return response()->json([
|
||||
'status' => $session->status,
|
||||
'completed_at' => optional($session->completed_at)->toIso8601String(),
|
||||
@@ -327,4 +338,151 @@ class CheckoutController extends Controller
|
||||
|
||||
return $price <= 0;
|
||||
}
|
||||
|
||||
private function attemptPaddleRecovery(
|
||||
CheckoutSession $session,
|
||||
CheckoutSessionService $sessions,
|
||||
CheckoutAssignmentService $assignment,
|
||||
PaddleTransactionService $transactions
|
||||
): void {
|
||||
if ($session->provider !== CheckoutSession::PROVIDER_PADDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($session->status, [
|
||||
CheckoutSession::STATUS_COMPLETED,
|
||||
CheckoutSession::STATUS_FAILED,
|
||||
CheckoutSession::STATUS_CANCELLED,
|
||||
], true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$metadata = $session->provider_metadata ?? [];
|
||||
$lastPollAt = $metadata['paddle_poll_at'] ?? null;
|
||||
$now = now();
|
||||
|
||||
if ($lastPollAt) {
|
||||
try {
|
||||
$lastPoll = Carbon::parse($lastPollAt);
|
||||
if ($lastPoll->diffInSeconds($now) < 15) {
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
// Ignore invalid timestamps.
|
||||
}
|
||||
}
|
||||
|
||||
$checkoutId = $metadata['paddle_checkout_id'] ?? $session->paddle_checkout_id ?? null;
|
||||
$transactionId = $metadata['paddle_transaction_id'] ?? $session->paddle_transaction_id ?? null;
|
||||
|
||||
if (! $checkoutId && ! $transactionId) {
|
||||
Log::info('[Checkout] Paddle recovery missing checkout reference, falling back to custom data scan', [
|
||||
'session_id' => $session->id,
|
||||
]);
|
||||
}
|
||||
|
||||
$metadata['paddle_poll_at'] = $now->toIso8601String();
|
||||
$session->forceFill([
|
||||
'provider_metadata' => $metadata,
|
||||
])->save();
|
||||
|
||||
try {
|
||||
$transaction = $transactionId ? $transactions->retrieve($transactionId) : null;
|
||||
|
||||
if (! $transaction && $checkoutId) {
|
||||
$transaction = $transactions->findByCheckoutId($checkoutId);
|
||||
}
|
||||
|
||||
if (! $transaction) {
|
||||
$transaction = $transactions->findByCustomData([
|
||||
'checkout_session_id' => $session->id,
|
||||
'package_id' => (string) $session->package_id,
|
||||
'tenant_id' => (string) $session->tenant_id,
|
||||
]);
|
||||
}
|
||||
} catch (PaddleException $exception) {
|
||||
Log::warning('[Checkout] Paddle recovery failed', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
'status' => $exception->status(),
|
||||
'message' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return;
|
||||
} catch (\Throwable $exception) {
|
||||
Log::warning('[Checkout] Paddle recovery failed', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
'message' => $exception->getMessage(),
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $transaction) {
|
||||
Log::info('[Checkout] Paddle recovery: transaction not found', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$status = strtolower((string) ($transaction['status'] ?? ''));
|
||||
$transactionId = $transactionId ?: ($transaction['id'] ?? null);
|
||||
|
||||
if ($transactionId && $session->paddle_transaction_id !== $transactionId) {
|
||||
$session->forceFill([
|
||||
'paddle_transaction_id' => $transactionId,
|
||||
])->save();
|
||||
}
|
||||
|
||||
if ($status === 'completed') {
|
||||
$sessions->markProcessing($session, [
|
||||
'paddle_status' => $status,
|
||||
'paddle_transaction_id' => $transactionId,
|
||||
'paddle_recovered_at' => $now->toIso8601String(),
|
||||
]);
|
||||
|
||||
$assignment->finalise($session, [
|
||||
'source' => 'paddle_poll',
|
||||
'provider' => CheckoutSession::PROVIDER_PADDLE,
|
||||
'provider_reference' => $transactionId,
|
||||
'payload' => $transaction,
|
||||
]);
|
||||
|
||||
$sessions->markCompleted($session, $now);
|
||||
|
||||
Log::info('[Checkout] Paddle session recovered via API', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (in_array($status, ['failed', 'cancelled', 'canceled'], true)) {
|
||||
$sessions->markFailed($session, 'paddle_'.$status);
|
||||
|
||||
Log::info('[Checkout] Paddle transaction failed', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Log::info('[Checkout] Paddle transaction pending', [
|
||||
'session_id' => $session->id,
|
||||
'checkout_id' => $checkoutId,
|
||||
'transaction_id' => $transactionId,
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user