web-next: /transfer-character (transferir personaje por SumUp con todas las condiciones)
- Nueva ruta /transfer-character (10€ SumUp); borra /transfer (Stripe) y actualiza
el link del panel.
- lib/transfer-character.ts: precheck con todas las condiciones — personaje offline,
contraseña, token de seguridad, 2FA activo, cuenta destino válida (≠ propia) y,
para Caballeros de la Muerte, la cuenta destino debe tener un personaje nivel >=55
y no tener ya un DK; + bloqueo de 5s tras transferencia reciente.
- El hook precheck de PaidServiceConfig ahora recibe {accountId,email,character,body}.
- TransferForm: contraseña + token (con ojos), provider sumup, confirm.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { executeSoapCommand } from './soap'
|
||||
import { creditDPoints } from './dpoints'
|
||||
import { checkFactionChangeEligibility } from './change-faction'
|
||||
import { checkTransferEligibility } from './transfer-character'
|
||||
import {
|
||||
getRenamePrice,
|
||||
getCustomizePrice,
|
||||
@@ -18,9 +19,16 @@ export interface PaidServiceConfig {
|
||||
productName: (character: string, meta: Meta) => string
|
||||
fulfill: (character: string, meta: Meta) => Promise<boolean>
|
||||
extraFields: string[] // campos (además de character) que el form envía y se guardan en metadata
|
||||
// Comprobación previa al pago (p.ej. condiciones de cambio de facción). Si `ok`
|
||||
// es false, se bloquea el checkout y se muestra `message`.
|
||||
precheck?: (accountId: number, character: string) => Promise<{ ok: boolean; message?: string }>
|
||||
// Comprobación previa al pago (p.ej. condiciones de cambio de facción / transferencia).
|
||||
// Si `ok` es false, se bloquea el checkout y se muestra `message`.
|
||||
precheck?: (ctx: PrecheckCtx) => Promise<{ ok: boolean; message?: string }>
|
||||
}
|
||||
|
||||
export interface PrecheckCtx {
|
||||
accountId: number
|
||||
email: string
|
||||
character: string
|
||||
body: Record<string, unknown>
|
||||
}
|
||||
|
||||
async function soapFulfill(command: string): Promise<boolean> {
|
||||
@@ -60,7 +68,7 @@ export const PAID_SERVICES: Record<string, PaidServiceConfig> = {
|
||||
price: () => getChangeFactionPrice(),
|
||||
productName: (c) => `Cambiar facción: ${c}`,
|
||||
fulfill: (c) => soapFulfill(`.char changef ${c}`),
|
||||
precheck: async (accountId, character) => {
|
||||
precheck: async ({ accountId, character }) => {
|
||||
const r = await checkFactionChangeEligibility(accountId, character)
|
||||
return { ok: r.ok, message: r.ok ? undefined : `No se puede cambiar la facción: el personaje ${r.reasons.join('; ')}.` }
|
||||
},
|
||||
@@ -83,6 +91,7 @@ export const PAID_SERVICES: Record<string, PaidServiceConfig> = {
|
||||
productName: (c, m) => `Transferir ${c} a la cuenta ${m.destination_account}`,
|
||||
fulfill: (c, m) => soapFulfill(`.char changeaccount ${m.destination_account} ${c}`),
|
||||
extraFields: ['destination_account'],
|
||||
precheck: ({ accountId, email, character, body }) => checkTransferEligibility(accountId, email, character, body),
|
||||
},
|
||||
// Compra de PD (Adquirir PD): acredita puntos a la cuenta que hizo el pago.
|
||||
// El importe lo elige el usuario, por eso `price` lee metadata.amount.
|
||||
|
||||
Reference in New Issue
Block a user