<MoonPayBuyButton> renders the Buy Button frame
inline in your layout. The frame renders the payment button that matches the
payment method in the quote (Apple Pay, Google Pay, or a saved card) and runs
the purchase on tap.
Pass headless to run the same purchase with no button. Use headless
mode for saved-card and bank transfer (SEPA) quotes when you
draw your own native purchase button.
Apple Pay and Google Pay inside a WebView have extra requirements. See Mobile
WebViews. When the wallet isn’t
available, the component emits an
"error" with code applePayUnavailable or
googlePayUnavailable: offer another payment method.BuyButtonSection.tsx
Props
Button settings
PassapplePayButtonSettings and googlePayButtonSettings as plain objects.
The frame applies the one that matches the button it renders, so you can pass
both. Every property is optional. Both settings are read at mount only.
The imperative client.setupBuyButton() method accepts the same two options.
Style the wallet buttons
style prop to match the button height you
choose. Both settings take width, height, borderRadius, paddingX,
paddingY, and style (black, white, or white-outline). Apple Pay also
takes type and locale. On Google Pay, white and white-outline render the
same white button with an outline. The settings have no effect in headless mode,
since the frame renders no button.
For the allowed values, defaults, and validation rules, see Apple Pay button
settings and Google Pay
button settings. Both
types are exported from @moonpay/platform-sdk-react-native.
BuyButtonEvent
Use event.kind to handle each event.
When the quote expires, the frame emits an
"error" event with
code: "quoteExpired". Fetch a new quote and update the quote prop to retry.
FrameTransaction
FrameTransaction is a discriminated union — the failure variant carries
failureCode and failureReason, the non-failure variant always carries id.
Pass id to
client.getTransaction()
to poll for the final status.
Headless mode
Passheadless when you draw your own native purchase button. The component
renders nothing visible and starts the purchase as soon as it mounts. Mount it
when the customer confirms the purchase in your UI, not before, because
mounting it is what starts the purchase. headless is mount-time only.
Headless mode sends the same BuyButtonEvent events, with
these differences:
- It accepts saved-card and bank transfer (
sepa) quotes for a connected customer only. An Apple Pay or Google Pay quote gets an"error"with codeunsupportedPaymentMethod, and a guest checkout quote getsinvalidQuote. - It never sends
"buttonPressed"or"cancelled". - After
"ready", it sends exactly one of"complete","challenge", or"error". - It reads a new
quoteonly after an"error"with codequoteExpired. At any other time the frame ignores the update, so it never starts a second purchase. - On
"challenge", render<MoonPayChallenge>withoutresume. The challenge frame finishes the purchase and sends its own"complete".
HeadlessBuy.tsx
Bank transfer
Bank transfer payments (SEPA for EUR) use the same headless flow as cards. You fetch a bank transfer quote withpaymentMethod: { type: "sepa" }, mount
<MoonPayBuyButton headless> with its signature, and read the transaction id
from the "complete" event. The difference is what happens after the
transaction is created: the customer sends the funds from their bank. Fetch the
transaction with
client.getTransaction()
and show the customer the bank details from bankTransferDepositInfo, including
the payment reference, and the amount to send from source.amount.
Bank transfers are a floating payment method, so the amounts are estimates until
the transfer settles. The quote returns exchangeRateType: "floating". Render
the estimated crypto amount with a tilde (for example, ~0.2345 BTC) and tell
the customer the final amount is set when their funds settle. See Exchange rate
type.
For the full walkthrough, including confirming availability, rendering the
deposit details, handling requotes and cancellations, and tracking the
transaction to a terminal status, see the Pay with bank
transfer guide.