### 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

Enter PIN

``` -------------------------------- ### 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) ```