The SDK ships with pytest and a FakeTransport you can borrow for your own tests.
make test # pytest -q — 54 tests
pytest tests/test_signature.py # one file
pytest -k webhook # by keywordCoverage at a glance:
test_signature.py— formula, empty-body collapse, cross-language parity vectortest_status.py— enum coverage includingUNKNOWNfallbacktest_config.py— defaults + validationtest_payment.py/test_payout.py— FakeTransport-driventest_webhook.py— includes the PHP-style payload regression testtest_transport.py— spins up a real loopbackhttp.server
from heleket_sdk import HeleketPayment, ClientOptions
from heleket_sdk.types import CreateInvoiceRequest
from tests.fakes import FakeTransport # or relative to your own test layout
def test_creates_invoice():
fake = FakeTransport().enqueue_json({
"state": 0,
"result": {"uuid": "u1", "url": "https://pay.heleket.com/pay/x"},
})
client = HeleketPayment(
merchant_id="merchant",
api_key="key",
options=ClientOptions(transport=fake),
)
invoice = client.create_invoice(
CreateInvoiceRequest(amount="15", currency="USD", order_id="o-1")
)
assert invoice.uuid == "u1"
# Assertions against what the client SENT:
sent = fake.last_request()
assert sent.method == "POST"
assert sent.url == "https://api.heleket.com/v1/payment"
assert sent.headers["merchant"] == "merchant"API:
| Call | What it does |
|---|---|
.enqueue_json(payload) |
Queue a 200 response with this JSON body |
.enqueue_json(payload, 422) |
Queue a non-200 response (validation, etc.) |
.enqueue(TransportResponse) |
Queue a fully custom response |
.fail_next("reset") |
Queue a transport-level failure (raises HttpError) |
.requests |
Every request the client made, in order |
.last_request() |
Most recent request — convenient for single-call tests |
from heleket_sdk import sign, WebhookVerifier
def test_verify_round_trip():
body = '{"type":"payment","uuid":"u1","status":"paid"}'
signature = sign(body, "my-secret")
signed = f'{{"type":"payment","uuid":"u1","status":"paid","sign":"{signature}"}}'
verifier = WebhookVerifier("my-secret")
payload = verifier.verify_raw(signed)
assert payload.status == "paid"When you want to test the actual HTTP path (TLS, header propagation through your reverse proxy logic, etc.), spin up http.server.HTTPServer. tests/test_transport.py shows the pattern.
Heleket's API is fairly closed-world, but two properties worth pinning down:
sign(body, key)is purely a function ofbody+key— no clock, no randomness. Same inputs → same hex.verify_raw(raw)accepts the bytes of any object whosesignfield is correct, regardless of key order. Shuffle non-sign fields, sign, verify.
If your handler is a route, use the framework's test client:
# FastAPI
from fastapi.testclient import TestClient
from app.main import app
def test_webhook_endpoint(client_app: TestClient):
body = b'{"type":"payment","uuid":"u1","status":"paid","sign":"<signature>"}'
response = client_app.post(
"/heleket-webhook",
content=body,
headers={"content-type": "application/json"},
)
assert response.status_code == 200# Django
from django.test import Client
def test_webhook_endpoint():
c = Client()
response = c.post(
"/heleket-webhook",
data=b'{"type":"payment","uuid":"u1","status":"paid","sign":"<signature>"}',
content_type="application/json",
)
assert response.status_code == 200Pre-compute the signature in your test setup with heleket_sdk.sign(...).