Files
MySMSAPio/QR_CODE_SETUP.md
2025-10-22 17:22:17 +08:00

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

  1. User opens Android SMS Gateway app
  2. Taps "Scan QR Code" or similar option
  3. Camera opens with QR scanner
  4. Scans the QR code from admin interface
  5. App parses JSON configuration
  6. All fields auto-populated:
    • API Base URL field
    • WebSocket URL field
    • API Key field
  7. User taps "Save" or "Connect"
  8. App connects to server
  9. Gateway appears as "Online" in admin interface

Expected Android App Code

The Android app should:

  1. Scan QR Code:
// Using ML Kit or ZXing library
val result = qrCodeScanner.scan()
val jsonString = result.text
  1. 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")
  1. Validate Version:
if (version != "1.0") {
    showError("Unsupported configuration version")
    return
}
  1. Save Configuration:
sharedPreferences.edit().apply {
    putString("api_key", apiKey)
    putString("api_base_url", apiBaseUrl)
    putString("websocket_url", websocketUrl)
    apply()
}
  1. 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

  1. Display Environment:

    • Only display QR code in secure locations
    • Ensure no cameras/recording devices nearby
    • Clear screen after scanning
  2. Network Security:

    • Use HTTPS/WSS in production (config.force_ssl = true)
    • Never use HTTP/WS in production
    • Implement rate limiting on WebSocket connections
  3. Key Management:

    • QR code shown only once during gateway creation
    • If compromised, deactivate gateway and create new one
    • Regularly audit active gateways
  4. 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:

  1. rqrcode gem installed: bundle show rqrcode
  2. Controller generates QR code: Check @qr_code_data in view
  3. Browser console for JavaScript errors
  4. 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:

  1. QR code scanner library issue
  2. JSON parsing error
  3. 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

  1. 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}"
  1. Navigate to Success Page:

    • Visit: http://localhost:3000/admin/gateways/new
    • Fill form and submit
    • Should redirect to gateway show page with QR code
  2. Test QR Code:

    • Open QR code scanner app on phone
    • Scan the displayed QR code
    • Verify JSON payload contains all fields
  3. 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

  1. Download QR Code:

    • Add "Download QR Code" button
    • Generate PNG image
    • Allow saving for later
  2. Email QR Code:

    • Send QR code via email
    • Secure time-limited link
    • Auto-expires after 1 hour
  3. Multiple QR Code Formats:

    • Different sizes (small, medium, large)
    • Different error correction levels
    • PNG, SVG, PDF options
  4. Configuration Presets:

    • Save common configurations
    • Apply preset to multiple gateways
    • Template system
  5. 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!