feat: implement subscription management and billing enhancements

This commit is contained in:
2026-04-29 20:10:26 +07:00
parent 120e19e667
commit db2dabed58
12 changed files with 223 additions and 28 deletions

View File

@@ -220,6 +220,10 @@ class BaseService:
class BillService(BaseService):
"""Service to handle all Bill-related operations."""
def __init__(self, session: aiohttp.ClientSession, payer_pays_commission: bool | None = None):
super().__init__(session)
self._payer_pays_commission = payer_pays_commission
async def create(
self,
amount: float,
@@ -229,9 +233,25 @@ class BillService(BaseService):
bill_type: BillType = BillType.NORMAL,
currency_in: Currency | None = None,
ttl: int | None = None,
payer_pays_commission: bool | None = None,
**kwargs: Any,
) -> BillCreateResponse:
"""Creates a new bill for payment."""
"""
Creates a new bill for payment.
Args:
amount: The payment amount.
shop_id: Unique shop identifier.
payer_pays_commission: If True, the payer pays the commission.
Overrides the client-level default.
"""
# Определяем итоговое значение: переданное в метод или значение по умолчанию из сервиса
final_ppc = (
payer_pays_commission
if payer_pays_commission is not None
else self._payer_pays_commission
)
payload = {
"amount": amount,
"shop_id": shop_id,
@@ -240,6 +260,7 @@ class BillService(BaseService):
"type": bill_type.value,
"currency_in": currency_in.value if currency_in else None,
"ttl": ttl,
"payer_pays_commission": int(final_ppc) if final_ppc is not None else None,
**kwargs,
}
return await self._post("bill/create", payload, BillCreateResponse)
@@ -326,28 +347,34 @@ class PallyClient:
Main asynchronous client for the Pally API.
Usage:
async with PallyClient(api_token="your_token") as client:
balance = await client.balance.get()
print(balance)
async with PallyClient(api_token="your_token", payer_pays_commission=True) as client:
bill = await client.bills.create(amount=100.0, shop_id="my_shop")
print(bill.link_url)
"""
def __init__(self, api_token: str, base_url: str = "https://pal24.pro/api/v1/"):
def __init__(
self,
api_token: str,
base_url: str = "https://pal24.pro/api/v1/",
payer_pays_commission: bool | None = None,
):
"""
Initializes the Pally API client.
Args:
api_token (str): The bearer token provided by Pally.
base_url (str): The base URL for the API.
payer_pays_commission (bool, optional): Global default for whether the payer pays the commission.
"""
self.api_token = api_token
self.base_url = base_url
self.payer_pays_commission = payer_pays_commission
self._session: aiohttp.ClientSession | None = None
@property
def session(self) -> aiohttp.ClientSession:
"""
Lazy-loads the aiohttp ClientSession.
This prevents creating a session outside of the asyncio event loop.
"""
if self._session is None or self._session.closed:
headers = {"Authorization": f"Bearer {self.api_token}", "Accept": "application/json"}
@@ -357,10 +384,10 @@ class PallyClient:
)
return self._session
# Using properties ensures that services always receive the active session context
@property
def bills(self) -> BillService:
return BillService(self.session)
# Передаем параметр плательщика комиссии в сервис счетов
return BillService(self.session, self.payer_pays_commission)
@property
def payments(self) -> PaymentService:
@@ -376,8 +403,6 @@ class PallyClient:
await self._session.close()
async def __aenter__(self) -> "PallyClient":
# Accessing the property ensures the session is instantiated
# properly within the async context block.
_ = self.session
return self