UnitPay
  • Products
  • Pricing
  • Docs
  • Help
  • About
  • Security
  • Legal
|
Demo Get a quote

Developer documentation

Embed the payment widget

Last updated: 08 May 2026

Contents

    The payment widget is a drop-in JavaScript snippet that opens the UnitPay payment form as a pop-up over your site. The customer pays without leaving your page; you receive the result the same way as for any other UnitPay flow — via the signed callback handler. Use it when you want a lighter-touch checkout than a redirect to a hosted page but still don't want to handle card data yourself.

    When to use the widget

    NeedRecommended option
    One-click checkout from a product page or cart, without leaving the sitePayment widget
    Server-controlled order amount, custom validation, fraud rulesinitPayment API
    Share a hosted URL by email, WhatsApp, or QR codePayment links
    Embed checkout in a mobile webviewPayment widget or hosted link — both render the same form

    Quick start

    Load the widget script and initialise a payment object inside an event handler. Compute the signature on your server — never expose the project secret key to the browser.

    <script src="https://widget.unitpay.net/unitpay.js" defer></script>
    <button type="button" data-action="pay">Pay IDR 150,000</button>
    document.addEventListener('click', function (event) {
      if (event.target.dataset.action !== 'pay') return;
    
      var payment = new UnitPay();
    
      payment.createWidget({
        publicKey: '123456-a875a',
        sum: 150000.00,
        account: 'invoice-2026-0184',
        currency: 'IDR',
        desc: 'Invoice #2026-0184',
        locale: 'en',
        signature: '<sha256-hex-digest from your server>'
      });
    
      payment.success(function (params) {
        // Customer completed the payment in the widget.
        // The authoritative confirmation still arrives via your callback handler.
        window.location.href = '/orders/' + params.account + '/thanks';
      });
    
      payment.error(function (message, params) {
        console.warn('Widget error:', message, params);
      });
    });

    Required parameters

    ParameterTypeDescription
    publicKeystringProject public key. Visible in the merchant cabinet under Settings → Project → Payment widget. Safe to ship in client-side code.
    sumnumberPayment amount in major currency units. Two decimal places maximum (for example, 150000.00 for IDR 150,000 or 10.00 for USD 10).
    accountstringCustomer or order identifier in your system. Returned unchanged in callbacks so you can reconcile the payment to the original order.
    descstringHuman-readable order description shown to the customer on the form and on the receipt.
    signaturestringSHA-256 hex digest computed on your server. See Signing the request below.

    Optional parameters

    ParameterTypeDescription
    currencystringISO 4217 currency code: IDR, USD, or EUR. Defaults to the project's primary currency.
    localestringWidget language: en or id. Auto-detected from the browser's navigator.language when omitted.
    paymentTypestringPre-select a payment method: card, qris, va, or another method enabled on your project. Skip to let the customer choose on the form.
    hideMenubooleanWhen true and a paymentType is set, hides the method-selection menu so the customer can only pay with that method.
    customerEmailstringCustomer email used for the receipt. Pre-fills the email field on the form.

    Signing the request

    The widget signature uses a fixed-order recipe (different from the alphabetical sort used by initPayment). Concatenate values separated by the literal four-character delimiter {up}, then take the lowercase SHA-256 hex digest:

    signature = sha256_hex(
      account + "{up}" +
      currency + "{up}" +
      desc + "{up}" +
      sum + "{up}" +
      secretKey
    )

    Notes on the recipe:

    • If you don't pass currency, omit it from the signature too — do not insert an empty string for it.
    • sum is serialised exactly as you pass it to createWidget: 150000.00, not "150000" or 150000.0. A formatting mismatch is the most common cause of "invalid signature" errors.
    • Compute the digest on your server. Send only the digest plus the public-safe parameters to the browser.
    • Rotate the secret key from Settings → Project → Secret key if you suspect compromise. Never commit it to client-side code or version control.

    Handling success and error events

    payment.success(callback) fires when the customer completes the payment inside the widget. The params object includes the account and sum you supplied; treat it as a UI hint only — the authoritative confirmation arrives on your server via the signed callback handler.

    payment.error(callback) fires when the widget cannot process the payment (invalid signature, declined card, customer cancellation). The first argument is a human-readable message; the second carries the parameters that triggered the error.

    Don't credit the order, ship the goods, or unlock the digital product on the success event alone. Treat the widget result as a hint, then wait for your callback handler to receive the signed PAY request before fulfilling.

    After a successful payment

    The widget triggers the same callback flow as every other UnitPay payment method: a signed CHECK request followed by a signed PAY request, both verifiable using your project secret key. See Callback handler. The account field in the callback echoes the value you set on createWidget, so you can match the result to the originating order.

    Limitations

    • The widget script must be loaded from https://widget.unitpay.net/unitpay.js. Self-hosting or proxying the script is not supported — new releases ship via that URL.
    • Your site's Content Security Policy must allow script-src https://widget.unitpay.net and frame-src https://pay.unitpay.net.
    • The widget renders inside an iframe. It cannot be embedded in pages served over plain HTTP — HTTPS is required.
    • One UnitPay instance handles one payment at a time. To support multiple "Pay" buttons on a page, create a fresh instance per click.
    • Some mobile in-app browsers (older Facebook / Instagram webviews) block third-party iframes; for those audiences, fall back to a hosted payment link.

    Next steps

    • Create a payment via API — server-side alternative when you need full control over the order intent.
    • Generate a payment link — share a hosted URL when you don't want to embed JavaScript.
    • Callback handler — verify the signed result on your server before fulfilling the order.
    • Refund a payment — reverse a charge made through the widget.

    Widget pembayaran adalah cuplikan JavaScript siap-pakai yang membuka formulir pembayaran UnitPay sebagai pop-up di atas situs Anda. Pelanggan membayar tanpa meninggalkan halaman; Anda menerima hasilnya seperti pada alur UnitPay lainnya — melalui callback handler bertanda tangan. Gunakan widget bila Anda ingin checkout yang lebih ringan daripada redirect ke halaman terhosting, namun tetap tidak ingin menangani data kartu sendiri.

    Kapan menggunakan widget

    KebutuhanOpsi yang disarankan
    Checkout sekali klik dari halaman produk atau keranjang, tanpa meninggalkan situsWidget pembayaran
    Jumlah pesanan dikendalikan server, validasi kustom, aturan anti-fraudAPI initPayment
    Bagikan URL terhosting via email, WhatsApp, atau kode QRTautan pembayaran
    Sertakan checkout di dalam webview aplikasi selulerWidget pembayaran atau tautan terhosting — keduanya merender formulir yang sama

    Mulai cepat

    Muat skrip widget dan inisialisasi objek pembayaran di dalam handler event. Hitung tanda tangan di server Anda — jangan pernah membocorkan kunci rahasia proyek ke browser.

    <script src="https://widget.unitpay.net/unitpay.js" defer></script>
    <button type="button" data-action="pay">Bayar Rp 150.000</button>
    document.addEventListener('click', function (event) {
      if (event.target.dataset.action !== 'pay') return;
    
      var payment = new UnitPay();
    
      payment.createWidget({
        publicKey: '123456-a875a',
        sum: 150000.00,
        account: 'invoice-2026-0184',
        currency: 'IDR',
        desc: 'Faktur #2026-0184',
        locale: 'id',
        signature: '<sha256-hex-digest dari server Anda>'
      });
    
      payment.success(function (params) {
        // Pelanggan menyelesaikan pembayaran di dalam widget.
        // Konfirmasi otoritatif tetap datang via callback handler Anda.
        window.location.href = '/orders/' + params.account + '/thanks';
      });
    
      payment.error(function (message, params) {
        console.warn('Kesalahan widget:', message, params);
      });
    });

    Parameter wajib

    ParameterTipeDeskripsi
    publicKeystringKunci publik proyek. Tampak di kabinet merchant pada Pengaturan → Proyek → Widget pembayaran. Aman disertakan di kode sisi-klien.
    sumnumberJumlah pembayaran dalam satuan utama mata uang. Maksimum dua tempat desimal (contoh: 150000.00 untuk IDR 150.000 atau 10.00 untuk USD 10).
    accountstringIdentifikasi pelanggan atau pesanan dalam sistem Anda. Dikembalikan tanpa perubahan pada callback agar Anda dapat merekonsiliasi pembayaran dengan pesanan asli.
    descstringDeskripsi pesanan yang mudah dibaca pelanggan, ditampilkan pada formulir dan kuitansi.
    signaturestringSHA-256 hex digest yang dihitung di server Anda. Lihat Menandatangani permintaan di bawah.

    Parameter opsional

    ParameterTipeDeskripsi
    currencystringKode mata uang ISO 4217: IDR, USD, atau EUR. Default ke mata uang utama proyek Anda.
    localestringBahasa widget: en atau id. Terdeteksi otomatis dari navigator.language bila dihilangkan.
    paymentTypestringPra-pilih metode pembayaran: card, qris, va, atau metode lain yang aktif pada proyek Anda. Lewatkan agar pelanggan memilih sendiri di formulir.
    hideMenubooleanBila true dan paymentType diatur, menu pemilihan metode disembunyikan sehingga pelanggan hanya dapat membayar dengan metode tersebut.
    customerEmailstringEmail pelanggan untuk kuitansi. Mengisi otomatis kolom email pada formulir.

    Menandatangani permintaan

    Tanda tangan widget menggunakan resep urutan-tetap (berbeda dari pengurutan abjad pada initPayment). Gabungkan nilai dengan pemisah literal empat karakter {up}, lalu ambil SHA-256 hex digest dengan huruf kecil:

    signature = sha256_hex(
      account + "{up}" +
      currency + "{up}" +
      desc + "{up}" +
      sum + "{up}" +
      secretKey
    )

    Catatan tentang resep:

    • Bila Anda tidak mengirim currency, hilangkan juga dari tanda tangan — jangan menyisipkan string kosong untuknya.
    • sum diserialkan persis seperti yang Anda kirim ke createWidget: 150000.00, bukan "150000" atau 150000.0. Ketidakcocokan format adalah penyebab paling umum dari kesalahan "tanda tangan tidak valid".
    • Hitung digest di server Anda. Kirim hanya digest beserta parameter yang aman-publik ke browser.
    • Rotasi kunci rahasia dari Pengaturan → Proyek → Kunci rahasia bila Anda mencurigai adanya kebocoran. Jangan pernah memasukkannya ke kode sisi-klien atau ke version control.

    Menangani event sukses dan error

    payment.success(callback) dipicu saat pelanggan menyelesaikan pembayaran di dalam widget. Objek params berisi account dan sum yang Anda berikan; perlakukan sebagai petunjuk UI saja — konfirmasi otoritatif tiba di server Anda melalui callback handler bertanda tangan.

    payment.error(callback) dipicu bila widget tidak dapat memproses pembayaran (tanda tangan tidak valid, kartu ditolak, pembatalan oleh pelanggan). Argumen pertama adalah pesan yang mudah dibaca; argumen kedua membawa parameter yang memicu kesalahan.

    Jangan mengkredit pesanan, mengirim barang, atau membuka produk digital hanya berdasarkan event sukses. Perlakukan hasil widget sebagai petunjuk, lalu tunggu callback handler Anda menerima permintaan PAY bertanda tangan sebelum melakukan pemenuhan pesanan.

    Setelah pembayaran berhasil

    Widget memicu alur callback yang sama dengan setiap metode pembayaran UnitPay lainnya: permintaan CHECK bertanda tangan diikuti permintaan PAY bertanda tangan, keduanya dapat diverifikasi dengan kunci rahasia proyek Anda. Lihat Penanganan callback. Field account pada callback mengembalikan nilai yang Anda atur pada createWidget, sehingga Anda dapat mencocokkan hasil dengan pesanan asli.

    Batasan

    • Skrip widget harus dimuat dari https://widget.unitpay.net/unitpay.js. Self-hosting atau mem-proxy skrip tidak didukung — rilis baru dikirim melalui URL tersebut.
    • Content Security Policy situs Anda harus mengizinkan script-src https://widget.unitpay.net dan frame-src https://pay.unitpay.net.
    • Widget dirender di dalam iframe. Tidak dapat disertakan pada halaman yang disajikan melalui HTTP biasa — HTTPS wajib.
    • Satu instance UnitPay menangani satu pembayaran pada satu waktu. Untuk mendukung beberapa tombol "Bayar" pada satu halaman, buat instance baru per klik.
    • Beberapa in-app browser di seluler (webview Facebook / Instagram versi lama) memblokir iframe pihak ketiga; untuk audiens tersebut, gunakan tautan pembayaran terhosting sebagai cadangan.

    Langkah selanjutnya

    • Membuat pembayaran melalui API — alternatif sisi-server bila Anda butuh kendali penuh atas niat pesanan.
    • Membuat tautan pembayaran — bagikan URL terhosting bila Anda tidak ingin menyertakan JavaScript.
    • Penanganan callback — verifikasi hasil bertanda tangan di server Anda sebelum memenuhi pesanan.
    • Pengembalian dana pembayaran — balik transaksi yang dilakukan melalui widget.

    Related documentation

    • Create a payment via API Membuat pembayaran melalui API
    • Generate a payment link Membuat tautan pembayaran
    • Callback handler Penanganan callback
    • Refund a payment Pengembalian dana pembayaran

    Company

    • About
    • Security
    • Contact

    Products

    • Online Payments
    • Payouts (USDT)
    • Pricing
    • Docs
    • Help

    Support

    • support@unitpay.net
    • sales@unitpay.net
    • compliance@unitpay.net
    • legal@unitpay.net

    WhatsApp

    +6285121084571

    Mon-Fri 09:00-18:00 WIB

    Legal

    • Privacy Policy
    • Cookie Policy
    • Terms of Service
    • Acceptable Use Policy
    • AML/CFT Statement
    • Legal Center

    Tidak puas? / Not satisfied?

    • Hubungi OJK / Contact OJK: 157 (24 jam) / (24h)
    • LAPS SJK: https://lapssjk.id
    • Email keluhan / Complaint email: complaints@unitpay.net
    • Didit
    • Didit
    • Amazon Web Services (Asia Pacific - Jakarta)
    • Iubenda
    |
    Sitemap

    (c) 2026 PT UNIT GLOBAL SYSTEM. All rights reserved. NPWP: 22.709.627.8-021.000 · NIB: 2511240128903