Skip to main content

Mobile Payments

Accept in-app payments securely with Omise's native mobile SDKs for iOS, Android, React Native, and Flutter with built-in tokenization and optimized checkout flows.

Overviewโ€‹

Omise provides native SDKs for mobile platforms that handle payment collection, card tokenization, and checkout flows entirely within your mobile app. The SDKs provide pre-built UI components and low-level APIs for custom integrations.

Key Features:

  • โœ… Native performance - Optimized for iOS and Android
  • โœ… Secure tokenization - Card data never touches your servers
  • โœ… Pre-built UI - Ready-to-use payment forms
  • โœ… Custom integration - Full control over UX
  • โœ… 40+ payment methods - Cards, wallets, QR, banking
  • โœ… Cross-platform - React Native & Flutter support
  • โœ… Biometric auth - Touch ID, Face ID, fingerprint support

Available SDKsโ€‹

iOS SDKโ€‹

Native Swift/Objective-C SDK for iPhone and iPad apps:

Features:

  • Native iOS payment forms
  • SwiftUI and UIKit support
  • Touch ID / Face ID authentication
  • Apple Pay integration
  • iOS 13+ support

View iOS SDK Guide โ†’

Android SDKโ€‹

Native Kotlin/Java SDK for Android apps:

Features:

  • Material Design components
  • Jetpack Compose support
  • Biometric authentication
  • Google Pay integration
  • Android 5.0+ (API 21+) support

View Android SDK Guide โ†’

React Nativeโ€‹

Cross-platform React Native module:

Features:

  • Works on iOS and Android
  • JavaScript/TypeScript API
  • Consistent cross-platform behavior
  • Compatible with Expo

View React Native Guide โ†’

Flutterโ€‹

Cross-platform Flutter plugin:

Features:

  • Dart API
  • iOS and Android support
  • Native performance
  • Seamless integration with Flutter apps

View Flutter Guide โ†’

Comparisonโ€‹

FeatureiOSAndroidReact NativeFlutter
LanguageSwiftKotlinJavaScriptDart
Pre-built UIโœ…โœ…โœ…โœ…
Custom UIโœ…โœ…โœ…โœ…
Card Tokenizationโœ…โœ…โœ…โœ…
3D Secureโœ…โœ…โœ…โœ…
Apple Payโœ…โŒโœ… (iOS)โœ… (iOS)
Google PayโŒโœ…โœ… (Android)โœ… (Android)
Biometric AuthTouch/Face IDFingerprintBothBoth
Min VersioniOS 13+API 21+0.60+2.0+

How It Worksโ€‹

Security Benefits:

  1. Card data never touches your app's server
  2. PCI compliance simplified (SAQ A)
  3. Secure tokenization over HTTPS
  4. No card data stored on device

Quick Startโ€‹

iOS (Swift)โ€‹

import OmiseSDK

// Configure SDK
let publicKey = "pkey_test_YOUR_PUBLIC_KEY"
OmiseSDK.configure(publicKey: publicKey)

// Create token
let request = OmiseTokenRequest(
name: "John Doe",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2027,
securityCode: "123"
)

OmiseSDK.createToken(request) { result in
switch result {
case .success(let token):
print("Token created: \(token.id)")
// Send token to your server
self.chargeCard(tokenId: token.id)
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}

Android (Kotlin)โ€‹

import co.omise.android.OmiseSDK
import co.omise.android.models.Token

// Configure SDK
OmiseSDK.initialize("pkey_test_YOUR_PUBLIC_KEY")

// Create token
val request = TokenRequest(
name = "John Doe",
number = "4242424242424242",
expirationMonth = 12,
expirationYear = 2027,
securityCode = "123"
)

OmiseSDK.createToken(request) { result ->
when (result) {
is Result.Success -> {
val token = result.data
println("Token created: ${token.id}")
// Send token to your server
chargeCard(token.id)
}
is Result.Error -> {
println("Error: ${result.exception.message}")
}
}
}

React Nativeโ€‹

import Omise from 'omise-react-native';

// Configure SDK
Omise.configure('pkey_test_YOUR_PUBLIC_KEY');

// Create token
const cardData = {
name: 'John Doe',
number: '4242424242424242',
expirationMonth: 12,
expirationYear: 2027,
securityCode: '123'
};

try {
const token = await Omise.createToken(cardData);
console.log('Token created:', token.id);
// Send to server
await chargeCard(token.id);
} catch (error) {
console.error('Error:', error.message);
}

Flutterโ€‹

import 'package:omise_flutter/omise_flutter.dart';

// Configure SDK
OmiseFlutter.initialize(publicKey: 'pkey_test_YOUR_PUBLIC_KEY');

// Create token
final cardData = CardData(
name: 'John Doe',
number: '4242424242424242',
expirationMonth: 12,
expirationYear: 2027,
securityCode: '123',
);

try {
final token = await OmiseFlutter.createToken(cardData);
print('Token created: ${token.id}');
// Send to server
await chargeCard(token.id);
} catch (e) {
print('Error: $e');
}

Server-Side Integrationโ€‹

After receiving the token from your mobile app, charge the card on your server:

// Node.js server
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY
});

app.post('/charge', async (req, res) => {
try {
const { token, amount } = req.body;

const charge = await omise.charges.create({
amount: amount,
currency: 'THB',
card: token
});

res.json({
success: true,
charge_id: charge.id,
status: charge.status
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});

Payment Methodsโ€‹

Credit/Debit Cardsโ€‹

All SDKs support credit and debit card tokenization:

// iOS
let card = OmiseCardRequest(
name: "John Doe",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2027,
securityCode: "123"
)

Mobile Bankingโ€‹

Support for mobile banking redirect flows:

// Android
val source = SourceRequest(
type = "mobile_banking_kbank",
amount = 100000,
currency = "THB"
)

Digital Walletsโ€‹

Integrate wallet payments:

// React Native
const source = await Omise.createSource({
type: 'truemoney',
amount: 50000,
currency: 'THB',
phoneNumber: '+66876543210'
});

Apple Pay (iOS only)โ€‹

import PassKit

let paymentRequest = PKPaymentRequest()
paymentRequest.merchantIdentifier = "merchant.your.app"
paymentRequest.supportedNetworks = [.visa, .masterCard, .amex]
paymentRequest.merchantCapabilities = .capability3DS
paymentRequest.countryCode = "TH"
paymentRequest.currencyCode = "THB"
paymentRequest.paymentSummaryItems = [
PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(value: 100.00))
]

let controller = PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)
controller?.delegate = self
present(controller!, animated: true)

Google Pay (Android only)โ€‹

val paymentDataRequest = PaymentDataRequest.newBuilder()
.setTransactionInfo(
TransactionInfo.newBuilder()
.setTotalPrice("100.00")
.setTotalPriceStatus(WalletConstants.TOTAL_PRICE_STATUS_FINAL)
.setCurrencyCode("THB")
.build()
)
.build()

val task = paymentsClient.loadPaymentData(paymentDataRequest)

3D Secure Supportโ€‹

All SDKs support 3D Secure authentication:

iOSโ€‹

// 3DS automatically handled
let charge = try await createCharge(tokenId: token.id)

if let authorizeUri = charge.authorizeUri {
// Show 3DS authentication
let safariVC = SFSafariViewController(url: authorizeUri)
present(safariVC, animated: true)
}

Androidโ€‹

// 3DS automatically handled
val charge = createCharge(token.id)

charge.authorizeUri?.let { uri ->
// Show 3DS authentication
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri))
startActivity(intent)
}

Best Practicesโ€‹

1. Store Public Key Securelyโ€‹

// iOS - Use Configuration
struct Config {
static let omisePublicKey = "pkey_test_YOUR_KEY"
}
// Android - Use BuildConfig
val publicKey = BuildConfig.OMISE_PUBLIC_KEY

2. Validate Inputโ€‹

// React Native validation
function validateCard(cardData) {
if (cardData.number.length < 13) {
throw new Error('Invalid card number');
}

if (cardData.expirationMonth < 1 || cardData.expirationMonth > 12) {
throw new Error('Invalid expiration month');
}

const currentYear = new Date().getFullYear();
if (cardData.expirationYear < currentYear) {
throw new Error('Card expired');
}

return true;
}

3. Handle Errors Gracefullyโ€‹

// iOS error handling
OmiseSDK.createToken(request) { result in
switch result {
case .success(let token):
self.processPayment(token: token)
case .failure(let error):
self.showError(message: self.userFriendlyMessage(for: error))
}
}

func userFriendlyMessage(for error: Error) -> String {
switch error {
case OmiseError.invalidCard:
return "Please check your card details"
case OmiseError.networkError:
return "Network error. Please try again"
default:
return "Payment failed. Please try again"
}
}

4. Show Loading Statesโ€‹

// Android loading state
viewModel.isLoading.observe(this) { isLoading ->
if (isLoading) {
progressBar.visibility = View.VISIBLE
submitButton.isEnabled = false
} else {
progressBar.visibility = View.GONE
submitButton.isEnabled = true
}
}

5. Use Biometric Authenticationโ€‹

// iOS biometric auth
import LocalAuthentication

func authenticateUser() {
let context = LAContext()
var error: NSError?

if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
localizedReason: "Authenticate to complete payment") { success, error in
if success {
self.processPayment()
}
}
}
}

Testingโ€‹

Test Cardsโ€‹

Use test cards in test mode:

// Success card
let testCard = CardData(
name: "Test Card",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2027,
securityCode: "123"
)

View all test cards โ†’

Test Modeโ€‹

// Enable test mode (use test public key)
let publicKey = "pkey_test_YOUR_TEST_KEY"
OmiseSDK.configure(publicKey: publicKey)

FAQโ€‹

Which SDK should I use?
  • Native app (Swift): iOS SDK
  • Native app (Kotlin/Java): Android SDK
  • React Native app: React Native SDK
  • Flutter app: Flutter SDK
Do SDKs work with Expo?

Yes, the React Native SDK is compatible with Expo, but you'll need to use a custom development client (not Expo Go) for some features.

Can I customize the payment form UI?

Yes, all SDKs provide both pre-built UI components and low-level APIs for completely custom UIs.

Do I need PCI compliance?

Using the SDKs for tokenization requires only SAQ A (simplest level). Card data never touches your servers.

Can I save cards for recurring payments?

Yes, use tokens to create customers and save cards for future charges:

// Create customer with card
const customer = await omise.customers.create({
email: 'user@example.com',
card: tokenFromMobile
});
How do I handle 3D Secure in mobile apps?

The SDKs automatically handle 3DS by opening the authentication page in a web view or browser. You just need to handle the return URL.

What's the minimum iOS/Android version?
  • iOS SDK: iOS 13.0+
  • Android SDK: Android 5.0 (API 21)+
  • React Native: React Native 0.60+
  • Flutter: Flutter 2.0+

Next Stepsโ€‹

  1. Choose your platform
  2. Install SDK
  3. Implement tokenization
  4. Add server-side charging
  5. Test with test cards
  6. Go live