### Laravel Backend Project Setup and Package Installation
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Commands to create a new Laravel project and install essential backend packages for authentication (Sanctum), queue management (Horizon), Redis, Pusher, QR code generation, permissions (Spatie), query building, data handling, and development tools (Telescope, PHPUnit, Pint, Larastan).
```bash
# Create Laravel project
composer create-project laravel/laravel payment-backend
cd payment-backend
# Install required packages
composer require laravel/sanctum
composer require laravel/horizon
composer require predis/predis
composer require pusher/pusher-php-server
composer require bacon/bacon-qr-code
composer require spatie/laravel-permission
composer require spatie/laravel-query-builder
composer require spatie/laravel-data
composer require laravel/telescope --dev
# Install development packages
composer require --dev phpunit/phpunit
composer require --dev laravel/pint
composer require --dev nunomaduro/larastan
```
--------------------------------
### Docker Image Setup for Laravel Application
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This Dockerfile snippet outlines the steps to build a production-ready Docker image for a Laravel application. It includes installing necessary PHP extensions, setting up Composer, copying application files, installing dependencies, optimizing autoloaders, caching configurations, setting file permissions, and configuring Supervisor for process management.
```bash
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Install Redis extension
RUN pecl install redis && docker-php-ext-enable redis
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
# Copy application
COPY . .
# Install dependencies
RUN composer install --no-dev --optimize-autoloader
# Generate optimized autoload files
RUN composer dump-autoload --optimize
# Cache config and routes
RUN php artisan config:cache && \
php artisan route:cache && \
php artisan view:cache
# Set permissions
RUN chown -R www-data:www-data /var/www/storage /var/www/bootstrap/cache
# Supervisor configuration
COPY docker/supervisor/laravel-worker.conf /etc/supervisor/conf.d/
CMD ["supervisord", "-n"]
```
--------------------------------
### Basic Dockerfile for Laravel PHP Application
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This Dockerfile defines the base image and initial dependencies for a Laravel PHP application. It starts with a PHP 8.2 FPM image and installs common tools like Git, cURL, and various PHP extensions necessary for a typical Laravel setup, along with Supervisor for process management.
```dockerfile
# Dockerfile for Laravel
FROM php:8.2-fpm
# Install dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
supervisor
```
--------------------------------
### Vue 3 Frontend Setup for Customer and Merchant Apps
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Commands to set up both the Customer and Merchant Vue 3 applications, including creating new projects and installing their respective dependencies such as Axios, Pinia, UI libraries (PrimeVue), PWA tools, Capacitor for mobile, and real-time communication libraries (Laravel Echo, Pusher.js).
```bash
# Customer App
npm create vue@latest customer-app
cd customer-app
npm install axios pinia @vueuse/core qrcode.vue3
npm install @vitejs/plugin-pwa vite-plugin-pwa
npm install primevue primeicons
npm install laravel-echo pusher-js
# Merchant App
npm create vue@latest merchant-app
cd merchant-app
npm install @capacitor/core @capacitor/ios @capacitor/android
npm install qr-scanner axios pinia
npm install primevue primeicons
```
--------------------------------
### Laravel QR Payment Package Consumer Installation
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/CLAUDE.md
These commands detail the steps for consumers to install the completed Laravel QR Payment package, including adding it via Composer, publishing its configuration, and running database migrations.
```bash
composer require xavierau/laravel-qr-payment
php artisan vendor:publish --provider="LaravelQrPaymentServiceProvider"
php artisan migrate
```
--------------------------------
### Laravel QR Payment Package Development Commands
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/CLAUDE.md
This section provides essential Bash commands for developers working on the Laravel QR Payment package, covering dependency installation, running tests, code quality checks, and publishing package assets.
```bash
# Package development
composer install # Install dependencies
composer test # Run package tests
composer run lint # Code quality checks
# Testing with Laravel testbench
vendor/bin/phpunit # Run PHPUnit tests
php artisan test # Laravel feature tests
# Package publishing (for consumers)
php artisan vendor:publish --provider="LaravelQrPaymentServiceProvider"
php artisan migrate # Run package migrations
```
--------------------------------
### Laravel Backend Environment Configuration (.env)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Example `.env` file configuration for the Laravel backend, defining application settings, database connection details, Redis settings, Pusher broadcast credentials, and payment-specific parameters like session TTLs and transaction limits.
```env
# .env file for Laravel
APP_NAME="QR Payment System"
APP_ENV=production
APP_KEY=base64:...
APP_DEBUG=false
APP_URL=https://api.payment.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=payment_system
DB_USERNAME=payment_user
DB_PASSWORD=secure_password
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
BROADCAST_DRIVER=pusher
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_app_key
PUSHER_APP_SECRET=your_app_secret
PUSHER_APP_CLUSTER=mt1
# Payment specific
PAYMENT_SESSION_TTL=300 # 5 minutes
PAYMENT_CONFIRMATION_TTL=120 # 2 minutes
PAYMENT_OFFLINE_LIMIT=50.00
PAYMENT_DAILY_LIMIT=10000.00
```
--------------------------------
### GitHub Actions CI/CD Pipeline for Laravel Deployment
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This YAML configuration defines a GitHub Actions workflow for continuous integration and deployment of the Laravel application. It includes a 'test' job to run PHP tests and a 'deploy' job that pulls the latest code, installs dependencies, runs migrations, clears caches, and restarts queues on the production server via SSH.
```yaml
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Install dependencies
run: composer install
- name: Run tests
run: php artisan test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/payment-system
git pull origin main
composer install --no-dev
php artisan migrate --force
php artisan config:cache
php artisan queue:restart
supervisorctl restart all
```
--------------------------------
### Install Laravel QR Payment Package via Composer
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
This command installs the `xavierau/laravel-qr-payment` package into your Laravel project using Composer, managing all necessary dependencies.
```bash
composer require xavierau/laravel-qr-payment
```
--------------------------------
### System Architecture Overview Diagram
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Illustrates the high-level architecture of the QR Payment System, showing the interaction between frontend applications (Customer and Merchant), API Gateway, Laravel Backend services, and data stores (MySQL, Redis, WebSocket).
```text
┌─────────────────────────────────────────────────────────────┐
│ Frontend Apps │
├──────────────────────────┬──────────────────────────────────┤
│ Customer App │ Merchant App │
│ (Vue 3 + PWA) │ (Vue 3 + Capacitor) │
└──────────────────────────┴──────────────────────────────────┘
│
│ HTTPS + JWT
▼
┌─────────────────────────────────────────────────────────────┐
│ API Gateway (Nginx) │
└─────────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ Laravel 12 Backend │
├─────────────────┬────────────────┬──────────────────────────┤
│ Auth Service │ Payment Service│ Notification Service │
├─────────────────┴────────────────┴──────────────────────────┤
│ Queue (Redis) │
├─────────────────┬────────────────┬──────────────────────────┤
│ MySQL │ Redis │ WebSocket (Pusher) │
└─────────────────┴────────────────┴──────────────────────────┘
```
--------------------------------
### Example Laravel QR Payment Configuration File
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
This PHP array demonstrates the structure of the `config/qr-payment.php` file, allowing customization of QR code properties, session timeouts, security settings, broadcasting, and fee calculations.
```php
return [
'qr_code' => [
'expiry_minutes' => env('QR_PAYMENT_QR_EXPIRY', 5),
'size' => 300,
'format' => 'svg', // svg, png
],
'session' => [
'timeout_minutes' => env('QR_PAYMENT_SESSION_TIMEOUT', 2),
'cleanup_frequency' => 'hourly',
],
'security' => [
'encryption_key' => env('QR_PAYMENT_ENCRYPTION_KEY'),
],
'broadcasting' => [
'enabled' => true,
'connection' => 'pusher',
],
'fees' => [
'percentage' => 2.5,
'fixed' => 0.30,
],
];
```
--------------------------------
### Laravel Cache Store Configuration
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This partial PHP snippet from config/cache.php shows the beginning of the 'stores' array definition for Laravel's caching configuration. It indicates where different cache drivers and their settings would be defined.
```php
// config/cache.php
'stores' => [
```
--------------------------------
### Vue.js Payment Confirmation Template (Partial)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Defines a portion of the user interface for payment confirmation, including action buttons (confirm/reject), a timer warning, and an authentication modal with biometric/PIN input options.
```Vue
Confirm Payment
{{ timeRemaining }} seconds remaining
Authenticate Payment
```
--------------------------------
### Configure Laravel Broadcasting with Pusher
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This PHP snippet shows how to configure Laravel's broadcasting connection to use Pusher. It defines the driver, API keys, application ID, cluster, and TLS settings, typically found in 'config/broadcasting.php'.
```php
// config/broadcasting.php
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
'encrypted' => true,
],
],
],
```
--------------------------------
### PHP User Token Verification Methods
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Illustrates a 'switch' statement for handling different token verification types (e.g., password, biometric) and a placeholder for biometric token verification logic within a user authentication context.
```php
return password_verify($token, $user->password);
default:
return false;
}
}
private function verifyBiometricToken(User $user, string $token): bool
{
// Implement biometric verification logic
// This would typically involve verifying a JWT token from the device
return true; // Placeholder
}
```
--------------------------------
### Laravel Production Environment Variables Configuration
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This snippet provides essential environment variables for a Laravel application deployed in a production environment. It covers application settings, database connection details, Redis cluster configuration for caching and queues, and security-related settings for sessions and Sanctum.
```bash
# Production environment variables
APP_ENV=production
APP_DEBUG=false
APP_URL=https://api.payment.com
# Database
DB_CONNECTION=mysql
DB_HOST=rds.amazonaws.com
DB_DATABASE=payment_prod
DB_USERNAME=payment_user
DB_PASSWORD=${DB_PASSWORD}
# Redis Cluster
REDIS_HOST=redis-cluster.aws.com
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_PORT=6379
# Queue Configuration
QUEUE_CONNECTION=redis
HORIZON_PREFIX=horizon:
HORIZON_MEMORY_LIMIT=256
# Security
SESSION_SECURE_COOKIE=true
SANCTUM_STATEFUL_DOMAINS=app.payment.com
```
--------------------------------
### Scoped CSS for Payment Confirmation Component (Partial)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Provides scoped CSS styling for the payment confirmation component, defining layouts, colors, and typography for various sections like merchant info, amount display, transaction details, and action buttons.
```CSS
.payment-confirmation {
display: flex;
flex-direction: column;
gap: 24px;
padding: 20px;
max-width: 400px;
margin: 0 auto;
}
.merchant-info {
text-align: center;
padding: 24px;
background: #f8f9fa;
border-radius: 16px;
}
.merchant-logo {
width: 80px;
height: 80px;
border-radius: 50%;
margin-bottom: 16px;
}
.verified-badge {
display: inline-flex;
align-items: center;
gap: 4px;
color: #4CAF50;
font-size: 14px;
margin-top: 8px;
}
.amount-display {
text-align: center;
padding: 32px 0;
}
.currency {
font-size: 32px;
color: #666;
vertical-align: top;
}
.amount {
font-size: 64px;
font-weight: 700;
color: #333;
}
.transaction-details {
background: #f8f9fa;
border-radius: 12px;
padding: 16px;
}
.transaction-details h4 {
margin: 0 0 12px 0;
color: #666;
font-size: 14px;
text-transform: uppercase;
}
.item {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #e0e0e0;
}
.item:last-child {
border-bottom: none;
}
.action-buttons {
display: flex;
flex-direction: column;
gap: 12px;
}
.timer-warning {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px;
```
--------------------------------
### Switch Camera (Vue.js)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Allows switching between available cameras (e.g., front-facing, environment) for the QR scanner. It ensures that multiple cameras are present before attempting to switch.
```JavaScript
const switchCamera = async () => {
if (scanner.value && hasMultipleCameras.value) {
await scanner.value.setCamera('environment');
}
};
```
--------------------------------
### Planned Laravel QR Payment Package Structure
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/CLAUDE.md
This snippet illustrates the intended directory and file structure for the Laravel QR Payment package, organizing core components like services, models, controllers, and configuration files.
```plaintext
src/
├── Services/ # Core payment processing services
├── Models/ # Eloquent models for payment entities
├── Controllers/ # API controllers for payment endpoints
├── Events/ # Payment workflow events
├── Jobs/ # Background payment processing
├── Middleware/ # Security and validation middleware
└── LaravelQrPaymentServiceProvider.php
config/qr-payment.php # Package configuration
database/migrations/ # Database schema
tests/ # Package tests
composer.json # Package definition
```
--------------------------------
### Publish Laravel QR Payment Configuration, Migrations, and Views
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
These Artisan commands publish the package's configuration file, database migrations, and optional view files to your Laravel application, allowing for customization and database setup.
```bash
# Publish config file
php artisan vendor:publish --provider="XavierAu\LaravelQrPayment\LaravelQrPaymentServiceProvider" --tag="config"
# Publish migrations
php artisan vendor:publish --provider="XavierAu\LaravelQrPayment\LaravelQrPaymentServiceProvider" --tag="migrations"
# Publish views (optional - for customization)
php artisan vendor:publish --provider="XavierAu\LaravelQrPayment\LaravelQrPaymentServiceProvider" --tag="views"
```
--------------------------------
### Test Complete Payment Flow in Laravel
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This test simulates a full payment transaction, from session creation to user confirmation, verifying API interactions and balance updates. It uses Laravel's testing utilities, Sanctum for authentication, and refreshes the database for each test.
```php
// tests/Feature/PaymentFlowTest.php
create([
'balance' => 1000,
'pin' => hash('sha256', '123456')
]);
$merchant = Merchant::factory()->create();
Sanctum::actingAs($user);
// Step 1: Create session
$response = $this->postJson('/api/payment/session', [
'device_id' => 'test-device'
]);
$response->assertStatus(201);
$session = $response->json('data');
// Step 2: Merchant validates QR
Sanctum::actingAs($merchant);
$response = $this->postJson('/api/merchant/validate-qr', [
'qr_data' => json_decode(base64_decode($session['qr_data']), true),
'merchant_id' => $merchant->id
]);
$response->assertStatus(200);
$this->assertTrue($response->json('valid'));
// Step 3: Merchant initiates payment
$response = $this->postJson('/api/merchant/payment/initiate', [
'session_id' => $session['session_id'],
'amount' => 50.00
]);
$response->assertStatus(201);
$transaction = $response->json('data');
// Step 4: User confirms payment
Sanctum::actingAs($user);
$response = $this->postJson('/api/payment/confirm', [
'transaction_id' => $transaction['transaction_id'],
'auth_method' => 'pin',
'auth_token' => '123456'
]);
$response->assertStatus(200);
$this->assertTrue($response->json('success'));
// Verify balances
$user->refresh();
$this->assertEquals(950, $user->balance);
}
```
--------------------------------
### Initiate Payment Logic (Vue.js)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Handles the core logic for initiating a payment after a QR code scan. It prepares transaction data, simulates an API call (actual API call assumed to be external), navigates to a waiting screen upon success, and manages error alerts and loading states.
```JavaScript
const initiatePayment = async () => {
try {
// Placeholder for the actual API call that uses the following data
// Example: const result = await axios.post('/api/initiate-payment', {
const result = {
transaction_id: 'TRX' + Math.random().toString(36).substr(2, 9) // Simulated result
};
// Data that would typically be sent to an API
const paymentData = {
session_id: currentSession.value.session_id,
amount: parseFloat(amount.value),
items: [] // Add items if needed
};
// Navigate to waiting screen
router.push({
name: 'payment-waiting',
params: {
transactionId: result.transaction_id
}
});
} catch (error) {
alert(error.message || 'Failed to initiate payment');
} finally {
submitting.value = false;
}
};
```
--------------------------------
### Configure Laravel API Authentication Middleware
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This PHP snippet demonstrates how to configure API middleware groups in 'app/Http/Kernel.php'. It includes 'EnsureFrontendRequestsAreStateful' for Sanctum, 'throttle:api' for rate limiting, 'SubstituteBindings', and custom middleware like 'CheckDeviceBinding' and 'RateLimitPayment'.
```php
// app/Http/Kernel.php
protected $middlewareGroups = [
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\CheckDeviceBinding::class,
],
];
protected $routeMiddleware = [
'auth:sanctum' => \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'device.check' => \App\Http\Middleware\CheckDeviceBinding::class,
'payment.limit' => \App\Http\Middleware\RateLimitPayment::class,
];
```
--------------------------------
### Test Payment Session Creation in Vue/Vitest
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This unit test verifies the `createSession` function within a Vue composable, ensuring it correctly calls the API to create a payment session. It mocks the API service and asserts that the expected session data is returned.
```javascript
// tests/unit/composables/usePayment.spec.js
import { describe, it, expect, vi } from 'vitest'
import { usePayment } from '@/composables/usePayment'
import api from '@/services/api'
vi.mock('@/services/api')
describe('usePayment', () => {
it('creates payment session', async () => {
const mockSession = {
session_id: 'test-session',
qr_data: 'mock-qr-data',
expires_at: '2025-05-31T12:00:00Z'
}
api.post.mockResolvedValue({
data: { data: mockSession }
})
const { createSession } = usePayment()
const result = await createSession()
expect(api.post).toHaveBeenCalledWith('/payment/session', {
device_id: expect.any(String)
})
expect(result).toEqual(mockSession)
})
```
--------------------------------
### QR Scanner Component Styling (CSS)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Provides the scoped CSS styles for the QR scanner component, defining its layout, appearance, and interactive elements. This includes styles for the scanner frame, overlay, header, action buttons, and payment input fields.
```CSS
.qr-scanner {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #000;
z-index: 1000;
}
.scanner-header {
position: absolute;
top: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background: linear-gradient(to bottom, rgba(0,0,0,0.8), transparent);
z-index: 10;
}
.scanner-header h2 {
color: white;
margin: 0;
}
.close-btn {
background: rgba(255,255,255,0.2);
border: none;
color: white;
width: 40px;
height: 40px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.scanner-container {
position: relative;
width: 100%;
height: 100%;
}
.scanner-video {
width: 100%;
height: 100%;
object-fit: cover;
}
.scanner-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
}
.scanner-frame {
width: 280px;
height: 280px;
border: 3px solid #4CAF50;
border-radius: 20px;
box-shadow: 0 0 0 999px rgba(0,0,0,0.5);
}
.scanner-actions {
position: absolute;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 20px;
z-index: 10;
}
.action-btn {
background: rgba(255,255,255,0.2);
border: none;
color: white;
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
backdrop-filter: blur(10px);
}
.amount-input {
padding: 20px;
}
.customer-info {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
background: #f8f9fa;
border-radius: 12px;
margin-bottom: 24px;
}
.customer-info img {
width: 48px;
height: 48px;
border-radius: 50%;
}
.member-badge {
display: inline-block;
padding: 4px 8px;
background: #4CAF50;
color: white;
border-radius: 4px;
font-size: 12px;
margin-top: 4px;
}
.amount-display {
display: flex;
align-items: center;
justify-content: center;
margin: 32px 0;
}
.currency {
font-size: 32px;
color: #666;
margin-right: 8px;
}
.amount-input-field {
font-size: 48px;
font-weight: 700;
border: none;
outline: none;
text-align: center;
width: 200px;
}
.preset-amounts {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 32px;
}
.preset-btn {
padding: 12px;
border: 2px solid #e0e0e0;
background: white;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.preset-btn:hover {
border-color: #4CAF50;
color: #4CAF50;
}
```
--------------------------------
### Manage QR Scanner Lifecycle (Vue.js)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Utilizes Vue's lifecycle hooks to initialize the QR scanner when the component is mounted and properly destroy it when the component is unmounted. This prevents resource leaks and ensures the scanner is active only when needed.
```JavaScript
onMounted(() => {
initScanner();
});
onUnmounted(() => {
if (scanner.value) {
scanner.value.destroy();
}
});
```
--------------------------------
### Laravel Logging Configuration for Monitoring
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This PHP snippet from config/logging.php demonstrates how to configure Laravel's logging channels. It sets up a 'stack' channel that combines 'daily' and 'slack' channels, and defines the 'slack' channel for sending error logs to a Slack webhook with custom username and emoji.
```php
// config/logging.php
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['daily', 'slack'],
'ignore_exceptions' => false,
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
'username' => 'Payment System',
'emoji' => ':boom:',
'level' => 'error',
],
],
```
--------------------------------
### Manage WebSocket Connections with Laravel Echo in JavaScript
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This JavaScript class ('WebSocketService') provides methods to connect to a Laravel Echo instance, subscribe to private payment channels, and handle various payment-related events (request, status, connection success/error). It also includes methods for unsubscribing and disconnecting.
```javascript
// src/services/websocket.js
import Echo from 'laravel-echo'
import Pusher from 'pusher-js'
class WebSocketService {
constructor() {
this.echo = null
this.channels = new Map()
}
connect(token) {
if (this.echo) {
return this.echo
}
window.Pusher = Pusher
this.echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
forceTLS: true,
auth: {
headers: {
Authorization: `Bearer ${token}`
}
}
})
return this.echo
}
subscribeToPaymentChannel(userId, callbacks) {
const channelName = `payment.${userId}`
if (this.channels.has(channelName)) {
return this.channels.get(channelName)
}
const channel = this.echo.private(channelName)
// Payment request listener
if (callbacks.onPaymentRequest) {
channel.listen('.payment.request', callbacks.onPaymentRequest)
}
// Payment status listener
if (callbacks.onPaymentStatus) {
channel.listen('.payment.status', callbacks.onPaymentStatus)
}
// Connection status listeners
channel.listen('.pusher:subscription_succeeded', () => {
console.log('Connected to payment channel')
callbacks.onConnected?.()
})
channel.listen('.pusher:subscription_error', (error) => {
console.error('Payment channel subscription error:', error)
callbacks.onError?.(error)
})
this.channels.set(channelName, channel)
return channel
}
unsubscribe(channelName) {
if (this.channels.has(channelName)) {
this.echo.leave(channelName)
this.channels.delete(channelName)
}
}
disconnect() {
if (this.echo) {
this.channels.forEach((channel, name) => {
this.echo.leave(name)
})
this.channels.clear()
this.echo.disconnect()
this.echo = null
}
}
}
export default new WebSocketService()
```
--------------------------------
### Test Insufficient Balance Handling in Laravel
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This test verifies that the payment system correctly handles scenarios where a user has insufficient balance. It asserts that the API returns a 400 status code and an 'Insufficient balance' message upon payment confirmation.
```php
public function test_handles_insufficient_balance()
{
$user = User::factory()->create([
'balance' => 10,
'pin' => hash('sha256', '123456')
]);
// ... Create session and transaction ...
Sanctum::actingAs($user);
$response = $this->postJson('/api/payment/confirm', [
'transaction_id' => 'test-transaction',
'auth_method' => 'pin',
'auth_token' => '123456'
]);
$response->assertStatus(400);
$this->assertEquals('Insufficient balance', $response->json('message'));
}
```
--------------------------------
### Vue.js Composable for Payment Session and Transaction Management
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This Vue.js composable provides functions to interact with a payment API, enabling the creation of new payment sessions, confirmation of transactions, and retrieval of transaction statuses. It manages loading and error states, and integrates with Vuex stores for state management.
```javascript
// src/composables/usePayment.js
import { ref, computed } from 'vue'
import { usePaymentStore } from '@/stores/payment'
import { useAuthStore } from '@/stores/auth'
import api from '@/services/api'
export function usePayment() {
const paymentStore = usePaymentStore()
const authStore = useAuthStore()
const loading = ref(false)
const error = ref(null)
const createSession = async () => {
loading.value = true
error.value = null
try {
const response = await api.post('/payment/session', {
device_id: authStore.deviceId
})
paymentStore.setCurrentSession(response.data.data)
return response.data.data
} catch (err) {
error.value = err.response?.data?.message || 'Failed to create session'
throw err
} finally {
loading.value = false
}
}
const confirmTransaction = async ({ transaction_id, auth_method, auth_token }) => {
loading.value = true
error.value = null
try {
const response = await api.post('/payment/confirm', {
transaction_id,
auth_method,
auth_token
})
paymentStore.clearCurrentTransaction()
return response.data.data
} catch (err) {
error.value = err.response?.data?.message || 'Payment failed'
throw err
} finally {
loading.value = false
}
}
const getTransactionStatus = async (transactionId) => {
try {
const response = await api.get(`/payment/transaction/${transactionId}`)
return response.data.data
} catch (err) {
console.error('Failed to get transaction status:', err)
return null
}
}
const regenerateSession = async () => {
paymentStore.clearCurrentSession()
return createSession()
}
return {
loading: computed(() => loading.value),
error: computed(() => error.value),
currentSession: computed(() => paymentStore.currentSession),
currentTransaction: computed(() => paymentStore.currentTransaction),
createSession,
confirmTransaction,
getTransactionStatus,
regenerateSession
}
}
```
--------------------------------
### Vue.js Payment Confirmation Logic (Composition API)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Implements the core logic for payment confirmation using Vue 3 Composition API. It handles state management, computed properties for formatting, a countdown timer, authentication flows (biometric/PIN), and interaction with payment/authentication composables and Vue Router.
```JavaScript
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { usePayment } from '@/composables/usePayment'
import { useAuth } from '@/composables/useAuth'
import { useRouter } from 'vue-router'
import PinInput from '@/components/Auth/PinInput.vue'
const props = defineProps({
transaction: {
type: Object,
required: true
}
})
const { confirmTransaction, rejectTransaction } = usePayment()
const { checkBiometric, authenticateBiometric } = useAuth()
const router = useRouter()
const confirming = ref(false)
const showAuthModal = ref(false)
const pin = ref('')
const timeRemaining = ref(120)
const biometricAvailable = ref(false)
const formattedAmount = computed(() => {
return new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(props.transaction.amount)
})
let timer = null
const startTimer = () => {
timer = setInterval(() => {
timeRemaining.value--
if (timeRemaining.value <= 0) {
clearInterval(timer)
handleTimeout()
}
}, 1000)
}
const handleTimeout = () => {
router.push({
name: 'payment-error',
params: {
error: 'Payment request expired'
}
})
}
const confirmPayment = () => {
showAuthModal.value = true
}
const authenticateWithBiometric = async () => {
try {
const token = await authenticateBiometric()
await processPayment('biometric', token)
} catch (error) {
console.error('Biometric auth failed:', error)
// Fallback to PIN
biometricAvailable.value = false
}
}
const authenticateWithPin = async () => {
await processPayment('pin', pin.value)
}
const processPayment = async (method, token) => {
confirming.value = true
showAuthModal.value = false
try {
const result = await confirmTransaction({
transaction_id: props.transaction.transaction_id,
auth_method: method,
auth_token: token
})
router.push({
name: 'payment-success',
params: {
transactionId: result.transaction_id
}
})
} catch (error) {
router.push({
name: 'payment-error',
params: {
error: error.message || 'Payment failed'
}
})
} finally {
confirming.value = false
}
}
const rejectPayment = async () => {
try {
await rejectTransaction(props.transaction.transaction_id)
router.push({ name: 'home' })
} catch (error) {
console.error('Failed to reject payment:', error)
}
}
onMounted(async () => {
startTimer()
biometricAvailable.value = await checkBiometric()
})
onUnmounted(() => {
if (timer) {
clearInterval(timer)
}
})
```
--------------------------------
### Test Payment Confirmation Handling in Vue/Vitest
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This unit test validates the `confirmTransaction` function in a Vue composable, checking its interaction with the payment confirmation API endpoint. It uses a mocked API response to ensure the function processes the transaction ID and authentication details correctly.
```javascript
it('handles payment confirmation', async () => {
const mockResponse = {
transaction_id: 'test-transaction',
status: 'completed'
}
api.post.mockResolvedValue({
data: { data: mockResponse }
})
const { confirmTransaction } = usePayment()
const result = await confirmTransaction({
transaction_id: 'test-transaction',
auth_method: 'pin',
auth_token: '123456'
})
expect(api.post).toHaveBeenCalledWith('/payment/confirm', {
transaction_id: 'test-transaction',
auth_method: 'pin',
auth_token: '123456'
})
expect(result).toEqual(mockResponse)
})
})
```
--------------------------------
### Manage Payment Sessions in Laravel API
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This PHP code defines the `PaymentSessionController` responsible for handling API requests related to payment sessions. It includes methods for creating new sessions, validating input, and retrieving existing sessions, providing JSON responses for success or failure.
```php
// app/Http/Controllers/Api/PaymentSessionController.php
sessionService->createSession(
$request->user(),
$request->validated()
);
return response()->json([
'success' => true,
'data' => new PaymentSessionResource($session)
], 201);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Failed to create payment session',
'error' => config('app.debug') ? $e->getMessage() : null
], 500);
}
}
public function show(string $sessionId): JsonResponse
{
$session = $this->sessionService->getSession($sessionId);
if (!$session) {
return response()->json([
'success' => false,
'message' => 'Session not found or expired'
], 404);
}
return response()->json([
'success' => true,
'data' => new PaymentSessionResource($session)
]);
}
}
```
--------------------------------
### SQL Database Schema for Laravel QR Payment
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Defines the database tables for notifications and Laravel's default failed jobs, including their columns, data types, and indexing. It also includes the concluding part of a transaction table definition, showing foreign key and index details.
```SQL
FOREIGN KEY (user_id) REFERENCES users(id),
INDEX idx_user_created (user_id, created_at),
INDEX idx_transaction_id (transaction_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Notifications table
CREATE TABLE notifications (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
type VARCHAR(50) NOT NULL,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL,
data JSON NULL,
read_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
INDEX idx_user_unread (user_id, read_at),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Failed jobs table (Laravel default)
CREATE TABLE failed_jobs (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
uuid VARCHAR(255) UNIQUE NOT NULL,
connection TEXT NOT NULL,
queue TEXT NOT NULL,
payload LONGTEXT NOT NULL,
exception LONGTEXT NOT NULL,
failed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
--------------------------------
### Run Tests for Laravel QR Payment Package
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
Commands to execute the test suite for the Laravel QR Payment package, including running all tests, running with test documentation, and running specific test groups.
```bash
# Run all tests
vendor/bin/phpunit
# Run with test documentation
vendor/bin/phpunit --testdox
# Run specific test group
vendor/bin/phpunit --group=customer
```
--------------------------------
### Bind Custom Services in Laravel QR Payment
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
Example of how to extend or replace default services within the Laravel QR Payment package by binding a custom implementation to an interface in the `AppServiceProvider`.
```php
// In AppServiceProvider
use XavierAu\LaravelQrPayment\Contracts\QrCodeServiceInterface;
public function register()
{
$this->app->bind(QrCodeServiceInterface::class, function ($app) {
return new CustomQrCodeService();
});
}
```
--------------------------------
### Toggle Camera Flash (Vue.js)
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Controls the camera's flash functionality for the QR scanner. It checks for flash availability and toggles the flash on or off, providing better scanning conditions in low light.
```JavaScript
const toggleFlash = async () => {
if (scanner.value && hasFlash.value) {
flashOn.value = !flashOn.value;
await scanner.value.setFlash(flashOn.value);
}
};
```
--------------------------------
### Retrieve Payment Transaction by ID in Laravel
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
This PHP function retrieves a payment transaction by its ID. It first attempts to fetch the transaction from the cache. If not found in the cache, it queries the database for the transaction and returns it.
```php
public function getTransaction(string $transactionId): ?Transaction
{
// Try cache first
$cached = Cache::get("payment:transaction:{$transactionId}");
if ($cached) {
return $cached;
}
return Transaction::where('transaction_id', $transactionId)->first();
}
```
--------------------------------
### Run Laravel QR Payment Database Migrations
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/README.md
After publishing, this Artisan command executes the package's database migrations, creating the necessary tables for QR payment functionality.
```bash
php artisan migrate
```
--------------------------------
### Redis Key Patterns for Laravel QR Payment
Source: https://github.com/xavierau/laravel-qr-payment/blob/main/prd/project_implememntation_guide.md
Outlines the various Redis key patterns used in the Laravel QR payment system for managing session data, transaction states, pending requests, rate limiting, device bindings, merchant caches, and daily statistics, specifying their respective Time-To-Live (TTL) durations.
```PHP
// Redis key patterns
payment:session:{session_id} - Payment session data (TTL: 5 minutes)
payment:transaction:{transaction_id} - Transaction state (TTL: 10 minutes)
payment:pending:{user_id} - Pending payment requests (TTL: 2 minutes)
payment:rate_limit:{user_id} - Rate limiting counter (TTL: 1 minute)
payment:device:{device_id} - Device session binding (TTL: 1 hour)
payment:merchant:cache:{merchant_id} - Merchant data cache (TTL: 1 hour)
payment:stats:daily:{date} - Daily statistics (TTL: 7 days)
```