-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebhook_receiver.py
More file actions
78 lines (56 loc) · 2.33 KB
/
Copy pathwebhook_receiver.py
File metadata and controls
78 lines (56 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
Minimal Flask webhook receiver.
pip install flask
export TRATOK_WEBHOOK_SECRET=<the secret you saved on /webhooks.php>
flask --app webhook_receiver run --port 8080
Then expose port 8080 publicly (ngrok, cloudflared, tailscale funnel)
and register that URL on https://hospitality.tratok.net/webhooks.php.
"""
from __future__ import annotations
import json
import os
import sys
from flask import Flask, request
from tratok_client import verify_webhook
SECRET = os.environ.get("TRATOK_WEBHOOK_SECRET", "")
if not SECRET:
print("Set TRATOK_WEBHOOK_SECRET in your environment.", file=sys.stderr)
sys.exit(1)
app = Flask(__name__)
@app.post("/tratok/webhook")
def receive() -> tuple[str, int]:
sig = request.headers.get("X-Webhook-Signature", "")
raw = request.get_data() # raw bytes BEFORE parsing
if not verify_webhook(SECRET, raw, sig):
return "bad signature", 401
payload = json.loads(raw)
event = payload.get("event")
data = payload.get("data", {})
# Dispatch on event type. Be tolerant of unknown events — the API
# may introduce new ones; treat them as no-ops.
if event == "booking.created":
handle_booking_created(data)
elif event == "booking.confirmed":
handle_booking_confirmed(data)
elif event == "booking.cancelled":
handle_booking_cancelled(data)
elif event == "payment.failed":
handle_payment_failed(data)
elif event in {"booking.modified", "review.created", "listing.updated", "payment.processed"}:
# Acknowledge without action for this demo.
pass
return "", 204
def handle_booking_created(data: dict) -> None:
print(f"[booking.created] #{data.get('booking_id')} "
f"{data.get('booking_type')} status={data.get('status')}")
def handle_booking_confirmed(data: dict) -> None:
print(f"[booking.confirmed] #{data.get('booking_id')} "
f"{data.get('guest_name')} TRAT={data.get('total_trat')}")
def handle_booking_cancelled(data: dict) -> None:
print(f"[booking.cancelled] #{data.get('booking_id')} "
f"refund_trat={data.get('refund_trat')}")
def handle_payment_failed(data: dict) -> None:
print(f"[payment.failed] #{data.get('booking_id')} "
f"expired_at={data.get('expired_at')}")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)