Реализация QR-кода для приёма криптоплатежей в мобильном приложении
QR для приёма платежа — не просто адрес в квадратиках. Правильный URI-формат позволяет плательщику автоматически заполнить сумму и валюту в своём кошельке. Неправильный размер или отсутствие error correction — и QR не считается половиной сканеров.
URI-форматы для разных блокчейнов
Стандартные форматы, которые распознают большинство кошельков:
-
Bitcoin (BIP-21):
bitcoin:1A2B3C4D5E6F?amount=0.001&label=Order+123 -
Ethereum (EIP-681):
ethereum:0xAbCd1234@1?value=500000000000000000(value в wei) -
ERC-20 transfer (EIP-681):
ethereum:0xTokenAddress@1/transfer?address=0xRecipient&uint256=1000000(USDC, 6 decimals) -
Solana (SPL):
solana:RecipientPubkey?amount=0.5&spl-token=TokenMintAddress&label=Payment
EIP-681 для ERC-20 — нотация неочевидная: сначала адрес контракта токена, потом метод transfer с получателем и суммой. Многие кошельки поддерживают упрощённый формат: ethereum:0xRecipient?value=X&contractAddress=0xToken.
Генерация QR с правильными параметрами
// iOS — генерация QR через CoreImage с нужным уровнем коррекции
import CoreImage.CIFilterBuiltins
func generateQRCode(from string: String, size: CGFloat = 300) -> UIImage {
let filter = CIFilter.qrCodeGenerator()
filter.message = Data(string.utf8)
filter.correctionLevel = "Q" // 25% error correction — для логотипа поверх QR
let transform = CGAffineTransform(scaleX: size / filter.outputImage!.extent.width,
y: size / filter.outputImage!.extent.height)
let scaledImage = filter.outputImage!.transformed(by: transform)
// Интерполяция nearest neighbor для чёткости
let context = CIContext()
let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent)!
return UIImage(cgImage: cgImage)
}
// Android — ZXing с кастомным размером
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.qrcode.QRCodeWriter
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
val hints = mapOf(
EncodeHintType.ERROR_CORRECTION to ErrorCorrectionLevel.Q,
EncodeHintType.MARGIN to 1,
EncodeHintType.CHARACTER_SET to "UTF-8"
)
val bitMatrix = QRCodeWriter().encode(uri, BarcodeFormat.QR_CODE, 512, 512, hints)
Уровень коррекции Q (25%) — оптимален, если поверх QR планируется логотип приложения. Без логотипа достаточно M (15%).
Динамическая сумма и выбор токена
Если в приложении есть поле ввода суммы перед генерацией QR — URI обновляется при каждом изменении суммы. Для ERC-20 важно учесть decimals при формировании value:
// Android — расчёт value для USDC (6 decimals)
val humanAmount = BigDecimal("100.50") // введено пользователем
val decimals = 6
val rawAmount = humanAmount.movePointRight(decimals).toBigInteger() // 100500000
val uri = "ethereum:${usdcContractAddress}@1/transfer?address=${recipientAddress}&uint256=$rawAmount"
Брендинг поверх QR
Логотип приложения в центре QR — стандартная практика. Центральная зона до 30% площади — безопасно при уровне коррекции Q. Логотип должен быть белым квадратом с иконкой, чтобы не нарушать контрастность модулей QR.
Сроки: 1 день: генерация QR по корректному URI-формату, поле ввода суммы, кнопки «Копировать» и «Поделиться», опциональный логотип в центре.







