定制 jiannius/senangpay 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

jiannius/senangpay

最新稳定版本:v1.0

Composer 安装命令:

composer require jiannius/senangpay

包简介

SenangPay SDK Wrapper

README 文档

README

A Laravel SDK wrapper for SenangPay, 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

  • PHP 8.3+
  • Laravel 13

Installation

composer require jiannius/senangpay

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

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 & 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.

Method Path Action Purpose
GET /__senangpay/redirect redirect Return URL — browser lands here after payment
GET /__senangpay/recurring recurring Recurring-payment callback (new/remove/terminate)
POST /__senangpay/webhook webhook Server-to-server callback

Routes 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

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)

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

Returns the first record from SenangPay's query_order_status response.

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

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

['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

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

SenangPay developer documentation:

License

MIT — see LICENSE.md.

统计信息

  • 总下载量: 615
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-01-12

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固