Checkout React Native SDK

A comprehensive React Native SDK for integrating payment processing into your React Native applications. This SDK provides a secure, user-friendly checkout experience with support for multiple payment methods, currencies, and customization options across both iOS and Android platforms.

Table of Contents

Overview

The Checkout React Native SDK allows you to integrate payment processing into your React Native app with just a few lines of code. It handles the complex payment flow, security, and user interface, so you can focus on your app's core functionality.

Github link

What does it do?

  • 💳 Processes payments securely
  • 🌍 Supports multiple currencies and payment methods
  • 📱 Handles both card and digital wallet payments
  • 🔐 Manages security and encryption automatically
  • 🔄 Cross-platform compatibility (iOS & Android)

Features

Multiple Payment Methods: Credit/Debit cards, Apple Pay, Google Pay, Samsung Pay, and more

Multi-Currency Support: Process payments in various currencies

Localization: Support for English and Arabic languages

Security: Built-in encryption and security measures

Card Scanner: Scan card details using device camera

Real-time Validation: Instant feedback on payment details

Cross-Platform: Works seamlessly on both iOS and Android

Requirements

  • React Native 0.78.0 or later
  • iOS 13.0 or later (for iOS)
  • Android API level 24 or later (for Android)
  • Node.js 16.0 or later
  • npm or yarn package manager

Installation

npm

npm install checkout-react-native

yarn

yarn add checkout-react-native

iOS Setup

After installing the package, you need to install the iOS dependencies:

cd ios && pod install && cd ..

Android Setup

For Android, the package should work out of the box. Make sure your android/app/build.gradle has the minimum SDK version set to 24:

android {
    defaultConfig {
        minSdkVersion 24
        // ... other config
    }
}

Hash String

To enhance payment security and ensure the integrity of each transaction request, the Tap Checkout SDK requires a hash String to be included in the configuration payload. This hash String is a secure HMAC-SHA256 signature, generated using your secret key, public key, amount, currency, and transaction reference and post URL.


1. Import Required Packages

// Required for HMAC hash generation
npm install crypto-js

2. Use This Function to Generate the Hash String


export function generateTapHashString({
  publicKey,
  secretKey,
  amount,
  currency,
  postUrl = '',
  transactionReference = '',
}) {
  const formattedAmount = amount.toFixed(2);

  const toBeHashed =
    `x_publickey${publicKey}` +
    `x_amount${formattedAmount}` +
    `x_currency${currency}` +
    `x_transaction${transactionReference}` +
    `x_post${postUrl}`;

  const hash = CryptoJS.HmacSHA256(toBeHashed, secretKey);
  return hash.toString(CryptoJS.enc.Hex);
}

Quick Start

Here's how to get started with the Checkout SDK in just 5 minutes:

1. Add Permissions

Add the following permissions to yourAndroidManifest.xmlas well in the runtime of the app:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.NFC" />

2. Create a Build Checkout

import { useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import { startCheckout } from 'checkout-react-native';
import type { CheckoutCallbacks } from 'checkout-react-native';

export default function App() {
  const [status, setStatus] = useState('Ready to start checkout');

  const handleStartCheckout = () => {
    const configurations = {
      hashString: '',
      language: 'en',
      themeMode: 'light',
      supportedPaymentMethods: 'ALL',
      paymentType: 'ALL',
      selectedCurrency: 'KWD',
      supportedCurrencies: 'ALL',
      supportedPaymentTypes: [],
      supportedRegions: [],
      supportedSchemes: [],
      supportedCountries: [],
      gateway: {
        publicKey: 'your_public_key',
        merchantId: 'your_merchant_ID',
      },
      customer: {
        firstName: 'Android',
        lastName: 'Test',
        email: '[email protected]',
        phone: { countryCode: '965', number: '55567890' },
      },
      transaction: {
        mode: 'charge',
        charge: {
          saveCard: true,
          auto: { type: 'VOID', time: 100 },
          redirect: {
            url: 'https://demo.staging.tap.company/v2/sdk/checkout',
          },
          threeDSecure: true,
          subscription: {
            type: 'SCHEDULED',
            amount_variability: 'FIXED',
            txn_count: 0,
          },
          airline: {
            reference: { booking: '' },
          },
        },
      },
      amount: '5',
      order: {
        id: '',
        currency: 'KWD',
        amount: '5',
        items: [
          {
            amount: '5',
            currency: 'KWD',
            name: 'Item Title 1',
            quantity: 1,
            description: 'item description 1',
          },
        ],
      },
      cardOptions: {
        showBrands: true,
        showLoadingState: false,
        collectHolderName: true,
        preLoadCardName: '',
        cardNameEditable: true,
        cardFundingSource: 'all',
        saveCardOption: 'all',
        forceLtr: false,
        alternativeCardInputs: { cardScanner: true, cardNFC: true },
      },
      isApplePayAvailableOnClient: true,
    };

    const callbacks: CheckoutCallbacks = {
      onSuccess: (data: string) => {
        setStatus(`Checkout successful: ${data}`);
        console.log('Checkout success:', data);
      },
      onError: (error: string) => {
        setStatus(`Checkout error: ${error}`);
        console.log('Checkout error:', error);
      },
      onClose: () => {
        setStatus('Checkout closed');
        console.log('Checkout closed');
      },
      onReady: () => {
        setStatus('Checkout ready');
        console.log('Checkout ready');
      },
    };

    startCheckout(configurations, callbacks);
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Checkout React Native Example</Text>
      <Text style={styles.status}>{status}</Text>
      <TouchableOpacity style={styles.button} onPress={handleStartCheckout}>
        <Text style={styles.buttonText}>Start Checkout</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  status: {
    fontSize: 16,
    marginBottom: 30,
    textAlign: 'center',
    color: '#666',
  },
  button: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 30,
    paddingVertical: 15,
    borderRadius: 8,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

That's it! You now have a working payment system.

Basic Usage

Understanding the Flow

sequenceDiagram
    participant App as Your App
    participant SDK as Checkout SDK
    participant Bridge as Native Bridge
    participant Native as Native SDK
    participant UI as Payment UI
    participant Server as Payment Server
    
    App->>SDK: startCheckout(config)
    SDK->>Bridge: Call native method
    Bridge->>Native: Initialize native SDK
    Native->>UI: Present checkout interface
    UI->>App: onReady callback
    
    Note over UI: User enters payment details
    
    UI->>Server: Process payment
    Server->>UI: Payment result
    
    alt Payment Success
        UI->>Native: onSuccess
        Native->>Bridge: Return success data
        Bridge->>SDK: Resolve promise
        SDK->>App: Return success result
    else Payment Failed
        UI->>Native: onError
        Native->>Bridge: Return error data
        Bridge->>SDK: Reject promise
        SDK->>App: Return error result
    end

Step-by-Step Integration

Step 1: Configure Your Payment

 const configurations = {
      hashString: '',
      language: 'en',
      themeMode: 'light',
      supportedPaymentMethods: 'ALL',
      paymentType: 'ALL',
      selectedCurrency: 'KWD',
      supportedCurrencies: 'ALL',
      supportedPaymentTypes: [],
      supportedRegions: [],
      supportedSchemes: [],
      supportedCountries: [],
      gateway: {
        publicKey: 'your_public_key',
        merchantId: 'your_merchant_ID',
      },
      customer: {
        firstName: 'Android',
        lastName: 'Test',
        email: '[email protected]',
        phone: { countryCode: '965', number: '55567890' },
      },
      transaction: {
        mode: 'charge',
        charge: {
          saveCard: true,
          auto: { type: 'VOID', time: 100 },
          redirect: {
            url: 'https://demo.staging.tap.company/v2/sdk/checkout',
          },
          threeDSecure: true,
          subscription: {
            type: 'SCHEDULED',
            amount_variability: 'FIXED',
            txn_count: 0,
          },
          airline: {
            reference: { booking: '' },
          },
        },
      },
      amount: '5',
      order: {
        id: '',
        currency: 'KWD',
        amount: '5',
        items: [
          {
            amount: '5',
            currency: 'KWD',
            name: 'Item Title 1',
            quantity: 1,
            description: 'item description 1',
          },
        ],
      },
      cardOptions: {
        showBrands: true,
        showLoadingState: false,
        collectHolderName: true,
        preLoadCardName: '',
        cardNameEditable: true,
        cardFundingSource: 'all',
        saveCardOption: 'all',
        forceLtr: false,
        alternativeCardInputs: { cardScanner: true, cardNFC: true },
      },
      isApplePayAvailableOnClient: true,
    };

Step 2: Start the Checkout with Callbacks

 const callbacks: CheckoutCallbacks = {
      onSuccess: (data: string) => {
        setStatus(`Checkout successful: ${data}`);
        console.log('Checkout success:', data);
      },
      onError: (error: string) => {
        setStatus(`Checkout error: ${error}`);
        console.log('Checkout error:', error);
      },
      onClose: () => {
        setStatus('Checkout closed');
        console.log('Checkout closed');
      },
      onReady: () => {
        setStatus('Checkout ready');
        console.log('Checkout ready');
      },
    };

Configuration

Basic Configuration Option

configurations = {
  // REQUIRED FIELDS
  "amount": "10.00",                    // Amount to charge
  "gateway": {...},                     // Gateway configuration
  "customer": {...},                    // Customer details
  "order": {...},                       // Order information
  
  // OPTIONAL FIELDS
  "language": "en",                     // "en" or "ar"
  "themeMode": "light",                 // "light", "dark", "dynamic"
  "supportedPaymentMethods": "ALL",     // "ALL" or specific methods
  "selectedCurrency": "USD",            // Default currency
  "paymentType": "ALL"                  // "ALL", "WEB", "CARD", "DEVICE"
};

Gateway Configuration

"gateway": {
   "publicKey": "pk_test_your_public_key",    // Your public key from the dashboard
   "merchantId": "your_merchant_id"           // Your merchant ID
}

⚠️ Important: Use pk_test_ for testing and pk_live_ for production.


Customer Configuration

"customer": {
  "firstName": "John",
  "lastName": "Doe",
  "email": "[email protected]",
  "phone": {
    "countryCode": "1",               // Country code without +
    "number": "1234567890"            // Phone number
  }
}

Order Configuration

"order": {
  "currency": "USD",                    // Currency code (USD, EUR, GBP, etc.)
  "amount": "25.99",                    // Order amount
  "items": [                            // Array of items
    {
      "name": "Product Name",
      "amount": "25.99",
      "currency": "USD",
      "quantity": 1,
      "description": "Product description"
    }
  ]
}

Callbacks(Should be removed)

The React Native SDK uses Promise-based callbacks instead of traditional callback functions. Here's how to handle different scenarios:

Success Callback

const handleSuccess = async () => {
  try {
    const result = await CheckoutSDK.startCheckout(config);
    
    if (result.success) {
      // Payment was processed successfully
      // The 'result.data' contains payment details in JSON format
      
      const { id, status, amount, currency, transaction } = result.data;
      
      console.log('Transaction ID:', id);
      console.log('Status:', status);
      console.log('Amount:', amount, currency);
      
      // Update your app's state
      saveTransactionDetails(id, status, amount, currency);
      updateUserAccount(id);
      showSuccessMessage('Payment completed successfully!');
      navigateToConfirmationScreen(id);
      
    } else {
      // Handle payment failure
      console.error('Payment failed:', result.error);
      showErrorMessage(result.error || 'Payment failed');
    }
  } catch (error) {
    console.error('Checkout exception:', error);
    showErrorMessage('Something went wrong. Please try again.');
  }
};

Error Handling

const handleCheckout = async () => {
  try {
    const result = await CheckoutSDK.startCheckout(config);
    
    if (result.success) {
      // Handle success
      showSuccessMessage('Payment completed successfully!');
    } else {
      // Handle specific error types
      const errorMessage = result.error || '';
      
      if (errorMessage.includes('cancelled')) {
        console.log('Payment was cancelled by user');
        showMessage('Payment was cancelled');
      } else if (errorMessage.includes('declined')) {
        console.warn('Payment was declined');
        showAlert('Payment Declined', 'Please check your card details and try again');
      } else if (errorMessage.includes('network')) {
        console.error('Network error');
        showAlert('Network Error', 'Please check your internet connection and try again');
      } else {
        console.error('Unknown payment error');
        showAlert('Error', 'Something went wrong. Please try again.');
      }
    }
  } catch (error) {
    // Handle exceptions (network issues, SDK errors, etc.)
    console.error('Checkout exception:', error);
    
    if (error.code === 'NETWORK_ERROR') {
      showAlert('Network Error', 'Please check your internet connection');
    } else if (error.code === 'INVALID_CONFIG') {
      showAlert('Configuration Error', 'Please check your payment configuration');
    } else {
      showAlert('Error', 'Something went wrong. Please try again.');
    }
  }
};

Loading States

const [isLoading, setIsLoading] = useState(false);

const handleCheckout = async () => {
  setIsLoading(true);
  
  try {
    const result = await CheckoutSDK.startCheckout(config);
    
    if (result.success) {
      showSuccessMessage('Payment completed successfully!');
    } else {
      showErrorMessage(result.error || 'Payment failed');
    }
  } catch (error) {
    showErrorMessage('Something went wrong. Please try again.');
  } finally {
    setIsLoading(false);
  }
};

return (
  <View>
    <Button 
      title={isLoading ? 'Processing...' : 'Pay Now'} 
      onPress={handleCheckout}
      disabled={isLoading}
    />
  </View>
);

Advanced Features

Theme Customization

// Light theme (default)
const lightConfig = {
  ...baseConfig,
  themeMode: 'light'
};

// Dark theme
const darkConfig = {
  ...baseConfig,
  themeMode: 'dark'
};

// Dyamic theme
const lightMonoConfig = {
  ...baseConfig,
  themeMode: 'dynamic'
};

Payment Method Selection

// Allow all payment methods
const allMethodsConfig = {
  ...baseConfig,
  supportedPaymentMethods: 'ALL'
};

// Specific payment methods
const specificMethodsConfig = {
  ...baseConfig,
  supportedPaymentMethods: ['VISA', 'MASTERCARD', 'APPLE_PAY', 'GOOGLE_PAY']
};

Card Options


  cardOptions: {
    showBrands: true,                   // Show card brand logos
    collectHolderName: true,            // Ask for cardholder name
    cardNameEditable: true,             // Allow editing card name
    saveCardOption: 'all',              // Show save card option
    alternativeCardInputs: {
      cardScanner: true,                // Enable card scanning
      cardNFC: true                     // Enable NFC reading
    }
  }

Multi-language Support

// English
const englishConfig = {
  ...baseConfig,
  language: 'en'
};

// Arabic
const arabicConfig = {
  ...baseConfig,
  language: 'ar'
};

Transaction Options

Capture Transaction

"transaction": {
  "mode": "charge",                      // Transaction mode
  "charge": {
  "metadata": {
   "value_1": "checkout_flutter"
   },
   "reference": {
      "transaction": "trans_01",
      "order": "order_01",
      "idempotent": "order_01" // optinal: generate the same charge ID for the same value
    },
    "saveCard": true,                    // Save card for future use
    "threeDSecure": true,                // Enable 3D Secure
    "redirect": {
      "url": "https://your-redirect-url.com" 
    }
  }
}

Authorize Transaction

"transaction": {
  "mode": "authorize",                     // Transaction mode
    "authorize": {
    "metadata": {
     "value_1": "checkout_flutter"
   	},
   "reference": {
      "transaction": "trans_01",
      "order": "order_01",
      "idempotent": "order_01" // optinal: generate the same charge ID for the same value
    },
  "saveCard": true,                        // Save card for future use
  "auto": {
     "type": "VOID", 
      "time": 100                         // Time in minutes
           },
  "redirect": {
    "url": "https://demo.staging.tap.company/v2/sdk/checkout",
    }
  }
}

Example App

The following example app demonstrates all SDK features:

Checkout React Native Example

Running the Example

  1. Clone the repository
  2. Install dependencies: npm install or yarn install
  3. Install iOS dependencies: cd ios && pod install && cd ..
  4. Add your test API keys in the example app
  5. Run the app:
    • iOS: npx react-native run-ios
    • Android: npx react-native run-android

Key Features Demonstrated

  • Basic Integration: Simple payment flow
  • Configuration Options: All customization options
  • Error Handling: Proper error handling patterns
  • UI Customization: Theme and language options
  • Cross-Platform: Works on both iOS and Android

Example App Structure

example/
├── App.tsx                    # Main example implementation
├── components/                # Reusable components
├── screens/                   # Different example screens
├── utils/                     # Utility functions
└── package.json              # Dependencies

Troubleshooting

Common Issues

1. SDK Not Starting

Problem: Nothing happens when calling startCheckout() Solution:

  • Check that all required fields are provided
  • Verify your public key is correct
  • Ensure the configuration object is valid
  • Check internet connectivity
  • Verify platform-specific setup (iOS pods, Android gradle)

2. Payment Fails Immediately

Problem: Promise rejects immediately Solution:

  • Verify your API keys are correct
  • Check network connectivity
  • Ensure amount is properly formatted
  • Verify merchant ID is registered
  • Check platform-specific requirements

3. iOS Build Issues

Problem: iOS build fails after installation Solution:

  • Run cd ios && pod install && cd ..
  • Clean build: cd ios && xcodebuild clean && cd ..
  • Reset Metro cache: npx react-native start --reset-cache
  • Check iOS deployment target (should be 13.0+)

4. Android Build Issues

Problem: Android build fails Solution:

  • Ensure minSdkVersion is set to 24 or higher
  • Clean build: cd android && ./gradlew clean && cd ..
  • Reset Metro cache: npx react-native start --reset-cache
  • Check Android SDK version compatibility

5. Promise Never Resolves

Problem: startCheckout() promise never resolves Solution:

  • Check that the native bridge is properly linked
  • Verify the native SDK is correctly installed
  • Ensure the configuration object is valid
  • Check for JavaScript errors in the console

Testing

  • Use test API keys for development
  • Test with different card numbers
  • Verify error handling with invalid data
  • Test on both iOS and Android platforms
  • Test on different device sizes and orientations

Architecture

SDK Structure Overview

graph TB
    A[React Native App] --> B[CheckoutSDK JS]
    B --> C[React Native Bridge]
    C --> D[iOS Native SDK]
    C --> E[Android Native SDK]
    
    D --> F[iOS Checkout UI]
    E --> G[Android Checkout UI]
    
    F --> H[Payment Gateway]
    G --> H
    
    B --> I[Promise Resolution]
    I --> J[Success Result]
    I --> K[Error Result]
    
    subgraph "Native Layer"
        D
        E
        F
        G
    end
    
    subgraph "JavaScript Layer"
        B
        I
        J
        K
    end

API Reference

CheckoutSDK

Methods

static async startCheckout(config: CheckoutConfig): Promise<CheckoutResult>

Starts the checkout process with the given configuration.

Parameters:

  • config: Checkout configuration object

Returns:

  • Promise<CheckoutResult>: Promise that resolves with the checkout result

Example:

try {
  const result = await CheckoutSDK.startCheckout(config);
  if (result.success) {
    console.log('Payment successful:', result.data);
  } else {
    console.error('Payment failed:', result.error);
  }
} catch (error) {
  console.error('Exception:', error);
}

CheckoutConfig

Configuration object for the checkout process.

Required Properties

interface CheckoutConfig {
  amount: string;                    // Payment amount
  currency: string;                  // Currency code
  publicKey: string;                 // Your public key
  merchantId: string;                // Your merchant ID
  customer: CustomerConfig;          // Customer details
  order: OrderConfig;                // Order information
}

Optional Properties

interface CheckoutConfig {
  // ... required properties ...
  
  language?: string;                 // "en" or "ar"
  themeMode?: string;                // "light", "dark", "dynamic"
  supportedPaymentMethods?: string | string[];  // "ALL" or specific methods
  paymentType?: string;              // "ALL", "WEB", "CARD", "DEVICE"
  cardOptions?: CardOptionsConfig;   // Card-specific options
  transaction?: TransactionConfig;   // Transaction options
}

CustomerConfig

interface CustomerConfig {
  firstName: string;                 // Customer's first name
  lastName: string;                  // Customer's last name
  email: string;                     // Customer's email
  phone: string;                     // Customer's phone number
}

OrderConfig

interface OrderConfig {
  id?: string;                       // Optional order ID
  amount: string;                    // Order amount
  currency: string;                  // Currency code
  items: OrderItemConfig[];          // Array of order items
}

OrderItemConfig

interface OrderItemConfig {
  name: string;                      // Item name
  amount: string;                    // Item amount
  currency: string;                  // Currency code
  quantity: number;                  // Item quantity
  description: string;               // Item description
}

CardOptionsConfig

interface CardOptionsConfig {
  showBrands?: boolean;              // Show card brand logos
  collectHolderName?: boolean;       // Ask for cardholder name
  cardNameEditable?: boolean;        // Allow editing card name
  saveCardOption?: string;           // Save card option
  alternativeCardInputs?: {
    cardScanner?: boolean;           // Enable card scanning
    cardNFC?: boolean;               // Enable NFC reading
  };
}

TransactionConfig

interface TransactionConfig {
  mode?: string;                     // "charge", "authorize", "save_card"
  saveCard?: boolean;                // Save card for future use
  threeDSecure?: boolean;            // Enable 3D Secure
  auto?: {
    type: string;                    // Auto type
    time: number;                    // Auto time
  };
  redirect?: {
    url: string;                     // Redirect URL
  };
  subscription?: {
    type: string;                    // Subscription type
    amount_variability: string;      // Amount variability
    txn_count: number;               // Transaction count
  };
}

CheckoutResult

Result object returned by the checkout process.

interface CheckoutResult {
  success: boolean;                  // Whether the payment was successful
  data?: any;                        // Payment data (if successful)
  error?: string;                    // Error message (if failed)
}

Error Types

interface CheckoutError extends Error {
  code?: string;                     // Error code
  message: string;                   // Error message
}

Preparing Your App for Release

When you're ready to publish your React Native app to the Play Store or share it with users it’s important to build it in release mode to improve performance and reduce app size. Before you start, please follow the official Flutter guide to sign your app:


Add ProGuard Rules

To further optimize and protect your Android app, we recommend adding a ProGuard file.

  • In your project, go to android/app/
  • Create a new file called proguard-rules.pro
  • Copy and paste the following content
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# ========================================
# REACT NATIVE CORE RULES
# ========================================

# Keep all React Native classes to prevent NoSuchMethodError
-keep class com.facebook.react.** { *; }
-keep interface com.facebook.react.** { *; }
-keepclassmembers class com.facebook.react.** { *; }

# Keep React Native dev support classes (fixes CxxInspectorPackagerConnection issues)
-keep class com.facebook.react.devsupport.** { *; }
-keepclassmembers class com.facebook.react.devsupport.** { *; }
-keep interface com.facebook.react.devsupport.** { *; }

# Keep React Native bridge classes
-keep class com.facebook.react.bridge.** { *; }
-keepclassmembers class com.facebook.react.bridge.** { *; }

# Keep React Native modules and their native methods
-keepclasseswithmembernames class * {
    native <methods>;
}

# Keep React Native Turbo Modules
-keep class com.facebook.react.turbomodule.** { *; }
-keep interface com.facebook.react.turbomodule.** { *; }

# Keep Hermes engine classes
-keep class com.facebook.hermes.** { *; }
-keep class com.facebook.jni.** { *; }

# ========================================
# KOTLIN SPECIFIC RULES
# ========================================

# Keep all Kotlin metadata to prevent reflection issues
-keep class kotlin.Metadata { *; }
-keep class kotlin.** { *; }
-keepclassmembers class kotlin.** { *; }

# Keep Kotlin coroutines completely
-keep class kotlinx.coroutines.** { *; }
-keepnames class kotlinx.coroutines.** { *; }
-keepclassmembers class kotlinx.coroutines.** { *; }
-dontwarn kotlinx.coroutines.**

# Keep all companion objects and singletons
-keepnames class * {
    public static ** Companion;
    public static ** INSTANCE;
}

# Keep Kotlin data classes and their properties
-keepclassmembers class * {
    @kotlin.jvm.JvmField <fields>;
    public ** component*();
    public ** copy(...);
    public ** copy$default(...);
}

# ========================================
# SERIALIZATION AND JSON
# ========================================

# Keep Gson classes
-keep class com.google.gson.** { *; }
-keep class * extends com.google.gson.TypeAdapter { *; }
-keep class * implements com.google.gson.TypeAdapterFactory { *; }
-keep class * implements com.google.gson.JsonSerializer { *; }
-keep class * implements com.google.gson.JsonDeserializer { *; }

# Keep serialization annotations
-keepclassmembers class * {
    @com.google.gson.annotations.SerializedName <fields>;
    @com.google.gson.annotations.Expose <fields>;
}

# ========================================
# NETWORK LIBRARIES
# ========================================

# Keep OkHttp3 classes completely
-dontwarn okhttp3.**
-dontwarn okio.**
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-keepnames class okhttp3.** { *; }

# Keep old OkHttp classes (com.squareup.okhttp) - used by some dependencies
-dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }

# Keep Retrofit classes completely  
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepnames class retrofit2.** { *; }

# ========================================
# ANDROID FRAMEWORK CLASSES
# ========================================

# Keep WebView related classes
-keep class android.webkit.** { *; }
-keep class * extends android.webkit.WebViewClient { *; }
-keep class * extends android.webkit.WebChromeClient { *; }

# Keep custom view classes with all constructors
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public <init>(android.content.Context, android.util.AttributeSet, int, int);
    public void set*(...);
    *** get*();
}

# Keep Parcelable implementations
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

# Keep enum classes
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
    **[] $VALUES;
    public *;
}

# Keep native methods
-keepclasseswithmembernames class * {
    native <methods>;
}

# ========================================
# ESSENTIAL ATTRIBUTES
# ========================================

# Keep all annotations and signatures for runtime reflection
-keepattributes *Annotation*
-keepattributes Signature
-keepattributes InnerClasses
-keepattributes EnclosingMethod
-keepattributes RuntimeVisibleAnnotations
-keepattributes RuntimeInvisibleAnnotations
-keepattributes RuntimeVisibleParameterAnnotations
-keepattributes RuntimeInvisibleParameterAnnotations

# Keep source file names and line numbers for better crash reports
-keepattributes SourceFile,LineNumberTable

# Keep exceptions for better debugging
-keepattributes Exceptions

# ========================================
# TAP PAYMENT SDK RULES
# ========================================

# Keep ALL Tap Checkout SDK classes - no obfuscation at all
-keep class company.tap.tapcheckout_android.** { *; }
-keep interface company.tap.tapcheckout_android.** { *; }
-keepnames class company.tap.tapcheckout_android.** { *; }
-keepclassmembers class company.tap.tapcheckout_android.** { *; }

# Keep all inner classes, companion objects, and nested classes
-keep class company.tap.tapcheckout_android.**$* { *; }
-keep class company.tap.tapcheckout_android.**$Companion { *; }

# Keep Tap Network Kit classes (fixes ClassCastException)
-keep class company.tap.tapnetworkkit.** { *; }
-keep interface company.tap.tapnetworkkit.** { *; }
-keepnames class company.tap.tapnetworkkit.** { *; }
-keepclassmembers class company.tap.tapnetworkkit.** { *; }
-keep class company.tap.tapnetworkkit.**$* { *; }

# Keep all Tap SDK related packages
-keep class company.tap.** { *; }
-keep interface company.tap.** { *; }
-keepclassmembers class company.tap.** { *; }

# ========================================
# LOTTIE ANIMATION RULES
# ========================================

# Keep all Lottie classes (fixes ClassCastException in LottieCompositionFactory)
-keep class com.airbnb.lottie.** { *; }
-keep interface com.airbnb.lottie.** { *; }
-keepclassmembers class com.airbnb.lottie.** { *; }
-keep class com.airbnb.lottie.**$* { *; }

# Don't warn about Lottie
-dontwarn com.airbnb.lottie.**

# Keep Lottie model classes
-keep class com.airbnb.lottie.model.** { *; }
-keep class com.airbnb.lottie.animation.** { *; }
-keep class com.airbnb.lottie.value.** { *; }

# ========================================
# MISSING CLASSES - IGNORE WARNINGS
# ========================================

# Suppress warnings for kotlinx.parcelize.Parcelize
-dontwarn kotlinx.parcelize.Parcelize

# Java beans classes - ignore warnings (not available on Android)
-dontwarn java.beans.**

# Jackson databind classes - ignore warnings
-dontwarn com.fasterxml.jackson.**

# Other JVM-specific classes not available on Android
-dontwarn java.lang.instrument.**
-dontwarn sun.misc.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
-dontwarn org.bouncycastle.**
-dontwarn org.openjsse.**


Message Mahmoud Allam









Build Your App for Release

Once you’ve set that up, you can build your app in release mode. Just run the commands in your terminal:

Support

For questions, issues, or feature requests: