Интеграция MoonPay для покупки крипты в мобильном приложении
MoonPay — один из наиболее распространённых on-ramp провайдеров. Поддерживает 160+ стран, карты Visa/Mastercard/Amex, Apple Pay, Google Pay, банковские переводы. Интеграция через виджет занимает день, но правильно подписанный URL и обработка коллбэков — отдельная история.
Получение API ключей и подпись URL
На dashboard.moonpay.com — создать аккаунт, получить publishable key (публичный, в приложении) и secret key (только на сервере). Без secret key нельзя подписать URL, без подписи MoonPay блокирует виджет.
Подпись — HMAC-SHA256 от строки запроса URL:
// Формирование подписанного URL — выполняется на бэкенде, не в приложении
// Серверная сторона (Node.js пример):
const crypto = require('crypto');
const queryString = new URL(widgetUrl).search; // "?apiKey=...&walletAddress=..."
const signature = crypto
.createHmac('sha256', process.env.MOONPAY_SECRET_KEY)
.update(queryString)
.digest('base64');
const signedUrl = `${widgetUrl}&signature=${encodeURIComponent(signature)}`;
Приложение запрашивает подписанный URL с собственного бэкенда, никогда не хранит secret key локально.
Открытие виджета на iOS и Android
// iOS — SFSafariViewController (рекомендуется MoonPay)
import SafariServices
let vc = SFSafariViewController(url: URL(string: signedUrl)!)
vc.preferredBarTintColor = UIColor(named: "AppBackground")
vc.preferredControlTintColor = UIColor(named: "AppTint")
present(vc, animated: true)
// Android — Chrome Custom Tabs
val customTabsIntent = CustomTabsIntent.Builder()
.setToolbarColor(ContextCompat.getColor(context, R.color.app_background))
.setShowTitle(true)
.build()
customTabsIntent.launchUrl(context, Uri.parse(signedUrl))
Не открывать виджет в обычном WebView — MoonPay явно это не рекомендует из соображений безопасности 3DS.
Параметры кастомизации
Ключевые query параметры виджета:
-
walletAddress— адрес для получения крипты -
currencyCode—eth,btc,sol,usdc_ethereumи т.д. -
baseCurrencyAmount— предзаполненная сумма в фиате -
baseCurrencyCode—usd,eur,gbp -
colorCode— цвет акцентов (URL-encoded hex,%23FF6600) -
language—ru,en,deи т.д. -
email— предзаполнить email для KYC (если известен) -
redirectURL— URL для возврата в приложение после покупки
Обработка результата через deeplink
После успешной покупки MoonPay редиректит на redirectURL. Регистрировать custom URL scheme в приложении:
// Android: AndroidManifest.xml
// <intent-filter>
// <data android:scheme="myapp" android:host="moonpay-success"/>
// </intent-filter>
override fun onNewIntent(intent: Intent) {
val uri = intent.data ?: return
if (uri.host == "moonpay-success") {
val txId = uri.getQueryParameter("transactionId")
// Показать экран успеха, обновить баланс через 30 сек
}
}
Дополнительно — webhook на бэкенде для надёжного получения статуса (transaction_completed, transaction_failed). MoonPay отправляет события на webhookUrl из настроек dashboard.
Сроки: 2–3 дня: серверная подпись URL, интеграция виджета через SFSafariViewController/CustomTabs, deeplink callback, обновление баланса после успешной покупки.







