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.services.networking.api_requests.step5_solve_api_problems import solve_api_problems from core.errors.logger import logger # from core.errors.exceptions import NetworkingError 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.api_requests.step1_get_or_post import send_data_to_server from core.services.networking.httpx import connect from core.services.networking.make_url import make_url # from core.utils.confirm_its_a_valid_key_choice import confirm_its_a_valid_key_choice 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)) # invoice_data_object.add_error_code("invalid_data") # return invoice_data_object 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)) # invoice_data_object.add_error_code("connection_error") return Result(valid=False, error_type=ResultError.CONNECTION, message=error_msg) # except ServerSideError as e: # error_msg = f"ServerSideError: {e}" # logger.error(error_msg, exc_info=True) # ticket_observer.notify("failed_output", subject=error_msg) # invoice_data_object.add_error_code("server_error") # return invoice_data_object # except Exception as e: # error_msg = f"Error: {e}" # logger.error(error_msg, exc_info=True) # ticket_observer.notify("unknown_error", subject=error_msg) # invoice_data_object.add_error_code("unknown_error") # return invoice_data_object ############### 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