> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Python SDK

> Waffo Python SDK installation, initialization, and usage guide.

## Requirements

* Python 3.9+
* pip

## Installation

```bash theme={null}
python -m pip install "waffo==0.2.0b1"
# or install the latest pre-release
python -m pip install --pre waffo
```

<Note>
  The Python SDK is currently in beta. Check the latest version on [PyPI](https://pypi.org/project/waffo/) before you go live.
</Note>

## Initialization

```python theme={null}
from waffo import Environment, Waffo, WaffoConfig

config = WaffoConfig(
    api_key="your-api-key",
    private_key="your-base64-encoded-private-key",
    waffo_public_key="waffo-public-key",
    merchant_id="your-merchant-id",
    environment=Environment.SANDBOX,
)

waffo = Waffo(config)
```

## Payment

```python theme={null}
from uuid import uuid4

payment_request_id = uuid4().hex

response = waffo.order().create(
    {
        "paymentRequestId": payment_request_id,
        "merchantOrderId": f"ORDER_{payment_request_id}",
        "orderCurrency": "HKD",
        "orderAmount": "100.00",
        "orderDescription": "Test Product",
        "notifyUrl": "https://your-site.com/webhook",
        "userInfo": {
            "userId": "user_123",
            "userEmail": "user@example.com",
            "userTerminal": "WEB",
        },
        "paymentInfo": {"productName": "ONE_TIME_PAYMENT"},
        "goodsInfo": {"goodsUrl": "https://your-site.com/product/001"},
    }
)

if response.is_success():
    data = response.get_data()
    print("Redirect action:", data.order_action if data else None)
    print("Acquiring Order ID:", data.acquiring_order_id if data else None)
```

## Inquiry

```python theme={null}
response = waffo.order().inquiry({"paymentRequestId": payment_request_id})
```

## Subscription

```python theme={null}
response = waffo.subscription().create({ ... })
inquiry = waffo.subscription().inquiry({"subscriptionId": "..."})
waffo.subscription().cancel({"subscriptionId": "..."})
```

## Refund

```python theme={null}
response = waffo.order().refund(
    {
        "refundRequestId": "ref_...",
        "acquiringOrderId": "ACQ...",
        "refundAmount": "50.00",
        "refundReason": "Customer requested",
    }
)

inquiry = waffo.refund().inquiry({"refundRequestId": "ref_..."})
```

## Webhook handling

```python theme={null}
from fastapi import FastAPI, Header, Request, Response
from waffo import Waffo

app = FastAPI()
waffo = Waffo.from_env()

waffo.webhook().on_payment(
    lambda notification: print(notification.get("result", {}).get("acquiringOrderId"))
)

@app.post("/webhook")
async def webhook(request: Request, x_signature: str | None = Header(default=None)) -> Response:
    body = (await request.body()).decode("utf-8")
    result = waffo.webhook().handle_webhook(body, x_signature)

    return Response(
        content=result.response_body,
        media_type="application/json",
        headers={"X-SIGNATURE": result.response_signature},
        status_code=200 if result.success else 400,
    )
```

## Error handling

```python theme={null}
from waffo import WaffoError, WaffoUnknownStatusError

try:
    response = waffo.order().create({ ... })
except WaffoUnknownStatusError:
    # Important: the payment may have succeeded! Confirm via the inquiry API
    inquiry = waffo.order().inquiry({"paymentRequestId": payment_request_id})
except WaffoError:
    # Client-side error (configuration, signature, etc.); fix and retry
    raise
```

## Package registry

* [PyPI](https://pypi.org/project/waffo/)
