webmobyle/paychangu-payments

Drop-in Paychangu payments for Laravel with Card, Mobile Money and Bank payment options

Installs: 11

Dependents: 0

Suggesters: 0

Security: 0

pkg:composer/webmobyle/paychangu-payments

1.0.5 2025-11-29 07:32 UTC

This package is auto-updated.

Last update: 2025-12-29 07:40:00 UTC


README

Packagist Version License Laravel

A clean, modern Laravel integration for Paychangu that supports hosted checkout, mobile money, card payments, webhook verification, and flexible payment recording.

This package is designed to be simple, extensible, and production-ready โ€” modeled after the structure of the webmobyle/dpo-payments package.

๐Ÿš€ Features

  • Paychangu Hosted Checkout support
  • Card and Mobile Money payment methods
  • Automatic creation & tracking of PaychanguCharge records
  • Webhook verification with HMAC-SHA256
  • Configurable callback_url and return_url
  • Elegant, Laravel-native API
  • Laravel 10/11/12 support

See CHANGELOG.md for release history.

๐Ÿ“ฆ Installation

Install via Composer:

composer require webmobyle/paychangu-payments

Publish the configuration and migrations:

php artisan vendor:publish --provider="Webmobyle\PaychanguPayments\PaychanguPaymentsServiceProvider" --tag=paychangu-config

php artisan vendor:publish --provider="Webmobyle\PaychanguPayments\PaychanguPaymentsServiceProvider" --tag=paychangu-migrations

Run migrations:

php artisan migrate

โš™๏ธ Configuration

Add these keys to your .env:

PAYCHANGU_PUBLIC_KEY=pub-xxx
PAYCHANGU_SECRET_KEY=sec-xxx

# For browser redirect after checkout
PAYCHANGU_RETURN_URL=https://your-domain.com/paychangu/callback

# For retun in case of cacellation or failure
PAYCHANGU_RETURN_URL=https://your-domain.com/paychangu/return

# For webhooks (server-to-server)
PAYCHANGU_CALLBACK_URL=https://your-domain.com/paychangu/webhook

# Webhook signature verification
PAYCHANGU_WEBHOOK_SECRET=your_webhook_secret_here

PAYCHANGU_CURRENCY=MWK

๐Ÿงฉ How It Works

Initiate a Payment

use Webmobyle\PaychanguPayments\PaychanguService;

public function createOrder()
{
    $order = Order::create([
    	'order_number'   => 'TST-'.now()->format('YmdHis'),
        'total_amount' => 10000,
        'email'  => 'customer@example.com',
    ]);

    $paychangu = app(PaychanguService::class);

    $response = $paychangu->initiate(
        payable: $order,
        amount: $order->total_amount,
        customer: [
            'email' => $order->email,
            'first_name'  => 'John',
            'last_name' => 'Mzoma',
        ],
        description: "Payment for Order #{$order->order_number}"
    );

    return redirect($response['checkout_url']);
}

Add the payments trait to your payable model

For example, App\Models\Order:

use Webmobyle\PaychanguPayments\Traits\HasPaychanguPayments;

class Order extends Model
{
    use HasPaychanguPayments;

    // ...
}

Sample Order Table Migration

public function up(): void
{
    Schema::create('orders', function (Blueprint $table) {
        $table->id();
        $table->string('order_number')->unique();
        $table->unsignedBigInteger('total_amount'); // store in MWK
        $table->enum('payment_status', ['PENDING', 'PAID'])->default('PENDING');
        $table->timestamp('paid_at')->nullable();
        $table->timestamps();
    });
}

If you want to customize the look of the results page in a given project

php artisan vendor:publish --provider="Webmobyle\PaychanguPayments\PaychanguPaymentsServiceProvider" --tag=paychangu-views

Then in your app, you can listen for this event to update orders, wallets, etc.

Listener in your app

<?php

namespace App\Listeners;

use Webmobyle\PaychanguPayments\Events\PaychanguPaymentVerified;

class MarkOrderPaidFromPaychangu
{
    public function handle(PaychanguPaymentVerified $event): void
    {
        $charge = $event->charge;
        $payable = $charge->payable;

        // Only handle for Order model, ignore others
        if (! $payable instanceof \App\Models\Order) {
            return;
        }

        if ($charge->isSuccessful()) {
            // Your custom logic. Example:
            if ($payable->payment_status !== 'PAID') {
                $payable->payment_status = 'PAID';
                $payable->paid_at = now();
                $payable->save();
            }
        }
    }
}

Register in EventServiceProvider

In app/Providers/EventServiceProvider.php:

protected $listen = [
    \Webmobyle\PaychanguPayments\Events\PaychanguPaymentVerified::class => [
        \App\Listeners\MarkOrderPaidFromPaychangu::class,
    ],
];

Like so;

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event to listener mappings for the application.
     *
     * @var array<class-string, array<int, class-string>>
     */
    protected $listen = [
        \Webmobyle\PaychanguPayments\Events\PaychanguPaymentVerified::class => [
            \App\Listeners\MarkOrderPaidFromPaychangu::class,
        ],
    ];

    /**
     * Register services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap services.
     */
    public function boot(): void
    {
        //
    }
}

๐Ÿ” Callback (Browser Redirect)

Handled automatically by the package.

Route:

/paychangu/callback

โฌ…๏ธ Return (Browser Redirect)

Implement this route and view for situations where the user cancels or there a is failure.

Route:

/paychangu/return

๐Ÿ“ก Webhook Handling

Handled automatically by the package.

Webhook endpoint:

POST /paychangu/webhook

The package:

  • Verifies signature
  • Re-verifies the transaction via Paychangu API
  • Updates the charge
  • Fires an event

๐Ÿงพ Events

PaychanguPaymentVerified

Triggered when a payment is successfully verified.

๐Ÿ“ Model: PaychanguCharge

Tracks all payment attempts and confirmations.

This model conects to a `mysqldatabase connection by default. To modify this behaviour add the following configuration key in theconfig/database.php` file.

'paychangu_connection' => env('PAYCHANGU_DB_CONNECTION', 'mysql'),

๐Ÿงฑ Requirements

DependencyVersion
PHP^8.2
Laravel10.x - 12.x
GuzzleHTTP^7.8

๐Ÿ“ฆ Versioning

This package follows Semantic Versioning (SemVer) โ€” tag releases like v1.0.0, v1.1.0, etc.

๐Ÿชช License

This package is open-sourced software licensed under the MIT License.

๐Ÿ‘ค Author

Barnett Temwa Msiska
Founder, Webmobyle Limited
๐Ÿ“ง barnett@webmobyle.com

โญ Support

If you find this package useful, please star it on Packagist or Bitbucket.
Contributions, pull requests, and issues are welcome!

Email: contact@webmobyle.com