承接 winpay/laravel-sdk 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

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

winpay/laravel-sdk

最新稳定版本:1.0.0

Composer 安装命令:

composer require winpay/laravel-sdk

包简介

Winpay Laravel SDK - Official Laravel wrapper for Winpay payment gateway

README 文档

README

Library Laravel resmi untuk Winpay Payment Gateway — integrasi SNAP API & Checkout Page.

Requires: PHP ^8.1, Laravel ^9.0 | ^10.0 | ^11.0

Install

composer require winpay/laravel-sdk

Service provider & facade terdaftar otomatis via auto-discovery.

Konfigurasi

Environment Variables (.env)

WINPAY_PARTNER_ID=your_partner_id
WINPAY_MERCHANT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQ..."
WINPAY_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIIBIj..."
WINPAY_CHANNEL_ID=WEB
WINPAY_BASE_URL=https://sandbox-api.bmstaging.id/snap
WINPAY_TIMEOUT=30
WINPAY_VERIFY_SSL=true
WINPAY_REGISTER_ROUTES=true

# Checkout Page (HMAC)
WINPAY_CHECKOUT_KEY=your_checkout_key
WINPAY_CHECKOUT_SECRET_KEY=your_checkout_secret_key
WINPAY_CHECKOUT_BASE_URL=https://sandbox-checkout.winpay.id

Key bisa inline PEM string atau path file:

# Inline
WINPAY_MERCHANT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvQ..."

# File path
WINPAY_MERCHANT_PRIVATE_KEY=/path/to/merchant-private.pem

Publish Config (opsional)

php artisan vendor:publish --tag=winpay-config

Cara Pakai

Via Facade

use Winpay;

$response = Winpay::snap()->va()->create([...]);

Via Dependency Injection

use Winpay\Core\WinpayClient;

class OrderController
{
    public function __construct(
        private readonly WinpayClient $winpay,
    ) {}

    public function store()
    {
        $response = $this->winpay->va->create([...]);
    }
}

Response Format

Semua method mengembalikan Winpay\Core\Models\WinpayResponse:

$response->responseCode     // string|null, e.g. "2002700"
$response->responseMessage  // string|null, e.g. "Successful"
$response->httpStatusCode   // int, e.g. 200
$response->data             // array, full response payload
$response->isSuccess()      // bool, true jika 2xx
$response->get('key')       // mixed, akses data by key
$response->get('key', 'default')

Services

Gunakan Winpay::snap() untuk akses semua channel dengan verb konsisten:

$snap = Winpay::snap();

$snap->va()->create($payload)
$snap->va()->inquiry($payload)
$snap->va()->status($payload)
$snap->va()->delete($payload)

$snap->qris()->create($payload)
$snap->qris()->status($payload)
$snap->qris()->cancel($payload)

$snap->ewallet()->create($payload)
$snap->ewallet()->status($payload)
$snap->ewallet()->cancel($payload)

$snap->creditCard()->create($payload)
$snap->creditCard()->status($payload)
$snap->creditCard()->cancel($payload)

$snap->retail()->create($payload)
$snap->retail()->status($payload)
$snap->retail()->cancel($payload)

$snap->report()->balance($payload)
$snap->report()->history($payload)
$snap->report()->statement($payload)

# Checkout Page (HMAC)
$snap->checkout()->create($payload)
$snap->checkout()->find($id)
$snap->checkout()->findByRef($merchantRef)
$snap->checkout()->update($id, $payload)
$snap->checkout()->delete($id)
$snap->checkout()->deleteByRef($merchantRef)

Virtual Account

use Winpay\Core\Enums\VaChannel;
use Winpay\Core\Enums\VaType;

// Create VA
$va = Winpay::snap()->va()->create([
    'partnerServiceId' => '35539457',
    'customerNo' => '9876543210',
    'virtualAccountNo' => '355394579876543210',
    'virtualAccountName' => 'John Doe',
    'virtualAccountTrxType' => VaType::ONE_OFF->value,
    'totalAmount' => ['value' => '100000.00', 'currency' => 'IDR'],
    'expiredDate' => '2026-12-31T23:59:59+07:00',
]);

// Inquiry VA
$va = Winpay::snap()->va()->inquiry([
    'partnerServiceId' => '35539457',
    'customerNo' => '9876543210',
    'virtualAccountNo' => '355394579876543210',
]);

// Status VA
$va = Winpay::snap()->va()->status([
    'partnerServiceId' => '35539457',
    'customerNo' => '9876543210',
    'virtualAccountNo' => '355394579876543210',
]);

// Delete VA
Winpay::snap()->va()->delete([
    'partnerServiceId' => '35539457',
    'customerNo' => '9876543210',
    'virtualAccountNo' => '355394579876543210',
]);

Bank Channel (VaChannel)

BRI, BNI, MANDIRI, MANDIRI_PC, PERMATA, BSI, MUAMALAT, BCA, CIMB, SINARMAS, BNC, MAYBANK

VA Type (VaType)

Enum Value Keterangan
VaType::ONE_OFF c Dibayar sekali, closed setelah dibayar
VaType::OPEN_RECURRING o Bisa dipakai berulang, nominal bebas
VaType::CLOSE_RECURRING r Bisa dipakai berulang, nominal tetap

QRIS

// Generate QRIS
$qris = Winpay::snap()->qris()->create([
    'partnerServiceId' => '35539457',
    'amount' => [
        'value' => '50000.00',
        'currency' => 'IDR',
    ],
    'merchantId' => 'MERCHANT001',
    'storeId' => 'STORE001',
    'validityPeriod' => '2026-12-31T23:59:59+07:00',
]);

// Query QRIS
$qris = Winpay::snap()->qris()->status([
    'originalReferenceNo' => 'ORIG_REF_001',
]);

// Cancel QRIS
Winpay::snap()->qris()->cancel([
    'originalReferenceNo' => 'ORIG_REF_001',
]);

E-Wallet

use Winpay\Core\Enums\EwalletChannel;

// Create Payment
$ewallet = Winpay::snap()->ewallet()->create([
    'partnerReferenceNo' => 'REF-001',
    'amount' => ['value' => '25000.00', 'currency' => 'IDR'],
    'additionalInfo' => [
        'channel' => EwalletChannel::DANA->value,
        'customerName' => 'John Doe',
    ],
]);

// Status
$ewallet = Winpay::snap()->ewallet()->status([
    'originalReferenceNo' => 'REF-001',
]);

// Cancel
Winpay::snap()->ewallet()->cancel([
    'originalReferenceNo' => 'REF-001',
]);

Channel (EwalletChannel)

Enum Value
EwalletChannel::SPEEDCASH SC
EwalletChannel::OVO OVO
EwalletChannel::DANA DANA
EwalletChannel::SHOPEEPAY SPAY
EwalletChannel::ASTRAPAY ASTRA

Credit Card

// Create Payment
$cc = Winpay::snap()->creditCard()->create([
    'partnerReferenceNo' => 'REF-001',
    'amount' => ['value' => '500000.00', 'currency' => 'IDR'],
    'additionalInfo' => [
        'channel' => 'CC',
        'customerName' => 'John Doe',
    ],
]);

// Status
$cc = Winpay::snap()->creditCard()->status([...]);

// Cancel
Winpay::snap()->creditCard()->cancel([...]);

Retail / OTC

use Winpay\Core\Enums\RetailChannel;

$retail = Winpay::snap()->retail()->create([
    'partnerServiceId' => '35539457',
    'customerNo' => '9876543210',
    'paymentCode' => '355394579876543210',
    'customerName' => 'John Doe',
    'totalAmount' => ['value' => '50000.00', 'currency' => 'IDR'],
    'additionalInfo' => [
        'channel' => RetailChannel::ALFAMART->value,
    ],
]);

// Status
$retail = Winpay::snap()->retail()->status([
    'originalReferenceNo' => 'REF-001',
]);

// Cancel
Winpay::snap()->retail()->cancel([
    'originalReferenceNo' => 'REF-001',
]);

Channel (RetailChannel)

Enum Value
RetailChannel::ALFAMART ALFAMART
RetailChannel::INDOMARET INDOMARET
RetailChannel::FASTPAY FASTPAY

Report

// Balance Inquiry
$balance = Winpay::snap()->report()->balance([
    'partnerServiceId' => '35539457',
]);

// Transaction History
$history = Winpay::snap()->report()->history([
    'fromDateTime' => '2026-01-01T00:00:00+07:00',
    'toDateTime' => '2026-12-31T23:59:59+07:00',
]);

// Bank Statement
$statement = Winpay::snap()->report()->statement([
    'accountNo' => '1234567890',
    'fromDateTime' => '2026-01-01T00:00:00+07:00',
    'toDateTime' => '2026-12-31T23:59:59+07:00',
]);

Checkout Page

Gunakan HMAC-SHA256 signature dengan header X-Winpay-Key, X-Winpay-Timestamp, X-Winpay-Signature.

// Create Invoice
$invoice = Winpay::snap()->checkout()->create([
    'customer' => [
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'phone' => '081234567890',
    ],
    'items' => [
        [
            'id' => 'ITEM001',
            'name' => 'Product A',
            'price' => 25000,
            'quantity' => 2,
        ],
    ],
    'totalAmount' => 50000,
    'merchantRef' => 'INV-001',
    'expiryMinutes' => 60,
    'successUrl' => 'https://example.com/success',
    'failureUrl' => 'https://example.com/failure',
]);

// Find by ID
$invoice = Winpay::snap()->checkout()->find('inv-id-123');

// Find by Merchant Reference
$invoice = Winpay::snap()->checkout()->findByRef('INV-001');

// Update Invoice
$invoice = Winpay::snap()->checkout()->update('inv-id-123', [
    'totalAmount' => 75000,
]);

// Delete by ID
Winpay::snap()->checkout()->delete('inv-id-123');

// Delete by Merchant Reference
Winpay::snap()->checkout()->deleteByRef('INV-001');

Callback / Webhook

Routes terdaftar otomatis saat provider di-boot. Bisa disable dengan:

WINPAY_REGISTER_ROUTES=false

Endpoint

Method URL Handler Channel
POST /api/winpay/callback/v1.0/transfer-va/payment vaPayment() VA
POST /api/winpay/callback/v1.0/qr/qr-mpm-notify qrisNotify() QRIS
POST /api/winpay/callback/v1.0/debit/notify debitNotify() eWallet / CC

Setiap callback akan:

  • Validasi tanda tangan RSA-SHA256 via WinpayClient::verifyCallback()
  • Dispatch event WinpayCallbackReceived
  • Return responseCode + responseMessage sesuai standar SNAP (401 jika signature invalid)

Custom Prefix

// Di routes/api.php
Winpay\Laravel\WinpayServiceProvider::callbackRoutes('webhook/winpay');

Listening Event

// Di App\Providers\EventServiceProvider.php
use Winpay\Laravel\Events\WinpayCallbackReceived;

protected $listen = [
    WinpayCallbackReceived::class => [
        HandleWinpayCallback::class,
    ],
];
class HandleWinpayCallback
{
    public function handle(WinpayCallbackReceived $event): void
    {
        if (! $event->verified) {
            logger()->warning('Winpay callback invalid signature', [
                'type' => $event->type,
            ]);
            return;
        }

        if ($event->transactionStatus === '00') {
            // Process successful payment
            // $event->type: 'va' | 'qris' | 'ewallet' | 'credit_card'
            // $event->payload: full request body
        }
    }
}

Error Handling

use Winpay\Core\Exceptions\WinpayException;
use Winpay\Core\Exceptions\HttpException;

try {
    $result = Winpay::snap()->va()->create([...]);
} catch (HttpException $e) {
    // 4xx/5xx — error dari server Winpay
    $e->getStatusCode(); // int
    $e->getMessage();    // string
    $e->getErrors();     // array|null (responseCode, responseMessage, full payload)
} catch (WinpayException $e) {
    // Config error, signature error, network error
}

Transaction Status (TransactionStatus)

Enum Value Arti
TransactionStatus::SUCCESS 00 Sukses
TransactionStatus::INITIATED 01 Initiated
TransactionStatus::PAYING 02 Sedang dibayar
TransactionStatus::PENDING 03 Pending
TransactionStatus::REFUNDED 04 Refund
TransactionStatus::CANCELED 05 Dibatalkan
TransactionStatus::FAILED 06 Gagal
TransactionStatus::NOT_FOUND 07 Tidak ditemukan

Testing

php vendor/bin/phpunit

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-09

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固