Search by

cloudbadak / payment-hub

trisnawan

Hubungkan ke payment gateway pilihan dengan berbagai kemudahan dalam instalasi dan switch ke payment gateway lain dikemudian hari

Package info

github.com/cloudbadak/payment-hub

pkg:composer/cloudbadak/payment-hub

Statistics

Installs: 24

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.3.0 2026-11-04 13:24 UTC

This package is auto-updated.

Last update: 2026-11-04 13:27:40 UTC


README

Library PHP untuk menerima pembayaran melalui Midtrans, Pivot, Xendit, iPaymu, OY Indonesia, dan Flip Business dengan antarmuka PaymentHub, PaymentRequest, dan PaymentResponse yang sama.

Instalasi

Memerlukan PHP 8.1+ serta ekstensi curl, json, dan openssl. PHP 8.1 diperlukan karena library menggunakan enum.

composer require cloudbadak/payment-hub

Provider dan kemampuan

Tabel ini menunjukkan metode yang diimplementasikan driver. Kanal yang tersedia tetap mengikuti aktivasi dan persyaratan akun merchant masing-masing.

Provider / class di Cloudbadak\PaymentHub\Providers VA E-wallet Kartu QRIS Outlet PayLater Saldo
Midtrans / MidtransPayment Ya GoPay, ShopeePay Token kartu Ya Alfamart, Indomaret Akulaku, Kredivo —
Pivot / PivotPayment Ya DANA, ShopeePay Checkout Ya — — Ya
Xendit / XenditPayment Ya Ya Payment token v3 Ya Alfamart, Indomaret Akulaku, Kredivo Ya
iPaymu / IPaymuPayment Ya DANA, ShopeePay Checkout Ya Alfamart, Indomaret Akulaku Ya
OY Indonesia / OYIndonesiaPayment Checkout Checkout Checkout Checkout — — —
Flip Business / FlipBusinessPayment Ya Ya Checkout Checkout Alfamart, Indomaret — —

Semua driver menyediakan pembuatan pembayaran, cek status, dan pemrosesan webhook. Metode atau kanal yang belum didukung melempar UnsupportedPaymentMethodException sebelum mengirim request. PurwantaraPayment sudah dihapus; aplikasi yang menggunakannya perlu beralih ke salah satu provider di atas.

Driver Midtrans menggunakan Core API v2, Xendit menggunakan Payments API v3, iPaymu menggunakan Direct Payment v2, OY menggunakan Payment Checkout, dan Flip menggunakan Accept Payment v3. Midtrans Snap Checkout dan BI-SNAP merupakan API berbeda dan belum diimplementasikan driver ini. OVO/DANA Midtrans tidak dipetakan ke endpoint Core API legacy.

Konfigurasi

Lihat .env.example untuk daftar variabel. Library membaca environment proses melalui getenv(); aplikasi/framework bertanggung jawab memuat file .env. Environment yang diterima adalah development, sandbox, dan production, dengan default development.

Xendit memakai URL API yang sama untuk mode test/live; mode ditentukan oleh secret key yang digunakan.

Midtrans dan keempat driver baru juga menerima konfigurasi langsung, dengan prioritas di atas environment:

use Cloudbadak\PaymentHub\Providers\MidtransPayment;
use Cloudbadak\PaymentHub\Providers\XenditPayment;
use Cloudbadak\PaymentHub\Providers\IPaymuPayment;
use Cloudbadak\PaymentHub\Providers\OYIndonesiaPayment;
use Cloudbadak\PaymentHub\Providers\FlipBusinessPayment;

// Pilih satu provider. Tanpa argumen, konfigurasi diambil dari environment.
$gateway = new MidtransPayment();
$gateway = new XenditPayment();
$gateway = new IPaymuPayment();
$gateway = new OYIndonesiaPayment();
$gateway = new FlipBusinessPayment();

// Alternatif konfigurasi langsung:
$gateway = new MidtransPayment([
    'environment' => 'development',
    'server_key' => 'YOUR_SANDBOX_SERVER_KEY',
]);
Driver Key konfigurasi constructor Environment
Midtrans server_key, client_key, environment MIDTRANS_SERVER_KEY, MIDTRANS_CLIENT_KEY, MIDTRANS_ENVIRONMENT
Xendit secret_key, webhook_token XENDIT_SECRET_KEY, XENDIT_WEBHOOK_TOKEN
iPaymu va, api_key, notify_url, environment IPAYMU_VA, IPAYMU_API_KEY, IPAYMU_NOTIFY_URL, IPAYMU_ENVIRONMENT
OY username, api_key, environment OY_USERNAME, OY_API_KEY, OY_ENVIRONMENT
Flip secret_key, webhook_token, environment, base_url FLIP_SECRET_KEY, FLIP_WEBHOOK_TOKEN, FLIP_ENVIRONMENT, FLIP_BASE_URL

Client key Midtrans bersifat opsional untuk request backend. Token kartu Midtrans diperoleh melalui integrasi frontend Midtrans; token() pada library ini bukan pembuat token kartu. Untuk Xendit, gunakan payment_token_id v3, bukan token kartu API legacy.

Flip menyatakan sebagian fitur Direct API v3 belum tersedia di sandbox umum. Jika akun memakai staging khusus, isi FLIP_BASE_URL dengan URL staging dari Flip beserta prefix /big_api/. Production memakai https://bigflip.id/api/.

Pivot dan cache token

Constructor Pivot tetap kompatibel dengan integrasi lama:

use Cloudbadak\PaymentHub\Driver\CacheManager;
use Cloudbadak\PaymentHub\Providers\PivotPayment;

$cacheManager = new CacheManager([
    'default' => 'file',
    'drivers' => [
        'file' => [
            'type' => 'file',
            'path' => sys_get_temp_dir() . '/payment-hub-cache',
        ],
    ],
]);
$gateway = new PivotPayment($cacheManager->driver());

Atur PIVOT_ID, PIVOT_SECRET, PIVOT_WEBHOOK, dan PIVOT_ENVIRONMENT. Token dienkripsi dalam cache dan dipisahkan menurut akun serta environment. Adapter Redis, Memcache, database, Laravel, dan CodeIgniter juga tersedia melalui CacheManager.

Membuat pembayaran

require 'vendor/autoload.php';

use Cloudbadak\PaymentHub\PaymentHub;
use Cloudbadak\PaymentHub\Providers\MidtransPayment;
use Cloudbadak\PaymentHub\Data\Customer;
use Cloudbadak\PaymentHub\Data\Item;
use Cloudbadak\PaymentHub\Data\PaymentRequest;
use Cloudbadak\PaymentHub\Enums\BankCode;

$paymentHub = new PaymentHub(new MidtransPayment());
$customer = new Customer('CUSTOMER1', 'John', 'Doe', 'john@example.com', '081234567890');
$request = new PaymentRequest('ORDER123', 25000, $customer);
$request->setBank(BankCode::BNI);
$request->addItem(new Item('SKU1', 'Kopi', 'Kopi kemasan', 1, 25000));
$request->setReturnUrl('https://example.com/payment/return');

$response = $paymentHub->charge($request);
// Simpan orderId, paymentId, dan lookupId ke database aplikasi.
$virtualAccount = $response->virtualAccountNumber;

Nominal menggunakan bilangan bulat dalam rupiah. Order ID harus terisi dan nominal harus positif. Midtrans membatasi order ID hingga 50 karakter; OY menerima order ID alfanumerik. Jika mengirim item, jumlah price × quantity harus sesuai nominal transaksi.

iPaymu Direct membutuhkan nama, email, nomor telepon pelanggan, dan notification URL. Flip membutuhkan nama dan email pelanggan. Persyaratan tambahan masing-masing kanal, termasuk detail pelanggan/item/seller PayLater, mengikuti dokumentasi provider.

Pilih satu metode pada setiap request:

use Cloudbadak\PaymentHub\Enums\EWalletCode;
use Cloudbadak\PaymentHub\Enums\OutletCode;
use Cloudbadak\PaymentHub\Enums\QRPaymentCode;
use Cloudbadak\PaymentHub\Enums\CardlessCreditCode;
use Cloudbadak\PaymentHub\Enums\PaymentType;

$request->setWallet(EWalletCode::DANA);                // e-wallet
$request->setOutlet(OutletCode::ALFAMART);             // kasir outlet
$request->setQRPayment(QRPaymentCode::QRIS);           // QRIS
$request->setCardlessCredit(CardlessCreditCode::AKULAKU); // PayLater
$request->setCardTokenId('PROVIDER_CARD_TOKEN');       // Midtrans/Xendit

// Checkout kartu Pivot/iPaymu/OY/Flip tidak membutuhkan token kartu:
$request->setType(PaymentType::CARD);

// Notification URL per request (iPaymu), mengalahkan IPAYMU_NOTIFY_URL:
$request->setNotificationUrl('https://example.com/webhooks/ipaymu');

Gunakan setReturnUrl() untuk pengembalian browser. URL ini berbeda dengan webhook. ShopeePay Midtrans membutuhkan success return URL. Pada OY, pelanggan menyelesaikan pembayaran melalui paymentWebUrl; redirect URL mengikuti konfigurasi layanan OY.

Opsi khusus provider

setProviderOptions() menambahkan parameter API yang belum memiliki field umum. Identitas pesanan, nominal, dan metode yang dibentuk driver tetap diprioritaskan. Midtrans/Pivot menggabungkan opsi nested; driver lain menerima opsi level atas (termasuk channel_properties Xendit).

$request->setProviderOptions([
    'channel_properties' => [
        'expires_at' => '2027-01-01T12:00:00Z',
    ],
]); // Contoh khusus Xendit; gunakan hanya properti yang diterima kanal terpilih.

Data seller tersedia melalui setSeller(new Seller(...)); driver Midtrans mengirimkannya sebagai seller_details. Untuk detail shipping/item tambahan PayLater, gunakan opsi sesuai schema provider.

Hasil pembayaran dan cek status

PaymentResponse menyediakan orderId, paymentId, lookupId, amount, type, dan status, ditambah instruksi pembayaran jika tersedia:

  • VA: virtualAccountNumber, billerCode, billerName.
  • QR: qrCodeUrl dan/atau qrCodeString.
  • Outlet: paymentCode.
  • Redirect: paymentWebUrl atau paymentAppUrl.
  • Kartu: cardType, cardBrand, cardMasked, cardApprovalCode.
  • Waktu: createdAt, expiredAt, updatedAt, paidAt sesuai data provider.

type dapat null jika status response provider tidak menyertakan metode pembayaran. Status umum: UNPAID, PAID, EXPIRED, FAILED, dan REFUND. Partial refund dipetakan ke REFUND; capture yang masih menunggu persetujuan tetap UNPAID.

$status = $paymentHub->get($response->lookupId);

Simpan lookupId karena identifier cek status berbeda menurut provider:

Provider Nilai untuk get()
Midtrans Order ID aplikasi
Pivot clientReferenceId / order ID aplikasi
Xendit payment_request_id
iPaymu TransactionId
OY partner_tx_id / order ID aplikasi
Flip link_id tagihan, sebagai string

Flip memakai ID tagihan 19 digit. Library mempertahankan bilangan JSON besar sebagai string; simpan ID tersebut sebagai string di aplikasi/database. paymentId dapat berbeda dari lookupId dan pada OY dapat berganti dari ID payment link menjadi referensi transaksi setelah pembayaran.

Saldo tersedia melalui $paymentHub->balance() untuk Pivot, Xendit, dan iPaymu. token() menghasilkan access token pada Pivot, dan null pada driver lain.

Webhook

Konfigurasikan endpoint aplikasi pada dashboard provider; iPaymu juga menerima notifyUrl per request. Library mengembalikan PaymentResponse setelah verifikasi:

Provider Verifikasi
Midtrans SHA-512 order_id + status_code + gross_amount + server_key
Pivot Header X-API-Key dibandingkan dengan PIVOT_WEBHOOK
Xendit Header X-Callback-Token dibandingkan dengan XENDIT_WEBHOOK_TOKEN
iPaymu Header X-Signature, HMAC-SHA256 payload terurut dengan merchant VA; JSON dan form didukung
OY Status diambil ulang melalui API dengan kredensial merchant; status/nominal callback tidak dipercaya
Flip Token validasi dalam body token; body form atau JSON dengan data didukung
// $paymentHub harus memakai provider yang sesuai endpoint ini.
$response = $paymentHub->webhook(); // membaca php://input dan header request

// Alternatif untuk framework: berikan body mentah, pertahankan header asli.
$response = $paymentHub->webhook($rawBody);

Verifikasi yang gagal atau body tidak valid menghasilkan exception. Setelah verifikasi, aplikasi perlu mencocokkan order dan nominal dengan database, memproses callback secara idempoten, serta mengembalikan respons HTTP sesuai kontrak provider. Library tidak menulis database atau mengirim HTTP response untuk aplikasi.

Penanganan error

  • UnsupportedPaymentMethodException: metode/kanal tidak tersedia pada driver.
  • RequestClientException: konfigurasi/input tidak valid, autentikasi webhook gagal, atau API menolak request.
  • RequestServerException: provider bermasalah atau response API tidak valid.
  • PaymentException: kegagalan pemrosesan token/enkripsi Pivot.

Pengujian

composer install
composer validate --strict
php vendor/phpunit/phpunit/phpunit

Test provider menggunakan driver sebenarnya dengan transport HTTP tiruan. Test ApiRequest memakai server HTTP lokal untuk memeriksa JSON, form, query, status HTTP, dan ID JSON besar. Seluruh test baru berjalan tanpa akun merchant atau transaksi uang sungguhan. Test live Pivot lama masih berstatus skipped/incomplete; validasi sandbox/live memerlukan kredensial dan aktivasi merchant.

Referensi API