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>
18 lines
742 B
TypeScript
18 lines
742 B
TypeScript
import type { RowDataPacket } from 'mysql2'
|
|
import { db, DB } from './db'
|
|
|
|
async function priceFrom(table: string, fallback: number): Promise<number> {
|
|
try {
|
|
const [rows] = await db(DB.default).query<RowDataPacket[]>(`SELECT price FROM ${table} LIMIT 1`)
|
|
return rows[0] ? Number(rows[0].price) : fallback
|
|
} catch {
|
|
return fallback
|
|
}
|
|
}
|
|
|
|
export const getRenamePrice = () => priceFrom('home_renameprice', 2.0)
|
|
export const getCustomizePrice = () => priceFrom('home_customizeprice', 1.0)
|
|
export const getChangeRacePrice = () => priceFrom('home_changeraceprice', 10.0)
|
|
export const getChangeFactionPrice = () => priceFrom('home_changefactionprice', 10.0)
|
|
export const getLevelUpPrice = () => priceFrom('home_levelupprice', 10.0)
|