resolveOrderId($request); $fallback = $this->resolveFallbackUrl(); if (! $orderId) { return redirect()->to($fallback); } $voucher = GiftVoucher::query() ->where('paypal_order_id', $orderId) ->first(); if (! $voucher) { return redirect()->to($fallback); } $successUrl = Arr::get($voucher->metadata ?? [], 'paypal_success_url') ?? Arr::get($voucher->metadata ?? [], 'success_url'); $cancelUrl = Arr::get($voucher->metadata ?? [], 'paypal_cancel_url') ?? Arr::get($voucher->metadata ?? [], 'return_url'); if (in_array($voucher->status, [GiftVoucher::STATUS_ISSUED, GiftVoucher::STATUS_REDEEMED], true)) { return redirect()->to($this->resolveSafeRedirect($this->appendOrderId($successUrl, $orderId), $fallback)); } try { $capture = $this->orders->captureOrder($orderId, [ 'request_id' => 'gift-voucher-'.$voucher->id, ]); } catch (PayPalException $exception) { return redirect()->to($this->resolveSafeRedirect($cancelUrl, $fallback)); } $this->vouchers->issueFromPayPal($voucher, $capture, $orderId); return redirect()->to($this->resolveSafeRedirect($this->appendOrderId($successUrl, $orderId), $fallback)); } protected function resolveOrderId(Request $request): ?string { $candidate = $request->query('token') ?? $request->query('order_id'); if (! is_string($candidate) || $candidate === '') { return null; } return $candidate; } protected function resolveFallbackUrl(): string { return rtrim((string) config('app.url', url('/')), '/') ?: url('/'); } protected function resolveSafeRedirect(?string $target, string $fallback): string { if (! $target) { return $fallback; } if (Str::startsWith($target, ['/'])) { return $target; } $appHost = parse_url($fallback, PHP_URL_HOST); $targetHost = parse_url($target, PHP_URL_HOST); if ($appHost && $targetHost && Str::lower($appHost) === Str::lower($targetHost)) { return $target; } return $fallback; } protected function appendOrderId(?string $url, string $orderId): ?string { if (! $url) { return null; } $parts = parse_url($url); if (! $parts) { return $url; } $query = []; if (! empty($parts['query'])) { parse_str($parts['query'], $query); } if (! isset($query['order_id'])) { $query['order_id'] = $orderId; } $scheme = $parts['scheme'] ?? null; $host = $parts['host'] ?? null; $port = isset($parts['port']) ? ':'.$parts['port'] : ''; $path = $parts['path'] ?? ''; $fragment = isset($parts['fragment']) ? '#'.$parts['fragment'] : ''; $queryString = $query ? '?'.http_build_query($query) : ''; if ($scheme && $host) { return $scheme.'://'.$host.$port.$path.$queryString.$fragment; } return $path.$queryString.$fragment; } }