WebView.
Building in React Native? Use the React Native SDK instead; it wraps this one.
Install
The SDK is on Maven Central asio.meld:meldsdk. New Android projects already list mavenCentral() in their repositories.
The library declares the
INTERNET and CAMERA permissions, which merge into your manifest. Camera is for KYC capture inside a provider’s surface.
A minified build needs no keep rules of your own. The SDK ships its R8 rules, and they cover an app that leaves out Google Play services Wallet too.
0.8.0 is the release that brings the wallet contract every Meld SDK shares: the readiness checks, the shared error codes with the order’s
paymentMethodType on each error, and the Activity mount. Everything else on this page works from 0.7.0, the first release with Google Pay.Configure the environment
Create the order on your backend
The order comes from your server. Your API key never ships in the app. See Cards or Wallets for the request. Return the response to the app unchanged: the SDK reads what it needs from it.Check readiness before you create the order
Two checks tell you what to offer, and both need 0.8.0 or later. They answerReady, Unavailable or Unknown, with the same meaning on every Meld SDK. See Wallets → The integration loop. Each answers once, on the main thread, within 5 seconds.
Before you quote
Ask whether this device can pay with a method at all, for example to decide whether to show a Google Pay entry point:GOOGLE_PAYasks Google Pay’sisReadyToPayfor any Visa, Mastercard, American Express or Discover card the customer has added. It answersReadywhen there is one andUnavailablewhen there is none. It answersUnknownwhen Google Play services is missing, out of date or slow, and, with the SDK configured forSANDBOX, when there is no card (see Google Pay in sandbox).APPLE_PAYanswersUnavailable: Apple Pay never runs on Android.- Any other method, such as
CREDIT_DEBIT_CARDor a bank transfer, answersUnknown: nothing on the device decides it.
After you quote
Each headless quote row carriespaymentMethodType and headlessPresentation. Ask the SDK whether this device can pay with a row, through its provider, before you offer it:
Ready: offer the method.Unavailable: hide the method. This SDK doesn’t present the row on this device, or Google Pay reports no card on this phone that the provider’s request accepts. No order exists, so there is nothing to track.Unknown: you may offer the method. Card rows answerUnknown, because nothing on the device decides whether a card pays. A Google Pay row answersUnknownwhen Google Play services is missing, out of date or slow, and, with the SDK configured forSANDBOX, when Google Pay finds no card.
Unavailable and Unknown carry a reason for your logs, and the SDK logs every Unknown reason under the MeldSDK tag. Readiness is advisory and moves no money. If you create the order anyway, the mounted order reports PAYMENT_METHOD_UNAVAILABLE when the device can’t pay, and that is the final word.
On 0.7.0, Meld.presentationCapabilities(presentation, paymentMethodType) answers only whether this build can present the row. Hide the row when its surface is unsupported.
Mount the order
mount on the main thread. Branch only on surface == "unsupported" and on embeddable. Every other surface value, such as embedded or native-wallet, is informational and can change between releases: see Surface is informational.
- Embeddable orders, the card forms, render into the
ViewGroupyou pass. Give it room. - Other orders, such as Google Pay, draw into none of your views and report
requiresUserGesture = true. Mount them from the customer’s tap withMeld.mount(order, activity, handlers). The payment then lives as long as that Activity: it ends only when the Activity is destroyed or you unmount, not when one of your views leaves its window. A configuration change the Activity doesn’t handle itself destroys it, and so ends the payment.
MeldMountException.MissingHost for an embeddable order, and MeldMountException.PresentationUnavailable when the Activity is not on screen. On 0.7.0, mount every order with a view. For a Google Pay order, the view only locates the Activity, and the payment ends when the view leaves its window, so keep it attached until a terminal callback.
Keep the handle until a terminal callback. handle.unmount() tears the surface down and delivers no callback. After onPaymentSubmitted you can unmount straight away: the SDK keeps a provider-hosted page alive for up to 60 seconds, so the provider can finish confirming the payment.
Events
Every callback runs on the main thread and receives the order’s id. The five events covers what each one means and how
onCancel and onError relate to the status.
Each mount delivers exactly one terminal callback, onPaymentSubmitted, onCancel or onError with recoverable: false, and drops every callback after it. If the session ends without one while you still hold the handle, you get onError with PAYMENT_OUTCOME_UNKNOWN, or with PAYMENT_REJECTED after a FAILED status. To retry after a terminal callback, create a new order.
Error codes
Every Meld SDK shares these codes, with the sameattemptMayExist for each: see Wallets → Error codes. They need 0.8.0 or later.
MeldErrorCode names these codes. error.attemptMayExist, or MeldErrorCode.attemptMayExist(code), is false only for the five codes that say no attempt exists, and true for every other code, including one this build doesn’t know.
error.paymentMethodType is the mounted order’s paymentMethodType, such as GOOGLE_PAY, or null when the order has none. Word your message from it rather than from the code.
detail carries the provider’s own event or code. Log it; don’t branch on it.
Card forms that fail before they show
The Banxa and Uphold card forms run a provider SDK, bundled with this one, inside theWebView. When that page fails before the form shows, they report a shared code, with the form’s own code in detail:
Codes the card forms pass through
The Android SDK adds no code of its own. Its card forms pass the provider’s other codes through, and each can follow a payment, soattemptMayExist is true for all of them:
Google Pay
Coinbase presents Google Pay through its own payment page. The SDK loads that page out of sight and presses its Google Pay button once, so the customer sees only Google Pay’s sheet. Such an order reportsembeddable = false, surface = "native-wallet" and requiresUserGesture = true.
Before you offer it, meet Before you go live: your own Coinbase project with Google Pay enabled, your app’s own approval in the Google Pay & Wallet Console, and a physical phone with Android System WebView 137 or later and Google Play services 25.18.30 or later. On a WebView without Payment Request support, Meld.capabilities reports unsupported.
How to test it, and what OR_BIBED_11 and the other failures mean, are in Wallets → Testing and Wallets → Troubleshooting.
What the SDK adds to your app
- From 0.7.0, the package queries for
org.chromium.intent.action.PAY,IS_READY_TO_PAYandUPDATE_PAYMENT_DETAILS, through which the provider page’s Payment Request reaches Google Pay. - From 0.8.0, Google Play services Wallet (
com.google.android.gms:play-services-wallet20.0.0), for the readiness checks only. Your merged manifest gains thecom.google.android.gms.wallet.api.enabledandcom.google.android.gms.versionmeta-data and the non-exportedcom.google.android.gms.common.api.GoogleApiActivity. - Nothing from Google Maps. Wallet uses
play-services-mapsonly for theLatLngof its loyalty, offer and gift card objects, which the SDK never builds, so the SDK excludes it. Your merged manifest gains none of Maps’ entries, such as the OpenGL ES 2uses-featurewithrequired="true". An app that uses Maps keeps its own dependency on it.
Leaving out Google Play services Wallet
Wallet is there for the readiness checks only, so you can exclude it:Unknown. A minified build still needs no rules of your own: the SDK’s R8 rules let Wallet be missing.
Provider notes
- Mercuryo. Create the order with the customer’s public IP as
clientIpAddress: Mercuryo binds its widget to it. Its KYC liveness check needs the camera, so request theCAMERApermission at run time before you mount. - Coinbase. Google Pay only, for US customers paying USD. See Google Pay with Coinbase.
unsupported.
Settlement
Settlement is your webhook.onPaymentSubmitted fires when the customer finishes paying, which is earlier: unmount and show a pending state until the webhook arrives.
See Configure webhooks.