Resume Payments for individual profiles stable. Also fixed a bug with errors in filtering invalid replies to getting new wireguard conifgs
This commit is contained in:
parent
52b3e1ba94
commit
430696b480
5 changed files with 96 additions and 50 deletions
|
|
@ -14,10 +14,12 @@ TRANSLATION_DICT = {
|
|||
ServerError.INVALID: ResultError.INVALID_INPUT,
|
||||
ServerError.MISSING_DATA: ResultError.INVALID_INPUT,
|
||||
ServerError.UNPAID: ResultError.SUBSCRIPTION,
|
||||
ServerError.SERVER_SIDE: ResultError.SERVER_SIDE
|
||||
ServerError.SERVER_SIDE: ResultError.SERVER_SIDE,
|
||||
ServerError.EXPIRED: ResultError.SUBSCRIPTION
|
||||
}
|
||||
|
||||
def format_server_response(api_response: ApiResponse, desired_type: str) -> Result:
|
||||
print("Starting format_server_response conversion")
|
||||
"""Turn an API response into a Result Object"""
|
||||
|
||||
# if it's in object format, then convert it,
|
||||
|
|
@ -33,28 +35,35 @@ def format_server_response(api_response: ApiResponse, desired_type: str) -> Resu
|
|||
logger.error("Can't convert server response.")
|
||||
return invalid_server_format()
|
||||
|
||||
conversion_worked, server_reply = validate_model(ServerReply, raw_reply)
|
||||
validated_model, server_reply = validate_model(ServerReply, raw_reply)
|
||||
|
||||
if not conversion_worked:
|
||||
if not validated_model:
|
||||
logger.error(f"Invalid structure for ServerReply. The original raw reply was {raw_reply}")
|
||||
return invalid_server_format(error_msg=server_reply)
|
||||
|
||||
# Sanity check:
|
||||
# Failure:
|
||||
if not server_reply.valid:
|
||||
logger.error(f"invalid server reply: {server_reply.error_type}")
|
||||
logger.error(f"invalid server reply: {server_reply.message}")
|
||||
final_return = translate_server_failure(server_reply)
|
||||
|
||||
print(f"final_return is {final_return}")
|
||||
return final_return # result object
|
||||
|
||||
print("Server claims the result was valid, let's check if it has the data type")
|
||||
if not hasattr(server_reply, desired_type):
|
||||
error_msg = "Developer Error: You're asking for a data type that isn't in the object!"
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg)
|
||||
|
||||
# Success! Extract and Return Data:
|
||||
if server_reply.valid:
|
||||
data = getattr(server_reply, desired_type)
|
||||
if data:
|
||||
return Result(valid=True, data=data)
|
||||
else:
|
||||
return Result(valid=False, error_type=ResultError.MISSING_DATA, message="Server Replied it was valid, but failed to provide the data.")
|
||||
|
||||
# Failure:
|
||||
logger.error(f"invalid server reply: {server_reply.error_type}")
|
||||
logger.error(f"invalid server reply: {server_reply.message}")
|
||||
error_type = translate_server_failure(server_reply.error_type)
|
||||
return Result(valid=False, error_type=error_type, message=server_reply.message)
|
||||
|
||||
# return Result(valid=False, error_type=error_type, message=server_reply.message)
|
||||
|
||||
|
||||
def translate_server_failure(server_reply: ServerReply) -> Result:
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ def register_wireguard_session(
|
|||
logger.error(error_msg)
|
||||
raise ConnectionError(error_msg)
|
||||
|
||||
wireguard_configuration = api_result.data
|
||||
print(f"wireguard_configuration type is {type(wireguard_configuration)}")
|
||||
# print(f"wireguard_configuration value is {wireguard_configuration}")
|
||||
# 2nd Layer Translation:
|
||||
result = format_server_response(api_response=api_result, desired_type="data")
|
||||
if not result.valid:
|
||||
# KILLING THE RESULT FOR NOW. Later, replace this error raise with the return of data,
|
||||
raise InvalidSubscriptionError(result.message)
|
||||
|
||||
if isinstance(wireguard_configuration, dict):
|
||||
logger.error("Server isn't returning a WG config, it's trying to tell you a ServerReply message...")
|
||||
return handle_config_error(wireguard_configuration)
|
||||
wireguard_configuration = result.data
|
||||
|
||||
if wireguard_configuration is None:
|
||||
raise InvalidSubscriptionError()
|
||||
|
|
@ -76,14 +76,25 @@ def register_wireguard_session(
|
|||
return Result(valid=True)
|
||||
|
||||
|
||||
# over-engineering:
|
||||
|
||||
def handle_config_error(wireguard_configuration: str|dict) -> Result:
|
||||
"""The server gave the wireguard config in an invalid format. First convert it to get the error."""
|
||||
server_reply = format_server_response(wireguard_configuration, "message")
|
||||
if server_reply.valid:
|
||||
return server_reply
|
||||
else:
|
||||
return Result(valid=False, error_type=ResultError.NODE_ERROR, message="server-side error with wireguard config format.")
|
||||
# print(f"wireguard_configuration type is {type(wireguard_configuration)}")
|
||||
# # print(f"wireguard_configuration value is {wireguard_configuration}")
|
||||
|
||||
# if isinstance(wireguard_configuration, dict):
|
||||
# print(f"wireguard_configuration is {type(wireguard_configuration)}")
|
||||
# print(f"wireguard_configuration is {wireguard_configuration}")
|
||||
# logger.error("Server isn't returning a WG config, it's trying to tell you a ServerReply message...")
|
||||
# return format_server_response(wireguard_configuration, "message")
|
||||
|
||||
|
||||
# def handle_config_error(wireguard_configuration: str|dict) -> Result:
|
||||
# """The server gave the wireguard config in an invalid format. First convert it to get the error."""
|
||||
# server_reply = format_server_response(wireguard_configuration, "message")
|
||||
# if server_reply.valid:
|
||||
# return server_reply
|
||||
# else:
|
||||
# return Result(valid=False, error_type=ResultError.NODE_ERROR, message="server-side error with wireguard config format.")
|
||||
|
||||
|
||||
def _generate_wireguard_keys() -> dict:
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ def _ensure_wireguard_configured(
|
|||
logger.info(f"[CONNECTION] Checking if the profile already has a wg config..")
|
||||
if not profile.has_wireguard_configuration():
|
||||
logger.info(f"[CONNECTION] Profile does NOT have WG keys and it needs it. Registering a NEW wg session..")
|
||||
register_wireguard_session(profile, connection_observer=connection_observer)
|
||||
registry_result = register_wireguard_session(profile, connection_observer=connection_observer)
|
||||
|
||||
|
||||
def _establish_with_renegotiation(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from core.infrastructure.thread_dispatch import MainThreadDispatcher
|
||||
from core.services.subscriptions.subscriptions_by_protocol import check_paid
|
||||
from core.services.subscriptions.subscriptions_by_protocol import check_paid, mark_as_paid
|
||||
|
||||
from core.controllers.tickets.TicketPayController import check_if_ticket_paid
|
||||
|
||||
|
|
@ -24,13 +24,13 @@ MAX_FAILED_CONNECTIONS = 8
|
|||
class CheckPaidTimer:
|
||||
_instance = None # CLASS VARIABLE - survives across __init__ calls
|
||||
|
||||
def __new__(cls, view_callback: Callable, billing_code: str, ui_dispatcher: MainThreadDispatcher, payment_type: PaymentType, connection_observer: ConnectionObserver):
|
||||
def __new__(cls, view_callback: Callable, billing_code: str, ui_dispatcher: MainThreadDispatcher, payment_type: PaymentType, connection_observer: ConnectionObserver, profile_id: int):
|
||||
"""Called before __init__ — controls instance creation"""
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self, view_callback: Callable, billing_code: str, ui_dispatcher: MainThreadDispatcher, payment_type: PaymentType, connection_observer: ConnectionObserver):
|
||||
def __init__(self, view_callback: Callable, billing_code: str, ui_dispatcher: MainThreadDispatcher, payment_type: PaymentType, connection_observer: ConnectionObserver, profile_id: int):
|
||||
# Guard: makes sure this entire class only runs once
|
||||
if hasattr(self, '_initialized'):
|
||||
return
|
||||
|
|
@ -42,6 +42,7 @@ class CheckPaidTimer:
|
|||
self.view_callback = view_callback
|
||||
self.ui_dispatcher = ui_dispatcher
|
||||
self.billing_code = billing_code
|
||||
self.profile_id = profile_id
|
||||
self.connection_observer = connection_observer
|
||||
self.payment_type = payment_type
|
||||
self.failed_connections = 0
|
||||
|
|
@ -99,7 +100,15 @@ class CheckPaidTimer:
|
|||
if result.valid:
|
||||
print("PAID! Stopping timer")
|
||||
self.stop_polling()
|
||||
message = "paid"
|
||||
|
||||
# SAVE:
|
||||
marked = mark_as_paid(profile_id=self.profile_id)
|
||||
if not marked.valid:
|
||||
message = marked.message
|
||||
else:
|
||||
message = "Paid! This invoice is paid"
|
||||
|
||||
# UPDATE UI:
|
||||
self.view_callback(paid=True, stopped=True, message=message)
|
||||
|
||||
# not yet paid:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from core.models.pydantic_models.ServerReply import ServerReply, ServerError, Su
|
|||
from core.models.Subscription import Subscription
|
||||
from core.Constants import Constants
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Result:
|
||||
"""Evaluates Payment Status from the Server"""
|
||||
|
|
@ -17,7 +18,6 @@ def check_paid(billing_code: str, connection_observer: ConnectionObserver) -> Re
|
|||
"billing_code": billing_code
|
||||
}
|
||||
url = f'{Constants.SP_BASE_URL}/v2/check_paid'
|
||||
print(f"url is {url}")
|
||||
|
||||
api_response = connect.single_endpoint(
|
||||
method="post",
|
||||
|
|
@ -162,7 +162,24 @@ def get_profile_subscription(profile_id: int) -> Subscription:
|
|||
return profile.subscription
|
||||
|
||||
|
||||
def save_billing_code(profile_id: int, billing_code: str, expires_at: str) -> Result:
|
||||
def mark_as_paid(profile_id: int) -> Result:
|
||||
"""Conclude the payment phase, by marking the sub as paid"""
|
||||
|
||||
logger.info("Marking as paid..")
|
||||
|
||||
# Get profile object:
|
||||
profile = Profile.find_by_id(profile_id)
|
||||
if not profile:
|
||||
error_msg = f"Invalid profile id of {profile_id}"
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||
|
||||
profile.subscription.billing_pending = False
|
||||
profile.save()
|
||||
return Result(valid=True)
|
||||
|
||||
|
||||
def save_billing_code(profile_id: int, billing_code: str, expires_at: datetime) -> Result:
|
||||
"""Checks if the billing code is already saved, and if not, saves it."""
|
||||
|
||||
logger.info("Saving billing code..")
|
||||
|
|
@ -187,32 +204,32 @@ def save_billing_code(profile_id: int, billing_code: str, expires_at: str) -> Re
|
|||
billing_pending=True
|
||||
)
|
||||
profile.save()
|
||||
return Result(valid=True)
|
||||
except Exception as e:
|
||||
error_msg = f"Legacy system wouldn't create or save Subscription object with {str(billing_code)} and {str(expires_at)} or type {type(expires_at)}, with error: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
return Result(valid=False, message=error_msg, error_type=ResultError.INVALID_INPUT)
|
||||
|
||||
return Result(valid=True)
|
||||
|
||||
|
||||
# # get the payment data singleton:
|
||||
# billing_data = PaymentData(instance_id=profile_id)
|
||||
# # get the payment data singleton:
|
||||
# billing_data = PaymentData(instance_id=profile_id)
|
||||
|
||||
# # new
|
||||
# if billing_data.billing_code is None:
|
||||
# billing_data.billing_code = billing_code
|
||||
# billing_data.save()
|
||||
# logger.info("saved billing_code")
|
||||
# return Result(valid=True)
|
||||
# # new
|
||||
# if billing_data.billing_code is None:
|
||||
# billing_data.billing_code = billing_code
|
||||
# billing_data.save()
|
||||
# logger.info("saved billing_code")
|
||||
# return Result(valid=True)
|
||||
|
||||
# # Already exists and is different:
|
||||
# if regular_billing.billing_code != billing_code:
|
||||
# error_msg = "Critical Error! Billing codes do NOT match"
|
||||
# logger.error(error_msg)
|
||||
# return Result(valid=False, error_type=ResultError.UNKNOWN, message=error_msg)
|
||||
# # Already exists and is different:
|
||||
# if regular_billing.billing_code != billing_code:
|
||||
# error_msg = "Critical Error! Billing codes do NOT match"
|
||||
# logger.error(error_msg)
|
||||
# return Result(valid=False, error_type=ResultError.UNKNOWN, message=error_msg)
|
||||
|
||||
# # already saved:
|
||||
# return Result(valid=True, message="Already saved.")
|
||||
# # already saved:
|
||||
# return Result(valid=True, message="Already saved.")
|
||||
|
||||
|
||||
def return_pre_existing_payment_data(profile_id: int, subscription: SubscriptionInvoice) -> Result:
|
||||
|
|
|
|||
Loading…
Reference in a new issue