Checkout & Webhooks
payment.checkout.tsx loader'ı ve Stripe checkout.session.completed olaylarının işlenmesi.
Coursio’da ödeme akışı Stripe Checkout ile tamamlanır; tamamlanan oturumlar webhook ile işlenir. Bu sayfa, payment.checkout.tsx loader’ının rolünü ve Stripe’tan gelen checkout.session.completed sinyallerinin nasıl işlendiğini açıklar.
payment.checkout.tsx — Loader’ın Rolü
Section titled “payment.checkout.tsx — Loader’ın Rolü”Dosya: app/routes/payment.checkout.tsx
Checkout sayfasına girildiğinde loader şunları yapar:
- Kimlik doğrulama: Oturum kontrolü; yoksa
/${lang}/login’e yönlendirme. - Sepet / tek ürün: URL’den
courseIdveyabundleId(veya sepet için birden fazla ürün) alınır; mükerrer satın alma kontrolü (paket veya kurs zaten alınmış mı). - Veritabanı: Sepet (
getCart), tek kurs (getCourseById), tek paket (getBundleById) paralel çekilir. - Bölgesel fiyat:
getCountryFromRequest(request, env, context?.cloudflare)ile ülke;getRegionalPriceFromRequest(db, priceTierId, request)ile fiyat ve para birimi alınır. Geliştirme için?test_country=TRile ülke taklidi yapılabilir. - Stripe Payment Methods: Kullanıcının kayıtlı kartları
stripe.paymentMethods.listile listelenir; varsayılan kart bilgisi de gelir. - Dönüş: Loader, checkout sayfasında kullanılacak veriyi döner: sepet içeriği, toplam tutar, bölgesel fiyat, para birimi sembolü, kayıtlı ödeme yöntemleri, tek kurs/paket bilgisi vb.
Checkout sayfası bu veriyle ödeme formunu ve (gerekirse) Stripe Checkout Session oluşturma / yönlendirme adımını sunar. Session oluşturulurken metadata içine userId, courseId/courseIds, bundleId/bundleIds, affiliateCode, saleType, instructorRef vb. eklenir; webhook tarafında bu metadata kullanılır.
Stripe Webhook — checkout.session.completed
Section titled “Stripe Webhook — checkout.session.completed”Dosya: app/routes/api.stripe.webhook.ts
Stripe, ödeme tamamlandığında checkout.session.completed event’ini webhook URL’ine (örn. /api/stripe/webhook) POST eder.
İmza Doğrulama
Section titled “İmza Doğrulama”- Gelen gövde ve Stripe-Signature header’ı,
STRIPE_WEBHOOK_SECRETile doğrulanır:stripe.webhooks.constructEventAsync(body, sig, webhookSecret). - Doğrulama başarısızsa istek reddedilir; böylece sahte ödeme bildirimi engellenir.
checkout.session.completed İşlenmesi
Section titled “checkout.session.completed İşlenmesi”- metadata:
userId,courseId/courseIds,bundleId/bundleIds,saleType,affiliateCodevb. okunur. - Mod kontrolü:
- subscription: Abonelik satın alma; kullanıcı abone yapılır (abonelik güncelleme fonksiyonu çağrılır).
- payment: Tek seferlik ödeme (kurs veya sepet).
- Payment modunda:
- Idempotency: Aynı
session.idiçin daha önce enrollment oluşturulmuşsa tekrar oluşturulmaz. - Enrollment: Satın alınan her kurs için
enrollmentstablosuna kayıt:userId,courseId,bundleId(paket satışıysa),stripeCheckoutSessionId,stripePaymentIntentId. - Komisyon motoru:
handleCourseSale(veya eşdeğer fonksiyon) çağrılır; toplam tutar, eğitmen/platform/affiliate oranlarına göre bölünür ve earnings tablosuna yazılır (instructor_ref, affiliate, organik vb. kurallara göre).
- Idempotency: Aynı
- Fatura / e-posta: İsteğe bağlı olarak fatura oluşturma ve satın alma bildirim e-postası tetiklenir.
Böylece checkout.session.completed tek bir event ile hem kayıt (enrollment) hem kazanç dağılımı (earnings) hem de (varsa) abonelik güncellemesi ve bildirimler yapılır.
Akış Özeti
Section titled “Akış Özeti”| Aşama | Açıklama |
|---|---|
| 1 | Kullanıcı checkout sayfasına girer → loader sepeti, fiyatı (bölgesel), ödeme yöntemlerini hazırlar. |
| 2 | Kullanıcı ödemeyi tamamlar → Stripe Checkout Session tamamlanır. |
| 3 | Stripe checkout.session.completed webhook’u gönderir → api.stripe.webhook imzayı doğrular. |
| 4 | Enrollment’lar oluşturulur; komisyon motoru earnings kayıtlarını yazar; abonelik/fatura/e-posta işlemleri yapılır. |
Diğer event’ler (örn. payment_intent.succeeded, abonelik iptali) de aynı webhook dosyasında idempotency ve enrollment/earnings kurallarına uygun şekilde işlenir; ana “ödeme tamamlandı” sinyali checkout.session.completed’dır.
İlgili Dosyalar
Section titled “İlgili Dosyalar”app/routes/api.stripe.webhook.ts— Stripe webhook; checkout.session.completed ve diğer event’lerin işlenmesi.app/routes/payment.checkout.tsx— Checkout sayfası loader ve Stripe Session oluşturma.app/routes/cart.tsx— Sepet sayfası.app/lib/stripe-connect-payout.ts— Connect transfer (admin onayı sonrası processPayoutTransfer).app/lib/payout-engine.ts— Payout talebi ve earnings mantığı.