gusmanwidodo/laravel-billing-midtrans

Midtrans (Snap) payment provider for gusmanwidodo/laravel-billing. Implements the PaymentProvider contract: Snap charge, SHA512 webhook verification, status mapping, and refund.

Maintainers

Package info

github.com/gusmanwidodo/laravel-billing-midtrans

pkg:composer/gusmanwidodo/laravel-billing-midtrans

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-08-26 13:19 UTC

This package is auto-updated.

Last update: 2026-08-26 13:22:15 UTC


README

Midtrans (Snap) payment provider for gusmanwidodo/laravel-billing. It implements the billing PaymentProvider contract, so once installed you can charge invoices through Midtrans and settle them from verified webhooks.

Tests License: MIT

Features

  • Snap charge — opens a Snap transaction and returns its token + redirect URL.
  • Webhook verification — validates the Midtrans SHA512 signature_key (order_id + status_code + gross_amount + serverKey). Forged/tampered notifications are rejected.
  • Status mapping — settlement/capture(accept) → succeeded, pending → pending, deny → failed, cancel/expire → canceled, refund → refunded.
  • Refund — calls the Midtrans refund endpoint.
  • Auto-registers itself into laravel-billing's provider registry.

Requirements

  • PHP ^8.3
  • gusmanwidodo/laravel-billing ^0.4
  • Laravel 12
  • A Midtrans account (server + client keys)

Installation

composer require gusmanwidodo/laravel-billing-midtrans
php artisan vendor:publish --tag=billing-midtrans-config

Set your keys in .env:

MIDTRANS_SERVER_KEY=your-server-key
MIDTRANS_CLIENT_KEY=your-client-key
MIDTRANS_PRODUCTION=false
MIDTRANS_AS_DEFAULT=false
# minor-unit decimals used by your invoices (2 = cents; IDR gross is whole rupiah)
MIDTRANS_DECIMALS=2

Usage

use Gusmanwidodo\Billing\Facades\Billing;

// 1. Charge an invoice via Midtrans -> pending intent with the Snap redirect URL.
$intent = Billing::charge($invoice, provider: 'midtrans');
$snapUrl = $intent->meta['redirect_url'];   // send the customer here
$snapToken = $intent->meta['snap_token'];   // or use with Snap.js

// 2. In your Midtrans webhook route, hand the raw body + headers to billing.
//    The signature is verified before anything is recorded.
Route::post('/webhooks/midtrans', function (Illuminate\Http\Request $request) {
    try {
        Billing::handleWebhook('midtrans', $request->getContent(), $request->headers->all());
    } catch (\RuntimeException $e) {
        abort(403); // signature verification failed
    }
    return response()->json(['ok' => true]);
});

// 3. Refund a succeeded intent.
Billing::refund($intent);

On a verified settlement/capture(accept) notification, a real Payment is recorded and the invoice becomes paid automatically. Settlement is idempotent (Midtrans may resend), keyed by the intent's external_id (the order_id).

Amounts & currency

laravel-billing stores money as integer minor units. Midtrans gross_amount is whole rupiah. This package converts using MIDTRANS_DECIMALS (default 2): 1_000_000 minor units → gross_amount = 10000. Set MIDTRANS_DECIMALS=0 if your invoices already store whole rupiah.

Security

Webhook signature verification is mandatory — Billing::handleWebhook('midtrans', ...) throws if the SHA512 signature_key does not match, so a forged or tampered notification never records a payment. Always also confirm status_code=200, fraud_status=accept, and a settlement/capture status (this package's mapping already enforces the fraud/status logic).

Testing

composer test   # 12 tests, all HTTP mocked via Http::fake (no real API key needed)

License

MIT © Gusman Widodo. See LICENSE.