Skip to content

Flask

pip install "natcashify[flask]"

Flask 3.0 or newer. The extension is sync only.

Configuration

Natcash(app) builds a NatcashClient from app.config, using the NATCASH_* keys (see Getting started). The sandbox is the default.

from decimal import Decimal

from flask import Flask, abort, redirect
from natcashify.core import Callback
from natcashify.flask import Natcash

app = Flask(__name__)
app.config.update(
    NATCASH_PRIVATE_KEY="...",
    NATCASH_PARTNER_CODE="...",
    NATCASH_FUNCTION_CODE="...",
    NATCASH_USERNAME="...",
    NATCASH_PASSWORD="...",
    NATCASH_CALLBACK_URL="https://shop.example/natcash/callback",
)
natcash = Natcash(app)


@app.post("/checkout")
def checkout():
    payment = natcash.client.create_payment("ORDER-001", Decimal("250"))
    return redirect(payment.checkout_url)


@app.get("/natcash/callback")
@natcash.callback
def callback(callback: Callback):
    order = orders.get(callback.order_number)
    if order is None:
        abort(404)
    if order.is_paid:
        return "paid"
    transaction = natcash.client.get_transaction(callback.order_number)
    if transaction.is_successful and transaction.amount == order.amount:
        order.mark_paid(transaction.transaction_id)
        return "paid"
    return "not paid"

natcash.client returns the client of the current app and needs an application context.

The callback decorator verifies the signature, aborts with 400 when it is invalid and passes the Callback as the first argument. It never calls get_transaction itself: the callback reaches your shop through the payer's browser, so confirm with the gateway and compare the amount before fulfilling. The browser replays the callback on refresh, so skip orders that are already paid, see Callbacks.

Application factory

import os

natcash = Natcash()


def create_app() -> Flask:
    app = Flask(__name__)
    app.config.update({k: v for k, v in os.environ.items() if k.startswith("NATCASH_")})
    natcash.init_app(app)
    return app

Testing

Pass a transport: Natcash(app, transport=FakeTransport(...)), and sign test callbacks with sign_callback, see Getting started.