mortogo321/laravel-thai-promptpay 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

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

mortogo321/laravel-thai-promptpay

Composer 安装命令:

composer require mortogo321/laravel-thai-promptpay

包简介

Thai PromptPay QR Code Payment Generator for Laravel

README 文档

README

Latest Version on Packagist Total Downloads GitHub License PHP Version Laravel Version Tests GitHub Stars

A Laravel package for generating Thai PromptPay QR codes following the BOT (Bank of Thailand) Thai QR Payment Standard. Supports phone numbers, National ID, Tax ID, and e-Wallet with full validation.

Supported Formats

Type Supported Sub-tag Format Example
Mobile Phone 01 10 digits (06/08/09) 0812345678
National ID 02 13 digits 1234567890123
Tax ID 02 13 digits 0123456789012
e-Wallet 03 15 digits 123456789012345
Bank Account - NOT SUPPORTED BOT spec: reserved

Note: Bank account numbers are NOT supported per BOT specification (marked as "reserved" - no Thai banks have implemented this).

Features

  • Generate PromptPay QR codes compliant with BOT Thai QR Payment Standard
  • Support for phone numbers, National ID, Tax ID, and e-Wallet
  • Validation methods for identifier and amount checking
  • Thai National ID checksum validation
  • Payload CRC verification for integrity checking
  • Support for fixed amount and open amount payments
  • Returns QR code as data URI or binary PNG
  • Built-in AJAX/API endpoints with rate limiting
  • Works with Axios, Fetch, Vue.js, React, and any frontend framework
  • Laravel auto-discovery support
  • Full test suite (68 tests, 151 assertions)

Requirements

  • PHP 8.2 - 8.5
  • Laravel 10.x, 11.x, or 12.x

Installation

composer require mortogo321/laravel-thai-promptpay

The package will automatically register its service provider.

Publish Configuration (Optional)

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

Basic Usage

Using Facade

use Mortogo321\LaravelThaiPromptPay\Facades\PromptPay;

// Generate QR code with phone number
$qrCode = PromptPay::generateQRCode('0812345678');

// Generate QR code with fixed amount
$qrCode = PromptPay::generateQRCode('0812345678', 100.50);

// Generate QR code with National ID
$qrCode = PromptPay::generateQRCode('1234567890123', 250.00);

// Generate QR code with custom size (default: 300px)
$qrCode = PromptPay::generateQRCode('0812345678', 100.00, 400);

// Generate payload string only
$payload = PromptPay::generatePayload('0812345678', 100.00);

// Generate QR code as binary PNG
$binary = PromptPay::generateQRCodeBinary('0812345678', 100.00);

Using Dependency Injection

use Mortogo321\LaravelThaiPromptPay\PromptPayQR;

class PaymentController extends Controller
{
    public function generateQR(PromptPayQR $promptpay)
    {
        $qrCode = $promptpay->generateQRCode('0812345678', 150.00);
        return view('payment', compact('qrCode'));
    }
}

Validation

Validate Identifier

use Mortogo321\LaravelThaiPromptPay\PromptPayQR;

$qr = new PromptPayQR();

// Validate without generating QR
$result = $qr->validate('0812345678');
// Returns: ['valid' => true, 'type' => 'mobile', 'formatted' => '0066812345678', 'error' => null]

$result = $qr->validate('invalid');
// Returns: ['valid' => false, 'type' => null, 'formatted' => null, 'error' => 'Invalid PromptPay ID format...']

Validate Amount

$qr->validateAmount(100.50);       // ['valid' => true, 'error' => null]
$qr->validateAmount(-50);          // ['valid' => false, 'error' => 'Amount cannot be negative']
$qr->validateAmount(9999999999);   // ['valid' => false, 'error' => 'Amount exceeds maximum...']
$qr->validateAmount(100.123);      // ['valid' => false, 'error' => 'Amount must have at most 2 decimal places']

Validate Payload Integrity

// Verify CRC checksum of a generated payload
$payload = $qr->generatePayload('0812345678', 100.00);
$isValid = $qr->validatePayload($payload);  // true

// Detect corrupted payload
$corrupted = substr($payload, 0, 10) . 'X' . substr($payload, 11);
$isValid = $qr->validatePayload($corrupted);  // false

Type Detection

// Get identifier type
$qr->getIdentifierType('0812345678');     // 'mobile'
$qr->getIdentifierType('1234567890123');  // 'tax_id'

// Specific type checks
$qr->isMobileNumber('0812345678');        // true (validates 06/08/09 prefix)
$qr->isMobileNumber('0212345678');        // false (02 is landline)
$qr->isNationalId('3320101323923');       // true (with checksum validation)
$qr->isTaxId('1234567890123');            // true

Get Supported Formats

$formats = PromptPayQR::getSupportedFormats();
// Returns array with all supported formats, sub-tags, and examples

Display QR Code in Blade

<div class="payment-qr">
    <h3>Scan to Pay</h3>
    <img src="{{ $qrCode }}" alt="PromptPay QR Code">
    <p>Amount: ฿{{ number_format($amount, 2) }}</p>
</div>

AJAX/API Usage

Available API Endpoints

All endpoints are rate-limited to 60 requests per minute.

Generate QR Code

POST /promptpay/generate

axios.post('/promptpay/generate', {
    identifier: '0812345678',  // Phone, National ID, or e-Wallet
    amount: 100.50,            // Optional (max 999,999,999.99, max 2 decimals)
    size: 300                  // Optional (100-1000, default: 300)
})
.then(response => {
    // response.data: { success, qr_code, identifier, type, amount }
    // type: 'mobile' | 'tax_id' | 'ewallet'
    document.getElementById('qr-image').src = response.data.qr_code;
});

Get Payload Only

POST /promptpay/payload

axios.post('/promptpay/payload', {
    identifier: '0812345678',
    amount: 100.50
});

Download QR Code

POST /promptpay/download

axios.post('/promptpay/download', {
    identifier: '0812345678',
    amount: 100.50
}, { responseType: 'blob' });

API Response Format

Success Response (200)

{
    "success": true,
    "qr_code": "data:image/png;base64,...",
    "identifier": "0812345678",
    "type": "mobile",
    "amount": 100.50
}

Error Response (422)

{
    "success": false,
    "message": "Invalid PromptPay ID format..."
}

Identifier Format Details

Phone Numbers

  • 0812345678 - Thai mobile (10 digits starting with 06/08/09)
  • 812345678 - Without leading 0 (9 digits)
  • 66812345678 - International format
  • 0066812345678 - PromptPay format

National ID / Tax ID

  • 1234567890123 - 13-digit number
  • Includes checksum validation for National ID

e-Wallet

  • 123456789012345 - 15-digit e-Wallet ID

API Reference

validate(string $identifier): array

Validate identifier without generating QR.

validateAmount(?float $amount): array

Validate payment amount (max 2 decimal places, max 999,999,999.99).

validatePayload(string $payload): bool

Verify CRC16-CCITT checksum of a complete payload.

getIdentifierType(string $identifier): ?string

Get identifier type ('mobile', 'tax_id', 'ewallet', or null).

isMobileNumber(string $identifier): bool

Check if valid Thai mobile number (06/08/09).

isNationalId(string $identifier): bool

Check if valid National ID with checksum validation.

isTaxId(string $identifier): bool

Check if valid Tax ID (13 digits).

generatePayload(string $identifier, ?float $amount = null): string

Generate PromptPay EMV QR code payload string.

generateQRCode(string $identifier, ?float $amount = null, int $size = 300): string

Generate QR code image as data URI.

generateQRCodeBinary(string $identifier, ?float $amount = null, int $size = 300): string

Generate QR code as binary PNG data.

getSupportedFormats(): array

Get list of all supported identifier formats.

Technical Specification

This package follows the BOT (Bank of Thailand) Thai QR Payment Standard:

  • AID: A000000677010111 (PromptPay Application ID)
  • Sub-tag 01: Mobile phone number (0066XXXXXXXXX format)
  • Sub-tag 02: National ID / Tax ID (13 digits)
  • Sub-tag 03: e-Wallet ID (15 digits)
  • CRC: CRC16-CCITT checksum (EMVCo standard)

Reference: BOT Thai QR Payment Specification

Testing

# Run all tests
composer test

# Run tests with coverage
composer test:coverage

# Run specific test suite
./vendor/bin/phpunit --testsuite=Unit
./vendor/bin/phpunit --testsuite=Feature

Test Coverage: 68 tests, 151 assertions

Code Quality

This package uses Laravel Pint for code style.

# Check code style
composer lint

# Fix code style
composer lint:fix

A pre-commit hook is included to automatically check code style before commits.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run tests (composer test)
  4. Run linting (composer lint:fix)
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

MIT License

Credits

Support

If you discover any issues, please create an issue on GitHub.

mortogo321/laravel-thai-promptpay 适用场景与选型建议

mortogo321/laravel-thai-promptpay 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 349 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 08 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「payment」 「laravel」 「qr-code」 「thailand」 「Promptpay」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 mortogo321/laravel-thai-promptpay 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mortogo321/laravel-thai-promptpay 我们能提供哪些服务?
定制开发 / 二次开发

基于 mortogo321/laravel-thai-promptpay 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-10-08