Layanan OCR
/Users/mac/Workspace/ocr_service/ adalah API FastAPI untuk membaca struk dan dokumen lampiran. Permintaan diproses sebagai job asinkron: klien menerima job_id, kemudian memeriksa status melalui polling atau menerima hasil lewat webhook. Worker dijalankan sebagai thread saat aplikasi FastAPI mulai.
Pipeline
- Ambil gambar dari URL atau storage.
- Validasi dan preprocessing gambar; PDF dikonversi dengan halaman pertama yang digunakan.
- Pilih provider berdasarkan karakteristik dokumen dan ketersediaan provider.
- Cek cache, lakukan OCR dengan retry/fallback, lalu parsing.
- Normalisasi, kategorisasi, cek duplikasi, dan simpan hasil.
- Kirim callback jika URL webhook backend dikonfigurasi.
Provider yang mempunyai adapter: PaddleOCR, Gemini, Google Document AI, Claude, GPT, dan OpenRouter. Aktifkan PaddleOCR dengan PADDLE_ENABLED=true atau isi kredensial provider eksternal. Bila seluruh provider gagal, job ditandai gagal.
Docker Compose
Compose OCR memerlukan network eksternal memo_backend_go_default. Mulai stack Go dahulu dari direktori apps/api/, lalu:
cd /Users/mac/Workspace/ocr_service
docker compose --env-file '../new bucket/Bucket/apps/api/.env' up -d --build
curl -fsS http://localhost:8015/health
Compose membaca deploy/compose.env dan menjalankan migrasi Alembic sebelum memulai API. Periksa file itu sebelum dipakai: endpoint storage, token, callback, dan kredensial provider harus sesuai lingkungan Anda. Dockerfile mengunduh model PaddleOCR saat build pertama.
| Layanan | Port host pada Compose |
|---|---|
| API OCR | 8015 |
| PostgreSQL OCR | 5434 |
| Redis OCR | 6381 |
Swagger OCR berada di http://localhost:8015/docs. Port di atas mengikuti file Compose saat ini.
Connector di Bucket
Buka menu Connector, lalu pilih kartu Aksario atau Aksario OCR Struk untuk membuka form konfigurasi. Kedua kartu memakai koneksi, URL, dan credential Aksario yang sama:
- Isi Service URL Aksario yang dapat dijangkau backend Bucket. Untuk API Bucket di Docker, gunakan
http://host.docker.internal:8015(atau port host yang dipetakan ke Aksario),http://ocr-service:8001bila keduanya pada network Docker yang sama, atauhttp://localhost:8015bila backend berjalan di host. Compose Bucket meneruskanhost.docker.internalke host danBUCKET_AKSARIO_SERVICE_ORIGINmengikutiOCR_DOCKER_SERVICE_URLsecara default. - Jika ingin memproses lampiran melalui API backend, buat API key akun melalui OCR Console, menu User & API key, lalu masukkan pada OCR account API key. Pemindaian KTP dan struk melalui widget hanya membutuhkan public widget key.
- Aktifkan connector, pilih Test connection, lalu Save configuration. Test memeriksa health dan pertukaran API key; tidak membuat job atau membuktikan bahwa provider/storage berhasil mengekstrak dokumen.
- Aktifkan Enable OCR pada perusahaan pengguna melalui Settings. Connector adalah konfigurasi koneksi bersama; switch perusahaan tetap menentukan lampiran yang diproses.
- Pada form memo baru/edit, gunakan Scan struk untuk ekstraksi interaktif. Upload biasa menyimpan lampiran tanpa menjalankan OCR. API attachment yang mengaktifkan OCR tetap mengirim job, menyimpan hubungan job dengan attachment, dan mengembalikan job ID untuk polling.
Konfigurasi tersimpan di PostgreSQL (connector_configs) dan berlaku pada request baru tanpa restart API. Sebelum pertama kali menyimpan, Bucket memakai environment sebagai default. Nilai API key dan token webhook tidak dikirim kembali ke browser. Field kosong mempertahankan secret lama; checkbox Remove saved credential/token menghapusnya. Payload database dienkripsi AES-GCM menggunakan kunci turunan JWT_SECRET; pertahankan secret itu bersama backup database, atau konfigurasi ulang connector ketika merotasinya.
KTP widget
Aksario juga menyediakan OCR KTP melalui widget browser. Isi Browser widget URL yang dapat dibuka oleh browser, misalnya http://localhost:8015, lalu tempel public widget key. URL backend dan browser boleh berbeda: Chrome di host memakai localhost, sedangkan API di Docker memakai host.docker.internal.
Gunakan HTTPS di production. Backend hanya membagikan widget key jika Browser widget URL adalah root origin tepercaya pada BUCKET_AKSARIO_WIDGET_ORIGIN (default http://localhost:8015). Widget key memang publik dan dibatasi oleh origin, berbeda dari account API key yang tetap terenkripsi dan hanya digunakan backend.
Connector dapat diaktifkan hanya dengan Service URL dan public widget key tanpa account API key. API key akun diperlukan hanya untuk OCR lampiran memo. Pemindaian KTP tersedia di formulir tambah/edit pegawai dan mengisi NIK, nama, tempat lahir, tanggal lahir ISO, dan alamat; tinjau hasil serta peringatan sebelum menyimpan.
Migration 000010_add_ocr_connector.up.sql harus diterapkan pada database deploy baru. Gunakan alur migration aplikasi, misalnya make -C apps/api db-apply-migrations.
Troubleshooting KTP
Saat konfigurasi scanner lengkap, formulir pegawai memuat Browser widget URL/widget/assets/embed.js di browser. Status loading, siap, atau gagal tampil pada formulir. Jika embed gagal dimuat, kegagalan tampil sebagai pesan error dan opsi retry tersedia; tutup lalu buka kembali formulir untuk membersihkan script gagal, memuat ulang embed, dan mencoba lagi.
Public widget key berbeda dari account API key: key widget memang dikirim ke browser, sedangkan account API key hanya untuk backend dan OCR lampiran memo. Browser widget URL harus dapat dijangkau browser; Service URL harus dapat dijangkau backend. Pada deployment HTTPS, URL http:// dapat diblokir sebagai mixed content; gunakan endpoint HTTPS yang dapat dijangkau browser.
OCR Struk pada memo baru dan edit
- Pilih kartu Aksario OCR Struk di Connector. Aktifkan koneksi, isi Browser widget URL (
http://localhost:8015untuk development) dan Public widget key. - Pada Aksario Console, pastikan key mengizinkan produk Struk dan origin website Bucket yang persis, misalnya
http://localhost:5173. Origin ini berbeda dari URL service. Browser melakukan preflight ke/widget/api/session; origin yang belum diizinkan menyebabkan CORS gagal. - Pada panel Attachments di
/memos/newatau form edit memo, pilih Scan struk, lalu upload dokumen di widget Aksario. - Hasil menampilkan merchant, tanggal, nomor struk, rincian item, pajak, diskon, dan total. Pilih impor rincian item atau satu baris total struk. Total struk dipilih secara default jika totalnya berbeda dari subtotal item, sehingga pajak/diskon dapat ikut diperhitungkan.
- Klik Add to memo. File struk asli otomatis diunggah sebagai lampiran bersama baris hasil OCR. Baris dan lampiran lama tetap disimpan; baris baru dapat diedit sebelum Save Memo. Jika unggahan gagal, review tetap tersedia dan belum ada baris/lampiran yang ditambahkan; klik Add to memo untuk mencoba lagi. Impor otomatis hanya tersedia untuk IDR; mata uang lain harus dikonversi dan diisi manual.
Pemindaian widget tidak memerlukan switch OCR perusahaan atau account API key. Bucket meminta file sumber melalui opsi widget includeSourceFile: true; Aksario mengirim file asli bersama hasil, lalu Bucket menyimpannya melalui API lampiran dengan skip_ocr=true agar tidak diproses dua kali. Widget Aksario harus mendukung supportsSourceFile; hasil scan lama tanpa file perlu dipindai ulang. Penutupan/discard review tidak mengunggah file atau mengubah memo. Kegagalan memuat script/session menampilkan pesan dan tombol retry.
Attachment dan callback
Attachment base URL opsional mengganti alamat file yang dikirim ke OCR. Bucket menambahkan storage key file ke URL dasar, misalnya http://memo_minio:9000/memos. Alamat harus mengembalikan isi file tanpa session browser. Jika kosong, Bucket memakai alamat S3 internal yang sudah dikonfigurasi, atau endpoint download lokal berdasarkan UUID attachment.
Polling hasil berjalan tanpa webhook. Untuk callback, isi Webhook token di Connector dengan nilai yang sama seperti BACKEND_WEBHOOK_TOKEN pada OCR Console, dan atur BACKEND_WEBHOOK_URL OCR ke URL backend yang dapat dijangkau OCR, misalnya http://api:8080/webhook/ocr. Konfigurasi tujuan webhook/provider/storage di OCR Console mengikuti mekanisme apply/restart milik OCR service.
Environment sebagai default
| Environment Bucket | Fungsi |
|---|---|
OCR_SERVICE_URL | Base URL OCR yang dapat dijangkau backend |
OCR_SERVICE_API_KEY | API key akun OCR; ditukar lewat POST /api/v1/auth/token dengan header X-API-Key |
OCR_WEBHOOK_TOKEN | Token callback yang diverifikasi pada /webhook/ocr |
OCR_SERVICE_TOKEN | Kompatibilitas bearer token integrasi lama; untuk OCR saat ini gunakan account API key |
Bucket menyimpan JWT sementara sesuai expires_in dan memperbaruinya sebelum kedaluwarsa. Key yang dicabut ditolak oleh OCR. Panduan integrasi OCR dan Swagger menjelaskan kontrak autentikasi/job.
Endpoint Bucket
Semua endpoint konfigurasi memakai JWT login Bucket, sama seperti halaman Settings:
GET /api/connector/ocr: konfigurasi tanpa secret, berikut flaghas_api_key,has_legacy_token, danhas_webhook_token.PUT /api/connector/ocr: simpan konfigurasi dan secret baru jika diisi.POST /api/connector/ocr/test: test nilai form tanpa menyimpan; secret kosong memakai nilai tersimpan.GET /api/ocr/jobs/{job_id}: polling melalui connector dan simpan status/hasil pada tracking attachment.
Python lokal
cd /Users/mac/Workspace/ocr_service
python3.11 -m venv .venv
.venv/bin/pip install -e '.[dev]'
cp -n .env.example .env
.venv/bin/alembic upgrade head
.venv/bin/uvicorn app.main:app --reload --port 8001
Sesuaikan .env lebih dulu. Jika PostgreSQL dan Redis berasal dari Compose OCR namun Python berjalan di host, port yang dipakai adalah 5434 dan 6381. OCR_WORKER_COUNT ada di konfigurasi, tetapi implementasi saat startup sekarang memulai satu worker thread per proses aplikasi.
Jika Redis tidak dapat dijangkau, job store memakai memori proses. Hasil mode fallback itu hilang saat proses dimulai ulang dan tidak cocok untuk beberapa replika API.