Panduan lengkap menerima pembayaran QRIS otomatis di WordPress & WooCommerce menggunakan Link Pembayaran Siap Pakai dan Webhook Real-time.
Ya, menggunakan Link Pembayaran (public_payment_url) adalah cara paling praktis, aman, dan tanpa repot di WordPress!
Pembeli klik tombol Checkout di WooCommerce atau submit formulir pesanan.
Server WordPress memanggil API Zy-Pay (POST /create-payment) dan mendapatkan public_payment_url.
Pembeli langsung dialihkan ke halaman bayar resmi (contoh: pay.php?id=...) yang menampilkan QRIS, total unik, dan timer hitung mundur.
Begitu scan via BCA/Mandiri/GoPay/ShopeePay/dll, Zy-Pay menembak Webhook ke WordPress dan order berubah status jadi LUNAS.
Anda bisa langsung memasang gateway Zy-Pay QRIS di toko online WooCommerce Anda dengan membuat 1 file plugin baru tanpa perlu coding ulang.
wp-content/plugins/.zypay-qris dan buat file zypay-qris.php di dalamnya.<?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');
}
?>
Jika Anda tidak menggunakan WooCommerce dan hanya memakai formulir pendaftaran / donasi di WordPress, Anda bisa menggunakan snippet di functions.php tema 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.'));
}
}
?>
Ketika pembeli menyelesaikan pembayaran, Zy-Pay mengirimkan data webhook secara instan. Berikut cara membuat endpoint penerima webhook resmi via REST API WordPress:
<?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);
}
?>
| 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. |