e7cff56954
- lib/stripe.ts: createCheckoutSession (crea sesión Stripe + StripeLog en
home_stripelog, success_url con {CHECKOUT_SESSION_ID}), isSessionPaid,
claimPaidCheckout (verifica pagado + no entregado, marca fulfilled -> evita
re-entregas; port de require_paid_stripe).
- lib/prices.ts: precios desde home_*price (rename/customize/race/faction/level).
- components/PaidServiceForm.tsx: selector + botón de pago -> redirige a la URL de
Checkout de Stripe (session.url, sin stripe.js).
- Rename: route /api/character/rename/checkout (guard + valida personaje + crea
checkout), página /rename (PaidServiceForm) y /rename/success (verifica pago y
ejecuta SOAP .char rename, i18n). STRIPE_* + NEXT_PUBLIC_STRIPE_PUBLIC_KEY en
.env.local. Namespace Rename.
Verificado: checkout sin sesión 401, /rename redirige a login, /rename/success con
session_id inválido no entrega el servicio (muestra error). Patrón para los demás
servicios de pago (cambiar precio + comando SOAP).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
import { getTranslations, setRequestLocale } from 'next-intl/server'
|
|
import { claimPaidCheckout } from '@/lib/stripe'
|
|
import { executeSoapCommand } from '@/lib/soap'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export default async function RenameSuccessPage({
|
|
params,
|
|
searchParams,
|
|
}: {
|
|
params: Promise<{ locale: string }>
|
|
searchParams: Promise<{ session_id?: string }>
|
|
}) {
|
|
const { locale } = await params
|
|
setRequestLocale(locale)
|
|
const { session_id } = await searchParams
|
|
const t = await getTranslations('Rename')
|
|
|
|
// Verifica el pago (una sola vez) y ejecuta el comando SOAP.
|
|
let okName: string | null = null
|
|
if (session_id) {
|
|
const claim = await claimPaidCheckout(session_id)
|
|
if (claim) {
|
|
const resp = await executeSoapCommand(`.char rename ${claim.characterName}`)
|
|
if (resp !== null) okName = claim.characterName
|
|
}
|
|
}
|
|
|
|
return (
|
|
<main className="mx-auto max-w-lg px-4 py-12 text-center">
|
|
<h1 className="mb-6 text-2xl font-bold text-amber-500">{t('successTitle')}</h1>
|
|
{okName ? (
|
|
<p className="text-green-400">{t('success', { name: okName })}</p>
|
|
) : (
|
|
<p className="text-red-400">{t('error')}</p>
|
|
)}
|
|
</main>
|
|
)
|
|
}
|