Cara Menerbitkan Kunci API CAPTCHA untuk Pelanggan Anda

provision captcha api keys - How to Provision CAPTCHA API Keys for Your Customers

Kalau Anda menjalankan CapSkip untuk orang lain, kunci API CAPTCHA bisa Anda terbitkan begitu seorang pelanggan membayar, langsung dari webhook penagihan Anda. Remote Key Management membuka tiga endpoint POST yang menambah, menampilkan, dan menghapus kunci pada instance yang sedang berjalan, dan kunci baru sudah aktif pada permintaan pemecahan berikutnya. Tanpa restart, tanpa langkah manual, dan tidak ada lagi yang menghalangi antara pembayaran yang lolos dan pelanggan yang mulai memecahkan CAPTCHA. Tulisan ini membahas cara menerbitkan kunci saat berlangganan, mencabutnya saat berhenti, menjaga daftar kunci tetap cocok dengan sistem penagihan Anda, dan satu kesalahan jaringan yang justru dipermudah oleh susunan ini.

Apa yang Anda butuhkan

  • CapSkip berjalan di sebuah mesin Windows yang Anda kendalikan. Mesin itulah layanan pemecahan Anda, dan hanya mesin itu yang perlu memasang aplikasinya. Pelanggan Anda tidak memasang apa pun.
  • Mode Server, supaya pelanggan itu benar-benar bisa menjangkaunya. Mode Local mendengarkan di alamat loopback dan hanya melayani perangkat itu sendiri, sedangkan mode Server mendengarkan di IP jaringan atau IP publik Anda sehingga mesin lain bisa terhubung. Keduanya dijelaskan di pengaturan koneksi, dan IP publik statis sebaiknya sudah ada sebelum Anda memberikan alamatnya kepada siapa pun.
  • Satu kali kunjungan ke jendela CapSkip untuk membuat token admin. Hanya langkah inilah yang terjadi di antarmuka, dan Anda tidak pernah mengulanginya.
  • Suatu tempat untuk menjalankan pemanggilannya: handler webhook penagihan Anda, backend dasbor Anda, atau sebuah terminal selama Anda masih menguji.

Satu hal perlu dinyatakan terus terang sebelum masuk ke kode, karena justru bagian inilah yang membuat model ini masuk akal. Kunci yang Anda bagikan adalah kunci yang Anda cetak sendiri. Ini bukan kredit yang Anda beli lalu Anda jual kembali, dan tidak ada meteran per pemecahan di belakangnya. CapSkip berjalan di perangkat keras Anda, jadi seratus kunci pelanggan berbiaya sama persis dengan satu kunci.

Langkah 1: aktifkan Remote Key Management

Sakelarnya ada di Settings, di bawah API Key Validation, lalu Advanced, lalu Remote Key Management. Aktifkan lalu tekan tombol Generate.

Token hanya ditampilkan satu kali dan disimpan sebagai hash bergaram saja, jadi tidak ada tempat untuk membacanya kembali nanti. Kalau hilang, buat yang baru, dan yang lama langsung tidak berlaku. Anggap itu tombol pencabutan akses Anda, karena tombol khusus untuk itu memang tidak ada. Simpan di tempat yang sama dengan rahasia lain milik sistem penagihan Anda, bukan di dalam kode aplikasi.

Endpoint ini berada di host dan port yang sama dengan yang sudah menjawab permintaan pemecahan Anda. Kalau pelanggan Anda berbicara ke port 8080, di situ pula API admin berada. Itu praktis, dan itu pula yang harus Anda waspadai: ada bagian tersendiri soal ini di bawah.

Selama fitur ini mati, setiap jalur admin mengembalikan 404 polos tanpa body. Jalur yang tidak dikenal mendapat jawaban yang persis sama, dan itu disengaja: orang yang menyisir port tidak bisa membedakan instance yang fiturnya dimatikan dari instance yang bahkan tidak mengenal fitur ini.

Langkah 2: terbitkan kunci saat pelanggan berlangganan

Ketiga endpoint memakai POST, menerima body JSON, dan mensyaratkan header Authorization yang membawa token sebagai kredensial Bearer. Pemanggilan tambah membutuhkan sebuah nama. Kirim namanya saja dan biarkan CapSkip yang membuat nilai kuncinya, dan di sini itulah yang Anda mau: pelanggan tidak seharusnya memilih kredensialnya sendiri.

# No install needed. Name the key after the customer, not after the plan.
curl -X POST http://YOUR_SERVER:8080/admin/keys/add \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{"name":"cust_10482"}'

# Response carries the value to show the customer once:
# {"errorId":0,"key":{"name":"cust_10482","key":"..."}}

Beri nama berdasarkan sesuatu yang stabil di sistem Anda sendiri, misalnya id pelanggan atau id langganan. Nama bersifat unik dan aturan itu ditegakkan saat penambahan, sehingga nama menjadi pegangan yang andal untuk setiap operasi berikutnya. Menamai kunci berdasarkan paket atau tanggal justru kesalahan yang membuat hari pembatalan jadi menyakitkan.

Aturan keunikan itu sekaligus menjadi pengaman idempotensi Anda. Penyedia pembayaran mengirim ulang webhook, dan peristiwa langganan yang terkirim ulang akan kembali sebagai 409 dengan ERROR_KEY_EXISTS, bukan diam-diam membuat kunci kedua untuk pelanggan yang sama. Perlakukan 409 itu sebagai keberhasilan di handler Anda, dan masalah pengiriman ulang pun selesai.

Nilainya kembali tepat satu kali, di dalam respons itu. Tampilkan ke pelanggan atau simpan di tempat yang dibaca dasbor Anda, sebab menampilkan daftar kunci belakangan adalah operasi admin dan bukan sesuatu yang ingin Anda jalankan hanya untuk memulihkan kredensial satu pelanggan.

Langkah 3: cabut kuncinya saat mereka berhenti

Penghapusan menerima tepat satu penanda, entah nilai kuncinya atau namanya. Karena Anda menamai kunci menurut pelanggan, namanya itulah yang dipakai:

# By name, which is unambiguous because names are unique.
curl -X POST http://YOUR_SERVER:8080/admin/keys/delete \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{"name":"cust_10482"}'

# By value works too, if that is what your records hold:
#   -d '{"key":"the-old-value"}'

Pencabutan berlaku pada permintaan pemecahan berikutnya, jadi akses berakhir tepat saat pemanggilan itu selesai. Sejak saat itu pemanggilan pelanggan tersebut gagal dengan ERROR_KEY_DOES_NOT_EXIST, dan itu sinyal yang cukup jelas: integrasi mereka bisa menampilkannya sebagai langganan yang habis masa berlakunya, bukan sebagai gangguan.

Tentukan dengan sadar kapan ini dijalankan. Menghapus pada peristiwa pembatalan memutus akses seketika, padahal pelanggan biasanya sudah membayar sampai akhir periode. Menghapus pada peristiwa akhir periode itulah yang sebenarnya diinginkan kebanyakan orang. Pembayaran gagal adalah kasus ketiga: memberi tenggang singkat sebelum pencabutan menimbulkan jauh lebih sedikit tiket dukungan daripada kunci yang lenyap saat kartu dicoba tagih ulang.

Langkah 4: cocokkan daftarnya dengan sistem penagihan Anda

Pemanggilan daftar cukup dengan objek kosong dan mengembalikan setiap kunci yang saat ini diterima instance.

# The audit: exactly who can solve right now.
curl -X POST http://YOUR_SERVER:8080/admin/keys/list \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" -d '{}'
{
  "errorId": 0,
  "keys": [
    { "name": "cust_10482", "key": "..." },
    { "name": "cust_10515", "key": "..." }
  ]
}

errorId bernilai 0 berarti berhasil, konvensi yang sama dipakai endpoint pemecahan. Jalankan ini secara terjadwal dan bandingkan namanya dengan langganan aktif Anda. Kunci tanpa langganan yang cocok berarti ada orang yang masih memecahkan CAPTCHA secara gratis, dan langganan tanpa kunci berarti pelanggan yang webhook penerbitannya hilang dan yang kemungkinan besar sebentar lagi membuka tiket. Keduanya diam sampai Anda memeriksanya, dan pemanggilan inilah satu-satunya tempat kebenarannya berada.

Menyambungkannya ke webhook langganan

Digabungkan, seluruh integrasinya hanyalah dua handler dan satu aturan idempotensi:

# pip install requests
import requests

BASE = "http://YOUR_SERVER:8080"
AUTH = {"Authorization": "Bearer YOUR_TOKEN"}

def admin(path, body):
    r = requests.post(f"{BASE}/admin/keys/{path}", json=body,
                      headers=AUTH, timeout=10)
    # 409 on add means the key already exists, which is what a
    # retried webhook looks like. Treat it as success, not failure.
    if r.status_code == 409:
        return None
    r.raise_for_status()
    return r.json()

def on_subscription_active(customer_id):
    created = admin("add", {"name": f"cust_{customer_id}"})
    return created["key"]["key"] if created else None

def on_subscription_ended(customer_id):
    admin("delete", {"name": f"cust_{customer_id}"})

Tangani None dari langganan yang terkirim ulang dengan sadar. Artinya kuncinya ada tetapi nilainya tidak bisa Anda lihat lagi, jadi kalau Anda gagal menyimpannya pada kali pertama, pemulihannya adalah menghapus lalu menambahkan ulang, bukan menampilkan daftar. Menyimpan nilainya begitu pertama kali Anda terima membuat situasi ini tidak pernah muncul.

Jangan biarkan API admin berada di port yang menghadap pelanggan

Untuk susunan seperti ini, bagian inilah yang paling penting, karena kepraktisan satu host dan satu port berlaku dua arah. Pelanggan Anda memang perlu menjangkau endpoint pemecahan. Endpoint admin berada di port yang sama, hanya dilindungi Bearer token, dan tidak ada pemeriksaan lapisan transport, jadi di port khusus token itu melintas sebagai HTTP teks terbuka. Siapa pun yang bisa mengamati lalu lintas itu bisa membacanya, dan siapa pun yang memegangnya bisa menerbitkan kunci untuk dirinya sendiri.

Pasang reverse proxy di depan instance lalu pisahkan dua kelompok penggunanya:

  • Terbitkan ke internet hanya jalur pemecahan, lewat HTTPS yang diakhiri di proxy, dan kembalikan 404 untuk apa pun di bawah jalur admin.
  • Jangkau endpoint admin dari backend Anda sendiri lewat rute privat: alamat loopback kalau layanan penagihan Anda berjalan di mesin Windows yang sama, selebihnya lewat jaringan privat, VPN, atau terowongan SSH.

Patokannya begini: token admin tidak boleh keluar dari infrastruktur Anda, dan port yang diajaknya bicara tidak boleh port yang bisa dijangkau pelanggan. Jangan pernah membuka jalur admin ke internet terbuka, baik fiturnya aktif maupun tidak.

Ada satu batasan lagi yang perlu diketahui, sebab dasbor pelanggan justru hal paling jelas yang ingin dibangun di sini. Browser tidak bisa memanggil endpoint ini, karena respons admin sengaja tidak membawa header CORS sama sekali. Dasbor Anda harus melewati backend Anda sendiri, dan di situlah memang tempat token seharusnya berada.

Ke mana kunci sebenarnya ditulis

Kunci masuk ke tempat kunci Anda memang sudah tersimpan. Direct Input dan From File adalah dua daftar yang terpisah, dan API membaca serta menulis ke daftar mana pun yang sedang dipilih. Mengganti sumbernya di jendela pengaturan juga mengubah apa yang dilihat endpoint, jadi pastikan dulu Anda sedang di mode yang mana sebelum bingung kenapa kunci yang baru saja diterbitkan tidak ada di daftar.

Mode file punya satu perilaku yang sebaiknya Anda ketahui lebih dulu: penulisan pertama akan menulis ulang berkas kunci teks biasa menjadi JSON. Tidak ada yang hilang, tetapi formatnya berubah permanen, jadi cadangkan dulu berkasnya kalau ada hal lain yang ikut membacanya. Kalau tidak ada berkas yang dipilih sama sekali, penulisan tidak punya tempat mendarat dan Anda akan mendapat ERROR_ADMIN_STORE_FAILURE dengan kode 500. Hampir selalu, 500 di sini berarti itu.

Daftar yang dibuat sebelum fitur ini ada masih mungkin memuat nama ganda, karena keunikan hanya ditegakkan saat penambahan. Menghapus berdasarkan nama pada kasus seperti itu mengembalikan ERROR_KEY_NAME_AMBIGUOUS dan tidak mengubah apa pun. Hapus berdasarkan nilainya saja, ambiguitasnya langsung hilang.

Tanda kutip di shell Windows, kalau Anda menguji dari mesin itu sendiri

CapSkip adalah aplikasi Windows, jadi mesin tempat Anda menguji pun sering kali Windows. Command Prompt tidak memperlakukan kutip tunggal sebagai tanda kutip. Perintah yang Anda salin mengirim tanda kutip itu sebagai bagian dari body JSON, parser menolaknya, dan Anda mendapat ERROR_ADMIN_BAD_REQUEST pada perintah yang tampak sepenuhnya benar.

ShellBody kosongDengan field
Command Prompt-d "{}"-d "{\"name\":\"prod\"}"
PowerShell, memakai curl.exe-d '{}'-d '{\"name\":\"prod\"}'
Git Bash, macOS, Linux-d '{}'-d '{"name":"prod"}'

Di PowerShell, panggil curl.exe dengan nama lengkapnya. curl polos di sana adalah alias untuk Invoke-WebRequest, yang menerima argumen yang sama sekali berbeda dan akan gagal dengan cara yang tidak ada hubungannya dengan API ini.

Kode kesalahan

StatusKodePenyebab
404teks biasaFitur mati, atau jalur tidak dikenal. Sengaja dibuat tidak bisa dibedakan.
401ERROR_ADMIN_UNAUTHORIZEDToken tidak ada, rusak, atau salah.
405ERROR_ADMIN_METHOD_NOT_ALLOWEDAnda mengirim sesuatu selain POST.
400ERROR_ADMIN_BAD_REQUESTBody bukan JSON yang sah, penambahan tidak menyertakan nama, atau penghapusan menyertakan kedua penanda atau tidak sama sekali.
409ERROR_KEY_EXISTSNama atau nilai itu sudah dipakai. Pada handler langganan, ini biasanya webhook yang terkirim ulang.
409ERROR_KEY_NAME_AMBIGUOUSPenghapusan berdasarkan nama cocok dengan beberapa kunci. Hapus berdasarkan nilai saja.
404ERROR_KEY_NOT_FOUNDPenghapusan tidak cocok dengan apa pun. Biasanya pembatalan yang sudah diproses sebelumnya.
500ERROR_ADMIN_STORE_FAILUREGagal menyimpan. Biasanya mode file tanpa berkas yang dipilih.

Kode-kode ini mendampingi kode kesalahan pemecahan, bukan menggantikannya, dan daftar lengkapnya ada di Dokumentasi API CapSkip.

FAQ

Seberapa cepat kunci baru benar-benar mulai bekerja?

Pada permintaan pemecahan berikutnya. Tidak ada yang di-cache dan tidak ada yang perlu dimuat ulang, jadi pelanggan yang menerima kuncinya dari halaman checkout Anda bisa memakainya pada menit yang sama. Pencabutan sama seketikanya ke arah sebaliknya, dan karena itulah waktu penjalanan handler pembatalan Anda adalah keputusan kebijakan, bukan keputusan teknis.

Apakah setiap kunci pelanggan tambahan menimbulkan biaya?

Tidak. CapSkip berjalan di perangkat keras milik Anda sendiri tanpa kuota per pemecahan, jadi sebuah kunci hanyalah label untuk pemanggil, bukan identitas penagihan. Buat satu per pelanggan, atau beberapa per pelanggan kalau Anda ingin memisahkan lingkungan mereka, dan hapus sama bebasnya. SDK pemecahan CAPTCHA membaca kunci mana pun yang Anda berikan, jadi cara membaginya sepenuhnya Anda yang merancang.

Bisakah saya mengukur atau membatasi laju seorang pelanggan lewat API ini?

Lewat API ini tidak bisa. Ia menambah, menampilkan, dan menghapus kunci, dan tidak ada pengaturan lain yang bisa dibaca atau diubah lewatnya. Kalau paket Anda dibedakan berdasarkan volume, hitung permintaannya di reverse proxy yang memang sudah Anda pasang di depan instance, berdasarkan kunci API yang dikirim pelanggan. Kunci menandai siapa pemanggilnya, dan proxy Anda yang memutuskan apa yang boleh dilakukan pemanggil itu.

Token admin saya hilang. Sekarang bagaimana?

Buat yang baru di panel pengaturan yang sama. Token lama langsung berhenti bekerja, jadi tidak ada langkah pembersihan dan tidak ada jeda ketika keduanya sama-sama berlaku. Pelanggan Anda tidak terpengaruh: kunci mereka tidak tersentuh dan mereka terus memecahkan CAPTCHA. Yang rusak hanyalah proses penerbitan milik Anda sendiri, sampai Anda memperbarui rahasia yang dibaca handler webhook Anda.

Versi paling singkatnya

Aktifkan Remote Key Management satu kali dan simpan token bersama rahasia penagihan Anda yang lain. Tambahkan kunci bernama pelanggan ketika langganannya aktif, perlakukan 409 pada pengiriman ulang sebagai keberhasilan, dan hapus dengan nama yang sama ketika langganannya berakhir. Tampilkan daftarnya secara terjadwal dan bandingkan dengan pelanggan aktif Anda, sebab hanya di situlah jawaban sebenarnya berada. Lalu pasang proxy di depan dan jauhkan jalur admin dari port yang bisa dilihat pelanggan Anda. Lakukan itu dan bypass captcha menjadi sesuatu yang bisa Anda jual kembali di perangkat keras Anda sendiri, diterbitkan secepat checkout Anda bisa memicu sebuah webhook.