Skip to content

Commit cfa1791

Browse files
simonhampclaude
andcommitted
Add post-purchase flow with sync license creation and success banner
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3f8061c commit cfa1791

2 files changed

Lines changed: 73 additions & 2 deletions

File tree

resources/views/course.blade.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
<x-layout title="The NativePHP Masterclass">
22
<div class="mx-auto max-w-5xl">
3+
@if (! empty($purchased))
4+
{{-- Purchase Success Banner --}}
5+
<div
6+
x-data="{ show: true }"
7+
x-show="show"
8+
x-transition
9+
class="mt-6 rounded-2xl border border-emerald-200 bg-emerald-50 p-6 text-center dark:border-emerald-800 dark:bg-emerald-950/50"
10+
>
11+
<div class="flex flex-col items-center gap-2">
12+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="size-10 text-emerald-600 dark:text-emerald-400">
13+
<path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z" clip-rule="evenodd" />
14+
</svg>
15+
<h2 class="text-xl font-semibold text-emerald-800 dark:text-emerald-200">
16+
You're in! Thank you for your purchase.
17+
</h2>
18+
<p class="max-w-md text-emerald-700 dark:text-emerald-300">
19+
We'll notify you as soon as the masterclass is ready.
20+
Keep an eye on your inbox for updates and early access content.
21+
</p>
22+
</div>
23+
</div>
24+
@endif
25+
26+
@if (session('error'))
27+
<div class="mt-6 rounded-2xl border border-red-200 bg-red-50 p-4 text-center text-red-700 dark:border-red-800 dark:bg-red-950/50 dark:text-red-300">
28+
{{ session('error') }}
29+
</div>
30+
@endif
31+
332
{{-- Hero Section --}}
433
<section
534
class="mt-12 md:mt-20"

routes/web.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,49 @@
6464
Route::view('/', 'welcome')->name('welcome');
6565
Route::redirect('pricing', 'blog/nativephp-for-mobile-is-now-free')->name('pricing');
6666
Route::view('alt-pricing', 'alt-pricing')->name('alt-pricing')->middleware('signed');
67-
Route::view('course', 'course')->name('course');
67+
Route::get('course', function (\Illuminate\Http\Request $request) {
68+
$purchased = false;
69+
70+
if ($request->has('session_id') && $request->user()) {
71+
try {
72+
$session = \Laravel\Cashier\Cashier::stripe()->checkout->sessions->retrieve($request->query('session_id'));
73+
74+
if ($session->payment_status === 'paid' && ! empty($session->metadata['cart_id'])) {
75+
$cart = \App\Models\Cart::with('items.product')->find($session->metadata['cart_id']);
76+
77+
if ($cart && ! $cart->isCompleted()) {
78+
$user = $request->user();
79+
80+
foreach ($cart->items as $item) {
81+
if ($item->isProduct() && $item->product) {
82+
if (! \App\Models\ProductLicense::where('user_id', $user->id)->where('product_id', $item->product_id)->exists()) {
83+
\App\Models\ProductLicense::create([
84+
'user_id' => $user->id,
85+
'product_id' => $item->product_id,
86+
'stripe_payment_intent_id' => $session->payment_intent,
87+
'price_paid' => $item->product_price_at_addition,
88+
'currency' => strtoupper($item->currency),
89+
'purchased_at' => now(),
90+
]);
91+
}
92+
}
93+
}
94+
95+
$cart->markAsCompleted();
96+
}
97+
98+
$purchased = true;
99+
}
100+
} catch (\Exception $e) {
101+
\Illuminate\Support\Facades\Log::warning('Failed to verify checkout session', [
102+
'session_id' => $request->query('session_id'),
103+
'error' => $e->getMessage(),
104+
]);
105+
}
106+
}
107+
108+
return view('course', ['purchased' => $purchased]);
109+
})->name('course');
68110

69111
Route::post('course/checkout', function (\Illuminate\Http\Request $request) {
70112
$user = $request->user();
@@ -106,7 +148,7 @@
106148
],
107149
'quantity' => 1,
108150
]],
109-
'success_url' => route('course').'?purchased=1',
151+
'success_url' => route('course').'?session_id={CHECKOUT_SESSION_ID}',
110152
'cancel_url' => route('course'),
111153
'customer' => $user->stripe_id,
112154
'metadata' => $metadata,

0 commit comments

Comments
 (0)