djlemmor / djpaykit-laravel
Laravel backend adapter for the DJPayKit QR payment widget.
Requires
- php: ^8.2
- illuminate/console: ^12.0
- illuminate/database: ^12.0
- illuminate/filesystem: ^12.0
- illuminate/http: ^12.0
- illuminate/routing: ^12.0
- illuminate/support: ^12.0
- illuminate/validation: ^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
README
Laravel 12 backend adapter for the DJPayKit QR payment widget.
It allows a website owner to configure payment methods such as GCash, Maya, and MariBank, upload private QR images, and expose controlled public endpoints for the DJPayKit widget.
Requirements
- PHP 8.2 or newer
- Laravel 12
- A Laravel filesystem disk
- Authentication middleware for administrator endpoints
Features
- GCash, Maya, and MariBank support
- Extensible provider configuration
- Private QR image storage
- Public payment-method API
- Controlled QR image responses
- Administrator CRUD endpoints
- Account-number privacy controls
- ULID payment-method identifiers
- Soft deletion
- Validated PNG, JPEG, and WebP uploads
- Safe QR replacement and cleanup
- Automated package tests
Installation
The package has not yet been published to Packagist. The standard installation command will become available after the first release:
composer require djlemmor/djpaykit-laravel
Then run:
# Publishes the configuration and database migration. php artisan djpaykit:install # Creates the DJPayKit database table. php artisan migrate
Local development installation
Add DJPayKit as a Composer path repository:
# Registers the local Laravel adapter. composer config repositories.djpaykit path ../DJPayKit/packages/laravel # Installs the development version. composer require djlemmor/djpaykit-laravel:@dev
Run the installer:
php artisan djpaykit:install php artisan migrate
Composer normally symlinks the package, so local DJPayKit changes become available without reinstalling it.
Configuration
The installation command publishes:
config/djpaykit.php
Important settings:
| Setting | Default | Purpose |
|---|---|---|
route_prefix |
api/djpaykit |
Prefix for all package routes |
api_middleware |
['api'] |
Middleware for public widget routes |
admin_middleware |
['api', 'auth'] |
Middleware for administrator routes |
storage_disk |
local |
Private QR and receipt storage |
maximum_image_size_kb |
5120 |
Maximum upload size in kilobytes |
maximum_image_width |
4096 |
Maximum QR width |
maximum_image_height |
4096 |
Maximum QR height |
default_currency |
PHP |
Default payment currency |
show_account_number_by_default |
false |
Default public account-number visibility |
proof_of_payment_enabled |
false |
Enables future receipt submissions |
Environment variables:
DJPAYKIT_ROUTE_PREFIX=api/djpaykit DJPAYKIT_STORAGE_DISK=local DJPAYKIT_PROOF_OF_PAYMENT_ENABLED=false
Administrator authentication
Administrator endpoints use the middleware configured in:
'admin_middleware' => ['api', 'auth'],
Applications using Sanctum can change it to:
/* * Requires an authenticated Sanctum user for administrator actions. */ 'admin_middleware' => ['api', 'auth:sanctum'],
DJPayKit does not create administrator users or decide which users are authorized. The host Laravel application remains responsible for authentication and authorization.
Storage security
QR images use Laravel's configured private disk:
'storage_disk' => 'local',
Laravel 12's local disk normally stores private files below:
storage/app/private
DJPayKit serves QR images through a controlled route. It never returns the underlying filesystem or cloud-storage path.
Do not move DJPayKit QR images to the public disk unless your application intentionally wants to bypass these controls.
Supported providers
The default providers are:
'providers' => [ 'gcash' => [ 'display_name' => 'GCash', ], 'maya' => [ 'display_name' => 'Maya', ], 'maribank' => [ 'display_name' => 'MariBank', ], ],
A host application can add another provider:
/* * Adds another provider without changing the package source. */ 'providers' => [ // Existing providers... 'instapay' => [ 'display_name' => 'InstaPay', ], ],
Provider IDs may contain lowercase letters, numbers, hyphens, and underscores.
Public API
List enabled payment methods
GET /api/djpaykit/payment-methods
Example response:
{
"data": [
{
"id": "01m0wvqzdj7czkf04tjc8443k6",
"provider": "gcash",
"displayName": "GCash",
"accountName": "DJ Business",
"accountNumber": null,
"qrImageUrl": "https://example.com/api/djpaykit/payment-methods/01m0wvqzdj7czkf04tjc8443k6/qr",
"instructions": "Include your order number."
}
]
}
accountNumber is null unless the owner enables
show_account_number for that payment method.
Disabled and soft-deleted methods are excluded.
Display a QR image
GET /api/djpaykit/payment-methods/{paymentMethod}/qr
The endpoint:
- Only serves enabled payment methods
- Reads from the configured private disk
- Allows PNG, JPEG, and WebP
- Sends
X-Content-Type-Options: nosniff - Does not expose the private storage path
- Returns
404for disabled, deleted, missing, or unsupported images
Administrator API
All administrator routes require the configured administrator middleware.
List payment methods
GET /api/djpaykit/admin/payment-methods
The administrator list includes enabled and disabled methods but excludes soft-deleted records and private QR paths.
Create a payment method
POST /api/djpaykit/admin/payment-methods Content-Type: multipart/form-data
Example using cURL:
# Replace TOKEN and the image path with actual values. curl -X POST "https://example.com/api/djpaykit/admin/payment-methods" \ -H "Accept: application/json" \ -H "Authorization: Bearer TOKEN" \ -F "provider=gcash" \ -F "display_name=GCash" \ -F "account_name=DJ Business" \ -F "account_number=0912 345 6789" \ -F "show_account_number=1" \ -F "is_enabled=1" \ -F "sort_order=10" \ -F "instructions=Include your order number." \ -F "qr_image=@/absolute/path/gcash.png"
Required fields:
providerdisplay_nameaccount_nameqr_image
Optional fields:
account_numberinstructionsshow_account_numberis_enabledsort_order
QR requirements:
- PNG, JPEG, or WebP
- Maximum 5 MB by default
- Maximum 4096×4096 pixels by default
- SVG is not accepted
Update a payment method
PATCH /api/djpaykit/admin/payment-methods/{paymentMethod}
All update fields are optional. The provider cannot be changed after creation.
Example replacing a QR:
# Stores the replacement before removing the currently working QR. curl -X PATCH \ "https://example.com/api/djpaykit/admin/payment-methods/PAYMENT_METHOD_ID" \ -H "Accept: application/json" \ -H "Authorization: Bearer TOKEN" \ -F "account_name=Updated Business" \ -F "qr_image=@/absolute/path/new-gcash.png"
If the database update fails, DJPayKit deletes the new upload and keeps the original QR.
Delete a payment method
DELETE /api/djpaykit/admin/payment-methods/{paymentMethod}
Deletion:
- Soft-deletes the database record
- Removes the associated QR image
- Prevents the public API from returning the method
- Returns HTTP
204 No Content
Error responses
Common status codes:
| Status | Meaning |
|---|---|
200 |
Successful list or update |
201 |
Payment method created |
204 |
Payment method deleted |
404 |
Payment method or QR not found |
422 |
Validation failed |
500 |
Unexpected storage or database failure |
Laravel returns validation errors in its normal JSON format:
{
"message": "The given data was invalid.",
"errors": {
"provider": ["The selected provider is not supported by DJPayKit."]
}
}
Routes
List all package routes:
php artisan route:list --name=djpaykit
DJPayKit registers:
GET api/djpaykit/admin/payment-methods
POST api/djpaykit/admin/payment-methods
PATCH api/djpaykit/admin/payment-methods/{paymentMethod}
DELETE api/djpaykit/admin/payment-methods/{paymentMethod}
GET api/djpaykit/payment-methods
GET api/djpaykit/payment-methods/{paymentMethod}/qr
Frontend widget integration
Install the core widget after it is published:
npm install @djlemmor/djpaykit
For local development:
# Installs the core package directly from the DJPayKit repository.
npm install ../DJPayKit/packages/core
Register the custom element in the application's JavaScript entry:
import { defineDJPayKitWidget } from "@djlemmor/djpaykit"; /* * Registers <djpaykit-widget> with the browser. */ defineDJPayKitWidget();
Example Laravel Blade integration:
{{-- Vite loads the JavaScript that registers the widget. --}} @vite('resources/js/app.js') <djpaykit-widget api-url="{{ url('/api/djpaykit/payment-methods') }}" order-reference="ORDER-1001" amount="500.00" currency="PHP" ></djpaykit-widget>
The first enabled method is selected automatically. Selecting another provider updates its account details and QR without reloading the page.
Widget events
The host checkout can observe provider selection:
document.addEventListener("djpaykit:provider-selected", (event) => { /* * detail contains paymentMethodId and provider. * It does not expose the account number. */ console.log(event.detail); });
The host checkout can also observe successful QR downloads:
document.addEventListener("djpaykit:qr-downloaded", (event) => { /* * detail contains paymentMethodId and provider. */ console.log(event.detail); });
For the simplest integration, serve the Laravel API and widget from the same origin. Cross-origin integrations require the host application's CORS configuration to allow the checkout website.
Package development
Install dependencies:
composer install
Run tests:
composer test
Run a specific test:
vendor/bin/phpunit tests/Feature/PublicPaymentMethodEndpointTest.php
On Windows, if Git Bash cannot run the Unix vendor launcher, use:
composer exec -- phpunit tests/Feature/PublicPaymentMethodEndpointTest.php
Current verified result:
Tests: 28
Assertions: 96
License
DJPayKit Laravel is open-source software licensed under the MIT License.