Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Duitnow Laravel Package

zarulizham/laravel-duitnow

A Laravel wrapper for DuitNow, Malaysia's real-time payment network. It simplifies initiating DuitNow payments, handling responses, and integrating with PayNet's DuitNow APIs so you can accept instant bank transfers in your Laravel app without building the integration yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its assets using the commands documented in the README. A typical setup looks like:

composer require zarulizham/laravel-duitnow

php artisan vendor:publish --provider="Zarulizham\DuitNow\DuitNowServiceProvider"

Check the provider/package README for the exact publish tags. Then inspect these first:

  • config/duitnow.php for credentials, environment/sandbox mode, callback URLs, and HTTP options.
  • src/ for the main service/facade/client class and any DTOs or enums.
  • routes/ for any package-provided callback/webhook routes.
  • database/migrations/ if the package publishes tables.
  • The README examples and package tests for real method signatures.

Set credentials in .env, never in committed config:

DUITNOW_ENV=sandbox
DUITNOW_CLIENT_ID=
DUITNOW_CLIENT_SECRET=
DUITNOW_PRIVATE_KEY=
DUITNOW_CALLBACK_URL="${APP_URL}/duitnow/callback"

First useful use case: create a sandbox payment/QR with a unique application reference, persist the local payment record, display the QR or redirect URL, and implement a callback endpoint that updates the record. Confirm the exact package method names in the README before wiring it into checkout.

Implementation Patterns

Wrap the package behind your own application service rather than calling it directly from controllers:

final class DuitNowPaymentService
{
    public function create(Order $order): Payment
    {
        $payment = Payment::create([
            'order_id' => $order->id,
            'reference' => (string) Str::uuid(),
            'amount_minor' => $order->total_minor,
            'currency' => 'MYR',
            'status' => 'pending',
        ]);

        $response = DuitNow::createPayment([
            'reference_id' => $payment->reference,
            'amount' => $payment->amount_minor,
            'currency' => 'MYR',
            'callback_url' => route('duitnow.callback'),
            'return_url' => route('checkout.return'),
        ]);

        $payment->update([
            'provider_reference' => $response['id'] ?? null,
            'payload' => $response,
        ]);

        return $payment;
    }
}

Use a local payment/transaction table as the source of truth. Store your reference, provider reference, amount in minor units, status, raw request/response, and timestamps. Add a unique constraint on your reference and the provider reference where possible.

For callbacks:

  1. Exclude the callback route from CSRF and auth middleware.
  2. Verify the package’s signature/token mechanism against the raw request body.
  3. Look up the local payment by reference.
  4. Ignore duplicate or already-final callbacks.
  5. Fetch/verify authoritative status from DuitNow if the package supports it.
  6. Update status inside a transaction and dispatch a domain event such as PaymentSucceeded.
  7. Return 200 quickly; push heavier work to a queue.

Use Laravel events/listeners for fulfilment, receipts, and notifications. Use a scheduled command to reconcile pending payments by polling status, because callbacks can be delayed or missed.

For tests, use Http::fake() around the package’s HTTP client if the package uses Laravel’s HTTP client, and exercise sandbox credentials in a staging environment. Test duplicate callbacks, failed signatures, amount mismatches, and out-of-order statuses.

Gotchas and Tips

  • DuitNow is asynchronous: do not mark an order paid from the return URL alone. Treat the return page as a status display and rely on verified callbacks plus reconciliation.
  • Verify webhook signatures using the raw request body. Re-encoding $request->all() can break canonicalisation.
  • Amounts are usually minor units. Avoid floats; store and compare integers.
  • Handle duplicate and out-of-order callbacks idempotently. Never move a payment from paid back to pending because a delayed callback arrives.
  • Public callbacks need a public HTTPS URL. Local development requires a tunnel and the tunnel URL must be registered with the provider.
  • Be careful with private keys in .env: multiline PEM values often need quoting or base64 decoding. Run php artisan config:clear after changes and remember config:cache freezes env values.
  • Do not log secrets, tokens, full private keys, or unnecessary customer PII. Log references and status transitions instead.
  • Configure timeouts and retries carefully. A timeout does not mean failure; reconcile before retrying a payment creation that may already exist.
  • The package is a small wrapper, not an official PayNet SDK. Pin a version, read the source for undocumented methods, and confirm which DuitNow product it covers: QR, online banking/fund transfer, request-to-pay, etc.
  • Extension points are usually the published config, service container bindings, events, and custom HTTP client options. If multi-tenant credentials are needed, avoid global config mutation; bind a configured client per tenant if the package supports it.
  • Add a local status enum and state machine around the package’s string statuses. This keeps your app stable if the package changes response shapes.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log