Apple의 In-App Purchase(IAP)는 iOS/macOS/tvOS 앱에서 디지털 상품 및 서비스를 구매할 수 있도록 하는 결제 시스템입니다.
앱 내에서 구매, 복원, 구독, 관리 등을 처리할 수 있으며, Apple의 StoreKit 프레임워크를 사용하여 구현합니다.
사용자가 구매할 수 있는 상품 목록을 불러오는 단계입니다.
func fetchProducts() {
let productIdentifiers: Set<String> = ["com.example.product1", "com.example.product2"]
let request = SKProductsRequest(productIdentifiers: productIdentifiers)
request.delegate = self
request.start()
}
사용자가 구매 버튼을 누르면 Apple의 SKPaymentQueue에 결제 요청을 추가합니다.
func purchase(product: SKProduct) {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
결제가 승인되면 Apple이 paymentQueue(_:updatedTransactions:) 콜백을 호출합니다.
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchased:
completeTransaction(transaction)
case .failed:
failTransaction(transaction)
case .restored:
restoreTransaction(transaction)
default:
break
}
}
}
이전에 구매한 아이템을 복원하려면 restoreCompletedTransactions()를 호출해야 합니다.
func restorePurchases() {
SKPaymentQueue.default().restoreCompletedTransactions()
}
Apple이 제공하는 영수증(receiptBase64)을 활용하여 결제가 정상적인지 확인해야 합니다.
func getReceiptBase64() -> String? {
guard let url = Bundle.main.appStoreReceiptURL,
let data = try? Data(contentsOf: url) else { return nil }
return data.base64EncodedString()
}
finishTransaction()을 호출하지 않으면 트랜잭션이 계속 남아 있어서 앱이 실행될 때마다 중복 처리될 수 있음.
func completeTransaction(_ transaction: SKPaymentTransaction) {
// 구매 완료 로직 처리
SKPaymentQueue.default().finishTransaction(transaction) // ✅ 반드시 호출해야 함!
}
restoreCompletedTransactions()는 소비형 상품에는 적용되지 않음.
구독형 상품(예: 월정액 서비스) 또는 비소비형 상품(예: 광고 제거)에서만 사용할 것.
클라이언트에서 직접 검증하면 보안에 취약 → 해킹 툴을 사용하면 결제를 우회할 수도 있음.
Apple 서버에서 영수증 검증을 수행하는 것이 보안적으로 더 안전함.
let receipt = getReceiptBase64()
let request = [
"receipt-data": receipt!,
"password": "YOUR_SHARED_SECRET"
]
sequenceDiagram
participant User
participant App_Client as App (Client)
participant StoreKit as Apple StoreKit
participant App_Server as App Server (Validation)
participant Apple_Receipt as Apple Receipt Server
User ->> App_Client: 1. 사용자 구매 요청
App_Client ->> StoreKit: 2. StoreKit에 결제 요청
StoreKit ->> App_Client: 3. 결제 승인
App_Client ->> StoreKit: 4. 트랜잭션 생성 및 완료 확인
App_Client ->> App_Server: 5. 영수증을 서버로 전송
App_Server ->> Apple_Receipt: 6. Apple 서버에서 영수증 검증
Apple_Receipt ->> App_Server: 7. 검증 결과 반환
App_Server ->> App_Client: 8. 앱에서 결제 완료 처리
App_Client ->> User: 9. 사용자에게 결제 완료 UI 표시
