Skip to main content
Wallet Elements provide Apple Pay and Google Pay buttons backed by the same transaction object and callback contract. Use them to collect tokenized wallet payment data and forward encrypted payloads to your backend for transaction processing.

Supported Wallet Elements

const applePay = await rinne.elements.applePay(transaction, options)
const googlePay = await rinne.elements.googlePay(transaction, options)
Both elements support the same core options (button, onCapture, onError, onCancel). googlePay() also supports colorScheme.

Options

interface WalletMountOptions {
  button?: {
    color?: 'black' | 'white'          // default: 'black'
    locale?: 'pt' | 'en' | 'es'        // default: 'pt'
    type?: 'book' | 'buy' | 'checkout' | 'donate' | 'order' | 'pay' | 'plain' | 'subscribe' // default: 'plain'
    borderRadius?: number
    size?: {
      width: string | number           // default: '100%'
      height: string | number          // default: '40px'
    }
  }
  colorScheme?: 'light' | 'dark'      // Google Pay only: iframe root color-scheme
  onCapture?: (payload, fail) => Promise<void> | void
  onError?: (error) => void
  onCancel?: () => void
}

Event Lifecycle

StageCallbackWhat you should do
User authorizes wallet paymentonCapture(payload, fail)Send payload.card_data to your backend and create/confirm the transaction
Backend processing failsfail({ message })Call fail() so the wallet UI exits processing state and can retry
User closes wallet sheetonCancel()Restore your checkout UI and keep cart state
Provider or SDK issueonError(error)Show a fallback payment method and log details for debugging

Button Behavior

CapabilityApple PayGoogle Pay
Button colorblack, whiteblack, white
Button typesbook, buy, checkout, donate, order, pay, plain, subscribeSame as Apple Pay
Locale inputpt, en, espt, en, es

Wallet Availability

Apple Pay and Google Pay buttons are not rendered when the environment does not support them. This happens silently — mount() resolves without rendering any visible element. Conditions that prevent rendering include:
  • Non-HTTPS origin
  • Browser or device without wallet support
  • No eligible card registered in the wallet
  • Apple Pay domain not verified (Apple Pay only)
Design your checkout layout so it gracefully handles an empty wallet button slot, or check support before mounting.

Apple Pay Domain Verification

Apple Pay only appears on domains that are verified with Apple. If your domain is not verified, the Apple Pay button will not render.
Before going live:
  • Ask Rinne support to validate every production domain/subdomain where Apple Pay is used and get your verification file
  • Keep the verification file available at /.well-known/apple-developer-merchantid-domain-association
  • Re-run verification when you add a new domain or subdomain
If this verification file is removed, replaced, or becomes unavailable, Apple can invalidate the domain and Apple Pay will stop working until the domain is verified again.

onCapture Contract

onCapture gives you encrypted wallet card data, payment method, and the transaction object you created.
interface WalletSuccessPayload {
  card_data: {
    network_token?: string
    cryptogram: string
    expiry_month: string
    expiry_year: string
    eci?: string | null
    token_provider?: string
    brand?: string
    last_digits?: string
    wallet_type?: 'APPLE_PAY' | 'GOOGLE_PAY'
    authentication_type?: string
    display_name?: string
  }
  payment_method: 'CREDIT_CARD' | 'DEBIT_CARD'
  transaction: EvTransaction
}
payment_method is inferred from wallet funding data and defaults to CREDIT_CARD when funding type is not provided by the provider.
onCapture: async (payload, fail) => {
  try {
    await sendToBackend(payload.card_data, payload.payment_method, payload.transaction)
  } catch (error) {
    fail({ message: error instanceof Error ? error.message : 'Payment failed' })
  }
}
If backend processing fails, call fail() inside onCapture. Without it, the wallet may stay in a processing state.
RinneJS only supports tokenized Google Pay payments with 3DS cryptogram authentication. Non-tokenized (PAN-only) payment methods are not accepted and will not be available for payment.

colorScheme (Google Pay)

Use colorScheme to align the Google Pay iframe with your page theme.
const colorScheme =
  document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'

const googlePay = await rinne.elements.googlePay(transaction, {
  button: { color: 'black', type: 'pay', locale: 'pt' },
  colorScheme,
  ...walletHandlers
})

Mount and Unmount

const element = await rinne.elements.applePay(transaction, options)
const mounted = await element.mount('#apple-pay-container')

// Later
mounted.unmount()
mount() accepts either a CSS selector or an HTMLElement.

Mount Errors

mount() throws if the target is missing or the provider cannot render the wallet button.
try {
  const applePay = await rinne.elements.applePay(transaction, options)
  await applePay.mount('#missing-wallet-slot')
} catch (error) {
  console.error('Wallet mount failed', error)
}

Full Wallet Example

const transaction = await rinne.transaction.create({
  amount: 1999,
  lineItems: [{ label: 'Demo Product', amount: 1999 }]
})

const colorScheme =
  document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'

const walletHandlers = {
  onCapture: async (payload, fail) => {
    try {
      const response = await fetch('/api/wallet/charge', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          cardData: payload.card_data,
          paymentMethod: payload.payment_method,
          amount: payload.transaction.details.amount
        })
      })

      if (!response.ok) {
        const body = await response.json()
        throw new Error(body.message ?? 'Charge failed')
      }
    } catch (error) {
      fail({ message: error instanceof Error ? error.message : 'Charge failed' })
    }
  },
  onError: (error) => console.error(error),
  onCancel: () => console.log('Cancelled')
}

const applePay = await rinne.elements.applePay(transaction, {
  button: { color: 'black', type: 'pay', locale: 'pt', borderRadius: 0 },
  ...walletHandlers
})
await applePay.mount('#apple-pay')

const googlePay = await rinne.elements.googlePay(transaction, {
  button: { color: 'black', type: 'pay', locale: 'pt', borderRadius: 0 },
  colorScheme,
  ...walletHandlers
})
await googlePay.mount('#google-pay')