100 lines
5.1 KiB
TypeScript
100 lines
5.1 KiB
TypeScript
import Topnav from '@/components/topnav'
|
|
import Footer from '@/components/footer'
|
|
import Stripe from 'stripe'
|
|
import { getPayload } from 'payload'
|
|
import { headers } from 'next/headers'
|
|
import { redirect } from 'next/navigation'
|
|
import configPromise from '@payload-config'
|
|
import Link from 'next/link'
|
|
import '../styles/payment-success.css'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
export const metadata = { title: 'تم تفعيل العضوية' }
|
|
|
|
type Props = { searchParams: Promise<{ session_id?: string }> }
|
|
|
|
/* Payment success — design from payment-success.html.
|
|
- real Stripe: verifies the checkout session_id with Stripe before
|
|
activating (paid + the checkout email matches the signed-in account)
|
|
- no session: nobody is activated here — /api/stripe/webhook is the primary
|
|
activator; this page only re-verifies a session it can prove */
|
|
export default async function PaymentSuccessPage({ searchParams }: Props) {
|
|
const { session_id: sessionId } = await searchParams
|
|
const stripeKey = process.env.STRIPE_SECRET_KEY
|
|
|
|
const payload = await getPayload({ config: configPromise })
|
|
const { user } = await payload.auth({ headers: await headers() })
|
|
if (!user) redirect('/login?next=/payment-success')
|
|
|
|
let activate = false
|
|
if (sessionId && stripeKey) {
|
|
try {
|
|
const stripe = new Stripe(stripeKey)
|
|
const session = await stripe.checkout.sessions.retrieve(sessionId)
|
|
activate =
|
|
session.payment_status === 'paid' &&
|
|
(session.customer_details?.email ?? '').toLowerCase() === user.email.toLowerCase()
|
|
} catch {
|
|
// Any Stripe failure (bad key, unknown session, network) → no activation.
|
|
activate = false
|
|
}
|
|
}
|
|
|
|
if (activate && user.role !== 'vip' && user.role !== 'admin') {
|
|
await payload.update({
|
|
collection: 'users',
|
|
id: user.id,
|
|
data: { role: 'vip' },
|
|
overrideAccess: true,
|
|
context: { systemActivation: true },
|
|
})
|
|
}
|
|
|
|
const vipNow = user.role === 'vip' || user.role === 'admin' || activate
|
|
|
|
return (
|
|
<div id="site" className="site-page page-payment-success">
|
|
<Topnav viewer={user} />
|
|
<main id="content">
|
|
<section className="section" data-od-id="payment-success">
|
|
<div className="container">
|
|
<article className="state-card">
|
|
<div className="status-mark" aria-hidden="true"><svg viewBox="0 0 32 32" fill="none" stroke="currentColor" strokeWidth={2}><path d="m8 17 5 5 11-13" /></svg></div>
|
|
{vipNow ? (
|
|
<>
|
|
<p className="eyebrow">تم الدفع · العضوية فعّالة</p>
|
|
<h1 data-od-id="success-title">مرحباً بك في عضوية أنور پآي.</h1>
|
|
<p className="lead">تم تفعيل وصولك إلى المحتوى الحصري وملفات العمل. بقيت خطوة قصيرة لاختيار نقطة البداية المناسبة لك.</p>
|
|
<dl className="summary" data-od-id="payment-summary">
|
|
<div className="summary-row"><dt>الحالة</dt><dd>عضوية فعّالة</dd></div>
|
|
<div className="summary-row"><dt>الخطة</dt><dd>عضوية فردية · شهرياً · <bdi dir="ltr">$10</bdi></dd></div>
|
|
<div className="summary-row"><dt>الوصول</dt><dd>كل محتوى العضوية وملفات الأعضاء</dd></div>
|
|
</dl>
|
|
<div className="next-step" data-od-id="next-step">
|
|
<h2 data-od-id="next-step-title">جهّز مسارك الأول</h2>
|
|
<p>حدد هدفك ومستواك في أقل من خمس دقائق، ثم ابدأ بعنصر محتوى واحد يناسبك.</p>
|
|
<div className="actions">
|
|
<Link className="btn btn-primary" href="/vip-onboarding" data-od-id="start-onboarding-cta">ابدأ إعداد العضوية</Link>
|
|
<Link className="btn btn-secondary" href="/posts/agent-loop-stop-condition" data-od-id="open-member-guide-cta">افتح محتوى الأعضاء</Link>
|
|
</div>
|
|
</div>
|
|
</>
|
|
) : (
|
|
<>
|
|
<p className="eyebrow">لم تكتمل عملية الدفع</p>
|
|
<h1 data-od-id="payment-incomplete-title">لم يتم تأكيد الدفع بعد</h1>
|
|
<p className="lead">لم نتمكن من تأكيد عملية دفع مرتبطة بحسابك. إن أتممت الدفع للتو فقد يحتاج التأكيد بضع دقائق، ويمكنك إعادة المحاولة من صفحة الاشتراك.</p>
|
|
<div className="actions">
|
|
<Link className="btn btn-primary" href="/subscription" data-od-id="retry-subscription-cta">العودة إلى صفحة الاشتراك</Link>
|
|
</div>
|
|
</>
|
|
)}
|
|
</article>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
<Footer />
|
|
</div>
|
|
)
|
|
}
|