@everypay/googlepay-rn-bridge
v2.0.0
Published
EveryPay Google Pay React Native Bridge (Android Only)
Downloads
187
Maintainers
Readme
@everypay/googlepay-rn-bridge
EveryPay Google Pay React Native Bridge (Android Only). Built on EveryPay Google Pay Android SDK. Full TypeScript support.
- 🔐 Backend Mode: Keep API credentials secure on your backend (recommended)
- 📦 SDK Integration: Built on EveryPay Android SDK for better maintainability
- 🛡️ Enhanced Security: API credentials never exposed in mobile app
- 🎯 Dual Mode Support: Backend Mode (recommended) + SDK Mode
- 🔄 Recurring Payments: Request MIT tokens for recurring payments
Upgrading from v1.x? See the Migration Guide for all breaking changes and step-by-step instructions.
Installation
npm install @everypay/googlepay-rn-bridgeyarn add @everypay/googlepay-rn-bridgeQuick Start
Backend Mode (Recommended) ⭐
Most secure approach - API credentials stay on your backend. You have full control over when and how API requests are made.
Step 1: Implement 2 backend endpoints (see guide)
Your backend needs these endpoints:
- POST /api/gpay/create-payment - Combines EveryPay
open_session+create_paymentAPI calls - POST /api/gpay/process-token - Calls EveryPay
payment_dataAPI to process the token
Step 2: Use GooglePayButton component:
import React, { useState, useEffect } from 'react';
import { GooglePayButton } from '@everypay/googlepay-rn-bridge';
import type {
EverypayConfig,
GooglePayBackendData
} from '@everypay/googlepay-rn-bridge';
function PaymentScreen() {
const [backendData, setBackendData] = useState<GooglePayBackendData | null>(null);
const config: EverypayConfig = {
environment: 'TEST', // or 'PRODUCTION'
countryCode: 'EE',
currencyCode: 'EUR'
};
// Fetch payment data when component mounts
useEffect(() => {
const fetchPaymentData = async () => {
try {
const response = await fetch('https://your-backend.com/api/gpay/create-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
amount: 10.50,
label: 'Product Purchase',
orderReference: 'ORDER-123',
customerEmail: '[email protected]',
}),
});
const data = await response.json();
setBackendData(data);
} catch (error) {
console.error('Failed to prepare payment:', error);
}
};
fetchPaymentData();
}, []);
// Process the Google Pay token
const handlePaymentToken = async (tokenData: any) => {
try {
const result = await fetch('https://your-backend.com/api/gpay/process-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(tokenData)
});
return result.json();
} catch (error) {
console.error('Failed to process token:', error);
throw error;
}
};
// Show Google Pay button only when backend data is ready
if (!backendData) {
return null; // Or show a loading indicator
}
return (
<GooglePayButton
config={config}
backendData={backendData}
onPressCallback={handlePaymentToken}
// Handle your back-end response here
onPaymentSuccess={(result) => result.state === 'failed' ? console.error('Error:', result) : console.log('Success!', result)}
onPaymentError={(error) => console.error('Payment failed:', error)}
onPaymentCanceled={() => console.log('Payment canceled')}
theme="dark"
buttonType="buy" // Options: buy, book, checkout, donate, order, pay, subscribe
style={{ marginHorizontal: 16 }}
/>
);
}How it works:
- Component mounts → automatically fetches payment data from your
/create-paymentendpoint (this should internally call both EveryPayopen_sessionandcreate_paymentAPIs) - When data arrives → Google Pay button appears (component initializes automatically)
- User presses Google Pay button → SDK shows Google Pay UI and retrieves token
onPressCallbackis called with the token → you send it to your/process-tokenendpoint- Your backend processes the payment and returns the result
📖 Full Backend Setup Guide: BACKEND_INTEGRATION.md
SDK Mode
API keys are stored in the app, no back-end service needed
Use GooglePayButton with SDK configuration:
import { GooglePayButton } from '@everypay/googlepay-rn-bridge';
import type { EverypayConfig } from '@everypay/googlepay-rn-bridge';
function PaymentScreen() {
const config: EverypayConfig = {
// ⚠️ Everypay API credentials in app
apiUsername: 'your_username',
apiSecret: 'your_secret',
apiUrl: 'https://payment.sandbox.lhv.ee', // or production URL
environment: 'TEST', // or 'PRODUCTION'
countryCode: 'EE',
accountName: 'EUR3D1',
customerUrl: 'https://your-site.com',
currencyCode: 'EUR'
};
const handlePayment = async (result: any) => {
// Payment already processed by SDK
console.log('Payment result:', result);
return result;
};
return (
<GooglePayButton
config={config}
amount={10.50}
label="Product Purchase"
orderReference="ORDER-123"
customerEmail="[email protected]"
onPressCallback={handlePayment}
onPaymentSuccess={(result) => console.log('Success!', result)}
onPaymentError={(error) => console.error('Error:', error)}
theme="dark"
buttonType="buy"
style={{ marginHorizontal: 16 }}
/>
);
}How it works:
- Component auto-detects SDK mode (no
backendDataprop provided, usesapiUsername+apiSecretfrom config) - Initializes SDK with your credentials
- On button press, shows Google Pay and processes payment via EveryPay API
- Calls your
onPressCallbackwith the payment result
Component Features
- ✅ Auto-mode detection - Automatically uses Backend or SDK mode based on config
- ✅ User-controlled flow - You decide when to fetch data and make API calls
- ✅ Single callback - Simple
onPressCallbackhandles payment flow - ✅ Native button - Official Google Pay button with multiple types
- ✅ Customizable sizing - Pass a
styleprop to control button dimensions and spacing - ✅ Type-safe - Pass typed data directly, full TypeScript support
- ✅ Both architectures - Works with old and new React Native architecture
Requirements
System Requirements
- Android only (iOS not supported)
- Must be distributed through Google Play store
- React Native 0.77 or higher
- Supports both old and new React Native architecture
Android Requirements
android {
compileSdkVersion 34 // or higher
defaultConfig {
minSdkVersion 24 // or higher (SDK requirement)
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}Configuration Steps
- Enable Google Pay in your app by adding the following meta-data element to your
android/app/src/main/AndroidManifest.xmlfile inside the<application>tag:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required for SDK mode only: Internet permission for EveryPay API calls -->
<uses-permission android:name="android.permission.INTERNET" />
<application
...>
<!-- Required: Enable Google Pay API -->
<meta-data
android:name="com.google.android.gms.wallet.api.enabled"
android:value="true" />
<activity ...>
...
</activity>
</application>
</manifest>API Reference
Configuration Types
EverypayConfig
interface EverypayConfig {
environment: 'TEST' | 'PRODUCTION';
countryCode: string; // e.g., 'EE'
// SDK Mode only (optional for Backend Mode)
apiUsername?: string;
apiSecret?: string;
apiUrl?: string;
accountName?: string;
customerUrl?: string; // Redirect URL. Required but not used in the app
// Optional
currencyCode?: string; // Default: 'EUR'
allowedCardNetworks?: ('MASTERCARD' | 'VISA')[];
allowedCardAuthMethods?: ('PAN_ONLY' | 'CRYPTOGRAM_3DS')[];
// Token request mode
requestToken?: boolean; // If true, request MIT token instead of making payment
}GooglePayBackendData
Data structure from backend for payment initialization:
interface GooglePayBackendData {
merchantId: string;
merchantName: string;
gatewayId: string;
gatewayMerchantId: string;
currency: string;
countryCode: string;
paymentReference: string;
mobileAccessToken: string;
amount: number;
label: string;
}GooglePayTokenData
Token data returned from SDK to be sent to backend:
interface GooglePayTokenData {
paymentReference: string;
mobileAccessToken: string;
signature: string;
intermediateSigningKey: {
signedKey: string;
signatures: string[];
};
protocolVersion: string;
signedMessage: string;
tokenConsentAgreed: boolean;
}GooglePayInitResult
Result returned by the initialization methods:
interface GooglePayInitResult {
isReady: boolean; // Whether Google Pay is available on the device
gatewayId: string; // Payment gateway identifier
gatewayMerchantId: string; // Gateway-specific merchant identifier
}Native Methods
Backend Mode Methods
// Initialize with backend data
initializeWithBackendData(
config: EverypayConfig,
backendData: GooglePayBackendData
): Promise<GooglePayInitResult>
// Make payment with backend data
makePaymentWithBackendData(
backendData: GooglePayBackendData
): Promise<GooglePayTokenData>
// Request MIT token with backend data (recurring payments)
requestTokenWithBackendData(
backendData: GooglePayBackendData
): Promise<GooglePayTokenData>SDK Mode Methods
// Initialize SDK mode
initializeSDKMode(config: EverypayConfig): Promise<GooglePayInitResult>
// Make payment SDK mode
makePaymentSDKMode(paymentData: {
amount: string;
label: string;
orderReference: string;
customerEmail: string;
customerIp?: string;
}): Promise<{ status: string }>
// Request MIT token SDK mode (recurring payments)
requestTokenSDKMode(label: string): Promise<TokenRequestResult>Utility Methods
// Check if payment is in progress
isProcessingPayment(): booleanButton Styling
The button defaults to alignSelf: 'stretch' (fills parent width) and height: 48. Pass a style prop to override:
<GooglePayButton
config={config}
backendData={backendData}
onPressCallback={handlePaymentToken}
style={{ marginHorizontal: 16 }}
cornerRadius={24}
/>Which style properties are safe to override:
| Property | Safe? | Notes |
| ---------------------------------- | ----- | ---------------------------------------------------- |
| margin*, padding* | ✅ | Affect outer layout only. |
| alignSelf, opacity | ✅ | Visual only. |
| backgroundColor | ✅ | Hidden behind the native button. |
| height, minHeight, maxHeight | ⚠️ | See below. |
| borderRadius | ❌ | Has no effect — use the cornerRadius prop instead. |
Height overrides require care. The native Google Pay button fetches card artwork (last 4 digits, network logo) asynchronously from Google servers and measures itself against the mounted height. Changing height after mount does not reliably re-layout the native view, so the button can end up with distorted artwork or empty space. If you need a non-default height, set it once at mount and verify on-device; the component will log a warning to help you notice the override.
Ensure the button follows Google Pay Brand Guidelines — proper size, color contrast, and clear space.
Button Types
The buttonType prop controls the label shown on the Google Pay button (see Google Pay Brand Guidelines for visual examples):
| Value | Button Label |
| ----------- | ------------------------------- |
| buy | "Buy with Google Pay" (default) |
| book | "Book with Google Pay" |
| checkout | "Checkout with Google Pay" |
| donate | "Donate with Google Pay" |
| order | "Order with Google Pay" |
| pay | "Google Pay" |
| subscribe | "Subscribe with Google Pay" |
Error Codes
| Code | Description |
| -------------------------------------------- | ------------------------------------ |
| E_ACTIVITY_DOES_NOT_EXIST | Activity not available |
| E_INIT_ERROR | Initialization failed |
| E_PAYMENT_ERROR | Payment processing error |
| E_PAYMENT_CANCELED | User canceled payment |
| E_UNABLE_TO_DETERMINE_GOOGLE_PAY_READINESS | Cannot check Google Pay availability |
| E_GOOGLE_PAY_API_ERROR | Google Pay API error |
Documentation
- 📖 Migration Guide - Migrating from v1.x to v2.0 (SDK migration)
- 📖 Backend Integration Guide - How to implement backend endpoints
- 📖 Recurring Payments Guide - Token requests for MIT and recurring payments
- 📖 TypeScript Types - Full type definitions
Mode Comparison
| Feature | Backend Mode ⭐ | SDK Mode | | --------------- | ------------------------- | ---------------------- | | Recommended | Yes | No | | Security | ✅ Credentials on backend | ❌ Credentials in app | | Complexity | Medium (requires backend) | Low | | Maintainability | ✅ Easy to update logic | ❌ Requires app update |
Troubleshooting
"Activity not available"
Ensure you're calling SDK methods when the app is in the foreground.
"Not initialized"
Call initializeWithBackendData() or initializeSDKMode() before making payments.
"Payment already in progress"
Check isProcessingPayment() before starting a new payment.
Security Best Practices
- Use Backend Mode if possible
- Never commit API credentials to version control
- Validate all inputs on your backend
- Use HTTPS for all backend communications
- Implement rate limiting on backend endpoints
- Log security events on backend
Testing
Test Environment
Use environment: 'TEST' with EveryPay sandbox credentials. This will also run the Google Pay in the test mode.
Important Notes
- ✅ Android only (iOS not supported)
- ✅ Supports both Old and New React Native architecture
- ✅ Complies with Google Pay API Acceptable Use Policy
- ⚠️ Requires distribution through Google Play Store
License
MIT
Made with create-react-native-library
