Closed Beta
Accept Apple Pay and Google Pay in your web application with just a few lines of code. RinneJS is fully typed, PCI compliant, and handles all the complexity of wallet payments for you.
Zero PCI Scope Card data is tokenized client-side. Your servers never touch sensitive data.
Simple Integration Initialize the SDK, create a transaction, and mount payment buttons with minimal setup.
Native UX Real Apple Pay and Google Pay buttons with native wallet experience.
Live Demo
Explore the SDK in action. Switch between code tabs to see initialization, transaction creation, and event handlers and button mounting—then try the live payment buttons:
Setup
Transaction
Handlers
Mount
// Initialize RinneJS
import { Rinne } from '@rinnebr/js'
const rinne = new Rinne ({
merchantId: 'your-merchant-id' ,
environment: 'sandbox'
})
// Create transaction (currency and country default to 'BRL' and 'BR')
const transaction = await rinne . transaction . create ({
amount: 314 , // R$ 3,14
lineItems: [
{ label: 'Piizza' , amount: 314 }
]
})
// Define event handlers
const onCapture = async ( payload , fail ) => {
try {
await processPayment ( payload . card_data )
} catch ( error ) {
fail ({ message: error . message })
}
}
const onError = ( err ) => console . error ( err )
const onCancel = () => console . log ( 'Cancelled' )
// Button configuration
const buttonConfig = {
type: 'plain' ,
color: 'black' ,
locale: 'pt' ,
borderRadius: 8 ,
size: { width: '100%' , height: '44px' }
}
// Mount Apple Pay element
const applePay = await rinne . elements . applePay ( transaction , {
button: buttonConfig ,
onCapture ,
onError ,
onCancel
})
await applePay . mount ( '#apple-pay-btn' )
This demo runs in sandbox mode—no real charges will occur. RinneJS currently supports 3DS-authenticated transactions only , ensuring the highest level of payment security. See browser support for compatibility details.
Installation
Quick start
Get Apple Pay and Google Pay running in under 5 minutes:
Initialize RinneJS
Import and configure RinneJS with your merchant credentials: import { Rinne } from '@rinnebr/js'
const rinne = new Rinne ({
merchantId: 'your-merchant-id' ,
environment: 'sandbox' // or 'production'
})
Create a transaction
Define the payment amount and details. Currency defaults to 'BRL' and country defaults to 'BR': const transaction = await rinne . transaction . create ({
amount: 2500 , // Amount in cents (R$ 25.00)
lineItems: [
{ label: 'Premium Plan' , amount: 2000 },
{ label: 'Tax' , amount: 500 }
]
})
Mount payment buttons
Create and display the wallet payment buttons: const applePay = await rinne . elements . applePay ( transaction , {
button: { color: 'black' , type: 'buy' },
onCapture : async ( payload , fail ) => {
try {
await processPayment ( payload . card_data )
} catch ( error ) {
fail ({ message: 'Payment failed' })
}
}
})
await applePay . mount ( '#apple-pay-button' )
Usage examples
Apple Pay
Google Pay
Both wallets
import { Rinne } from '@rinnebr/js'
const rinne = new Rinne ({
merchantId: 'your-merchant-id' ,
environment: 'sandbox'
})
const transaction = await rinne . transaction . create ({
amount: 1999 ,
currency: 'BRL' ,
lineItems: [{ label: 'Demo Product' , amount: 1999 }]
})
const applePay = await rinne . elements . applePay ( transaction , {
button: { color: 'black' , type: 'buy' , locale: 'en' },
onCapture : async ( payload , fail ) => {
try {
await processPayment ( payload . card_data )
} catch ( error ) {
fail ({ message: error . message })
}
},
onCancel : () => console . log ( 'Cancelled' )
})
await applePay . mount ( '#apple-pay-button' )
import { Rinne } from '@rinnebr/js'
const rinne = new Rinne ({
merchantId: 'your-merchant-id' ,
environment: 'sandbox'
})
const transaction = await rinne . transaction . create ({
amount: 1999 ,
currency: 'BRL' ,
lineItems: [{ label: 'Demo Product' , amount: 1999 }]
})
const googlePay = await rinne . elements . googlePay ( transaction , {
button: { color: 'black' , type: 'buy' , locale: 'en' },
onCapture : async ( payload , fail ) => {
try {
await processPayment ( payload . card_data )
} catch ( error ) {
fail ({ message: error . message })
}
},
onCancel : () => console . log ( 'Cancelled' )
})
await googlePay . mount ( '#google-pay-button' )
import { Rinne } from '@rinnebr/js'
const rinne = new Rinne ({
merchantId: 'your-merchant-id' ,
environment: 'production'
})
async function setupCheckout () {
const transaction = await rinne . transaction . create ({
amount: 4999 ,
currency: 'BRL' ,
country: 'BR' ,
lineItems: [
{ label: 'Annual Subscription' , amount: 4499 },
{ label: 'Tax' , amount: 500 }
]
})
const handlers = {
onCapture : async ( payload , fail ) => {
try {
const response = await fetch ( '/api/payments' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
cardData: payload . card_data ,
paymentMethod: payload . payment_method ,
transactionId: payload . transaction . id
})
})
if ( ! response . ok ) throw new Error ( 'Payment failed' )
window . location . href = '/success'
} catch ( error ) {
fail ({ message: error . message })
}
},
onError : ( error ) => {
console . error ( 'Payment error:' , error )
alert ( 'Payment unavailable. Try another method.' )
},
onCancel : () => {
console . log ( 'User cancelled payment' )
}
}
// Mount Apple Pay
const applePay = await rinne . elements . applePay ( transaction , {
button: { color: 'black' , type: 'pay' },
... handlers
})
await applePay . mount ( '#apple-pay' )
// Mount Google Pay
const googlePay = await rinne . elements . googlePay ( transaction , {
button: { color: 'black' , type: 'pay' },
... handlers
})
await googlePay . mount ( '#google-pay' )
}
setupCheckout ()
API reference
Rinne class
The main entry point for the SDK.
const rinne = new Rinne ( options : Options )
Merchant ID from the merchant owner of the transaction
environment
'sandbox' | 'production'
default: "production"
Environment to use for API calls
Custom API base URL (for advanced use cases)
Transaction
Create a transaction before mounting payment elements.
const transaction = await rinne . transaction . create ( params )
Payment amount in cents (e.g., 1000 = $10.00)
ISO 4217 currency code (e.g., 'BRL', 'USD')
ISO 3166 country code (e.g., 'BR', 'US')
Itemized breakdown displayed in wallet UI lineItems : [
{ label: 'Product' , amount: 800 },
{ label: 'Shipping' , amount: 200 }
]
Payment elements
Apple Pay
const applePay = await rinne . elements . applePay ( transaction , options )
await applePay . mount ( '#container' )
Google Pay
const googlePay = await rinne . elements . googlePay ( transaction , options )
await googlePay . mount ( '#container' )
Mount options
Both applePay() and googlePay() accept the same options:
Show Button customization options
color
'black' | 'white'
default: "black"
Button background color
Button label type: 'plain', 'buy', 'book', 'checkout', 'donate', 'order', 'pay', 'subscribe'
locale
'pt' | 'en' | 'es'
default: "pt"
Button language
Custom dimensions: { width: '100%', height: '48px' }
Called when payment is authorized. You must call fail() if processing fails. onCapture : async ( payload , fail ) => {
try {
await processPayment ( payload . card_data )
} catch ( error ) {
fail ({ message: error . message })
}
}
Called when an error occurs (wallet unavailable, config error, etc.) onError : ( error ) => {
console . error ( error . code , error . message )
}
Called when user closes the wallet dialog without paying onCancel : () => {
console . log ( 'Payment cancelled' )
}
Black button button : {
color : 'black' ,
type : 'buy' ,
locale : 'en'
}
White button button : {
color : 'white' ,
type : 'checkout' ,
locale : 'pt'
}
Custom size button : {
size : {
width : '300px' ,
height : '56px'
},
borderRadius : 12
}
Subscribe button button : {
type : 'subscribe' ,
color : 'black' ,
locale : 'en'
}
Type Apple Pay Google Pay plainPay Pay buyBuy with Apple Pay Buy with Google Pay bookBook with Apple Pay Book with Google Pay checkoutCheck out with Apple Pay Check out with Google Pay donateDonate with Apple Pay Donate with Google Pay orderOrder with Apple Pay Order with Google Pay payPay with Apple Pay Pay with Google Pay subscribeSubscribe with Apple Pay Subscribe with Google Pay
Handling payments
The onCapture callback
Critical : Always call fail() if your backend processing fails. This notifies the wallet dialog to show an error state and allows the user to retry.
onCapture : async ( payload , fail ) => {
try {
// payload contains card_data, payment_method, and transaction
const response = await fetch ( '/api/process-payment' , {
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' },
body: JSON . stringify ({
cardData: payload . card_data ,
paymentMethod: payload . payment_method ,
transactionId: payload . transaction . id
})
})
if ( ! response . ok ) {
throw new Error ( 'Payment processing failed' )
}
// Success! Wallet dialog closes automatically
window . location . href = '/order-confirmation'
} catch ( error ) {
// MUST call fail() to notify the wallet
fail ({ message: error . message || 'Unable to process payment' })
}
}
Capture payload structure
The payload object in onCapture contains:
{
card_data : CardData // Encrypted payment token and card details
payment_method : 'CREDIT_CARD' | 'DEBIT_CARD' // Card funding type
transaction : Transaction // Original transaction object
}
The payment_method is automatically determined from the card’s funding type. If the funding type is not available in the wallet response, it defaults to 'CREDIT_CARD'.
Card data structure
The payload.card_data object contains:
{
cryptogram : string // Payment cryptogram for authorization
expiry_month : string // Card expiry month
expiry_year : string // Card expiry year
wallet_type : 'APPLE_PAY' | 'GOOGLE_PAY'
last_digits ?: string // Last 4 digits of card
brand ?: string // Card brand (Visa, Mastercard, etc.)
network_token ?: string // Network tokenized PAN
eci ?: string // E-commerce indicator
}
Error handling
onError : ( error ) => {
switch ( error . code ) {
case 'PROVIDER_ERROR' :
// Apple Pay or Google Pay service issue
showMessage ( 'Payment service unavailable' )
break
case 'VALIDATION_ERROR' :
// Invalid configuration
console . error ( 'Config error:' , error . details )
break
case 'CONFIGURATION_ERROR' :
// Merchant setup issue
console . error ( 'Setup error:' , error . message )
break
default :
console . error ( 'Unknown error:' , error )
}
}
TypeScript support
RinneJS is written in TypeScript and exports all type definitions:
import type {
Options ,
Environment ,
TransactionCreateParams ,
WalletSuccessPayload ,
WalletError ,
WalletButtonOptions ,
CardData ,
ApplePayElement ,
GooglePayElement ,
MountedElement
} from '@rinnebr/js'
Requirements
Both Apple Pay and Google Pay require your website to be served over HTTPS. Payment buttons will not function on insecure HTTP connections.
Apple Pay domain verification
To accept Apple Pay, you must verify your domain with Rinne. Contact support to complete the verification process.
If your website uses CSP headers, add these directives: script-src https://js.evervault.com;
connect-src https://keys.evervault.com https://api.evervault.com https://api.rinne.com.br https://api-sandbox.rinne.com.br;
frame-src https://ui-components.evervault.com;
For payments to work, users must:
Have at least one card added to their Apple Wallet or Google Pay
Use a supported browser and device
Be located outside Mainland China (Apple Pay restriction)
Browser support
Browser Apple Pay Google Pay Safari (iOS 10+, macOS 10.12+) ✅ ✅ Chrome ✅ ✅ Firefox ❌ ✅ Edge ✅ ✅
Complete example
import { useEffect , useRef } from 'react'
import { Rinne } from '@rinnebr/js'
export function CheckoutButton ({ amount , onSuccess }) {
const applePayRef = useRef ( null )
const googlePayRef = useRef ( null )
useEffect (() => {
const rinne = new Rinne ({
merchantId: process . env . RINNE_MERCHANT_ID ,
environment: 'production'
})
async function setup () {
const transaction = await rinne . transaction . create ({
amount ,
currency: 'BRL' ,
country: 'BR'
})
const handlers = {
onCapture : async ( payload , fail ) => {
try {
await fetch ( '/api/charge' , {
method: 'POST' ,
body: JSON . stringify ({ cardData: payload . card_data })
})
onSuccess ()
} catch ( e ) {
fail ({ message: e . message })
}
}
}
const applePay = await rinne . elements . applePay ( transaction , {
button: { type: 'pay' },
... handlers
})
await applePay . mount ( applePayRef . current )
const googlePay = await rinne . elements . googlePay ( transaction , {
button: { type: 'pay' },
... handlers
})
await googlePay . mount ( googlePayRef . current )
}
setup ()
}, [ amount ])
return (
< div className = "payment-buttons" >
< div ref = { applePayRef } />
< div ref = { googlePayRef } />
</ div >
)
}
Next steps