Files
anwar-pi-website/web/src/app/(frontend)/payment-success/page.tsx
T

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>
)
}