A minimal MonCash client in Python (Django) with token caching
poze a month ago344 gadeen
0
I'd rather not depend on an unmaintained package. What does a small, correct MonCash client look like in Python for a Django project?
Anviwònman:Django 5.1Python 3.12
Dyagnostik IA
Se IA ki fè l. Se pa yon repons — kominote a anba a konfime oswa korije l. Toujou verifye anvan ou fye l.
1 Repons
4
✓✓ Repons yo aksepte
A small client is ~40 lines, and you'll understand every one of them. That matters when money is involved.
# payments/moncash.py
import time
import requests
from django.conf import settings
class MonCash:
def __init__(self):
self.api = settings.MONCASH_API # sandbox or live
self.gateway = settings.MONCASH_GATEWAY
self._token = None
self._expires_at = 0.0
self.http = requests.Session()
def _token_value(self) -> str:
if self._token and time.time() < self._expires_at - 10:
return self._token
r = self.http.post(
f"{self.api}/oauth/token",
auth=(settings.MONCASH_CLIENT_ID, settings.MONCASH_CLIENT_SECRET), # HTTP Basic
data={"scope": "read,write", "grant_type": "client_credentials"}, # form-encoded
headers={"Accept": "application/json"},
timeout=15,
)
r.raise_for_status()
body = r.json()
self._token, self._expires_at = body["access_token"], time.time() + body["expires_in"]
return self._token
def _post(self, path: str, payload: dict) -> dict:
r = self.http.post(f"{self.api}{path}", json=payload, timeout=20,
headers={"Authorization": f"Bearer {self._token_value()}"})
if r.status_code == 401: # token expired between check and call
self._token = None
return self._post(path, payload)
r.raise_for_status()
return r.json()
def create_payment(self, order_id: str, amount: int) -> str:
token = self._post("/v1/CreatePayment", {"amount": amount, "orderId": order_id})["payment_token"]["token"]
return f"{self.gateway}/Payment/Redirect?token={token}"
def transaction(self, transaction_id: str) -> dict | None:
return self._post("/v1/RetrieveTransactionPayment", {"transactionId": transaction_id}).get("payment")
def order(self, order_id: str) -> dict | None:
return self._post("/v1/RetrieveOrderPayment", {"orderId": order_id}).get("payment")
moncash = MonCash()
Always set timeouts. A requests call without one can hang a worker forever when the network is unstable. And note the 401 retry above only retries once, because the recursive call gets a fresh token.
Konekte pou di lòt moun si li te mache.
answered a month ago
Marie Louis 2.2k
Sign in and verify your email to post an answer.