fix payment
This commit is contained in:
+38
-15
@@ -1,7 +1,11 @@
|
||||
"""Heleket payment integration."""
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
import aiohttp
|
||||
|
||||
from config.settings import settings
|
||||
@@ -9,6 +13,12 @@ from config.settings import settings
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _make_sign(body_bytes: bytes, api_key: str) -> str:
|
||||
"""Генерирует подпись запроса: md5(base64(body) + api_key)."""
|
||||
b64 = base64.b64encode(body_bytes).decode("utf-8")
|
||||
return hashlib.md5((b64 + api_key).encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
class HelketPayment:
|
||||
"""Heleket payment gateway. Принимает сумму в рублях напрямую."""
|
||||
|
||||
@@ -19,6 +29,21 @@ class HelketPayment:
|
||||
self.shop_id = settings.HELEKET_SHOP_ID
|
||||
self._mock = not (self.api_key and self.shop_id)
|
||||
|
||||
def _post_headers(self, body_bytes: bytes) -> dict:
|
||||
"""Заголовки для POST-запроса с подписью."""
|
||||
return {
|
||||
"merchant": self.api_key,
|
||||
"sign": _make_sign(body_bytes, self.api_key),
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def _get_headers(self) -> dict:
|
||||
"""Заголовки для GET-запроса (тело пустое)."""
|
||||
return {
|
||||
"merchant": self.api_key,
|
||||
"sign": _make_sign(b"", self.api_key),
|
||||
}
|
||||
|
||||
async def create_invoice(self, amount_rub: int, order_id: str) -> Optional[dict]:
|
||||
"""
|
||||
Создаёт счёт на сумму в рублях.
|
||||
@@ -32,21 +57,20 @@ class HelketPayment:
|
||||
"mock": True,
|
||||
}
|
||||
|
||||
payload = {
|
||||
"amount": str(amount_rub),
|
||||
"currency": "RUB",
|
||||
"order_id": order_id,
|
||||
"url_callback": settings.HELEKET_WEBHOOK_URL,
|
||||
}
|
||||
body = json.dumps(payload, separators=(",", ":")).encode("utf-8")
|
||||
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
payload = {
|
||||
"shop_id": self.shop_id,
|
||||
"amount": str(amount_rub),
|
||||
"currency": "RUB",
|
||||
"order_id": order_id,
|
||||
"url_return": "",
|
||||
"url_callback": "",
|
||||
}
|
||||
headers = {"merchant": self.api_key, "Content-Type": "application/json"}
|
||||
async with session.post(
|
||||
f"{self.BASE_URL}/payment",
|
||||
json=payload,
|
||||
headers=headers,
|
||||
data=body,
|
||||
headers=self._post_headers(body),
|
||||
timeout=aiohttp.ClientTimeout(total=15),
|
||||
) as resp:
|
||||
data = await resp.json()
|
||||
@@ -70,18 +94,17 @@ class HelketPayment:
|
||||
return "pending"
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
headers = {"merchant": self.api_key}
|
||||
async with session.get(
|
||||
f"{self.BASE_URL}/payment/info/{payment_id}",
|
||||
headers=headers,
|
||||
headers=self._get_headers(),
|
||||
timeout=aiohttp.ClientTimeout(total=15),
|
||||
) as resp:
|
||||
data = await resp.json()
|
||||
if data.get("state") == 0:
|
||||
status = data.get("result", {}).get("status", "")
|
||||
if status == "paid":
|
||||
if status in ("paid", "paid_over"):
|
||||
return "paid"
|
||||
if status in ("cancel", "expired"):
|
||||
if status in ("cancel", "expired", "fail", "wrong_amount"):
|
||||
return "expired"
|
||||
return "pending"
|
||||
return "error"
|
||||
|
||||
Reference in New Issue
Block a user