Merge pull request #9 from machka-pasla/codex/update-payment-methods-variables-and-readme.md

Add payment method toggles and new pricing variables
This commit is contained in:
Machka Pasla
2025-06-24 01:18:49 +03:00
committed by GitHub
5 changed files with 60 additions and 36 deletions
+20 -10
View File
@@ -31,20 +31,30 @@ YOOKASSA_PAYMENT_SUBJECT=payment
# If unset, bot will use polling while YooKassa uses webhooks. # If unset, bot will use polling while YooKassa uses webhooks.
TELEGRAM_WEBHOOK_BASE_URL=https://webhooks.yourdomain.tld TELEGRAM_WEBHOOK_BASE_URL=https://webhooks.yourdomain.tld
# Subscription Prices (integer values) # Payment Methods
PRICE_1_MONTH=150 YOOKASSA_ENABLED=True
PRICE_3_MONTHS=300 STARS_ENABLED=True
PRICE_6_MONTHS=500 TRIBUTE_ENABLED=True
PRICE_12_MONTHS=900
# Telegram Stars Prices (integer values) # Subscription Options
1_MONTH_ENABLED=True
RUB_PRICE_1_MONTH=150
STARS_PRICE_1_MONTH=0 STARS_PRICE_1_MONTH=0
STARS_PRICE_3_MONTHS=0
STARS_PRICE_6_MONTHS=0
STARS_PRICE_12_MONTHS=0
# Tribute Payment Links
TRIBUTE_LINK_1_MONTH= TRIBUTE_LINK_1_MONTH=
3_MONTHS_ENABLED=True
RUB_PRICE_3_MONTHS=300
STARS_PRICE_3_MONTHS=0
TRIBUTE_LINK_3_MONTHS= TRIBUTE_LINK_3_MONTHS=
6_MONTHS_ENABLED=True
RUB_PRICE_6_MONTHS=500
STARS_PRICE_6_MONTHS=0
TRIBUTE_LINK_6_MONTHS= TRIBUTE_LINK_6_MONTHS=
12_MONTHS_ENABLED=True
RUB_PRICE_12_MONTHS=900
STARS_PRICE_12_MONTHS=0
TRIBUTE_LINK_12_MONTHS= TRIBUTE_LINK_12_MONTHS=
# API key for verifying Tribute webhook signatures # API key for verifying Tribute webhook signatures
TRIBUTE_API_KEY= TRIBUTE_API_KEY=
+4 -1
View File
@@ -93,7 +93,10 @@ This Telegram bot is designed to automate the sale and management of subscriptio
* `YOOKASSA_PAYMENT_MODE`: e.g., `full_prepayment`. * `YOOKASSA_PAYMENT_MODE`: e.g., `full_prepayment`.
* `YOOKASSA_PAYMENT_SUBJECT`: e.g., `service`. * `YOOKASSA_PAYMENT_SUBJECT`: e.g., `service`.
* `TELEGRAM_WEBHOOK_BASE_URL`: (Optional) If you want Telegram updates via webhook. Can be the same as `YOOKASSA_WEBHOOK_BASE_URL`. If not set, the bot will use polling for Telegram updates. * `TELEGRAM_WEBHOOK_BASE_URL`: (Optional) If you want Telegram updates via webhook. Can be the same as `YOOKASSA_WEBHOOK_BASE_URL`. If not set, the bot will use polling for Telegram updates.
* `PRICE_X_MONTH`: Prices for different subscription durations. * **Payment Method Toggles:** `YOOKASSA_ENABLED`, `STARS_ENABLED`, `TRIBUTE_ENABLED`.
* **Subscription Options:** For each duration you can use variables like
`1_MONTH_ENABLED`, `RUB_PRICE_1_MONTH`, `STARS_PRICE_1_MONTH`, `TRIBUTE_LINK_1_MONTH`
(and corresponding variables for `3_MONTHS`, `6_MONTHS`, `12_MONTHS`).
* **Panel API Settings:** * **Panel API Settings:**
* `PANEL_API_URL`: Full URL to your Remnawave panel's API (e.g., `http://localhost:3000/api` or `https://panel.yourdomain.com/api`). * `PANEL_API_URL`: Full URL to your Remnawave panel's API (e.g., `http://localhost:3000/api` or `https://panel.yourdomain.com/api`).
* `PANEL_API_KEY`: API Key for authenticating with the Remnawave panel. * `PANEL_API_KEY`: API Key for authenticating with the Remnawave panel.
+1
View File
@@ -111,6 +111,7 @@ async def select_subscription_period_callback_handler(
currency_symbol_val, currency_symbol_val,
current_lang, current_lang,
i18n, i18n,
settings,
) )
try: try:
+6 -5
View File
@@ -112,16 +112,17 @@ def get_payment_method_keyboard(months: int, price: float,
tribute_url: Optional[str], tribute_url: Optional[str],
stars_price: Optional[int], stars_price: Optional[int],
currency_symbol_val: str, lang: str, currency_symbol_val: str, lang: str,
i18n_instance) -> InlineKeyboardMarkup: i18n_instance, settings: Settings) -> InlineKeyboardMarkup:
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs) _ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
if stars_price is not None: if settings.STARS_ENABLED and stars_price is not None:
builder.button(text=_("pay_with_stars_button"), builder.button(text=_("pay_with_stars_button"),
callback_data=f"pay_stars:{months}:{stars_price}") callback_data=f"pay_stars:{months}:{stars_price}")
if tribute_url: if settings.TRIBUTE_ENABLED and tribute_url:
builder.button(text=_("pay_with_tribute_button"), url=tribute_url) builder.button(text=_("pay_with_tribute_button"), url=tribute_url)
builder.button(text=_("pay_with_yookassa_button"), if settings.YOOKASSA_ENABLED:
callback_data=f"pay_yk:{months}:{price}") builder.button(text=_("pay_with_yookassa_button"),
callback_data=f"pay_yk:{months}:{price}")
builder.button(text=_(key="cancel_button"), builder.button(text=_(key="cancel_button"),
callback_data="main_action:subscribe") callback_data="main_action:subscribe")
builder.adjust(1) builder.adjust(1)
+29 -20
View File
@@ -36,10 +36,19 @@ class Settings(BaseSettings):
TELEGRAM_WEBHOOK_BASE_URL: Optional[str] = None TELEGRAM_WEBHOOK_BASE_URL: Optional[str] = None
PRICE_1_MONTH: Optional[int] = Field(default=None) YOOKASSA_ENABLED: bool = Field(default=True)
PRICE_3_MONTHS: Optional[int] = Field(default=None) STARS_ENABLED: bool = Field(default=True)
PRICE_6_MONTHS: Optional[int] = Field(default=None) TRIBUTE_ENABLED: bool = Field(default=True)
PRICE_12_MONTHS: Optional[int] = Field(default=None)
MONTH_1_ENABLED: bool = Field(default=True, alias="1_MONTH_ENABLED")
MONTH_3_ENABLED: bool = Field(default=True, alias="3_MONTHS_ENABLED")
MONTH_6_ENABLED: bool = Field(default=True, alias="6_MONTHS_ENABLED")
MONTH_12_ENABLED: bool = Field(default=True, alias="12_MONTHS_ENABLED")
RUB_PRICE_1_MONTH: Optional[int] = Field(default=None)
RUB_PRICE_3_MONTHS: Optional[int] = Field(default=None)
RUB_PRICE_6_MONTHS: Optional[int] = Field(default=None)
RUB_PRICE_12_MONTHS: Optional[int] = Field(default=None)
STARS_PRICE_1_MONTH: Optional[int] = Field(default=None) STARS_PRICE_1_MONTH: Optional[int] = Field(default=None)
STARS_PRICE_3_MONTHS: Optional[int] = Field(default=None) STARS_PRICE_3_MONTHS: Optional[int] = Field(default=None)
@@ -170,27 +179,27 @@ class Settings(BaseSettings):
def subscription_options(self) -> Dict[int, float]: def subscription_options(self) -> Dict[int, float]:
options: Dict[int, float] = {} options: Dict[int, float] = {}
if self.PRICE_1_MONTH is not None: if self.MONTH_1_ENABLED and self.RUB_PRICE_1_MONTH is not None:
options[1] = float(self.PRICE_1_MONTH) options[1] = float(self.RUB_PRICE_1_MONTH)
if self.PRICE_3_MONTHS is not None: if self.MONTH_3_ENABLED and self.RUB_PRICE_3_MONTHS is not None:
options[3] = float(self.PRICE_3_MONTHS) options[3] = float(self.RUB_PRICE_3_MONTHS)
if self.PRICE_6_MONTHS is not None: if self.MONTH_6_ENABLED and self.RUB_PRICE_6_MONTHS is not None:
options[6] = float(self.PRICE_6_MONTHS) options[6] = float(self.RUB_PRICE_6_MONTHS)
if self.PRICE_12_MONTHS is not None: if self.MONTH_12_ENABLED and self.RUB_PRICE_12_MONTHS is not None:
options[12] = float(self.PRICE_12_MONTHS) options[12] = float(self.RUB_PRICE_12_MONTHS)
return options return options
@computed_field @computed_field
@property @property
def stars_subscription_options(self) -> Dict[int, int]: def stars_subscription_options(self) -> Dict[int, int]:
options: Dict[int, int] = {} options: Dict[int, int] = {}
if self.STARS_PRICE_1_MONTH is not None: if self.STARS_ENABLED and self.MONTH_1_ENABLED and self.STARS_PRICE_1_MONTH is not None:
options[1] = self.STARS_PRICE_1_MONTH options[1] = self.STARS_PRICE_1_MONTH
if self.STARS_PRICE_3_MONTHS is not None: if self.STARS_ENABLED and self.MONTH_3_ENABLED and self.STARS_PRICE_3_MONTHS is not None:
options[3] = self.STARS_PRICE_3_MONTHS options[3] = self.STARS_PRICE_3_MONTHS
if self.STARS_PRICE_6_MONTHS is not None: if self.STARS_ENABLED and self.MONTH_6_ENABLED and self.STARS_PRICE_6_MONTHS is not None:
options[6] = self.STARS_PRICE_6_MONTHS options[6] = self.STARS_PRICE_6_MONTHS
if self.STARS_PRICE_12_MONTHS is not None: if self.STARS_ENABLED and self.MONTH_12_ENABLED and self.STARS_PRICE_12_MONTHS is not None:
options[12] = self.STARS_PRICE_12_MONTHS options[12] = self.STARS_PRICE_12_MONTHS
return options return options
@@ -198,13 +207,13 @@ class Settings(BaseSettings):
@property @property
def tribute_payment_links(self) -> Dict[int, str]: def tribute_payment_links(self) -> Dict[int, str]:
links: Dict[int, str] = {} links: Dict[int, str] = {}
if self.TRIBUTE_LINK_1_MONTH: if self.TRIBUTE_ENABLED and self.MONTH_1_ENABLED and self.TRIBUTE_LINK_1_MONTH:
links[1] = self.TRIBUTE_LINK_1_MONTH links[1] = self.TRIBUTE_LINK_1_MONTH
if self.TRIBUTE_LINK_3_MONTHS: if self.TRIBUTE_ENABLED and self.MONTH_3_ENABLED and self.TRIBUTE_LINK_3_MONTHS:
links[3] = self.TRIBUTE_LINK_3_MONTHS links[3] = self.TRIBUTE_LINK_3_MONTHS
if self.TRIBUTE_LINK_6_MONTHS: if self.TRIBUTE_ENABLED and self.MONTH_6_ENABLED and self.TRIBUTE_LINK_6_MONTHS:
links[6] = self.TRIBUTE_LINK_6_MONTHS links[6] = self.TRIBUTE_LINK_6_MONTHS
if self.TRIBUTE_LINK_12_MONTHS: if self.TRIBUTE_ENABLED and self.MONTH_12_ENABLED and self.TRIBUTE_LINK_12_MONTHS:
links[12] = self.TRIBUTE_LINK_12_MONTHS links[12] = self.TRIBUTE_LINK_12_MONTHS
return links return links