b3184fbdfe
El módulo monolítico (~3200 líneas) se convierte en un paquete cuyo __init__.py re-exporta todas las vistas, de modo que `views.X`, `from home.views import X` y la cadena 'home.views.not_found' (handler404) siguen funcionando sin tocar urls.py. Módulos por sección: _base (imports comunes + require_paid_stripe), auth, pages, account, recruit, characters, store, points, guild, history, players y payments. Cada submódulo hereda los imports con `from ._base import *`; las dependencias entre secciones se resuelven con imports explícitos (guild->auth, recruit/history->account). Se eliminan dos definiciones duplicadas que quedaban muertas al cargar: - get_character_image (primera copia, idéntica a la efectiva) - store_novawow_success_view (stub sin SOAP, pisado por la versión real) Validado con `manage.py check` (0 issues), resolución de las 100 rutas y un chequeo estático de nombres no definidos por módulo. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
69 lines
2.8 KiB
Python
69 lines
2.8 KiB
Python
"""Imports y utilidades compartidas por el paquete de vistas (`home.views`).
|
|
|
|
Cada submódulo de vistas hace `from ._base import *` para heredar estos imports
|
|
y el decorador `require_paid_stripe`.
|
|
"""
|
|
import socket, hashlib, gmpy2, binascii, os, re, json, logging, secrets
|
|
from collections import Counter
|
|
from datetime import datetime, timedelta
|
|
from decimal import Decimal, ROUND_HALF_UP
|
|
from functools import wraps
|
|
|
|
from django import forms
|
|
from django.conf import settings
|
|
from django.contrib import messages
|
|
from django.contrib.auth import logout
|
|
from django.db import connections
|
|
from django.http import HttpResponse, JsonResponse
|
|
from django.shortcuts import render, redirect
|
|
from django.urls import reverse
|
|
from django.utils import timezone
|
|
from django.utils.crypto import get_random_string
|
|
from django.utils.timezone import now
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
import stripe
|
|
|
|
from ..ac_soap import execute_soap_command
|
|
from ..library_correo import enviar_correo
|
|
from ..pagos_stripe import create_checkout_session, is_session_paid
|
|
from ..pagos_sumup import crear_checkout, crear_checkout_battlepay, obtener_checkout
|
|
from ..zone_definitions import get_zone_name
|
|
from .. import bnet
|
|
from ..models import (
|
|
Noticia, ClienteCategoria, ServerSelection, RecruitAFriend, DownloadClientPage,
|
|
ContentCreator, RecruitReward, ClaimedReward, AccountActivation, SecurityToken,
|
|
GuildRenameSettings, VoteSite, VoteLog, HomeApiPoints, UnstuckHistory, ReviveHistory,
|
|
RenamePrice, CustomizePrice, ChangeRacePrice, ChangeFactionPrice, LevelUpPrice,
|
|
GoldPrice, TransferPrice, Category, Item, StripeLog, LoginAttempt, Pedido,
|
|
)
|
|
|
|
# Configuración del logger
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def require_paid_stripe(redirect_to='index'):
|
|
"""
|
|
Protege las vistas de "éxito" de pago: exige un `session_id` de Stripe
|
|
realmente PAGADO en la URL (Stripe lo añade tras el pago) y evita re-entregas
|
|
marcando el StripeLog como `fulfilled`. Cierra el bypass de ir directo a la
|
|
success-url sin pagar.
|
|
"""
|
|
def deco(view):
|
|
@wraps(view)
|
|
def wrapper(request, *args, **kwargs):
|
|
session_id = request.GET.get('session_id')
|
|
if not is_session_paid(session_id):
|
|
messages.error(request, 'No se ha podido verificar el pago.')
|
|
return redirect(redirect_to)
|
|
log = StripeLog.objects.filter(session_id=session_id).first()
|
|
if log is not None and log.fulfilled:
|
|
messages.info(request, 'Este pago ya había sido procesado.')
|
|
return redirect(redirect_to)
|
|
response = view(request, *args, **kwargs)
|
|
if log is not None:
|
|
log.fulfilled = True
|
|
log.save(update_fields=['fulfilled'])
|
|
return response
|
|
return wrapper
|
|
return deco
|