import { randomUUID } from 'crypto' import { getSession } from '@/lib/session' import { getGameCharacters, findCharacterByName } from '@/lib/characters' import { checkGift } from '@/lib/gift-check' import { priceStoreCart, purchaseStoreCart, storeEuroTotal, createStoreOrder, storeConcept, giftMail, isValidCharName, type StoreCartLine, } from '@/lib/store' import { CARD_MIN_EUR } from '@/lib/store-pricing' import { createCheckoutSession } from '@/lib/stripe' import { createSumUpCheckout, sumupConfigured } from '@/lib/sumup' function safeLocale(v: unknown): string { return v === 'en' ? 'en' : 'es' } /** * Envío de un regalo: es la compra de la tienda pero el correo va a OTRO * personaje y diciendo quién lo manda. Mismo catálogo y mismo carrito * (`priceStoreCart`), así que los precios se recalculan igual contra la BD. * * A diferencia de la tienda exige, como el original: personaje de origen de tu * cuenta, personaje de destino que exista, y token de seguridad. */ export async function POST(request: Request) { const session = await getSession() if (!session.accountId || !session.username) { return Response.json({ success: false, error: 'notAuthenticated' }, { status: 401 }) } let body: { source?: string destination?: string items?: StoreCartLine[] security_token?: string provider?: string locale?: string } = {} try { body = await request.json() } catch { return Response.json({ success: false, error: 'invalidRequest' }, { status: 400 }) } const check = await checkGift(session.accountId, body) if ('error' in check) return Response.json({ success: false, error: check.error }) const { source, destination } = check const cart = await priceStoreCart(Array.isArray(body.items) ? body.items : []) if (!cart) return Response.json({ success: false, error: 'emptyCart' }) const provider = String(body.provider ?? 'balance') const mail = giftMail(source) if (provider === 'stripe' || provider === 'sumup') { const amount = storeEuroTotal(cart.pdTotal, cart.vpTotal) const minEur = CARD_MIN_EUR[provider] if (amount < minEur) return Response.json({ success: false, error: 'amountTooLow', min: minEur }) const ref = randomUUID() // El pedido se guarda a nombre del DESTINO: es a quien hay que entregarlo // cuando la pasarela confirme el pago. if (!(await createStoreOrder(ref, session.accountId, destination, cart))) { return Response.json({ success: false, error: 'genericError' }) } const site = process.env.SITE_URL || '' const ip = (request.headers.get('x-forwarded-for') || '').split(',')[0].trim() || '0.0.0.0' const productName = storeConcept(cart, { bnetEmail: session.bnetEmail, account: session.username, character: `${source} → ${destination}`, ip, }) // `sender` lo necesita la entrega para redactar el correo del regalo. const metadata = { service: 'send-gift', order_ref: ref, sender: source } const back = `${site}/${safeLocale(body.locale)}/send-gift` if (provider === 'sumup') { if (!sumupConfigured()) return Response.json({ success: false, error: 'notConfigured' }) const r = await createSumUpCheckout({ accountId: session.accountId, username: session.username || '', email: session.bnetEmail || '', acoreIp: ip, amount, points: 0, reference: ref, description: productName, returnUrl: `${site}/service-success?service=send-gift&provider=sumup&ref=${ref}`, service: 'send-gift', characterName: destination, metadata, }) if (!r.success || !r.url) return Response.json({ success: false, error: r.error || 'sumupError' }) return Response.json({ success: true, url: r.url }) } const r = await createCheckoutSession({ accountId: session.accountId, username: session.username || '', email: session.bnetEmail || '', acoreIp: ip, amount, characterName: destination, productName, successUrl: `${site}/service-success?service=send-gift&name=${encodeURIComponent(destination)}`, cancelUrl: back, metadata, }) if (!r.success || !r.url) return Response.json({ success: false, error: 'stripeError' }) return Response.json({ success: true, url: r.url }) } // Saldo PD/PV: se cobra a TU cuenta y el correo va al personaje de destino. const r = await purchaseStoreCart(session.accountId, destination, cart, mail) if (!r.success) return Response.json({ success: false, error: r.error }) return Response.json({ success: true }) }