ข้ามไปยังเนื้อหาหลัก

iOS SDK

Omise iOS SDK ให้บริการวิธีที่ปลอดภัยและสะดวกในการผสานรวมการประมวลผลการชำระเงินเข้ากับแอปพลิเคชัน iOS ของคุณ สร้างขึ้นสำหรับ Swift และ Objective-C โดยจัดการการสร้าง token ของข้อมูลการชำระเงินที่ละเอียดอ่อนและรองรับวิธีการชำระเงินหลักทั้งหมดที่มีในเอเชียตะวันออกเฉียงใต้

ภาพรวม

iOS SDK ช่วยให้คุณสามารถ:

  • สร้าง token บัตรเครดิต อย่างปลอดภัยโดยไม่ให้ข้อมูลบัตรเข้าถึงเซิร์ฟเวอร์ของคุณ
  • สร้าง payment source สำหรับวิธีการชำระเงินทางเลือก
  • ใช้งาน 3D Secure authentication flows
  • สร้างฟอร์มการชำระเงินที่กำหนดเอง ด้วยคอมโพเนนต์ UI แบบ native ของ iOS
  • รองรับการยืนยันตัวตนแบบไบโอเมตริกซ์ ด้วย Touch ID และ Face ID
  • จัดการข้อผิดพลาดอย่างเหมาะสม ด้วยประเภทข้อผิดพลาดที่ครอบคลุม

คุณสมบัติหลัก

  • Native Swift API พร้อมรองรับ async/await
  • ความเข้ากันได้กับ Objective-C สำหรับโปรเจกต์เก่า
  • คอมโพเนนต์ UI ที่สร้างไว้ล่วงหน้าเพื่อการผสานรวมที่รวดเร็ว
  • การตรวจสอบความถูกต้องของข้อมูลนำเข้าที่ครอบคลุม
  • ความยืดหยุ่นของเครือข่ายและการลองใหม่อัตโนมัติ
  • ความปลอดภัยของประเภทอย่างเต็มที่ด้วย Swift generics
  • รองรับ SwiftUI และ UIKit
  • การผสานรวม Combine framework

ข้อกำหนด

  • iOS 12.0 หรือใหม่กว่า
  • Xcode 13.0 หรือใหม่กว่า
  • Swift 5.5+ หรือ Objective-C
  • CocoaPods 1.10+, Swift Package Manager หรือ Carthage

การติดตั้ง

Swift Package Manager (แนะนำ)

เพิ่ม iOS SDK เข้าไปในโปรเจกต์ของคุณโดยใช้ Swift Package Manager:

  1. ใน Xcode ไปที่ File > Add Packages
  2. ใส่ repository URL:
    https://github.com/omise/omise-ios
  3. เลือกเวอร์ชัน 5.0.0 หรือใหม่กว่า
  4. เพิ่มไปยัง target ของคุณ

หรือเพิ่มเข้าไปใน Package.swift ของคุณ:

dependencies: [
.package(url: "https://github.com/omise/omise-ios", from: "5.0.0")
]

CocoaPods

เพิ่ม SDK เข้าไปใน Podfile ของคุณ:

platform :ios, '12.0'
use_frameworks!

target 'YourApp' do
pod 'OmiseSDK', '~> 5.0'
end

จากนั้นรัน:

pod install

Carthage

เพิ่มเข้าไปใน Cartfile ของคุณ:

github "omise/omise-ios" ~> 5.0

รัน:

carthage update --use-xcframeworks

จากนั้นลาก OmiseSDK.xcframework ที่สร้างแล้วเข้าไปในโปรเจกต์ของคุณ

เริ่มต้นอย่างรวดเร็ว

1. Import SDK

import OmiseSDK
// Objective-C
@import OmiseSDK;

2. กำหนดค่า Client

เริ่มต้น SDK ด้วย public key ของคุณ:

import OmiseSDK

class PaymentService {
let client: OmiseClient

init() {
// Initialize with public key
client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
}
}
// Objective-C
@interface PaymentService : NSObject
@property (nonatomic, strong) OMSClient *client;
@end

@implementation PaymentService

- (instancetype)init {
self = [super init];
if (self) {
_client = [[OMSClient alloc] initWithPublicKey:@"pkey_test_5xyzyx5xyzyx5xyzyx5"];
}
return self;
}

@end

3. สร้าง Token

ใช้ 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)")
}
}

ใช้ 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

// การกำหนดค่าพื้นฐาน
let client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")

// การกำหนดค่าขั้นสูง
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)

การกำหนดค่าเครือข่าย

// การกำหนดค่า URLSession ที่กำหนดเอง
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)

การสร้าง Token

การสร้าง Token บัตรพื้นฐาน

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)
}

พร้อมที่อยู่สำหรับการเรียกเก็บเงิน

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)
}

การตรวจสอบก่อนสร้าง Token

func validateAndTokenize(
number: String,
expirationMonth: Int,
expirationYear: Int,
securityCode: String
) async throws -> Token {
// ตรวจสอบหมายเลขบัตร
guard CardValidator.isValid(number: number) else {
throw ValidationError.invalidCardNumber
}

// ตรวจสอบวันหมดอายุ
guard CardValidator.isValid(expirationMonth: expirationMonth, year: expirationYear) else {
throw ValidationError.invalidExpiry
}

// ตรวจสอบ 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 "หมายเลขบัตรไม่ถูกต้อง"
case .invalidExpiry:
return "วันหมดอายุไม่ถูกต้อง"
case .invalidCVV:
return "รหัสความปลอดภัยไม่ถูกต้อง"
}
}
}

การสร้าง Payment Source

ธนาคารอินเทอร์เน็ต

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
)

// นำผู้ใช้ไปยังหน้ายืนยันการชำระเงิน
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)

// แสดง QR code ให้กับผู้ใช้
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

ฟอร์มบัตรเครดิตที่สร้างไว้ในตัว

SDK ให้บริการฟอร์มบัตรเครดิตที่สร้างไว้ล่วงหน้า:

import OmiseSDK

class PaymentViewController: UIViewController {

func presentCreditCardForm() {
let publicKey = "pkey_test_5xyzyx5xyzyx5xyzyx5"

let creditCardFormController = CreditCardFormViewController.makeCreditCardFormViewController(
withPublicKey: publicKey
)

creditCardFormController.delegate = self
creditCardFormController.handleErrors = true

present(creditCardFormController, animated: true)
}
}

extension PaymentViewController: CreditCardFormDelegate {
func creditCardForm(_ controller: CreditCardFormViewController, didSucceedWithToken token: Token) {
dismiss(animated: true) {
print("Token created: \(token.id)")
self.sendTokenToServer(token.id)
}
}

func creditCardForm(_ controller: CreditCardFormViewController, didFailWithError error: Error) {
dismiss(animated: true) {
self.showError(error.localizedDescription)
}
}
}

ตัวเลือกวิธีการชำระเงินที่กำหนดเอง

func presentPaymentMethodChooser() {
let capability = try await client.retrieveCapability()

let chooser = PaymentSourceChooserViewController.makePaymentChooserNavigationViewController(
publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5",
amount: 100000,
currency: .thb,
capability: capability
)

chooser.delegate = self
present(chooser, animated: true)
}

extension PaymentViewController: PaymentSourceChooserDelegate {
func paymentSourceChooser(
_ controller: PaymentSourceChooserViewController,
didCompleteWith token: Token
) {
dismiss(animated: true) {
self.sendTokenToServer(token.id)
}
}

func paymentSourceChooser(
_ controller: PaymentSourceChooserViewController,
didCompleteWith source: Source
) {
dismiss(animated: true) {
self.handlePaymentSource(source)
}
}

func paymentSourceChooser(
_ controller: PaymentSourceChooserViewController,
didFailWithError error: Error
) {
dismiss(animated: true) {
self.showError(error.localizedDescription)
}
}
}

การตรวจสอบความถูกต้องของข้อมูลนำเข้า

การตรวจสอบหมายเลขบัตร

import OmiseSDK

// ตรวจสอบรูปแบบหมายเลขบัตร
let cardNumber = "4242424242424242"
let isValid = CardValidator.isValid(number: cardNumber)

// ตรวจหายี่ห้อบัตร
let brand = CardBrand.detect(from: cardNumber)
switch brand {
case .visa:
print("บัตร Visa")
case .masterCard:
print("Mastercard")
case .jcb:
print("บัตร JCB")
default:
print("ยี่ห้อไม่รู้จัก")
}

// จัดรูปแบบหมายเลขบัตรด้วยช่องว่าง
let formatted = CardNumber.format(cardNumber) // "4242 4242 4242 4242"

การตรวจสอบวันหมดอายุ

// ตรวจสอบวันหมดอายุ
let month = 12
let year = 2025

let isValid = CardValidator.isValid(expirationMonth: month, year: year)

// ตรวจสอบว่าบัตรหมดอายุหรือไม่
let isExpired = CardValidator.isExpired(month: month, year: year)

การตรวจสอบ CVV

// ตรวจสอบ CVV สำหรับยี่ห้อบัตร
let cvv = "123"
let cardBrand = CardBrand.visa

let isValid = CardValidator.isValid(securityCode: cvv, for: cardBrand)

การตรวจสอบที่กำหนดเอง

struct CardFormValidator {
static func validate(
number: String,
expirationMonth: Int,
expirationYear: Int,
securityCode: String,
name: String
) -> ValidationResult {
var errors: [String] = []

// ตรวจสอบหมายเลขบัตร
if !CardValidator.isValid(number: number) {
errors.append("หมายเลขบัตรไม่ถูกต้อง")
}

// ตรวจสอบวันหมดอายุ
if !CardValidator.isValid(expirationMonth: expirationMonth, year: expirationYear) {
errors.append("บัตรไม่ถูกต้องหรือหมดอายุแล้ว")
}

// ตรวจสอบ CVV
let brand = CardBrand.detect(from: number)
if !CardValidator.isValid(securityCode: securityCode, for: brand) {
errors.append("รหัสความปลอดภัยไม่ถูกต้อง")
}

// ตรวจสอบชื่อ
if name.trimmingCharacters(in: .whitespaces).isEmpty {
errors.append("ต้องระบุชื่อผู้ถือบัตร")
}

return errors.isEmpty ? .valid : .invalid(errors: errors)
}
}

enum ValidationResult {
case valid
case invalid(errors: [String])
}

การยืนยันตัวตน 3D Secure

การจัดการ 3D Secure Flow

import OmiseSDK
import SafariServices

class PaymentViewController: UIViewController {

func processPaymentWithToken(_ tokenId: String) async {
do {
// สร้างการเรียกเก็บเงินบนเซิร์ฟเวอร์ของคุณ
let charge = try await createChargeOnServer(tokenId: tokenId)

// ตรวจสอบว่าต้องการ 3D Secure หรือไม่
if let authorizeURL = charge.authorizeURL {
await handle3DSecure(url: authorizeURL)
} else {
handleSuccessfulPayment(charge)
}
} catch {
handleError(error)
}
}

func handle3DSecure(url: URL) async {
await withCheckedContinuation { continuation in
let safariVC = SFSafariViewController(url: url)
safariVC.delegate = self
present(safariVC, animated: true) {
self.threeDSecureContinuation = continuation
}
}
}

private var threeDSecureContinuation: CheckedContinuation<Void, Never>?
}

extension PaymentViewController: SFSafariViewControllerDelegate {
func safariViewController(
_ controller: SFSafariViewController,
didCompleteInitialLoad didLoadSuccessfully: Bool
) {
guard didLoadSuccessfully else {
controller.dismiss(animated: true)
threeDSecureContinuation?.resume()
handleError(NSError(domain: "3DS", code: -1, userInfo: nil))
return
}
}

func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
threeDSecureContinuation?.resume()
// ตรวจสอบสถานะการเรียกเก็บเงินบนเซิร์ฟเวอร์ของคุณ
Task {
await verifyChargeStatus()
}
}
}

การจัดการข้อผิดพลาด

ประเภทข้อผิดพลาด

do {
let token = try await client.send(request)
} catch let error as OmiseError {
switch error {
case .api(let apiError):
// ข้อผิดพลาด API จากเซิร์ฟเวอร์
print("API Error: \(apiError.message)")
handleAPIError(apiError)

case .network(let networkError):
// ข้อผิดพลาดการเชื่อมต่อเครือข่าย
print("Network Error: \(networkError.localizedDescription)")
showNetworkError()

case .invalidRequest(let message):
// พารามิเตอร์คำขอไม่ถูกต้อง
print("Invalid Request: \(message)")

case .authenticationFailure:
// Public key ไม่ถูกต้อง
print("การยืนยันตัวตนล้มเหลว - ตรวจสอบ public key ของคุณ")

default:
print("ข้อผิดพลาดที่ไม่รู้จัก: \(error)")
}
} catch {
print("ข้อผิดพลาดที่ไม่คาดคิด: \(error)")
}

การจัดการข้อผิดพลาด API

func handleAPIError(_ error: APIError) {
switch error.code {
case "invalid_card":
showAlert(title: "บัตรไม่ถูกต้อง", message: "กรุณาตรวจสอบรายละเอียดบัตรของคุณ")

case "insufficient_fund":
showAlert(title: "ยอดเงินไม่เพียงพอ", message: "บัตรของคุณมียอดเงินไม่เพียงพอ")

case "failed_processing":
showAlert(title: "การชำระเงินล้มเหลว", message: "ไม่สามารถประมวลผลการชำระเงินของคุณได้")

case "invalid_security_code":
showAlert(title: "CVV ไม่ถูกต้อง", message: "กรุณาตรวจสอบรหัสความปลอดภัยของคุณ")

default:
showAlert(title: "ข้อผิดพลาด", message: error.message)
}
}

ลอจิกการลองใหม่

func createTokenWithRetry(maxAttempts: Int = 3) async throws -> Token {
var lastError: Error?

for attempt in 1...maxAttempts {
do {
return try await createToken()
} catch {
lastError = error

// อย่าลองใหม่สำหรับข้อผิดพลาดการตรวจสอบ
if case OmiseError.invalidRequest = error {
throw error
}

// รอก่อนลองใหม่
if attempt < maxAttempts {
try await Task.sleep(nanoseconds: UInt64(attempt) * 1_000_000_000)
}
}
}

throw lastError ?? OmiseError.unknown
}

แนวทางปฏิบัติที่ดีที่สุด

ความปลอดภัย

// ✅ ควรทำ: ใช้ test key สำหรับการพัฒนา
let testKey = "pkey_test_5xyzyx5xyzyx5xyzyx5"

// ❌ ไม่ควรทำ: ฮาร์ดโค้ด production key
// let productionKey = "pkey_5xyzyx5xyzyx5xyzyx5"

// ✅ ควรทำ: โหลด key จากการกำหนดค่า
let publicKey = Bundle.main.object(forInfoPlistKey: "OmisePublicKey") as? String

// ❌ ไม่ควรทำ: บันทึกข้อมูลที่ละเอียดอ่อน
// print("Card number: \(cardNumber)")

// ✅ ควรทำ: ใช้การบันทึกที่ทำความสะอาดแล้ว
print("Token created: \(token.id)")

การจัดการหน่วยความจำ

class PaymentManager {
private weak var client: OmiseClient?
private var currentTask: Task<Token, Error>?

func tokenizeCard() async throws -> Token {
// ยกเลิกคำขอก่อนหน้า
currentTask?.cancel()

let task = Task {
try await client?.send(request)
}
currentTask = task

return try await task.value
}

func cancelPendingRequests() {
currentTask?.cancel()
}
}

ประสบการณ์ผู้ใช้

class PaymentViewController: UIViewController {
private let activityIndicator = UIActivityIndicatorView(style: .large)

func processPayment() {
showLoadingIndicator()

Task {
do {
let token = try await createToken()
hideLoadingIndicator()
await sendToServer(token)
} catch {
hideLoadingIndicator()
showError(error)
}
}
}

private func showLoadingIndicator() {
activityIndicator.startAnimating()
view.isUserInteractionEnabled = false
}

private func hideLoadingIndicator() {
activityIndicator.stopAnimating()
view.isUserInteractionEnabled = true
}
}

การทดสอบ

โหมดทดสอบ

// ใช้ test public key
let client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")

// หมายเลขบัตรทดสอบ
let testCards = [
"4242424242424242", // สำเร็จ
"4111111111111111", // ล้มเหลว
"4000000000000002", // ต้องการ 3D Secure
]

Unit Testing

import XCTest
@testable import YourApp

class PaymentTests: XCTestCase {
var client: OmiseClient!

override func setUp() {
super.setUp()
client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")
}

func testTokenCreation() async throws {
let request = Token.CreateRequest(
name: "Test User",
number: "4242424242424242",
expirationMonth: 12,
expirationYear: 2025,
securityCode: "123"
)

let token = try await client.send(request)

XCTAssertNotNil(token.id)
XCTAssertTrue(token.id.hasPrefix("tokn_test_"))
}

func testInvalidCardNumber() async {
let request = Token.CreateRequest(
name: "Test User",
number: "1234567890123456",
expirationMonth: 12,
expirationYear: 2025,
securityCode: "123"
)

do {
_ = try await client.send(request)
XCTFail("ควรจะมีข้อผิดพลาดสำหรับบัตรที่ไม่ถูกต้อง")
} catch {
XCTAssertNotNil(error)
}
}
}

UI Testing

class PaymentUITests: XCTestCase {
var app: XCUIApplication!

override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}

func testPaymentFlow() {
// นำทางไปยังหน้าจอการชำระเงิน
app.buttons["ชำระเงินตอนนี้"].tap()

// กรอกรายละเอียดบัตร
let cardNumberField = app.textFields["หมายเลขบัตร"]
cardNumberField.tap()
cardNumberField.typeText("4242424242424242")

let expiryField = app.textFields["วันหมดอายุ"]
expiryField.tap()
expiryField.typeText("12/25")

let cvvField = app.secureTextFields["CVV"]
cvvField.tap()
cvvField.typeText("123")

// ส่ง
app.buttons["ส่ง"].tap()

// ตรวจสอบความสำเร็จ
XCTAssertTrue(app.alerts["การชำระเงินสำเร็จ"].exists)
}
}

การแก้ไขปัญหา

ปัญหาทั่วไป

ปัญหา: ข้อผิดพลาด "Invalid public key"

// วิธีแก้: ตรวจสอบรูปแบบ public key ของคุณ
// Test keys: pkey_test_*
// Live keys: pkey_*

let client = OmiseClient(publicKey: "pkey_test_5xyzyx5xyzyx5xyzyx5")

ปัญหา: ข้อผิดพลาด network timeout

// วิธีแก้: เพิ่ม timeout
var config = OmiseClient.Configuration(publicKey: "pkey_test_...")
config.timeout = 60.0
let client = OmiseClient(configuration: config)

ปัญหา: การสร้าง token ล้มเหลวโดยไม่มีเสียง

// วิธีแก้: เพิ่มการจัดการข้อผิดพลาดที่เหมาะสม
do {
let token = try await client.send(request)
print("สำเร็จ: \(token.id)")
} catch {
print("ข้อผิดพลาด: \(error)")
// เพิ่ม breakpoint ที่นี่เพื่อดีบัก
}

ปัญหา: การเปลี่ยนเส้นทาง 3D Secure ไม่ทำงาน

// วิธีแก้: ตรวจสอบให้แน่ใจว่า Info.plist รวม LSApplicationQueriesSchemes
// เพิ่มเข้าไปใน Info.plist:
// <key>LSApplicationQueriesSchemes</key>
// <array>
// <string>https</string>
// </array>

ปัญหา: ข้อผิดพลาดการ build หลังจากติดตั้ง

# วิธีแก้: ทำความสะอาด build folder
# Xcode > Product > Clean Build Folder
# หรือใช้ command line:
rm -rf ~/Library/Developer/Xcode/DerivedData

โหมดดีบัก

// เปิดใช้งานการบันทึกดีบัก
#if DEBUG
client.enableDebugLogging = true
#endif

// จะบันทึกคำขอและการตอบกลับเครือข่ายทั้งหมด

คู่มือการย้ายข้อมูล

การย้ายจาก v4.x ไปยัง v5.x

รุ่น v5.x แนะนำการรองรับ async/await และลบ API ที่เลิกใช้แล้วบางตัว:

ก่อน (v4.x):

client.send(request) { result in
switch result {
case .success(let token):
print(token.id)
case .failure(let error):
print(error)
}
}

หลัง (v5.x):

// ตัวเลือก 1: ใช้ async/await
let token = try await client.send(request)

// ตัวเลือก 2: ใช้ completion handlers ต่อไป (ยังรองรับอยู่)
client.send(request) { result in
// เหมือนเดิม
}

การเปลี่ยนแปลงที่ทำลายความเข้ากันได้:

  1. เวอร์ชัน iOS ขั้นต่ำตอนนี้เป็น 12.0 (เดิมเป็น 10.0)
  2. เวอร์ชัน Swift ขั้นต่ำคือ 5.5 (เดิมเป็น 5.0)
  3. OmiseSDKConfiguration เปลี่ยนชื่อเป็น OmiseClient.Configuration
  4. ลบประเภทวิธีการชำระเงินที่เลิกใช้แล้วบางประเภท

คำถามที่พบบ่อย

ฉันสามารถใช้ SDK นี้กับ SwiftUI ได้หรือไม่?

ได้ SDK ทำงานได้อย่างสมบูรณ์แบบกับ SwiftUI คุณสามารถใช้ async/await API ได้โดยตรงใน SwiftUI view และ view model ของคุณ

struct PaymentView: View {
@StateObject private var viewModel = PaymentViewModel()

var body: some View {
Button("ชำระเงินตอนนี้") {
Task {
await viewModel.processPayment()
}
}
}
}

SDK รองรับ Combine หรือไม่?

แม้ว่า SDK จะไม่ให้ Combine publisher แบบ native แต่คุณสามารถ wrap async/await API ได้อย่างง่ายดาย:

extension OmiseClient {
func sendPublisher(_ request: Token.CreateRequest) -> AnyPublisher<Token, Error> {
Future { promise in
Task {
do {
let token = try await self.send(request)
promise(.success(token))
} catch {
promise(.failure(error))
}
}
}
.eraseToAnyPublisher()
}
}

ฉันสามารถปรับแต่งคอมโพเนนต์ UI ที่สร้างไว้ในตัวได้หรือไม่?

ได้ คุณสามารถปรับแต่งสี ฟอนต์ และคุณสมบัติลักษณะอื่นๆ:

let theme = CreditCardFormTheme()
theme.primaryColor = .systemBlue
theme.errorColor = .systemRed
theme.font = UIFont.systemFont(ofSize: 16)

creditCardFormController.theme = theme

ฉันจะจัดการการส่ง App Store ได้อย่างไร?

SDK เป็นไปตามข้อกำหนดของ App Store ตรวจสอบให้แน่ใจว่า:

  1. ใช้ test key ระหว่างการพัฒนา
  2. เปลี่ยนเป็น production key สำหรับการปล่อย
  3. อย่าบันทึกข้อมูลที่ละเอียดอ่อนใน production
  4. รวมนโยบายความเป็นส่วนตัวสำหรับการประมวลผลการชำระเงิน

ฉันสามารถบันทึกรายละเอียดบัตรเพื่อใช้ในอนาคตได้หรือไม่?

SDK สร้าง token ที่สามารถบันทึกไว้บนเซิร์ฟเวอร์ของคุณได้ ใช้ Customers API บน backend ของคุณเพื่อแนบ token เข้ากับลูกค้าสำหรับการเรียกเก็บเงินในอนาคต

SDK รองรับ Apple Pay หรือไม่?

SDK มุ่งเน้นที่การสร้าง token บัตร สำหรับ Apple Pay ให้ใช้ PassKit framework และแปลง payment token บนเซิร์ฟเวอร์ของคุณ

ความแตกต่างระหว่าง token และ source คืออะไร?

  • Token แทนบัตรเครดิต/เดบิตสำหรับการเรียกเก็บเงินทันที
  • Source แทนวิธีการชำระเงินทางเลือกที่ต้องการขั้นตอนเพิ่มเติม

Token มีอายุการใช้งานนานแค่ไหน?

Token หมดอายุหลังจาก 30 นาทีหากไม่ได้ใช้ เมื่อใช้เพื่อสร้างการเรียกเก็บเงินหรือแนบกับลูกค้าแล้ว จะถูกเก็บอย่างถาวร

ฉันสามารถทดสอบด้วยหมายเลขบัตรจริงได้หรือไม่?

ไม่ได้ ใช้หมายเลขบัตรทดสอบเสมอในโหมดทดสอบ บัตรจริงจะถูกปฏิเสธในโหมดทดสอบ

SDK ทำงานกับ Catalyst ได้หรือไม่?

ได้ SDK รองรับ Mac Catalyst สำหรับแอป iPad ที่ทำงานบน macOS

ทรัพยากรที่เกี่ยวข้อง

  • ภาพรวม Mobile SDK - เปรียบเทียบ mobile SDK ทั้งหมด
  • Android SDK - การพัฒนา Android
  • Charges API - สร้างการเรียกเก็บเงินจาก token
  • Customers API - บันทึกบัตรเพื่อใช้ในอนาคต
  • GitHub Repository - โค้ดต้นฉบับและตัวอย่าง
  • API Reference - เอกสาร API ที่สมบูรณ์

ขั้นตอนถัดไป

  1. ตั้งค่าบัญชีของคุณ เพื่อรับ API key
  2. ผสานรวมบนเซิร์ฟเวอร์ของคุณ เพื่อสร้างการเรียกเก็บเงินจาก token
  3. ทดสอบการผสานรวมของคุณ ด้วยบัตรทดสอบ
  4. เปิดใช้งานจริง ด้วย production key

การสนับสนุน

ต้องการความช่วยเหลือเกี่ยวกับ iOS SDK หรือไม่?