Metadata-Version: 2.4
Name: toanchetpay-sdk
Version: 1.0.0
Summary: Python SDK for ACLEDA ToanchetPay
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: qr
Requires-Dist: qrcode[pil]<9,>=7.4; extra == "qr"
Dynamic: license-file

# ToanchetPay Python SDK

Python port of the adjacent ToanchetPay PHP SDK. Supports Python 3.10+, with no required runtime dependencies.

## Install

From this directory:

```sh
python -m pip install .
# Optional PNG QR support:
python -m pip install ".[qr]"
```

## Quick start

```python
import os
from toanchetpay import (
    ToanchetPayConfig, ToanchetPayClient, ToanchetPayTransaction, PaymentForm,
)

config = ToanchetPayConfig(
    merchant_id=os.environ["TOANCHETPAY_MERCHANT_ID"],
    login_id=os.environ["TOANCHETPAY_LOGIN_ID"],
    password=os.environ["TOANCHETPAY_PASSWORD"],
    secret_key=os.environ["TOANCHETPAY_SECRET_KEY"],
    merchant_name=os.environ["TOANCHETPAY_MERCHANT_NAME"],
)
client = ToanchetPayClient(config)
transaction = ToanchetPayTransaction.standard(
    txid="ORDER-001",
    purchase_amount="10.00",
    purchase_currency="USD",
    purchase_date="20261019",  # Use the purchaseDate format specified by your bank integration.
    purchase_desc="Order payment",
    invoiceid="INV-001",
)
session = client.open_session(transaction)
html = PaymentForm(config).generate(
    session, transaction.to_dict(),
    success_url="https://your-store.example/payment/success",
    error_url="https://your-store.example/payment/error",
)
# Return html as a text/html response from your web framework.
status = client.get_transaction_status(session.payment_token_id)
print(status.is_success(), status.is_confirmed())
```

The default URL is the PHP SDK's UAT host, `https://epaymentuat.acledabank.com.kh`.
Set `base_url` to the bank-provided production host when appropriate. TLS verification is enabled by default; timeout defaults to 30 seconds. Keep credentials on the server.

## Payment types

All factories take the six standard fields shown above, followed by optional `item="1"`, `quantity="1"`, `expiry_time="5"`:

| Factory | Additional fields / behavior |
| --- | --- |
| `standard(...)` | Hosted payment page |
| `mpgs(...)` | `paymentCard=1` |
| `khqr(...)` | `operationType=3` |
| `khqr_pos(..., terminal_id, counter_id)` | `operationType=5`, terminal and counter |
| `deeplink(..., opr_device, call_back_url)` | Mobile device and callback |

POS and deeplink additional arguments precede `item`, `quantity`, and `expiry_time`.
Use `with_payment_card`, `with_operation_type`, `with_terminal`, and `with_deeplink` for fluent overrides.
Pass amounts and transaction fields as strings to preserve decimal formatting. API payloads retain the original camelCase field names; Python methods and attributes use snake_case. `config.from_dict()` accepts the original PHP configuration aliases too.

## QR codes

```python
from pathlib import Path
from toanchetpay import QrCodeGenerator

if session.has_qr_value():
    qr = QrCodeGenerator(size=300, margin=10)
    Path("payment.png").write_bytes(qr.to_png(session.qr_value))
    data_uri = qr.to_base64_data_uri(session.qr_value)
```

QR size and margin are pixels. Modules use integer scaling and the result is centered on the requested canvas.

## Errors and custom transport

Catch `ValidationException` for invalid input, `HttpException` for transport/JSON errors (`status_code`), or `ApiException` for nonzero bank codes (`api_code`, `api_message`). All extend `ToanchetPayException`. As in the PHP SDK, nonzero status codes raise before a status response is returned. Responses expose the original JSON in `.raw`.

Inject a transport with `ToanchetPayClient(config, http=your_transport)`. It must implement `post_json(url, payload) -> dict`. The default transport uses Python's standard library and does not automatically retry payments.

## Verification

```sh
python -m unittest discover -s tests -v
```

Tests use fake bank responses and mocked HTTP, without credentials or network access. Live bank integration and optional QR rendering require separate validation in your environment. This port follows the supplied PHP source; it does not independently certify the bank protocol.
