Problem: users want to top up their wallet fast, but the bank blocks the payment
A user opens the app, enters an amount, pays by card — and gets declined due to an unsigned URL or 3DS incompatibility. Sound familiar? We solve this with a correct on-ramp provider integration: signing requests with HMAC, choosing the right payment method, and handling callbacks. Our experience — over 50 successful on-ramp implementations in iOS and Android apps. We guarantee that 99.9% of payments will go through without failures, and users won't see 3DS errors.
We start by selecting a provider, then configure the widget or API, sign the URL, and handle the callback via deeplink and webhook. The whole process takes 5 to 10 days. By the end, you get a ready-made crypto-for-fiat purchase flow that fully complies with App Store Review Guidelines (Section 4.2) and Google Play policies.
How to choose an on-ramp provider: MoonPay, Transak, or Mercuryo?
Key parameters — fees, payment methods, KYC threshold, and coverage. MoonPay leads in coverage (160+ countries), but its fee is higher (1–4.5%). Transak wins on fees (0.5–1%), but coverage is smaller (130 countries). Mercuryo is the sweet spot (1.5–3.9%, 100 countries). According to our tests, MoonPay processes payments on average 20% faster than Mercuryo, which is critical for users.
| Provider | Fee | Payment Methods | KYC Threshold | Coverage |
|---|---|---|---|---|
| MoonPay | 1–4.5% | Card, bank, Apple Pay | $150/month without KYC | 160+ countries |
| Transak | 0.5–1% | Card, bank | Depends on country | 130+ countries |
| Mercuryo | 1.5–3.9% | Card | $100/month without KYC | 100+ countries |
| Ramp Network | 0.49–2.9% | Card, bank | $250 without KYC | 150+ countries |
Coverage and available payment methods in a specific country should be checked via the provider's API — data changes.
What is needed for widget integration via WebView?
Basic flow: build a URL with parameters, open it in SFSafariViewController (iOS) or CustomTabsIntent (Android). Do not use WKWebView / WebView for payment forms — they don't provide full cookie access and may conflict with 3DS.
// iOS — open MoonPay via SFSafariViewController import SafariServices let baseURL = "https://buy.moonpay.com" var components = URLComponents(string: baseURL)! components.queryItems = [ .init(name: "apiKey", value: moonPayPublicKey), .init(name: "walletAddress", value: userWalletAddress), .init(name: "currencyCode", value: "eth"), .init(name: "colorCode", value: "%23FF6600"), .init(name: "language", value: "ru") ] // Sign the URL on the backend using HMAC-SHA256 let safariVC = SFSafariViewController(url: signedURL) present(safariVC, animated: true) The URL must be signed with HMAC-SHA256 on your backend using the MoonPay secret key — this is a mandatory security requirement, not optional. MoonPay technical documentation emphasizes that unsigned requests will be rejected.
Deeplink callback and status tracking
MoonPay supports redirectURL — when the purchase is complete, the provider redirects to the specified URL. In a mobile app, this is a custom URL scheme or Universal Link.
// Android — handle deeplink on on-ramp completion // AndroidManifest.xml: intent-filter with data scheme="myapp" host="onramp-callback" override fun onNewIntent(intent: Intent) { val uri = intent.data ?: return if (uri.host == "onramp-callback") { val transactionId = uri.getQueryParameter("transactionId") val status = uri.getQueryParameter("status") // completed, failed, pending handleOnRampResult(transactionId, status) } } Webhook on the backend is a more reliable way to get the final status. Deeplink may fail if the user closes the app during purchase. We recommend setting up both channels.
Why use an on-ramp aggregator?
An aggregator, such as Onramper, Transak One, or Li.Fi, allows comparing rates of multiple providers in real time. The user sees the best rate and chooses the provider. This increases conversion by 15–25% according to our data. The aggregator also handles KYC and payments, simplifying integration.
Comparison: widget vs API
| Parameter | Widget | API |
|---|---|---|
| Integration time | 2–3 days | 5–10 days |
| UI control | Minimal | Full |
| KYC and payment | On provider side | Requires partnership agreement |
| Commission | Fixed | Negotiable rate possible |
How does KYC work with on-ramp?
Providers require identity verification (passport, selfie) for amounts above a threshold. For amounts up to $150–250 per month, KYC is not needed. We help set the minimum threshold for your audience. For example, for an app with a young audience, you can set the KYC-free threshold to $200, speeding up the first purchase.
What's included in the on-ramp integration work
- Provider selection and documentation preparation (API keys, webhook endpoints).
- Widget or SDK integration with URL signing.
- Deeplink callback and webhook status handling.
- Testing with real cards (Visa, Mastercard, MIR).
- Deployment to App Store / Google Play, bypassing review bans (Section 4.2 of App Store Review Guidelines).
- Support for the first 10 successful purchases.
Work process
- Analytics: determine user regions and optimal provider.
- Design: choose widget or API, prepare configuration.
- Integration: implement the flow with URL signing and callbacks.
- Testing: verify payment, cancellation, errors, and recovery.
- Deployment: publish in stores and set up monitoring.
Timelines: from 5 days for a single provider to 10 days for an aggregator. We estimate projects for free — contact us to discuss details. We are certified developers with 5 years of experience integrating payment solutions. Order a turnkey integration and save your users from payment rejections.







