Logo
PAMC
M
Weerachai Tamboon

WS1: Payment QR Code Generator

Status:UAT & Sign-off
Link:https://pam-barcode-gen.workflowdeep.com/ (staging)
Started: 19 Aug 2026 25 hours budget Deployed — UAT Pending
Phase 1
Root Cause Analysis
Phase 1.5
Solution Proposal
Phase 2
Remediation & Deploy
Phase 3
UAT & Sign-off

Problem Statement

Reported Issue When generating QR codes sequentially for different debtors/contracts, the displayed Ref1 and Ref2 values appear correct. However, when the QR code is scanned and payment is made, the system references the previous QR code's data — causing payments to be recorded against the wrong debtor/contract.

Business Impact

Payments recorded to wrong debtor account
Incorrect contract linkage for payment records
Disrupts reconciliation — requires manual correction
Risk to customer trust — QR planned as primary payment channel

Root Cause Analysis

Complete

Stack: Plain PHP (no framework) • picqer/php-barcode-generator • phpqrcode library • Apache • No database

// generate_barcode.php — Line 46 $filename = $tempDir . 'qrcode.png'; // ← THE BUG: Single shared file for ALL users // Developer's commented-out fix (never enabled): //$filename = $tempDir . 'qrcode_' . uniqid() . '.png';

Findings

Single shared QR file: Every generation overwrites temp/qrcode.png — race condition between users
No session isolation: No user sessions, no per-request unique identifiers
No database: Entirely stateless, file-based output
Security gaps: display_errors enabled in production, no input validation, no CSRF
Previous workaround: .htaccess disables caching (confirms known issue was recognized)

QR Payload Structure

$barcodeValue = "|{$Position_A}\n{$Position_B}\n{$Position_C}\n{$Position_D}"; // Position_A = '050556401193214' → Biller ID (hardcoded) // Position_B = National ID → Ref1 // Position_C = Contract Number → Ref2 // Position_D = Payment Amount

Solution

Deployed

Option B: New React Application

  • React + Vite + Tailwind — modern stack
  • Client-side QR generation (eliminates race condition entirely)
  • Proper state management & input validation
  • Responsive design, Thai language support
  • PDF & image export working
  • HTTPS with auto-SSL via Certbot

Option A: Fix Existing Code

  • Enable unique filenames per generation
  • Add file cleanup mechanism
  • Same PHP stack — harder to maintain
  • No modern UX improvements

Deployment Details

Live
URL: https://pam-barcode-gen.workflowdeep.com (Staging)
Server: 157.85.xxx.xxx — Ubuntu 24.04, Nginx, Node 20
Stack: React 19 + Vite + Tailwind (static build)
SSL: Let's Encrypt (Certbot auto-renewal)

Browser Verification (24 Aug 2026)

7/7 Pass
Page Load & SSL — HTTPS valid, HTTP redirects
UI Rendering — Logos, fonts, responsive layout all correct
Barcode Generation — Code128 SVG renders with correct BOT payload
QR Code — Renders correct data (bank scan pending for EMVCo format)
PDF & Image Export — html2canvas + jsPDF working
Navigation / Routing — SPA fallback working, no 404s
Console & Network — Zero JS errors, all requests 200/304
Minor follow-ups: ① Scan QR with bank app to confirm EMVCo acceptance • ② Disable html2canvas debug logging • ③ Consider stripping dashes from Ref.2 input

Tasks

Phase 1: Root Cause Analysis
Done — Aug 19–24
Phase 2: Remediation (React rewrite + deploy)
Done — Aug 24
Phase 3: UAT and Sign-off
In Progress — Pending PAMC

Analysis Checklist

7/7
Review source code of QR Generator
Trace QR generation flow (Ref1/Ref2)
Inspect cache/session/temp handling
Review DB mapping & queries
Check payment callback handling
Identify root cause
Deliver RCA Report

Deliverables

Root Cause Analysis Report
New React Application (replaces legacy PHP)
Deployment to pam-barcode-gen.workflowdeep.com
Automated Deployment Script
Browser Verification Report (7/7 pass)
UAT Evidence + PAMC Sign-off
Bank app QR scan confirmation

Acceptance Criteria

Correct Ref1/Ref2 per QR generation
No stale data from previous generation
Payment records to correct debtor (bank scan pending)
Multi-generation sequential test pass
Same/different amount cases pass
Same/different debtor cases pass
No Critical/High defects
PAMC UAT Sign-off