sp-hydra-veil-core/core/controllers/tickets/TicketPayController.py

169 lines
6.9 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from core.essentials.observers.ConnectionObserver import ConnectionObserver
from core.observers.TicketObserver import TicketObserver
#
from core.models.invoice.TicketInvoice import TicketInvoice
from core.services.prepare_tickets.get_pub_key import get_pub_key
from core.observers.BaseObserver import BaseObserver
from core.services.payment_phase.save_and_send_intitial_billing import save_and_send_intitial_billing
from core.services.networking.api_requests.ApiResponseModel import ApiResponse, ErrorType
from core.models.Result import Result, ResultError
from core.errors.logger import logger
from core.services.prepare_tickets.ticket_tracker import does_ticket_tracker_exist
from core.services.prepare_tickets.setup_ticket_tracker import setup_ticket_tracker
from core.services.networking.httpx import connect
from core.services.networking.make_url import make_url
from core.services.helpers.valid_profile_quantity import valid_profile_quantity
from core.errors.exceptions import *
from core.controllers.tickets.TicketSyncController import sync_ticket_prices
from core.services.payment_phase.ticket_config_tools import do_we_have_billing_id
"""
Inputs: Which plan (key), which crypto, and how many profiles
Outputs: a temp billing code & crypto address. (or "error")
"""
def initiate_payment(
how_many_profiles: int,
which_key: str,
which_cryptocurrency: str,
ticket_observer: TicketObserver,
connection_observer: ConnectionObserver,
bypass_existing: bool,
) -> TicketInvoice:
###############
if bypass_existing == False:
tickets_exist_already, path = does_ticket_tracker_exist()
logger.debug(f"tickets_exist_already is {tickets_exist_already}")
if tickets_exist_already:
return Result(valid=False, error_type=ResultError.ALREADY_EXISTS, message="There's already a ticket billing session in progress. Do you want to wipe it?")
else:
made_ticket_tracker = setup_ticket_tracker(how_many_profiles=how_many_profiles)
logger.debug(f"Ticket Tracker doesn't exist, so we made it: {made_ticket_tracker} for {how_many_profiles} profiles")
billing_id = do_we_have_billing_id()
if billing_id:
error_msg = "Billing code exists already"
logger.error(error_msg)
return Result(valid=False, error_type=ResultError.BILLING_CODE_EXISTS, data=billing_id, message=error_msg)
rejected_choices = [None, "", False]
if how_many_profiles in rejected_choices:
notification = "Missing profile quantity, to initiate payment"
logger.error(notification)
ticket_observer.notify("failed_input", subject=notification)
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=notification)
if not valid_profile_quantity(how_many_profiles):
notification = "Invalid profile quantity"
logger.error(notification)
ticket_observer.notify("failed_input", subject=notification)
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message="You've picked a currently unsupported profile quantity")
if which_key in rejected_choices:
notification = "Missing key plan, to initiate payment"
logger.error(notification)
ticket_observer.notify("failed_input", subject=notification)
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message="You didn't pick a key plan. It's either blank, none, or invalid.")
# get & save the public key:
public_key_results = get_pub_key(which_key, connection_observer, "local")
if not isinstance(public_key_results, dict):
notification = f"Invalid Key chosen or the server is down for that key."
logger.error(notification)
ticket_observer.notify("failed_input", subject=notification)
# invoice_data_object.add_error_code("no_pub_key")
# return invoice_data_object
status = public_key_results.get("valid", False)
if status == False:
message = public_key_results.get(
"message", "Please fix before you continue"
)
error_code = public_key_results.get("error_code", "No error_code")
notification = f"Connection Issues or Invalid Key chosen. {error_code}"
logger.error(notification)
ticket_observer.notify("failed_input", subject=notification)
return Result(valid=False, error_type=ResultError.CONNECTION, message="There were connection issues with getting the right key.")
# In this case, the controller is going to send the whole JSON payload to the service,
# instead of passing 4 values seperately.
payload = {
"which_key": which_key,
"payment_type": "crypto",
"which_cryptocurrency": which_cryptocurrency,
"how_many_profiles": how_many_profiles,
}
try:
return save_and_send_intitial_billing(
payload=payload,
connection_observer=connection_observer
)
except ValueError as e:
if ticket_observer:
ticket_observer.notify("failed_input", subject=str(e))
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=str(e))
except ConnectionError as e:
error_msg = "There were connection issues with getting the right key."
logger.error(error_msg, exc_info=True)
if ticket_observer:
ticket_observer.notify("connection_error", subject=str(e))
return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg)
def check_if_paid(
temp_billing_code: str,
ticket_observer: TicketObserver,
connection_observer: ConnectionObserver,
) -> dict:
rejected_reasons = [None, "", False]
if temp_billing_code in rejected_reasons:
error_msg = "Invalid Temp Billing Code"
logger.error(f"{error_msg} inside the check_if_paid function", exc_info=True)
ticket_observer.notify("failed_input", subject=error_msg)
return {"valid": False, "error_code": "rejected"}
else:
# prep the JSON payload:
payload = {"temp_billing_code": temp_billing_code}
# prep endpoint:
which_endpoint = "check_paid"
url = make_url(which_endpoint)
# literally send:
api_reply_object = connect.single_endpoint(
method="post",
url=url,
observer=connection_observer,
payload=payload
)
if not api_reply_object.valid:
error_msg = f"Connection/API Error: {api_reply_object.message}"
logger.error(f"[TICKET PayController] 2nd Post Request inside ticketpay controller had a {error_msg}")
return {"valid": False, "message": error_msg}
# return the payload with GUI/CLI to interpret results:
reply_dict = api_reply_object.data
logger.debug(f"[TICKET PayController] We have a valid reply from the API inside ticketpay controller of {reply_dict}")
return reply_dict