PHPackages                             jiannius/senangpay - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Payment Processing](/categories/payments)
4. /
5. jiannius/senangpay

ActiveLibrary[Payment Processing](/categories/payments)

jiannius/senangpay
==================

SenangPay SDK Wrapper

v1.0(1mo ago)01.0kMITPHPPHP ^8.3

Since May 13Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/jiannius/senangpay)[ Packagist](https://packagist.org/packages/jiannius/senangpay)[ RSS](/packages/jiannius-senangpay/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (5)Versions (3)Used By (0)

Jiannius SenangPay
==================

[](#jiannius-senangpay)

A Laravel SDK wrapper for [SenangPay](https://senangpay.my), the Malaysian payment gateway. It signs the outbound hash, validates inbound callbacks (regular and recurring), and wires the redirect / callback / webhook routes so you only have to write the controller actions.

Requirements
------------

[](#requirements)

- PHP 8.3+
- Laravel 13

Installation
------------

[](#installation)

```
composer require jiannius/senangpay
```

The service provider is auto-discovered. Nothing to publish.

Configuration
-------------

[](#configuration)

Add a `senangpay` entry to `config/services.php`:

```
'senangpay' => [
    'merchant_id' => env('SENANGPAY_MERCHANT_ID'),
    'secret_key'  => env('SENANGPAY_SECRET_KEY'),
    'sandbox'     => env('SENANGPAY_SANDBOX', false),
],
```

In the SenangPay dashboard (*Menu → Settings → Profile → Shopping Cart Integration Link*), set **Hash Type to SHA256**. MD5 is not supported by this package and will silently mismatch every signature.

Routes &amp; the host controller
--------------------------------

[](#routes--the-host-controller)

The service provider registers three routes under the `/__senangpay` prefix and dispatches them to `App\Http\Controllers\SenangpayController` in your app. You must create that controller.

MethodPathActionPurposeGET`/__senangpay/redirect``redirect`Return URL — browser lands here after paymentGET`/__senangpay/recurring``recurring`Recurring-payment callback (new/remove/terminate)POST`/__senangpay/webhook``webhook`Server-to-server callbackRoutes are registered with `->withoutMiddleware('web')` so the webhook is not blocked by CSRF.

```
namespace App\Http\Controllers;

class SenangpayController extends Controller
{
    public function redirect()
    {
        $sp = app('senangpay');

        if (! $sp->validatePayload()) {
            abort(403);
        }

        return match ($sp->getStatus()) {
            'success' => view('checkout.success'),
            'failed'  => view('checkout.failed'),
            default   => view('checkout.pending'),
        };
    }

    public function webhook()
    {
        $sp = app('senangpay');

        if (! $sp->validatePayload()) {
            abort(403);
        }

        // Update your order here. MUST be idempotent — SenangPay calls this
        // webhook multiple times for the same transaction (see "Host-app
        // contracts" below).

        return 'OK'; // Literal string "OK". No HTML, no JSON, no redirect.
    }

    public function recurring()
    {
        $sp = app('senangpay');

        if (! $sp->validateRecurringPayload()) {
            abort(403);
        }

        $action = request()->input('action');
        // 'new_schedule' | 'remove_schedule' | 'terminate'
    }
}
```

Usage
-----

[](#usage)

### Redirect to checkout

[](#redirect-to-checkout)

`checkout()` returns a Laravel `RedirectResponse` to SenangPay's hosted payment page. Return it directly from your controller.

```
return app('senangpay')->checkout([
    'order_id' => $order->id,
    'name'     => $order->customer_name,
    'email'    => $order->customer_email,
    'phone'    => $order->customer_phone,
    'detail'   => 'Order #' . $order->id,
    'amount'   => $order->total, // numeric, e.g. 49.90
]);
```

`amount` is normalised to a two-decimal string (`"49.90"`) before hashing — pass it as a plain number, not a pre-formatted string.

### Query an order's status (server-to-server)

[](#query-an-orders-status-server-to-server)

```
$status = app('senangpay')->queryOrderStatus($orderId);
```

Returns the first record from SenangPay's `query_order_status` response.

### Normalised payment status

[](#normalised-payment-status)

When called inside the `redirect` or `webhook` action, `getStatus()` collapses SenangPay's mixed numeric/string status values into one of `success`, `failed`, `pending`, or `null`.

```
$result = app('senangpay')->getStatus(); // 'success' | 'failed' | 'pending' | null
```

### Per-tenant credentials at runtime

[](#per-tenant-credentials-at-runtime)

Setters override the `config('services.senangpay.*')` defaults for the current request.

```
$sp = app('senangpay')
    ->setMerchantId($tenant->senangpay_merchant_id)
    ->setSecretKey($tenant->senangpay_secret_key)
    ->setSandbox($tenant->senangpay_sandbox);
```

### Test the connection

[](#test-the-connection)

```
['success' => $ok, 'error' => $err] = app('senangpay')->test();
```

Hits `query_order_status` with a dummy order id — useful for a settings-page "Test credentials" button.

Host-app contracts
------------------

[](#host-app-contracts)

These aren't enforced by the package. Get them wrong and integrations silently break.

1. **The `webhook` action must respond with the literal string `OK`.** No HTML tags, no JSON, no redirect. If SenangPay doesn't see `OK` in the response body, the callback is treated as failed and the merchant gets an email.
2. **The `webhook` action must be idempotent on `(order_id, status_id)`.** SenangPay retries on a schedule: first call ~5 minutes after the transaction starts (if pending), real-time on any status change, and a final call ~1 hour after the transaction starts. A successful payment will hit your webhook multiple times.
3. **The dashboard hash type must be SHA256.** This package does not support MD5.

Reference
---------

[](#reference)

SenangPay developer documentation:

- [Index](https://guide.senangpay.com/developer-tools)
- [Hash type &amp; credentials](https://guide.senangpay.com/merchant-id-and-secret-key)
- [Return URL parameters](https://guide.senangpay.com/return-url)
- [Callback URL](https://guide.senangpay.com/what-is-callback-url-and-how-to-set-it)
- [Query order status](https://guide.senangpay.com/query-order-status)
- [Query transaction status](https://guide.senangpay.com/query-transaction-status)
- [Recurring callback](https://guide.senangpay.com/enhancement-of-recurring-features)

License
-------

[](#license)

MIT — see [LICENSE.md](LICENSE.md).

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance90

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

52d ago

Major Versions

v0.1 → v1.02026-05-13

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/101174228?v=4)[Jiannius Technologies Sdn. Bhd.](/maintainers/jiannius)[@jiannius](https://github.com/jiannius)

---

Top Contributors

[![tjloong](https://avatars.githubusercontent.com/u/2275921?v=4)](https://github.com/tjloong "tjloong (5 commits)")

### Embed Badge

![Health badge](/badges/jiannius-senangpay/health.svg)

```
[![Health](https://phpackages.com/badges/jiannius-senangpay/health.svg)](https://phpackages.com/packages/jiannius-senangpay)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.1k](/packages/craftcms-cms)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M572](/packages/shopware-core)[chameleon-system/chameleon-base

The Chameleon System core.

1028.6k5](/packages/chameleon-system-chameleon-base)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
