Metadata-Version: 2.4
Name: transaksikita
Version: 1.0.0
Summary: Official Python SDK for TransaksiKita Payment Gateway
Author-email: TransaksiKita <transaksikitaa@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://transaksikita.tech
Project-URL: Documentation, https://github.com/zzamcodes17/transaksikita-python
Project-URL: Repository, https://github.com/zzamcodes17/transaksikita-python
Project-URL: Issues, https://github.com/zzamcodes17/transaksikita-python/issues
Keywords: payment,gateway,qris,indonesia,transaksikita
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Office/Business :: Financial :: Point-Of-Sale
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# TransaksiKita Python SDK

<p align="center">
  <a href="https://pypi.org/project/transaksikita/"><img src="https://img.shields.io/pypi/v/transaksikita" alt="PyPI version"></a>
  <a href="https://pypi.org/project/transaksikita/"><img src="https://img.shields.io/pypi/pyversions/transaksikita" alt="Python versions"></a>
  <a href="https://github.com/zzamcodes17/transaksikita-python/blob/main/LICENSE"><img src="https://img.shields.io/github/license/zzamcodes17/transaksikita-python" alt="License"></a>
</p>

**Official Python SDK** untuk [TransaksiKita Payment Gateway](https://transaksikita.tech) — Terima pembayaran QRIS di aplikasi Python Anda.

- **Zero dependencies** — hanya menggunakan built-in `urllib`
- **Type hints** lengkap dengan dataclasses
- **Retry otomatis** dengan exponential backoff
- **Python 3.10+**

---

## Instalasi

```bash
pip install transaksikita
```

## Quick Start

```python
from transaksikita import TransaksiKita, CreatePaymentParams

# Inisialisasi
tk = TransaksiKita(
    project_id="PROJECT_ID",
    public_key="tk_sandbox_xxxx",
    secret_key="sk_sandbox_xxxx",
)

# Test koneksi
info = tk.ping()
print(f"Project: {info.project_name} ({info.mode})")

# Buat pembayaran
payment = tk.create_payment(CreatePaymentParams(
    amount=50000,
    customer_name="Budi Santoso",
    description="Pembelian Paket Premium",
    reference_id="ORDER-001",
))

print(f"Checkout URL: {payment.checkout_full_url}")
print(f"QRIS: {payment.qris_payload}")
```

## Daftar API

### `TransaksiKita(*, project_id, public_key, secret_key, ...)`

Inisialisasi SDK client.

| Parameter | Tipe | Wajib | Default | Deskripsi |
|-----------|------|-------|---------|-----------|
| `project_id` | `str` | ✅ | — | Project ID dari dashboard |
| `public_key` | `str` | ✅ | — | Public Key (`tk_sandbox_xxx` / `tk_production_xxx`) |
| `secret_key` | `str` | ✅ | — | Secret Key (`sk_sandbox_xxx` / `sk_production_xxx`) |
| `base_url` | `str` | ❌ | `https://transaksikita.tech` | Base URL API |
| `timeout` | `int` | ❌ | `30` | Request timeout dalam detik |
| `max_retries` | `int` | ❌ | `0` | Jumlah retry jika gagal (max: 3) |

### `tk.ping() -> PingData`

Test koneksi ke API.

```python
info = tk.ping()
print(info.project_name)  # "Toko Saya"
print(info.mode)           # "sandbox"
```

### `tk.create_payment(params) -> PaymentData`

Buat pembayaran baru.

| Parameter | Tipe | Wajib | Deskripsi |
|-----------|------|-------|-----------|
| `amount` | `int` | ✅ | Nominal dalam Rupiah (min: 500) |
| `customer_name` | `str` | ❌ | Nama customer |
| `description` | `str` | ❌ | Deskripsi pembayaran |
| `reference_id` | `str` | ❌ | ID referensi unik Anda |
| `expired_minutes` | `int` | ❌ | Waktu expired (5-1440 menit) |
| `payment_method` | `str` | ❌ | `"QRIS"` atau `""` |
| `idempotency_key` | `str` | ❌ | Cegah duplikasi |
| `sandbox` | `bool` | ❌ | Force sandbox mode |

```python
payment = tk.create_payment(CreatePaymentParams(
    amount=100000,
    customer_name="Budi",
    description="Order #123",
    reference_id="ORD-123",
    expired_minutes=30,
))
```

### `tk.check_status(payment_id) -> PaymentStatusData`

Cek status pembayaran.

```python
status = tk.check_status("PAY-xxxxx")

if status.status == "paid":
    print(f"Dibayar pada: {status.paid_at}")
    print(f"Jumlah: {TransaksiKita.format_rupiah(status.paid_amount)}")
elif status.status == "pending":
    remaining_min = status.remaining_ms // 60000
    print(f"Sisa waktu: {remaining_min} menit")
```

### `tk.cancel_payment(payment_id) -> CancelPaymentData`

Batalkan pembayaran (hanya status `pending`).

```python
result = tk.cancel_payment("PAY-xxxxx")
print(result.status)  # "cancelled"
```

### `tk.list_payments(*, page, limit, status) -> ListPaymentsResult`

Daftar pembayaran dengan filter.

```python
# 10 pembayaran terbaru
result = tk.list_payments(limit=10)
for p in result.data:
    print(f"{p.payment_id}: {p.status} - Rp{p.amount}")

# Filter yang sudah bayar
paid = tk.list_payments(status="paid")

# Pagination
page2 = tk.list_payments(page=2, limit=20)
print(f"Halaman {page2.pagination.page} dari {page2.pagination.total_pages}")
```

### `tk.verify_callback(payload) -> bool`

Verifikasi callback payload dari TransaksiKita.

```python
# Flask
@app.route("/callback", methods=["POST"])
def callback():
    is_valid = tk.verify_callback(request.json)
    if not is_valid:
        return {"error": "Invalid"}, 400

    data = request.json
    if data["status"] == "paid":
        # Update database...
        pass
    return {"received": True}
```

### `tk.wait_for_payment(payment_id, interval, max_attempts) -> PaymentStatusData`

Polling sampai status berubah dari pending.

```python
result = tk.wait_for_payment("PAY-xxxxx", interval=3, max_attempts=120)
if result.status == "paid":
    print("Pembayaran berhasil!")
```

### `TransaksiKita.format_rupiah(amount) -> str`

Format angka ke Rupiah.

```python
TransaksiKita.format_rupiah(50000)    # "Rp 50.000"
TransaksiKita.format_rupiah(1500000)  # "Rp 1.500.000"
```

## Error Handling

```python
from transaksikita import TransaksiKita, TransaksiKitaError, CreatePaymentParams

tk = TransaksiKita(
    project_id="xxx",
    public_key="tk_sandbox_xxx",
    secret_key="sk_sandbox_xxx",
    max_retries=2,
)

try:
    payment = tk.create_payment(CreatePaymentParams(amount=50000))
except TransaksiKitaError as e:
    print(f"Error: {e}")
    print(f"Status code: {e.status_code}")
    print(f"Detail: {e.detail}")

    if e.is_auth_error():
        print("Cek kembali API keys Anda")
    elif e.is_rate_limited():
        print("Terlalu banyak request, coba lagi nanti")
    elif e.is_validation_error():
        print("Parameter tidak valid")
    elif e.is_retryable():
        print("Error sementara, bisa di-retry")
```

## Contoh Django

```python
# views.py
import json
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from transaksikita import TransaksiKita, CreatePaymentParams

tk = TransaksiKita(
    project_id="xxx",
    public_key="tk_sandbox_xxx",
    secret_key="sk_sandbox_xxx",
)

def create_order(request):
    payment = tk.create_payment(CreatePaymentParams(
        amount=75000,
        customer_name="Customer",
        reference_id=f"ORDER-{request.user.id}",
    ))
    return JsonResponse({"checkout_url": payment.checkout_full_url})

@csrf_exempt
def payment_callback(request):
    payload = json.loads(request.body)
    if not tk.verify_callback(payload):
        return JsonResponse({"error": "Invalid"}, status=400)

    if payload["status"] == "paid":
        # Update order status...
        pass
    return JsonResponse({"received": True})
```

## Environment Variables

Anda bisa menggunakan environment variables:

```python
import os
from transaksikita import TransaksiKita

tk = TransaksiKita(
    project_id=os.environ["TK_PROJECT_ID"],
    public_key=os.environ["TK_PUBLIC_KEY"],
    secret_key=os.environ["TK_SECRET_KEY"],
)
```

```bash
export TK_PROJECT_ID="your-project-id"
export TK_PUBLIC_KEY="tk_sandbox_xxxx"
export TK_SECRET_KEY="sk_sandbox_xxxx"
```

## License

MIT — [PT Azvera Technology Indonesia](https://transaksikita.tech)
