Use of a pre-existing billing code, to then connect

This commit is contained in:
SimplifiedPrivacy 2026-10-22 21:20:59 -04:00
parent b68d1ea6bd
commit f54ed5686a
5 changed files with 117 additions and 18 deletions

View file

@ -7,6 +7,7 @@ from datetime import datetime
from enum import Enum
from typing import Any, Optional
class ServerError(str, Enum):
"""Why the Server's Operation was False."""
NONE = "none"
@ -24,8 +25,9 @@ class ServerError(str, Enum):
SERVER_SIDE = "server_side"
# @validate_types
@dataclass_json
@validate_types
@dataclass
class ServerReply():
"""Server-Client Communication Format."""
@ -38,7 +40,12 @@ class ServerReply():
boolean_result: Optional[bool] = None
conf: Optional[str] = None
payment_status: Optional[bool] = None
expires_at: Optional[datetime] = None
expires_at: Optional[datetime] = field(
default=None,
metadata=config(
decoder=lambda x: datetime.fromisoformat(x.replace('Z', '+00:00')) if x else None
)
)

View file

@ -9,6 +9,7 @@ from core.errors.logger import logger
from core.errors.error_shortcuts import not_supported
from core.observers.Notifications import Notifications, EventType
from typing import Optional
def _mark_profile_as_paid(profile_id: int):
"""Save to disk that an individual profile is paid."""
@ -68,7 +69,7 @@ def mark_as_paid() -> Result:
return Result(valid=True)
def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Result:
def check_paid(billing_code: str, connection_observer: ConnectionObserver, get_expired_date: Optional[bool] = False) -> Result:
"""
Purpose:
Evaluates Payment Status for EITHER payment category
@ -95,6 +96,11 @@ def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Re
"billing_code": billing_code
}
#-----------------
# Just get paid or not
#-----------------
if not get_expired_date:
result = api_call_and_extraction(
desired_type="payment_status",
method=ApiCall.POST,
@ -114,3 +120,27 @@ def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Re
else:
return Result(valid=False, error_type=ResultError.UNPAID, message="The API call went through, but this subscription is not yet paid.")
#-----------------
# Find out if Paid & Get expiration:
#-----------------
# Get entire ServerReply
server_reply = api_call_and_extraction(
desired_type=None,
method=ApiCall.POST,
url=url,
connection_observer=connection_observer,
payload=submit_data,
return_server_reply=True # get server reply
)
if not server_reply.valid:
return server_reply
payment_status = server_reply.payment_status
expires_at = server_reply.expires_at
if payment_status and expires_at:
return Result(valid=True, data=expires_at, message="Paid with an expiration")
return Result(valid=False, error_type=ResultError.UNPAID, message="The API call went through, but this subscription is not yet paid.")

View file

@ -0,0 +1,38 @@
from core.services.payment_phase.payment_update_tools import check_paid
from core.services.subscriptions.subscriptions_by_protocol import save_billing_code, wipe_billing_cycle_IF_its_this_profile
from core.services.payment_phase.payment_state import OverallPaymentCycle
from core.models.Result import Result
from core.errors.logger import logger
from core.observers.ConnectionObserver import ConnectionObserver
def check_then_save_billing_code(profile_id: int, billing_code: str, connection_observer: ConnectionObserver) -> Result:
"""Check if a billing code is paid for, and if it is, then save it and wipe the profile's billing cycle"""
logger.info(f"Checking payment status of a pre-existing billing code for profile {str(profile_id)}")
payment_result = check_paid(billing_code=billing_code, connection_observer=connection_observer, get_expired_date=True)
if not payment_result.valid:
logger.error(f"Check of paid came back that it's NOT paid, despite the user using a pre-existing billing code. {payment_result.message}")
return payment_result
expires_at = payment_result.data
saved = save_billing_code(
profile_id=profile_id,
billing_code=billing_code,
expires_at=expires_at,
which_ticket=None,
billing_pending=False
)
if saved.valid:
print("save worked, we are clearing the billing cycle")
wiped = wipe_billing_cycle_IF_its_this_profile(profile_id)
if not wiped.valid:
logger.error(f"Unable to wipe the current billing cycle: {wiped.message}")
return wiped
else:
logger.error(f"failed to save the new billing code, returning the saved result {saved}")
return saved

View file

@ -14,6 +14,8 @@ from core.observers.TicketObserver import TicketObserver
from core.services.assassin.ticket_respawn import respawn_profile
from core.services.assassin import assassin_tools
from core.errors.logger import logger
from core.services.payment_phase.payment_state import OverallPaymentCycle
from core.services.subscriptions.subscriptions_by_protocol import wipe_billing_cycle_IF_its_this_profile
from core.Errors import InvalidSubscriptionError, MissingSubscriptionError, ConnectionTerminationError, ProfileActivationError, ProfileDeactivationError, MissingLocationError, ConnectionUnprotectedError, EndpointVerificationError, ProfileStateConflictError
from core.controllers.ApplicationController import ApplicationController
@ -310,6 +312,14 @@ def destroy_profile(
2) Disabling it,
3) Destroying it on disk & cache
"""
####################################
# ACTIVE BILLING STATE:
####################################
wiped = wipe_billing_cycle_IF_its_this_profile(profile.id)
if not wiped.valid:
logger.error(f"Unable to wipe the current billing cycle: {wiped.message}")
return wiped
####################################
# RESPAWN TICKET
####################################

View file

@ -474,6 +474,20 @@ def get_current_billing_data(category: Optional[PaymentCategory] = None, profile
return Result(valid=True, data=billing_data)
def wipe_billing_cycle_IF_its_this_profile(profile_id) -> Result:
# Overall State:
payment_cycle = OverallPaymentCycle()
if not payment_cycle:
return Result(valid=True)
if payment_cycle.billing_code != profile_id:
return Result(valid=True)
return wipe_billing_cycle(inserted_profile_id=profile.id)
def wipe_billing_cycle(inserted_profile_id: Optional[int] = None) -> Result:
"""Wipes the entire overall cycle"""
logger.info("Wiping the overall cycle, so this cycle no longer blocks other new ones")
@ -573,10 +587,10 @@ def wipe_subscription(profile_id: int) -> Result:
@type_checker
def save_billing_code(profile_id: int, billing_code: str, expires_at: datetime, which_ticket: Optional[int] = None) -> Result:
def save_billing_code(profile_id: int, billing_code: str, expires_at: datetime, which_ticket: Optional[int] = None, billing_pending: bool = True) -> Result:
"""Checks if the billing code is already saved, and if not, saves it."""
logger.info("Saving billing code..")
logger.info(f"Saving billing code with the billing_pending as {billing_pending}")
PRE_REQS = [profile_id, billing_code, expires_at]
if None in PRE_REQS:
@ -595,7 +609,7 @@ def save_billing_code(profile_id: int, billing_code: str, expires_at: datetime,
profile.subscription = Subscription(
billing_code=billing_code,
expires_at=expires_at,
billing_pending=True
billing_pending=billing_pending
)
if which_ticket:
profile.ticket = which_ticket