Загрузка...

Script
FreeKassa SBP

Thread in Python created by Эксфадор Dec 5, 2025. (bumped Jan 23, 2026) 710 views

  1. Эксфадор
    Костыли - костыльные

    Python
    import time
    import hmac
    import hashlib
    from dataclasses import dataclass
    from urllib.parse import urlencode

    import requests


    @dataclass
    class FreeKassaConfig:
    api_url: str = "https://api.freekassa.com/v1/"
    shop_id: int =
    api_key: str = ""
    secret_word_1: str = ""
    secret_word_2: str = ""
    amount: int = 10
    currency: str = "RUB"
    payment_system_id: int = 44 # сбп - 44 # карты - 36 # сбер пэй - 43
    client_email: str = "fgdfggfgg@mail.ru"
    client_ip: str = "127.0.0.1" # при 44 , нельзя указывать 127.0.0.1, лишь ip сервера или 2ip.ru
    poll_interval_seconds: int = 10
    max_poll_minutes: int = 10


    class FreeKassaClient:
    def __init__(self, config: FreeKassaConfig | None = None) -> None:
    self.config = config or FreeKassaConfig()

    def make_signature(self, data: dict) -> str:
    data = {k: v for k, v in data.items() if v is not None}
    sorted_items = sorted(data.items())
    message = "|".join(str(v) for _, v in sorted_items)
    sign = hmac.new(
    self.config.api_key.encode("utf-8"),
    message.encode("utf-8"),
    hashlib.sha256,
    ).hexdigest()
    return sign

    def api_request(self, route: str, payload: dict) -> dict:
    payload = {k: v for k, v in payload.items() if v is not None}
    payload["shopId"] = self.config.shop_id
    payload["nonce"] = time.time_ns()
    payload["signature"] = self.make_signature(payload)

    debug_payload = {k: v for k, v in payload.items() if k != "signature"}
    print(f"Отправляем запрос {route} с данными (без signature):")
    print(debug_payload)

    response = requests.post(self.config.api_url + route, json=payload, timeout=10)

    if response.status_code == 401:
    raise RuntimeError(f"FreeKassaAuthError: {response.text}")
    if response.status_code == 400:
    raise RuntimeError(f"FreeKassaError: {response.text}")
    if response.status_code != 200:
    raise RuntimeError(
    f"HTTP error {response.status_code} for {route}: {response.text}"
    )

    data = response.json()
    print(f"Ответ API {route}:", data)
    return data

    def make_sci_link(self, payment_id: str) -> str:
    amount_str = f"{self.config.amount:.2f}".replace(",", ".")
    sign_str = (
    f"{self.config.shop_id}:"
    f"{amount_str}:"
    f"{self.config.secret_word_1}:"
    f"{self.config.currency}:"
    f"{payment_id}"
    )
    md5_hash = hashlib.md5(sign_str.encode("utf-8")).hexdigest()

    params = {
    "m": self.config.shop_id,
    "oa": amount_str,
    "currency": self.config.currency,
    "o": payment_id,
    "s": md5_hash,
    "i": self.config.payment_system_id,
    "em": self.config.client_email,
    }
    return "https://pay.fk.money/?" + urlencode(params)

    def create_order(self, payment_id: str) -> dict:
    params = {
    "paymentId": payment_id,
    "amount": self.config.amount,
    "currency": self.config.currency,
    "email": self.config.client_email,
    "ip": self.config.client_ip,
    "i": self.config.payment_system_id,
    }

    data = self.api_request("orders/create", params)

    if data.get("type") != "success":
    raise RuntimeError(f"Ошибка при создании заказа: {data}")

    return data

    def get_order_status(self, payment_id: str, fk_order_id: int | None = None) -> int | None:
    params = {
    "orderId": fk_order_id,
    "paymentId": payment_id,
    }

    data = self.api_request("orders", params)

    if data.get("type") != "success":
    print("Ошибка при получении статуса заказа:", data)
    return None

    orders = data.get("orders") or []
    if not orders:
    print("API /orders не вернул ни одного заказа по заданным фильтрам.")
    return None

    order = orders[0]

    status = order.get("orderStatus")
    if status is None:
    status = order.get("status")
    if status is None:
    status = order.get("order_status")

    if status is None:
    print("Не удалось определить поле статуса в заказе. Полный объект заказа:")
    print(order)

    return status


    class OrderPoller:
    def __init__(self, client: FreeKassaClient) -> None:
    self.client = client

    def poll_status(self, payment_id: str, fk_order_id: int | None = None) -> None:
    print("Начинаю опрос статуса заказа...")
    start_time = time.time()

    while True:
    status = self.client.get_order_status(payment_id, fk_order_id)
    elapsed_min = int((time.time() - start_time) / 60)

    print(f"[{elapsed_min} мин] Статус заказа: {status}")

    if status == 1:
    print(" Оплата прошла (статус = 1).")
    break
    elif status in (6, 8, 9):
    print(" Платёж неуспешен (возврат/ошибка/отмена).")
    break

    if elapsed_min >= self.client.config.max_poll_minutes:
    print(" Время ожидания истекло, прекращаю опрос.")
    break

    time.sleep(self.client.config.poll_interval_seconds)


    def main() -> None:
    client = FreeKassaClient()

    payment_id = str(int(time.time()))
    print(
    f"Создаём заказ на {client.config.amount} "
    f"{client.config.currency} с paymentId={payment_id}..."
    )

    order_data = client.create_order(payment_id)
    pay_url = order_data.get("location") or order_data.get("Location")
    fk_order_id = order_data.get("orderId")

    print(f"Номер заказа FreeKassa (orderId): {fk_order_id}")
    print("Ссылка на оплату (передайте её клиенту):")
    print(pay_url)

    poller = OrderPoller(client)
    poller.poll_status(payment_id, fk_order_id)


    if __name__ == "__main__":
    main()
     
  2. protect
    там вебхуки есть
     
  3. MRAZLZT
    MRAZLZT Jan 5, 2026 Telegram моя жизнь 47 Oct 9, 2023
    Ну хуже еще ничего не видел :hmm:
     
  4. 123bw
    123bw Jan 9, 2026 6 Nov 29, 2020
    import time
    import hmac
    import hashlib
    from dataclasses import dataclass
    from typing import Optional

    from urllib.parse import urlencode

    import aiohttp


    class FreeKassaError(Exception):
    pass


    class FreeKassaAuthError(FreeKassaError):
    pass


    class FreeKassaAPIError(FreeKassaError):
    pass


    class FreeKassaTimeoutError(FreeKassaError):
    pass


    @dataclass(slots=True)
    class FreeKassaConfig:
    api_url: str = "
    shop_id: int = 0
    api_key: str = ""
    secret_word_1: str = ""
    secret_word_2: str = ""
    amount: float = 10.0
    currency: str = "RUB"
    payment_system_id: int = 44
    client_email: str = "test@mail.ru"
    client_ip: str = "1.1.1.1"
    poll_interval_seconds: int = 10
    max_poll_minutes: int = 10


    class FreeKassaClient:
    def __init__(self, config: Optional[FreeKassaConfig] = None) -> None:
    self.config = config or FreeKassaConfig()
    self.session: Optional[aiohttp.ClientSession] = None

    async def __aenter__(self) -> "FreeKassaClient":
    self.session = aiohttp.ClientSession()
    return self

    async def __aexit__(self, *_: object) -> None:
    if self.session:
    await self.session.close()

    def _signature(self, payload: dict) -> str:
    message = "|".join(str(v) for _, v in sorted(payload.items()))
    return (
    self.config.api_key.encode(),
    message.encode(),
    hashlib.sha256,
    ).hexdigest()

    async def _request(self, route: str, payload: dict) -> dict:
    if not self.session:
    raise RuntimeError("Session not initialized")

    payload = {k: v for k, v in payload.items() if v is not None}
    payload.update(
    shopId=self.config.shop_id,
    nonce=time.time_ns(),
    )
    payload["signature"] = self._signature(payload)

    try:
    async with (
    self.config.api_url + route,
    json=payload,
    timeout=aiohttp.ClientTimeout(total=10),
    ) as response:
    text = await response.text()

    if response.status == 401:
    raise FreeKassaAuthError(text)
    if response.status != 200:
    raise FreeKassaAPIError(text)

    return await response.json()

    except aiohttp.ClientError as exc:
    raise FreeKassaTimeoutError(str(exc)) from exc

    async def create_order(self, payment_id: str) -> dict:
    data = await self._request(
    "orders/create",
    {
    "paymentId": payment_id,
    "amount": self.config.amount,
    "currency": self.config.currency,
    "email": self.config.client_email,
    "ip": self.config.client_ip,
    "i": self.config.payment_system_id,
    },
    )

    if data.get("type") != "success":
    raise FreeKassaAPIError(data)

    return data

    async def order_status(
    self,
    payment_id: str,
    order_id: Optional[int],
    ) -> Optional[int]:
    data = await self._request(
    "orders",
    {
    "paymentId": payment_id,
    "orderId": order_id,
    },
    )

    if data.get("type") != "success":
    return None

    orders = data.get("orders") or []
    if not orders:
    return None

    order = orders[0]
    return (
    order.get("orderStatus")
    or order.get("status")
    or order.get("order_status")
    )

    def sci_link(self, payment_id: str) -> str:
    amount = f"{self.config.amount:.2f}"
    sign = hashlib.md5(
    f"{self.config.shop_id}:{amount}:{self.config.secret_word_1}:{self.config.currency}:{payment_id}".encode()
    ).hexdigest()

    return " + urlencode(
    {
    "m": self.config.shop_id,
    "oa": amount,
    "currency": self.config.currency,
    "o": payment_id,
    "s": sign,
    "i": self.config.payment_system_id,
    "em": self.config.client_email,
    }
    )


    class OrderPoller:
    SUCCESS_STATUS = 1
    FAIL_STATUSES = {6, 8, 9}

    def __init__(self, client: FreeKassaClient) -> None:
    self.client = client

    async def poll(
    self,
    payment_id: str,
    order_id: Optional[int],
    ) -> None:
    deadline = time.time() + self.client.config.max_poll_minutes * 60

    while time.time() < deadline:
    status = await self.client.order_status(payment_id, order_id)

    if status == self.SUCCESS_STATUS:
    print("Оплата прошла")
    return

    if status in self.FAIL_STATUSES:
    print("Платёж неуспешен")
    return

    await aiohttp.helpers.sleep(
    self.client.config.poll_interval_seconds
    )

    print("Ожидание истекло")


    async def main() -> None:
    payment_id = str(int(time.time()))

    async with FreeKassaClient() as client:
    order = await client.create_order(payment_id)

    order_id = order.get("orderId")
    pay_url = order.get("location") or order.get("Location")

    print(pay_url)

    poller = OrderPoller(client)
    await poller.poll(payment_id, order_id)


    if __name__ == "__main__":
    import asyncio

    (main())
     
    1. FL_Jargonium
      avatar123bw, засунь его в блок кода
Loading...