iOS SDK
The Omise iOS SDK provides a secure and convenient way to integrate payment processing into your iOS applications. Built for Swift and Objective-C, it handles tokenization of sensitive payment data and supports all major payment methods available in Southeast Asia.
概要
The iOS SDK enables you to:
- Tokenize credit cards securely without card data touching your servers
- Create payment sources for alternative payment methods
- Implement 3D Secure authentication flows
- Build custom payment forms with native iOS UI components
- サポート biometric authentication with Touch ID and Face ID
- Handle errors gracefully with comprehensive error types
Key Features
- Native Swift API with async/await support
- Objective-C compatibility for legacy projects
- Pre-built UI components for rapid integration
- Comprehensive input validation
- Network resilience and automatic retries
- Full type safety with Swift generics
- SwiftUI and UIKit support
- Combine framework integration
要件
- iOS 12.0 or later
- Xcode 13.0 or later
- Swift 5.5+ or Objective-C
- CocoaPods 1.10+, Swift Package Manager, or Carthage
インストール
Swift Package Manager (Recommended)
Add the iOS SDK to your project using Swift Package Manager:
- In Xcode, go to File > Add Packages
- Enter the repository URL:
https://github.com/omise/omise-ios - Select version 5.0.0 or later
- Add to your target
Or add it to your Package.swift:
dependencies: [
.package(url: "https://github.com/omise/omise-ios", from: "5.0.0")
]
CocoaPods
Add the SDK to your Podfile:
platform :ios, '12.0'
use_frameworks!
target 'YourApp' do
pod 'OmiseSDK', '~> 5.0'
end
Then run:
pod install
Carthage
Add to your Cartfile:
github "omise/omise-ios" ~> 5.0
Run:
carthage update --use-xcframeworks
Then drag the built OmiseSDK.xcframework into your project.
クイックスタート
1. Import the SDK
import OmiseSDK
// Objective-C
@import OmiseSDK;
2. Configure the Client
Initialize the SDK with your public key:
import OmiseSDK
class Paymentサービス {
let client: OmiseClient
init() {
// Initialize with public key
client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
}
}
// Objective-C
@interface Paymentサービス : NSObject
@property (nonatomic, strong) OMSClient *client;
@end
@implementation Paymentサービス
- (instancetype)init {
self = [super init];
if (self) {
_client = [[OMSClient alloc] initWithPublicKey:@"pkey_test_5xyzyx5xyzyx5xyzyx5"];
}
return self;
}
@end
3. Create a Token
Using Async/Await (Swift 5.5+)
func createToken() async throws -> Token {
let request = Token.CreateRequest(
name: "John Doe",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2025,
securityCode: "123"
)
let token = try await client.send(request)
print("Token created: \(token.id)")
return token
}
// 使用方法
Task {
do {
let token = try await createToken()
// Send token to your server
await sendTokenToServer(token.id)
} catch {
print("Error: \(error.localizedDescription)")
}
}
Using Completion Handlers
func createToken(completion: @escaping (Result<Token, Error>) -> Void) {
let request = Token.CreateRequest(
name: "John Doe",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2025,
securityCode: "123"
)
client.send(request) { result in
DispatchQueue.main.async {
completion(result)
}
}
}
// 使用方法
createToken { result in
switch result {
case .success(let token):
print("Token created: \(token.id)")
self.sendTokenToServer(token.id)
case .failure(let error):
print("Error: \(error.localizedDescription)")
}
}
Objective-C
OMSTokenRequest *request = [[OMSTokenRequest alloc] init];
request.name = @"John Doe";
request.number = @"4242424242424242";
request.expirationMonth = 12;
request.expirationYear = 2025;
request.securityCode = @"123";
[self.client send:request callback:^(OMSToken * _Nullable token, NSError * _Nullable error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
return;
}
NSLog(@"Token created: %@", token.tokenId);
[self sendTokenToServer:token.tokenId];
}];
構成
Client Configuration
// Basic configuration
let client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
// Advanced configuration
var config = OmiseClient.Configuration(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
config.apiVersion = "2019-05-29"
config.timeout = 60.0
config.sessionConfiguration = .default
let client = OmiseClient(configuration: config)
Network Configuration
// Custom URLSession configuration
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30
sessionConfig.timeoutIntervalForResource = 60
sessionConfig.requestCachePolicy = .reloadIgnoringLocalCacheData
var config = OmiseClient.Configuration(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
config.sessionConfiguration = sessionConfig
let client = OmiseClient(configuration: config)
トークンの作成
Basic Card Tokenization
func tokenizeCard(
name: String,
number: String,
expirationMonth: Int,
expirationYear: Int,
securityCode: String
) async throws -> Token {
let request = Token.CreateRequest(
name: name,
number: number,
expirationMonth: expirationMonth,
expirationYear: expirationYear,
securityCode: securityCode
)
return try await client.send(request)
}
With Billing Address
func tokenizeCardWithAddress() async throws -> Token {
let address = Token.Address(
street1: "123 Wireless Road",
street2: "Lumpini",
city: "Pathum Wan",
state: "Bangkok",
postalCode: "10330",
country: "TH"
)
let request = Token.CreateRequest(
name: "John Doe",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2025,
securityCode: "123",
billingAddress: address
)
return try await client.send(request)
}
Validation Before Tokenization
func validateAndTokenize(
number: String,
expirationMonth: Int,
expirationYear: Int,
securityCode: String
) async throws -> Token {
// Validate card number
guard CardValidator.isValid(number: number) else {
throw ValidationError.invalidCardNumber
}
// Validate expiry
guard CardValidator.isValid(expirationMonth: expirationMonth, year: expirationYear) else {
throw ValidationError.invalidExpiry
}
// Validate CVV
guard CardValidator.isValid(securityCode: securityCode) else {
throw ValidationError.invalidCVV
}
let request = Token.CreateRequest(
name: "John Doe",
number: number,
expirationMonth: expirationMonth,
expirationYear: expirationYear,
securityCode: securityCode
)
return try await client.send(request)
}
enum ValidationError: LocalizedError {
case invalidCardNumber
case invalidExpiry
case invalidCVV
var errorDescription: String? {
switch self {
case .invalidCardNumber:
return "Invalid card number"
case .invalidExpiry:
return "Invalid expiration date"
case .invalidCVV:
return "Invalid security code"
}
}
}
支払いソースの作成
インターネットバンキング
func createInternetBankingSource(amount: Int64, bank: InternetBanking) async throws -> Source {
let request = Source.CreateRequest(
amount: amount,
currency: .thb,
type: .internetBanking(bank)
)
return try await client.send(request)
}
// 使用方法
let source = try await createInternetBankingSource(
amount: 100000, // 1,000.00 THB
bank: .bay
)
// Redirect user to authorize payment
if let authorizeURL = source.authorizeURL {
UIApplication.shared.open(authorizeURL)
}
Mobile Banking
func createMobileBankingSource(amount: Int64, bank: MobileBanking) async throws -> Source {
let request = Source.CreateRequest(
amount: amount,
currency: .thb,
type: .mobileBanking(bank)
)
return try await client.send(request)
}
// 使用方法
let source = try await createMobileBankingSource(
amount: 50000, // 500.00 THB
bank: .scb
)
PromptPay
func createPromptPaySource(amount: Int64) async throws -> Source {
let request = Source.CreateRequest(
amount: amount,
currency: .thb,
type: .promptPay
)
return try await client.send(request)
}
// 使用方法
let source = try await createPromptPaySource(amount: 100000)
// Display QR code to user
if let qrCodeURL = source.scanQRCodeURL {
displayQRCode(url: qrCodeURL)
}
TrueMoney Wallet
func createTrueMoneySource(amount: Int64, phoneNumber: String) async throws -> Source {
let request = Source.CreateRequest(
amount: amount,
currency: .thb,
type: .trueMoney,
phoneNumber: phoneNumber
)
return try await client.send(request)
}
// 使用方法
let source = try await createTrueMoneySource(
amount: 100000,
phoneNumber: "0812345678"
)
Alipay
func createAlipaySource(amount: Int64) async throws -> Source {
let request = Source.CreateRequest(
amount: amount,
currency: .thb,
type: .alipay
)
return try await client.send(request)
}
UIコンポーネント
Built-in Credit Card Form
The SDK provides a pre-built credit card form:
import OmiseSDK
class PaymentViewコントローラー: UIViewコントローラー {
func presentCreditCardForm() {
let publicKey = "pkey_test_5xyzyx5xyzyx5xyzyx5"
let creditCardFormコントローラー = CreditCardFormコントローラー.makeCreditCardFormViewコントローラー(
withPublicKey: publicKey
)
creditCardFormコントローラー.delegate = self
creditCardFormコントローラー.handleErrors = true
present(creditCardFormコントローラー, animated: true)
}
}
extension PaymentViewコントローラー: CreditCardFormDelegate {
func creditCardForm(_ controller: CreditCardFormコントローラー, didSucceedWithToken token: Token) {
dismiss(animated: true) {
print("Token created: \(token.id)")
self.sendTokenToServer(token.id)
}
}
func creditCardForm(_ controller: CreditCardFormコントローラー, didFailWithError error: Error) {
dismiss(animated: true) {
self.showError(error.localizedDescription)
}
}
}
Custom Payment Source Chooser
func presentPaymentMethodChooser() {
let capability = try await client.retrieveCapability()
let chooser = PaymentSourceChooserコントローラー.makePaymentChooserNavigationコントローラー(
publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5",
amount: 100000,
currency: .thb,
capability: capability
)
chooser.delegate = self
present(chooser, animated: true)
}
extension PaymentViewコントローラー: PaymentSourceChooserDelegate {
func paymentSourceChooser(
_ controller: PaymentSourceChooserコントローラー,
didCompleteWith token: Token
) {
dismiss(animated: true) {
self.sendTokenToServer(token.id)
}
}
func paymentSourceChooser(
_ controller: PaymentSourceChooserコントローラー,
didCompleteWith source: Source
) {
dismiss(animated: true) {
self.handlePaymentSource(source)
}
}
func paymentSourceChooser(
_ controller: PaymentSourceChooserコントローラー,
didFailWithError error: Error
) {
dismiss(animated: true) {
self.showError(error.localizedDescription)
}
}
}
入力検証
Card Number Validation
import OmiseSDK
// Validate card number format
let cardNumber = "4242424242424242"
let isValid = CardValidator.isValid(number: cardNumber)
// Detect card brand
let brand = CardBrand.detect(from: cardNumber)
switch brand {
case .visa:
print("Visa card")
case .masterCard:
print("Mastercard")
case .jcb:
print("JCB card")
default:
print("Unknown brand")
}
// Format card number with spaces
let formatted = CardNumber.format(cardNumber) // "4242 4242 4242 4242"
Expiry Date Validation
// Validate expiry date
let month = 12
let year = 2025
let isValid = CardValidator.isValid(expirationMonth: month, year: year)
// Check if card is expired
let isExpired = CardValidator.isExpired(month: month, year: year)
CVV Validation
// Validate CVV for card brand
let cvv = "123"
let cardBrand = CardBrand.visa
let isValid = CardValidator.isValid(securityCode: cvv, for: cardBrand)
Custom Validation
struct CardFormValidator {
static func validate(
number: String,
expirationMonth: Int,
expirationYear: Int,
securityCode: String,
name: String
) -> ValidationResult {
var errors: [String] = []
// Validate card number
if !CardValidator.isValid(number: number) {
errors.append("Invalid card number")
}
// Validate expiry
if !CardValidator.isValid(expirationMonth: expirationMonth, year: expirationYear) {
errors.append("Invalid or expired card")
}
// Validate CVV
let brand = CardBrand.detect(from: number)
if !CardValidator.isValid(securityCode: securityCode, for: brand) {
errors.append("Invalid security code")
}
// Validate name
if name.trimmingCharacters(in: .whitespaces).isEmpty {
errors.append("Cardholder name is required")
}
return errors.isEmpty ? .valid : .invalid(errors: errors)
}
}
enum ValidationResult {
case valid
case invalid(errors: [String])
}