- lib/stripe.ts: createCheckoutSession acepta metadata; claimPaidCheckout la
recupera de la sesión Stripe y la devuelve.
- lib/paid-services.ts: config unificado con fulfill(character, meta) + extraFields.
gold -> UPDATE characters money (BD directa, no SOAP), transfer -> SOAP
.char changeaccount. Los 5 simples usan soapFulfill.
- checkout [service]: lee extraFields -> metadata, precio depende de metadata (gold),
valida precio>0. service-success llama cfg.fulfill(name, metadata).
- prices.ts: getTransferPrice, getGoldOptions/goldPriceFor (home_goldprice).
- GoldForm (personaje + cantidad) y TransferForm (personaje + destino); páginas
/gold y /transfer. Catálogos Paid.gold/transfer.
Verificado: /gold /transfer redirigen a login, checkout 401 sin sesión, home OK.
NOTA: transfer no valida aún el token de seguridad ni reglas AC (nivel>=55, DK).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- lib/paid-services.ts: config PAID_SERVICES (rename/customize/change-race/
change-faction/level-up) con comando SOAP, precio y productName por servicio.
- app/api/character/[service]/checkout: ruta de checkout GENÉRICA (valida servicio +
personaje, crea la sesión Stripe con successUrl /service-success?service=...).
- app/[locale]/service-success: página de éxito ÚNICA que verifica el pago
(claimPaidCheckout) y ejecuta el comando SOAP del servicio.
- components/ServicePageContent: contenido común (guardas + PaidServiceForm).
- 5 páginas mínimas /rename /customize /change-race /change-faction /level-up.
- Catálogo Paid (por servicio: title/pay/success) sustituye a Rename.
Verificado: 5 páginas redirigen a login, checkout 401 sin sesión, servicio inválido
404, service-success con pago inválido no entrega (muestra error). Pendiente: gold
(cantidad) y transfer (destino+token), variantes del patrón.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 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>