Use this file to discover all available pages before exploring further.
Python’s ecosystem makes it straightforward to integrate OwnPay into any web framework or backend service. This guide uses the widely available requests library to demonstrate the complete integration flow: creating payment intents, verifying outcomes, handling incoming webhooks, issuing refunds, and gracefully managing API errors — all against OwnPay’s JSON REST API.
OwnPay has no official Python SDK package at this time. All integration is done directly over HTTP using requests (or any HTTP client you prefer, such as httpx or aiohttp).
Using a Session object means the Authorization header is sent automatically on every request, and the underlying TCP connection is reused for efficiency.
After the customer returns to your redirect_url, verify the payment status before fulfilling the order:
def get_payment(payment_id: str): """Retrieve a payment intent and its transaction details.""" resp = session.get(f"{BASE_URL}/payments/{payment_id}") resp.raise_for_status() return resp.json()["data"]def verify_and_fulfill(payment_id: str, expected_reference: str): data = get_payment(payment_id) if data["status"] != "completed": raise ValueError(f"Payment not completed — status: {data['status']}") if data.get("reference") != expected_reference: raise ValueError("Reference mismatch — possible replay attack") print(f"Payment confirmed: {data['trx_id']} for {data['amount']} {data['currency']}") # Fulfil the order here return data
Always verify the payment server-side by calling GET /payments/{payment_id} or GET /transactions/{trx_id}. Never rely solely on query parameters appended to your redirect_url — they can be tampered with.
OwnPay POSTs a payment.completed event to your callback_url. Here is a Flask handler that processes the event and re-verifies the transaction before taking action:
from flask import Flask, request, jsonifyapp = Flask(__name__)@app.route("/webhooks/ownpay", methods=["POST"])def ownpay_webhook(): event = request.get_json(force=True) if not event or event.get("event") != "payment.completed": return jsonify({"ok": False, "reason": "unrecognised event"}), 400 trx_id = event["data"]["trx_id"] # Re-verify by fetching from the API — never trust the payload alone resp = session.get(f"{BASE_URL}/transactions/{trx_id}") if resp.status_code != 200: return jsonify({"ok": False, "reason": "transaction not found"}), 400 transaction = resp.json()["data"] if transaction["status"] != "completed": return jsonify({"ok": False, "reason": "not completed"}), 400 # Safe to fulfil the order print(f"Fulfilling order for reference: {transaction.get('reference')}") return jsonify({"ok": True}), 200
Your webhook endpoint must return an HTTP 2xx response within 10 seconds. For heavyweight processing (database writes, emails, third-party calls), enqueue a background job and return 200 immediately.