Skip to main content
<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

Pass applePayButtonSettings 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
Set the height in the component’s 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

Pass headless 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 code unsupportedPaymentMethod, and a guest checkout quote gets invalidQuote.
  • It never sends "buttonPressed" or "cancelled".
  • After "ready", it sends exactly one of "complete", "challenge", or "error".
  • It reads a new quote only after an "error" with code quoteExpired. At any other time the frame ignores the update, so it never starts a second purchase.
  • On "challenge", render <MoonPayChallenge> without resume. The challenge frame finishes the purchase and sends its own "complete".
For the frame-level behavior, see Headless mode on the Buy Button frame.
HeadlessBuy.tsx
For the end-to-end card payment walkthrough, see the Pay with card guide. For details on the challenge flow, see Handle challenges.

Bank transfer

Bank transfer payments (SEPA for EUR) use the same headless flow as cards. You fetch a bank transfer quote with paymentMethod: { 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.
The customer must include the payment reference with their bank transfer. Transfers sent without it are rejected. Surface this prominently in your own UI, for example, “Always include your payment reference or your transfer will be rejected.” See Bank-transfer deposit details.