Kembali ke Dashboard | API Docs QRIS
Buka Panduan Google Apps Script →
WORDPRESS & WOOCOMMERCE INTEGRATION

Integrasi Payment Gateway Zy-Pay di WordPress

Panduan lengkap menerima pembayaran QRIS otomatis di WordPress & WooCommerce menggunakan Link Pembayaran Siap Pakai dan Webhook Real-time.

1. Bagaimana Alur Kerjanya? Apakah via Link Pembayaran?

Ya, menggunakan Link Pembayaran (public_payment_url) adalah cara paling praktis, aman, dan tanpa repot di WordPress!

1

Checkout di Website

Pembeli klik tombol Checkout di WooCommerce atau submit formulir pesanan.

2

Generate Link Bayar

Server WordPress memanggil API Zy-Pay (POST /create-payment) dan mendapatkan public_payment_url.

3

Redirect Pembeli

Pembeli langsung dialihkan ke halaman bayar resmi (contoh: pay.php?id=...) yang menampilkan QRIS, total unik, dan timer hitung mundur.

4

Otomatis Lunas

Begitu scan via BCA/Mandiri/GoPay/ShopeePay/dll, Zy-Pay menembak Webhook ke WordPress dan order berubah status jadi LUNAS.

Keuntungan Menggunakan Link Pembayaran Zy-Pay:
  • Halaman pembayaran sudah memiliki sistem real-time polling status: otomatis mendeteksi ketika QRIS dibayar tanpa perlu refresh manual.
  • Mendukung tombol Download QRIS untuk memudahkan pembeli yang membuka dari smartphone.
  • Anti-bentrok nominal berkat generator Kode Unik Otomatis dari sistem Zy-Pay.

2. Integrasi WooCommerce (Plugin 1-File Siap Pakai)

Anda bisa langsung memasang gateway Zy-Pay QRIS di toko online WooCommerce Anda dengan membuat 1 file plugin baru tanpa perlu coding ulang.

Langkah Pemasangan:

  1. Buka folder hosting WordPress Anda di wp-content/plugins/.
  2. Buat folder baru bernama zypay-qris dan buat file zypay-qris.php di dalamnya.
  3. Salin seluruh kode PHP di bawah ini dan paste ke dalam file tersebut.
  4. Buka menu Plugins di Admin WordPress Anda, lalu klik Activate pada plugin "Zy-Pay QRIS Payment Gateway".
  5. Masuk ke WooCommerce → Settings → Payments → Zy-Pay QRIS untuk memasukkan API Key Anda.
wp-content/plugins/zypay-qris/zypay-qris.php
<?php
/**
 * Plugin Name: Zy-Pay QRIS Payment Gateway for WooCommerce
 * Description: Terima pembayaran QRIS otomatis real-time via Zy-Pay Payment Gateway.
 * Version: 1.0.0
 * Author: Zy-Pay / Cutiezy.id
 */

if (!defined('ABSPATH')) exit;

add_action('plugins_loaded', 'init_zypay_qris_gateway');

function init_zypay_qris_gateway() {
    if (!class_exists('WC_Payment_Gateway')) return;

    class WC_Gateway_ZyPay_QRIS extends WC_Payment_Gateway {
        public function __construct() {
            $this->id                 = 'zypay_qris';
            $this->icon               = 'https://cutiezy.id/zy-pay/assets/qris-icon.png';
            $this->has_fields         = false;
            $this->method_title       = 'Zy-Pay QRIS Otomatis';
            $this->method_description = 'Terima pembayaran QRIS otomatis (BCA, Mandiri, BRI, BNI, GoPay, OVO, ShopeePay, DANA).';

            $this->init_form_fields();
            $this->init_settings();

            $this->title       = $this->get_option('title', 'QRIS Otomatis (Instant Payment)');
            $this->description = $this->get_option('description', 'Bayar instan melalui QRIS menggunakan semua e-wallet & mobile banking.');
            $this->api_key     = $this->get_option('api_key');
            $this->expiry      = $this->get_option('expiry', '30');

            add_action('woocommerce_update_options_payment_gateways_' . $this->id, array($this, 'process_admin_options'));
            add_action('woocommerce_api_zypay_webhook', array($this, 'handle_webhook_callback'));
        }

        public function init_form_fields() {
            $this->form_fields = array(
                'enabled' => array(
                    'title'   => 'Aktifkan Gateway',
                    'type'    => 'checkbox',
                    'label'   => 'Aktifkan pembayaran QRIS Zy-Pay',
                    'default' => 'yes'
                ),
                'title' => array(
                    'title'   => 'Judul Pembayaran',
                    'type'    => 'text',
                    'default' => 'QRIS Otomatis (All E-Wallet & Bank)'
                ),
                'description' => array(
                    'title'   => 'Deskripsi',
                    'type'    => 'textarea',
                    'default' => 'Scan QRIS memakai BCA, Mandiri, BRI, DANA, GoPay, OVO, ShopeePay, atau LinkAja.'
                ),
                'api_key' => array(
                    'title'       => 'Zy-Pay API Key',
                    'type'        => 'password',
                    'description' => 'Dapatkan dari Dashboard Zy-Pay → API Keys QRIS.',
                    'default'     => ''
                ),
                'expiry' => array(
                    'title'       => 'Masa Berlaku QRIS (Menit)',
                    'type'        => 'number',
                    'default'     => '30',
                    'description' => 'Durasi waktu pembayaran sebelum kedaluwarsa (default: 30 menit).'
                )
            );
        }

        // Proses Checkout: Redirect pembeli ke Link Pembayaran Zy-Pay
        public function process_payment($order_id) {
            $order = wc_get_order($order_id);
            $apiKey = trim($this->api_key);

            if (empty($apiKey)) {
                wc_add_notice('Konfigurasi pembayaran Zy-Pay belum lengkap (API Key kosong).', 'error');
                return;
            }

            $webhook_url = WC()->api_request_url('zypay_webhook');
            $endpoint    = 'https://cutiezy.id/zy-pay/api/v1/create-payment';

            $body = array(
                'amount'         => (int)round($order->get_total()),
                'description'    => 'Order #' . $order->get_order_number() . ' - ' . $order->get_billing_first_name(),
                'webhook_url'    => $webhook_url,
                'expiry_minutes' => (int)$this->expiry
            );

            $response = wp_remote_post($endpoint, array(
                'headers' => array(
                    'Content-Type' => 'application/json',
                    'X-API-Key'    => $apiKey
                ),
                'body'    => json_encode($body),
                'timeout' => 30
            ));

            if (is_wp_error($response)) {
                wc_add_notice('Koneksi ke gateway pembayaran gagal: ' . $response->get_error_message(), 'error');
                return;
            }

            $result = json_decode(wp_remote_retrieve_body($response), true);

            if (!empty($result['success']) && !empty($result['data']['public_payment_url'])) {
                // Simpan transaksi di post meta
                $order->update_meta_data('_zypay_trx_id', $result['data']['transaction_id']);
                $order->update_meta_data('_zypay_payment_url', $result['data']['public_payment_url']);
                $order->update_status('pending', 'Menunggu pembayaran QRIS Zy-Pay...');
                $order->save();

                WC()->cart->empty_cart();

                // Redirect pembeli ke link pembayaran resmi Zy-Pay
                return array(
                    'result'   => 'success',
                    'redirect' => $result['data']['public_payment_url']
                );
            } else {
                $errMsg = $result['error'] ?? 'Gagal membuat tagihan QRIS.';
                wc_add_notice('Error Pembayaran: ' . $errMsg, 'error');
                return;
            }
        }

        // Webhook Receiver saat QRIS terbayar
        public function handle_webhook_callback() {
            $rawPayload = file_get_contents('php://input');
            $data = json_decode($rawPayload, true);

            if (!$data || empty($data['transaction_id'])) {
                status_header(400);
                echo json_encode(array('status' => 'error', 'message' => 'Payload tidak valid'));
                exit;
            }

            $trxId  = $data['transaction_id'];
            $status = strtolower($data['status'] ?? '');

            // Cari order berdasarkan _zypay_trx_id
            $orders = wc_get_orders(array(
                'meta_key'   => '_zypay_trx_id',
                'meta_value' => $trxId,
                'limit'      => 1
            ));

            if (empty($orders)) {
                status_header(404);
                echo json_encode(array('status' => 'error', 'message' => 'Order tidak ditemukan'));
                exit;
            }

            $order = $orders[0];

            if ($status === 'paid') {
                if (!$order->is_paid()) {
                    $order->payment_complete($trxId);
                    $order->add_order_note('Pembayaran QRIS Zy-Pay berhasil diverifikasi (Status: PAID).');
                }
            } elseif (in_array($status, array('expired', 'cancelled', 'cancel'))) {
                $order->update_status('cancelled', 'Pembayaran QRIS kedaluwarsa atau dibatalkan.');
            }

            status_header(200);
            echo json_encode(array('status' => 'success'));
            exit;
        }
    }

    function add_zypay_qris_gateway($methods) {
        $methods[] = 'WC_Gateway_ZyPay_QRIS';
        return $methods;
    }
    add_filter('woocommerce_payment_gateways', 'add_zypay_qris_gateway');
}
?>

3. Integrasi Formulir WordPress (WPForms / Fluent Forms / CF7)

Jika Anda tidak menggunakan WooCommerce dan hanya memakai formulir pendaftaran / donasi di WordPress, Anda bisa menggunakan snippet di functions.php tema Anda.

Contoh Snippet Pembuat Tagihan Form:

functions.php (Tema Aktif Anda)
<?php
// Fungsi pembantu membuat tagihan Zy-Pay di WordPress
function buat_tagihan_zypay($nominal, $keterangan, $nama_pembeli = '') {
    $apiKey = 'ak_your_api_key_di_dashboard';
    $url    = 'https://cutiezy.id/zy-pay/api/v1/create-payment';

    $body = array(
        'amount'         => (int)$nominal,
        'description'    => $keterangan . ($nama_pembeli ? " ($nama_pembeli)" : ''),
        'expiry_minutes' => 30,
        'webhook_url'    => home_url('/wp-json/zypay/v1/webhook')
    );

    $response = wp_remote_post($url, array(
        'headers' => array(
            'Content-Type' => 'application/json',
            'X-API-Key'    => $apiKey
        ),
        'body'    => json_encode($body),
        'timeout' => 30
    ));

    if (is_wp_error($response)) {
        return false;
    }

    $json = json_decode(wp_remote_retrieve_body($response), true);
    if (!empty($json['success']) && !empty($json['data']['public_payment_url'])) {
        return $json['data']['public_payment_url']; // Link bayar pembeli
    }

    return false;
}

// Contoh redirect setelah submit form custom:
add_action('wp_ajax_nopriv_proses_bayar_form', 'handler_proses_bayar_form');
add_action('wp_ajax_proses_bayar_form', 'handler_proses_bayar_form');

function handler_proses_bayar_form() {
    $nominal = isset($_POST['nominal']) ? (int)$_POST['nominal'] : 0;
    $nama    = sanitize_text_field($_POST['nama'] ?? '');

    if ($nominal < 1000) {
        wp_send_json_error(array('message' => 'Minimal nominal Rp 1.000'));
    }

    $link_bayar = buat_tagihan_zypay($nominal, 'Pembayaran Form Web', $nama);

    if ($link_bayar) {
        wp_send_json_success(array('redirect_url' => $link_bayar));
    } else {
        wp_send_json_error(array('message' => 'Gagal membuat tagihan pembayaran.'));
    }
}
?>

4. Menerima Notifikasi Webhook Otomatis di WordPress

Ketika pembeli menyelesaikan pembayaran, Zy-Pay mengirimkan data webhook secara instan. Berikut cara membuat endpoint penerima webhook resmi via REST API WordPress:

functions.php — REST API Webhook Endpoint
<?php
// Mendaftarkan endpoint: https://domainanda.com/wp-json/zypay/v1/webhook
add_action('rest_api_init', function () {
    register_rest_route('zypay/v1', '/webhook', array(
        'methods'             => 'POST',
        'callback'            => 'zypay_handle_custom_webhook',
        'permission_callback' => '__return_true'
    ));
});

function zypay_handle_custom_webhook(WP_REST_Request $request) {
    $data = $request->get_json_params();

    if (empty($data) || empty($data['transaction_id'])) {
        return new WP_REST_Response(array('success' => false, 'message' => 'Payload kosong'), 400);
    }

    $trx_id = sanitize_text_field($data['transaction_id']);
    $status = strtolower($data['status'] ?? '');
    $amount = (int)($data['amount'] ?? 0);

    if ($status === 'paid') {
        // Logika bisnis Anda saat lunas:
        // 1. Ubah status order di database
        // 2. Kirim email aktivasi / produk digital ke pembeli
        // 3. Kirim notifikasi WhatsApp ke admin
        error_log("ZYPAY WEBHOOK SUCCESS: Transaksi {$trx_id} telah LUNAS senilai Rp {$amount}");
    }

    return new WP_REST_Response(array('success' => true, 'message' => 'Webhook diterima'), 200);
}
?>

5. Tips & Troubleshooting

Isu / Pertanyaan Solusi & Penjelasan
Error: 401 Unauthorized Pastikan X-API-Key sudah sesuai dengan API Key yang aktif di menu API Keys QRIS di Dashboard Zy-Pay.
Rate limit: Cooldown 3 Detik Zy-Pay memiliki sistem proteksi anti-spam tombol 1 request per 3 detik per user untuk mencegah pembeli menekan tombol bayar berulang kali.
Webhook tidak terpanggil di localhost Zy-Pay membutuhkan domain publik dengan SSL (HTTPS). Jika sedang development di localhost, gunakan ngrok untuk tunneling URL webhook.
Apakah aman tanpa SSL di WordPress? Sangat disarankan website WordPress Anda menggunakan HTTPS agar komunikasi API Key aman dari intercept jaringan.