QR Code Payments: Making Crypto Transactions User-Friendly
QR codes have revolutionized cryptocurrency payments, making them as easy as scanning with a smartphone. This guide covers QR code payment implementation and best practices.
Why QR Codes for Crypto Payments?
User Experience Benefits
- Simple: Just scan and pay
- Fast: No manual address entry
- Error-Free: Eliminates typos in addresses
- Mobile-Friendly: Perfect for smartphone users
- Familiar: Users already know how to scan QR codes
Business Benefits
- Higher Conversion: Easier payments = more completed transactions
- Reduced Errors: No incorrect addresses
- Better UX: Professional payment experience
- Mobile Optimization: Reach mobile-first customers
QR Code Standards
Payment URI Format
Cryptocurrency QR codes use URI schemes:
ethereum:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb?value=1000000000000000000
bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa?amount=0.001
BIP-21 Standard
Bitcoin Improvement Proposal 21 defines QR code format:
bitcoin:ADDRESS?amount=AMOUNT&label=LABEL&message=MESSAGE
Generating QR Codes
JavaScript Implementation
const QRCode = require('qrcode');
async function generatePaymentQR(invoice) {
const paymentURI = `ethereum:${invoice.depositAddress}?value=${invoice.amountWei}`;
// Generate QR code as data URL
const qrCodeDataURL = await QRCode.toDataURL(paymentURI, {
width: 300,
margin: 2,
color: {
dark: '#000000',
light: '#FFFFFF'
}
});
return qrCodeDataURL;
}
// Usage
const invoice = {
depositAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
amount: '1.0',
amountWei: '1000000000000000000'
};
const qrCode = await generatePaymentQR(invoice);React Component
import QRCode from 'qrcode.react';
function PaymentQRCode({ address, amount, currency }) {
const paymentURI = `${currency}:${address}?amount=${amount}`;
return (
<div className="payment-qr">
<QRCode
value={paymentURI}
size={256}
level="H"
includeMargin={true}
/>
<p className="address">{address}</p>
<p className="amount">{amount} {currency}</p>
</div>
);
}Best Practices
1. Clear Visual Design
- Large QR Code: Minimum 256x256 pixels
- High Contrast: Black on white
- Error Correction: Use level H for reliability
- White Border: Include margin around code
2. Include Payment Details
Display alongside QR code:
- Amount: Clearly show payment amount
- Currency: Which cryptocurrency
- Address: Full address (for verification)
- Expiration: Time remaining
3. Mobile Optimization
function MobilePaymentQR({ invoice }) {
return (
<div className="mobile-payment">
<div className="qr-container">
<QRCode value={invoice.paymentURI} size={300} />
</div>
<div className="payment-details">
<h3>Amount: {invoice.amount} {invoice.currency}</h3>
<p className="address">{invoice.depositAddress}</p>
<button onClick={() => copyAddress(invoice.depositAddress)}>
Copy Address
</button>
</div>
<div className="timer">
<p>Expires in: {formatTime(invoice.expiresIn)}</p>
</div>
</div>
);
}4. Deep Linking
Enable direct wallet opening:
function generateDeepLink(address, amount, currency) {
// MetaMask
const metamaskLink = `https://metamask.app.link/dapp/pay?address=${address}&amount=${amount}`;
// Trust Wallet
const trustLink = `trust://wc?uri=${encodeURIComponent(paymentURI)}`;
// Generic
return {
metamask: metamaskLink,
trust: trustLink,
generic: paymentURI
};
}Payment Flow with QR Codes
Step 1: Generate Invoice
async function createInvoiceWithQR(amount, currency) {
// Create invoice
const invoice = await paymentGateway.createInvoice({
amount,
currency
});
// Generate QR code
const qrCode = await generatePaymentQR(invoice);
return {
...invoice,
qrCode
};
}Step 2: Display QR Code
function PaymentPage({ invoice }) {
return (
<div className="payment-page">
<h2>Scan to Pay</h2>
<div className="qr-section">
<img src={invoice.qrCode} alt="Payment QR Code" />
<p>Scan with your crypto wallet</p>
</div>
<div className="details">
<p><strong>Amount:</strong> {invoice.amount} {invoice.currency}</p>
<p><strong>Address:</strong> {invoice.depositAddress}</p>
<button onClick={() => copyToClipboard(invoice.depositAddress)}>
Copy Address
</button>
</div>
<PaymentStatus invoiceId={invoice.id} />
</div>
);
}Step 3: Monitor Payment
function PaymentStatus({ invoiceId }) {
const [status, setStatus] = useState('PENDING');
useEffect(() => {
const interval = setInterval(async () => {
const invoice = await checkInvoiceStatus(invoiceId);
setStatus(invoice.status);
if (invoice.status === 'CONFIRMED') {
clearInterval(interval);
// Redirect to success page
}
}, 3000);
return () => clearInterval(interval);
}, [invoiceId]);
return (
<div className="status">
<p>Status: {status}</p>
{status === 'PENDING' && <p>Waiting for payment...</p>}
{status === 'DETECTED' && <p>Payment detected, confirming...</p>}
{status === 'CONFIRMED' && <p>Payment confirmed!</p>}
</div>
);
}Advanced Features
Multi-Currency QR Codes
Support multiple cryptocurrencies:
function generateMultiCurrencyQR(invoice) {
const qrCodes = {
USDT: generateQR('ethereum', invoice.usdtAddress, invoice.amount),
BTC: generateQR('bitcoin', invoice.btcAddress, invoice.amount),
ETH: generateQR('ethereum', invoice.ethAddress, invoice.amount)
};
return qrCodes;
}Dynamic QR Codes
Update QR code based on payment status:
function DynamicQR({ invoice }) {
const [qrValue, setQrValue] = useState(invoice.paymentURI);
useEffect(() => {
if (invoice.status === 'PARTIALLY_PAID') {
const remaining = invoice.amountExpected - invoice.amountReceived;
setQrValue(generateURI(invoice.address, remaining));
}
}, [invoice.status]);
return <QRCode value={qrValue} />;
}Testing QR Codes
Test Checklist
- QR code scans correctly
- Amount is correct
- Address is correct
- Works on iOS and Android
- Works with major wallets
- Error correction works
- Mobile responsive
Testing Tools
- QR Code Scanner Apps: Test on real devices
- Online Scanners: Verify QR content
- Wallet Apps: Test actual payment flow
Common Issues and Solutions
QR Code Not Scanning
Solutions:
- Increase QR code size
- Improve contrast
- Add error correction
- Ensure good lighting
Wrong Amount
Solution: Always verify amount in QR code URI matches displayed amount.
Address Mismatch
Solution: Display full address alongside QR code for verification.
Conclusion
QR codes make cryptocurrency payments as easy as traditional mobile payments. Implementing them correctly significantly improves user experience and conversion rates.
Start using QR code payments with FromChain and make crypto payments effortless!
