Pagos y retiros
Los administradores pueden ver los ingresos a nivel de plataforma y por usuario, revisar la cola de retiros (cashout) de creadores y configurar los ajustes globales de retiro/monetización. Cuatro páginas: /payments (resumen), /payments/cashouts (revisión manual de retiros), /payments/settings (configuración global), /payments/users/[userId] (detalle por usuario).
Esta es la contraparte del lado de administración a la que remite explícitamente el documento de cara al usuario Retiros de creador (Cashout) ("La revisión de administrador de las solicitudes de retiro manual ... y el interruptor de plataforma Stripe-vs-manual viven en el esquema de GraphQL de administración por separado y en frontend-admin — no cubiertos por esta página"). Anteriormente no estaba documentada — este es un documento nuevo.
Checklist de implementación
Resumen de pagos (/payments)
- Panel de ingresos globales (
adminGetGlobalRevenue)
Cola de revisión de retiros (/payments/cashouts)
- Listar solicitudes de retiro, filtrables por estado/usuario/proveedor/rango de fechas (
adminGetCashouts) - Buscar un retiro individual por id, sin verificación de propiedad (
adminGetCashout) - Ver el CLABE/RFC/dirección de facturación registrados de un usuario para revisión manual (
adminGetPayoutProfile) - Cancelar un retiro, con un motivo (
adminCancelCashout) - Marcar un retiro manual como en proceso (
adminMarkCashoutProcessing) - Completar un retiro manual, con una referencia (
adminCompleteManualCashout) - Rechazar un retiro manual, devolviendo las monedas al creador (
adminRejectManualCashout) - Congelar/descongelar de emergencia la cuenta de retiro de un usuario, independientemente de su estado en Stripe Connect (
adminSetPayoutAccountDisabled)
Ajustes globales de retiro (/payments/settings)
- Ver la configuración actual (
adminGetPayoutSettings) - Actualizar la configuración (
adminUpdatePayoutSettings), que cubre:coinsPerUsd— tasa de conversión de moneda a efectivopayoutHoldDays— período de espera antes de que un retiro sea elegibleminCashoutCoins— saldo mínimo para solicitar un retiropayoutsEnabledGlobally— interruptor de apagado a nivel de plataformaplatformCashoutFeePercent— la comisión de la plataforma sobre cada retirocashoutProvider— el interruptor Stripe-vs-manual al que se refiere el documento de retirosverificationPriceCoins— precio de la verificación de pago (también se configura aquí, no en una pantalla dedicada de configuración de verificación)referralReferrerBonusCoins/referralReferredBonusCoins— los dos bonos de registro por referido (ver Programa de referidos)
Ingresos por usuario (/payments/users/[userId])
- Detalle de ingresos por usuario (
adminGetUserRevenue)
Dónde vive esto
Backend
apps/backend/graphql/types/admin/payout-admin.type.js— esquema de todas las operaciones anterioresapps/backend/graphql/resolvers/admin/payout-admin.resolver.js— resolversapps/backend/managers/admin-managers/payout-admin.manager.js— lógica de negocio de revisión de retirosapps/backend/managers/admin-managers/payout-settings.manager.js— lee/escribe la fila únicaSystemSettingque respalda la configuración anterior
Frontend — apps/frontend-admin/src/app/payments/page.tsx, payments/cashouts/page.tsx, payments/settings/page.tsx, payments/users/[userId]/page.tsx.
Referencia de GraphQL
query GlobalRevenue($dateFrom: DateTime, $dateTo: DateTime) {
adminGetGlobalRevenue(dateFrom: $dateFrom, dateTo: $dateTo) {
totalCoinsPurchased totalPurchaseRevenue completedPurchases totalCashedOut
paidCashoutCount pendingCashoutCount canceledCashoutCount failedCashoutCount
netRevenue activePayoutAccounts
}
}
query Cashouts($filters: AdminCashoutFilters, $limit: Int, $offset: Int) {
adminGetCashouts(filters: $filters, limit: $limit, offset: $offset) {
id coinAmount cashAmount currency status provider providerTransferId
createdAt failureReason canceledReason user { id username }
}
}
# AdminCashoutFilters: { status, userId, provider, dateFrom, dateTo }
query Cashout($id: ID!) { adminGetCashout(id: $id) { id status coinAmount cashAmount provider } }
query PayoutProfile($userId: ID!) {
adminGetPayoutProfile(userId: $userId) { clabe rfc billingAddressLine1 billingCity billingState billingZip billingCountry }
}
mutation CancelCashout($id: ID!, $reason: String) { adminCancelCashout(id: $id, reason: $reason) { id status } }
mutation MarkCashoutProcessing($id: ID!) { adminMarkCashoutProcessing(id: $id) { id status } }
mutation CompleteManualCashout($id: ID!, $reference: String) {
adminCompleteManualCashout(id: $id, reference: $reference) { id status }
}
mutation RejectManualCashout($id: ID!, $reason: String) {
adminRejectManualCashout(id: $id, reason: $reason) { id status }
}
mutation SetPayoutAccountDisabled($userId: ID!, $disabled: Boolean!, $reason: String) {
adminSetPayoutAccountDisabled(userId: $userId, disabled: $disabled, reason: $reason) { userId adminDisabled }
}
query PayoutSettings { adminGetPayoutSettings {
coinsPerUsd payoutHoldDays minCashoutCoins payoutsEnabledGlobally
platformCashoutFeePercent cashoutProvider verificationPriceCoins
referralReferrerBonusCoins referralReferredBonusCoins
}}
mutation UpdatePayoutSettings($input: PayoutSettingsInput!) {
adminUpdatePayoutSettings(input: $input) { id coinsPerUsd payoutHoldDays cashoutProvider }
}
query UserRevenue($userId: ID!) {
adminGetUserRevenue(userId: $userId) {
totalCoinsPurchased totalAmountSpent completedPurchases lifetimeEarned
lifetimeCashedOut totalCashedOutAmount currentBalance availableForCashout cashoutCount
}
}