laravel-tinopay maintained by tinovn
Laravel TinoPay
Nhận webhook giao dịch từ TinoPay, lưu lịch sử giao dịch và bắn event để ứng dụng Laravel tự cộng tiền / xác nhận đơn hàng.
Yêu cầu: PHP 8.0+, Laravel 9 – 13.
Cài đặt
composer require tinovn/laravel-tinopay
Chưa đưa lên Packagist thì khai báo repository dạng path hoặc VCS trong composer.json của ứng dụng:
"repositories": [
{ "type": "vcs", "url": "<git url của laravel-tinopay>" }
]
Publish và chạy migration (tạo bảng tinopay_transactions):
php artisan vendor:publish --tag="tinopay-migrations"
php artisan migrate
Publish config (tuỳ chọn):
php artisan vendor:publish --tag="tinopay-config"
return [
'webhook_token' => env('TINOPAY_WEBHOOK_TOKEN'),
'pattern' => env('TINOPAY_MATCH_PATTERN', 'TP'),
'url' => env('TINOPAY_URL', 'https://ipn.pay.tino.vn'),
'api_token' => env('TINOPAY_API_TOKEN'),
'qr_template' => env('TINOPAY_QR_TEMPLATE', 'default'),
];
| Biến | Ý nghĩa |
|---|---|
TINOPAY_WEBHOOK_TOKEN |
Trùng Token xác thực của webhook trên TinoPay |
TINOPAY_MATCH_PATTERN |
Tiền tố mã thanh toán, trùng Cấu trúc mã thanh toán trên TinoPay |
TINOPAY_URL |
Địa chỉ TinoPay. Server ngoài tino.vn dùng địa chỉ proxy do tino.vn cung cấp |
TINOPAY_API_TOKEN |
API Token, chỉ cần khi gọi TinoPay::transactions() |
TINOPAY_QR_TEMPLATE |
default (khung TinoPay kèm logo ngân hàng) hoặc only-qr |
Publish view email (tuỳ chọn):
php artisan vendor:publish --tag="tinopay-views"
Cấu hình trên TinoPay
- Cài đặt → Cấu trúc mã thanh toán: thêm tiền tố trùng
TINOPAY_MATCH_PATTERN(VDTP). - Tích hợp → Webhooks → Thêm webhook:
- URL:
https://<domain>/api/tinopay/webhook - Tài khoản ngân hàng / VA: tài khoản nhận tiền
- Token xác thực: trùng
TINOPAY_WEBHOOK_TOKEN - Sự kiện: Tiền vào (hoặc Tất cả nếu cần xử lý cả tiền ra)
- URL:
Sử dụng
Mỗi webhook hợp lệ được lưu vào tinopay_transactions. Nếu tìm thấy mã thanh toán (field code, hoặc trong content), package bắn TinoPayWebhookEvent với $info là phần sau tiền tố: TP123456 → 123456.
php artisan make:listener TinoPayWebhookListener
<?php
namespace App\Listeners;
use App\Models\User;
use TinoPay\TinoPay\Events\TinoPayWebhookEvent;
use TinoPay\TinoPay\Notifications\TinoPayTopUpSuccessNotification;
class TinoPayWebhookListener
{
public function handle(TinoPayWebhookEvent $event): void
{
if ($event->tinoPayWebhookData->transferType === 'in') {
// Trường hợp $info là user id
$user = User::query()->find($event->info);
if ($user) {
// Cộng tiền: $event->tinoPayWebhookData->transferAmount
$user->notify(new TinoPayTopUpSuccessNotification($event->tinoPayWebhookData));
}
} else {
// Tiền ra
}
}
}
-
Laravel 11 trở lên: listener trong
app/Listenersđược tự gắn với event, không cần đăng ký thêm (đăng ký thêm sẽ bị gọi 2 lần). Nếu listener chưa chạy, thêm vàoboot()củaAppServiceProvider:\Illuminate\Support\Facades\Event::listen( \TinoPay\TinoPay\Events\TinoPayWebhookEvent::class, \App\Listeners\TinoPayWebhookListener::class, ); -
Laravel 10 trở xuống: thêm vào
$listencủaapp/Providers/EventServiceProvider.php.
TinoPayWebhookData gồm: transactionId, gateway, transactionDate, accountNumber, virtualAccount, code, content, transferType, transferAmount, referenceCode.
Mã QR và API
use TinoPay\TinoPay\Facades\TinoPay;
// Link ảnh VietQR (PNG). BIDV: điền số tài khoản ảo (VA). Nội dung tối đa 25 ký tự.
$src = TinoPay::qrUrl('BIDV', 'V4TINOGROUP', amount: 150000, memo: 'TP'.$user->id, accountName: 'CONG TY ABC');
// Danh sách ngân hàng: code, name, shortName, bin, ...
$banks = TinoPay::banks();
// Lịch sử giao dịch (cần TINOPAY_API_TOKEN). Mặc định trong ngày, tối đa 90 ngày.
$page = TinoPay::transactions([
'type' => 'in',
'transaction_date_from' => '2026-10-01',
'transaction_date_to' => '2026-10-27',
'per_page' => 50,
]);
Webhook
TinoPay gửi POST JSON kèm header ALLPAY-TOKEN: <token> và Authorization: Apikey <token>:
{
"transaction_id": "…", "gateway": "BIDV", "transactionDate": "2026-10-23 10:00:00",
"accountNumber": "…", "code": "TP123456", "content": "TP123456 thanh toan",
"transferType": "in", "transferAmount": 150000, "referenceCode": "…", "virtualAccount": "V4TINOGROUP"
}
| Kết quả | HTTP |
|---|---|
| Ghi nhận thành công | 200 |
Giao dịch trùng transaction_id (bỏ qua) |
200 |
| Sai token | 401 |
JSON lỗi / thiếu transaction_id và referenceCode |
400 |
TinoPay tự gửi lại webhook (sau 5 phút, tối đa 3 lần) khi nhận mã non-2xx.
Thử bằng curl
curl --location 'https://domain.com/api/tinopay/webhook' \
--header 'Content-Type: application/json' \
--header 'Authorization: Apikey đây_là_khóa_bí_mật' \
--data '{
"transaction_id": "TEST-0001",
"gateway": "BIDV",
"transactionDate": "2026-10-27 10:00:00",
"accountNumber": "1234567890",
"code": "TP1",
"content": "TP1 nap tien",
"transferType": "in",
"transferAmount": 100000,
"referenceCode": "FT0001",
"virtualAccount": null
}'
Kiểm thử
composer install
composer test
Giấy phép
MIT. Xem LICENSE.md.