11 KiB
QR Code Gateway Setup
Overview
The gateway registration now includes QR code generation for quick and easy Android app configuration. When a new gateway is created, the system automatically generates a QR code containing all necessary configuration data.
What's Included in the QR Code
The QR code contains a JSON payload with:
{
"api_key": "gw_live_a6e2b250dade8f6501256a8717723fc3f8ab7d4e7cb26aad470d65ee8478a82c",
"api_base_url": "http://localhost:3000",
"websocket_url": "ws://localhost:3000/cable",
"version": "1.0"
}
Fields Explained
| Field | Description | Example |
|---|---|---|
api_key |
Gateway authentication key | gw_live_... (64 chars) |
api_base_url |
Base URL for API endpoints | http://localhost:3000 or https://api.example.com |
websocket_url |
WebSocket connection URL | ws://localhost:3000/cable or wss://api.example.com/cable |
version |
Configuration format version | 1.0 |
Features
1. QR Code Display
Location: Gateway creation success page (/admin/gateways/:id after creation)
Visual Features:
- High-quality SVG QR code
- Error correction level: High (L=H)
- White background with border
- Centered display
- Info badge explaining contents
2. Manual Configuration Fallback
If QR scanning is unavailable, the page also displays:
- API Base URL (with individual copy button)
- WebSocket URL (with individual copy button)
- API Key (with individual copy button)
- "Copy All" button to copy all three fields at once
3. Copy to Clipboard Functions
Individual Field Copy:
copyField('api-base-url') // Copies just the API base URL
copyField('ws-url') // Copies just the WebSocket URL
copyField('api-key') // Copies just the API key
Copy All Configuration:
copyAllConfig() // Copies all fields as formatted text
Output format:
API Base URL: http://localhost:3000
WebSocket URL: ws://localhost:3000/cable
API Key: gw_live_a6e2b250dade8f6501256a8717723fc3f8ab7d4e7cb26aad470d65ee8478a82c
Implementation Details
Gem Used
rqrcode v2.0+
- Pure Ruby QR code generator
- No external dependencies
- SVG output support
- High error correction
Added to Gemfile:
gem "rqrcode", "~> 2.0"
Controller Method
File: app/controllers/admin/gateways_controller.rb
def generate_qr_code_data(api_key)
require "rqrcode"
# Determine URLs based on request
base_url = request.base_url
ws_url = request.base_url.sub(/^http/, "ws") + "/cable"
# Create JSON configuration
config_data = {
api_key: api_key,
api_base_url: base_url,
websocket_url: ws_url,
version: "1.0"
}.to_json
# Generate QR code with high error correction
qr = RQRCode::QRCode.new(config_data, level: :h)
# Return as SVG string
qr.as_svg(
offset: 0,
color: "000",
shape_rendering: "crispEdges",
module_size: 4,
standalone: true,
use_path: true
)
end
View Integration
File: app/views/admin/gateways/show.html.erb
The QR code is displayed using:
<div class="bg-white p-4 rounded-lg shadow-inner border-2 border-gray-200">
<%= @qr_code_data.html_safe %>
</div>
URL Detection
The system automatically detects the correct URLs based on the request:
Development
- Base URL:
http://localhost:3000 - WebSocket URL:
ws://localhost:3000/cable
Production (HTTP)
- Base URL:
http://api.example.com - WebSocket URL:
ws://api.example.com/cable
Production (HTTPS) - Recommended
- Base URL:
https://api.example.com - WebSocket URL:
wss://api.example.com/cable
Note: WebSocket URL automatically changes from http to ws and https to wss.
Android App Integration
QR Code Scanning Flow
- User opens Android SMS Gateway app
- Taps "Scan QR Code" or similar option
- Camera opens with QR scanner
- Scans the QR code from admin interface
- App parses JSON configuration
- All fields auto-populated:
- API Base URL field
- WebSocket URL field
- API Key field
- User taps "Save" or "Connect"
- App connects to server
- Gateway appears as "Online" in admin interface
Expected Android App Code
The Android app should:
- Scan QR Code:
// Using ML Kit or ZXing library
val result = qrCodeScanner.scan()
val jsonString = result.text
- Parse JSON:
val config = JSONObject(jsonString)
val apiKey = config.getString("api_key")
val apiBaseUrl = config.getString("api_base_url")
val websocketUrl = config.getString("websocket_url")
val version = config.getString("version")
- Validate Version:
if (version != "1.0") {
showError("Unsupported configuration version")
return
}
- Save Configuration:
sharedPreferences.edit().apply {
putString("api_key", apiKey)
putString("api_base_url", apiBaseUrl)
putString("websocket_url", websocketUrl)
apply()
}
- Connect to Server:
// Connect to WebSocket
webSocketClient.connect(websocketUrl, apiKey)
// Test API connection
apiClient.setBaseUrl(apiBaseUrl)
apiClient.setAuthToken(apiKey)
apiClient.sendHeartbeat()
Security Considerations
QR Code Security
✅ Secure:
- QR code displayed only once after creation
- Requires admin authentication to view
- Session-based display (not in URL)
- Page cannot be refreshed to see QR code again
⚠️ Warning:
- Anyone with camera access to the screen can scan the QR code
- QR code contains full API key in plaintext JSON
- Suitable for secure environments only
Best Practices
-
Display Environment:
- Only display QR code in secure locations
- Ensure no cameras/recording devices nearby
- Clear screen after scanning
-
Network Security:
- Use HTTPS/WSS in production (
config.force_ssl = true) - Never use HTTP/WS in production
- Implement rate limiting on WebSocket connections
- Use HTTPS/WSS in production (
-
Key Management:
- QR code shown only once during gateway creation
- If compromised, deactivate gateway and create new one
- Regularly audit active gateways
-
Mobile App Security:
- Store configuration in encrypted SharedPreferences
- Use Android Keystore for API key storage
- Implement certificate pinning for API calls
- Validate SSL certificates for WebSocket connections
Troubleshooting
QR Code Not Displaying
Check:
rqrcodegem installed:bundle show rqrcode- Controller generates QR code: Check
@qr_code_datain view - Browser console for JavaScript errors
- View source - SVG should be present
Fix:
bundle install
bin/rails restart
QR Code Too Complex to Scan
Symptom: QR scanner can't read the code
Cause: JSON payload too long (rare, but possible with very long URLs)
Solution:
- Use shorter domain names
- Reduce module_size in controller (current: 4)
- Lower error correction level (current: :h, try :m or :l)
Wrong URLs in QR Code
Symptom: QR code contains localhost in production
Cause: request.base_url not detecting correctly
Fix: Set environment variables in production
# .env or config
RAILS_FORCE_SSL=true
RAILS_RELATIVE_URL_ROOT=https://api.example.com
Or override in controller:
base_url = ENV['API_BASE_URL'] || request.base_url
Android App Can't Parse QR Code
Symptom: App shows "Invalid QR code" error
Causes:
- QR code scanner library issue
- JSON parsing error
- Wrong configuration version
Debug:
try {
val json = JSONObject(qrCodeText)
Log.d("QR", "API Key: ${json.getString("api_key")}")
Log.d("QR", "Base URL: ${json.getString("api_base_url")}")
Log.d("QR", "WS URL: ${json.getString("websocket_url")}")
} catch (e: Exception) {
Log.e("QR", "Parse error: ${e.message}")
}
Testing
Manual QR Code Test
- Create Test Gateway:
bin/rails console
gateway = Gateway.new(
device_id: "test-qr-001",
name: "QR Test Gateway",
priority: 1,
status: "offline"
)
raw_key = gateway.generate_api_key!
puts "Gateway ID: #{gateway.id}"
puts "Raw Key: #{raw_key}"
-
Navigate to Success Page:
- Visit:
http://localhost:3000/admin/gateways/new - Fill form and submit
- Should redirect to gateway show page with QR code
- Visit:
-
Test QR Code:
- Open QR code scanner app on phone
- Scan the displayed QR code
- Verify JSON payload contains all fields
-
Test Copy Buttons:
- Click individual copy buttons (API URL, WS URL, API Key)
- Verify green checkmark feedback
- Click "Copy All" button
- Paste in text editor - verify format
Automated Test
# test/controllers/admin/gateways_controller_test.rb
test "should generate QR code on gateway creation" do
post admin_gateways_url, params: {
gateway: {
device_id: "test-001",
name: "Test Gateway",
priority: 5
}
}
assert_response :redirect
gateway = Gateway.last
get admin_gateway_url(gateway)
assert_response :success
assert_select 'svg' # QR code should be present as SVG
end
Configuration Examples
Local Development
{
"api_key": "gw_live_abc123...",
"api_base_url": "http://localhost:3000",
"websocket_url": "ws://localhost:3000/cable",
"version": "1.0"
}
Staging Environment
{
"api_key": "gw_live_def456...",
"api_base_url": "https://staging-api.example.com",
"websocket_url": "wss://staging-api.example.com/cable",
"version": "1.0"
}
Production Environment
{
"api_key": "gw_live_ghi789...",
"api_base_url": "https://api.example.com",
"websocket_url": "wss://api.example.com/cable",
"version": "1.0"
}
Future Enhancements
Possible Improvements
-
Download QR Code:
- Add "Download QR Code" button
- Generate PNG image
- Allow saving for later
-
Email QR Code:
- Send QR code via email
- Secure time-limited link
- Auto-expires after 1 hour
-
Multiple QR Code Formats:
- Different sizes (small, medium, large)
- Different error correction levels
- PNG, SVG, PDF options
-
Configuration Presets:
- Save common configurations
- Apply preset to multiple gateways
- Template system
-
Advanced Security:
- Encrypted QR code payload
- Time-limited configuration URLs
- Two-factor gateway activation
Summary
✅ Implemented: QR code generation with all gateway configuration ✅ Features: Scan QR code OR manual copy/paste ✅ Security: One-time display, session-based, admin-only ✅ UX: Copy buttons with visual feedback, clear instructions ✅ Production Ready: Automatic URL detection (HTTP/HTTPS/WS/WSS)
The QR code feature makes gateway setup much faster and reduces configuration errors by eliminating manual typing of long API keys!