View in English

  • 메뉴 열기 메뉴 닫기
  • Apple Developer
검색
검색 닫기
  • Apple Developer
  • 뉴스
  • 둘러보기
  • 디자인
  • 개발
  • 배포
  • 지원
  • 계정
페이지에서만 검색

빠른 링크

5 빠른 링크

비디오

메뉴 열기 메뉴 닫기
  • 컬렉션
  • 주제
  • 전체 비디오
  • 소개

WWDC23 컬렉션으로 돌아가기

스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.

  • 소개
  • 코드
  • StoreKit 2 및 Xcode 내 StoreKit Testing의 새로운 기능

    StoreKit 2의 최신 개선 사항과 Xcode의 StoreKit Testing에 대해 알아보세요. 앱 내 구입 홍보, StoreKit 메시지, 트랜잭션 모델, RenewalInfo 모델, 구독 관리용 App Store 시트에 대한 API 업데이트를 함께 살펴봅니다. 기기 내에서의 영수증 검증을 위해 SHA-256로 업그레이드하는 방법과 API를 사용하여 SwiftUI 뷰를 생성하는 방법도 알아보세요. 또한 앱 내 구입 및 구독을 디버깅하고 테스트할 수 있도록 Xcode에서 StoreKit Testing을 시작하는 방법도 알려드립니다. 트랜잭션 인스펙터를 알아보고, StoreKit 구성 에디터의 최신 업데이트 내용을 살펴보고, StoreKit 오류를 시뮬레이션하여 앱의 오류 처리를 테스트하는 방법을 배워보세요.

    리소스

    • Message
    • Setting up StoreKit Testing in Xcode
    • StoreKit
    • Submit feedback
    • Supporting promoted In-App Purchases in your app
    • Testing failing subscription renewals and In-App Purchases
    • Turn on Family Sharing for in-app purchases in App Store Connect
      • HD 비디오
      • SD 비디오

    관련 비디오

    WWDC23

    • 앱 내 구입 테스트 기능 살펴보기
    • App Store Connect의 새로운 기능
    • SwiftUI용 StoreKit 알아보기

    WWDC22

    • StoreKit 테스팅의 새로운 기능
    • What's new with in-app purchase

    WWDC21

    • StoreKit 2 소개
  • 비디오 검색…
    Array
    • 1:42 - Create a listener for promoted in-app purchases

      // Create a listener for promoted in-app purchases
      import StoreKit
      
      let promotedPurchasesListener = Task {
          for await promotion in PurchaseIntent.intents {
              // Process promotion
              let product = promotion.product
      
              // Purchase promoted product
              do {
                  let result = try await product.purchase()
                  // Process result
              }
              catch {
                  // Handle error
              }
          }
      }
    • 2:57 - Check promotion order

      // Check promotion order
      import StoreKit
      
      do {
          let promotions = try await Product.PromotionInfo.currentOrder
      
          if promotions.isEmpty {
              // No local promotion order set
          }
      
          for promotion in promotions {
              let productID = promotion.productID
              let productVisibility = promotion.visibility
              // Check promoted products
          }
      }
      catch {
          // Handle error
      }
    • 3:26 - Set a promotion order

      // Set a promotion order
      import StoreKit
      
      let newPromotionOrder: [String] = [
          "acorns.individual",
          "nectar.cup",
          "sunflowerseeds.pile"
      ]
      
      do {
          try await Product.PromotionInfo.updateProductOrder(byID: newPromotionOrder)
      }
      catch {
          // Handle error
      }
    • 4:02 - Update promotion visibility

      // Update promotion visibility
      import StoreKit
      
      // Hide “acorns.individual”
      do {
          try await Product.PromotionInfo.updateProductVisibility(.hidden, for: "acorns.individual")
      }
      catch {
          // Handle error
      }
    • 4:17 - Update promotion visibility (alternative method)

      // Update promotion visibility
      import StoreKit
      
      do {
        let promotions = try await Product.PromotionInfo.currentOrder
      
        // Hide the first product
        if var firstPromotion = promotions.first {
          firstPromotion.visibility = .hidden
          try await firstPromotion.update()
        }
      }
      catch {
        // Handle error
      }
    • 8:32 - Product view

      // Product view
      import SwiftUI
      import StoreKit
      
      struct BirdFoodShop: View {
          let productID: String
          let productImage: String
      
          var body: some View {
              ProductView(id: productID) {
                  BirdFoodProductIcon(for: productID)
              }
              .productViewStyle(.large)
          }
      }
    • 8:52 - Store view

      // Store view
      import SwiftUI
      import StoreKit
      
      struct BirdFoodShop: View {
          let productIDs: [String]
      
          var body: some View {
              StoreView(ids: productIDs) { product in
                  BirdFoodIcon(productID: product.id)
              }
          }
      }
    • 9:19 - Subscription view

      // Subscription view
      import SwiftUI
      import StoreKit
      
      struct BackyardBirdsPassShop: View {
          let groupID: String
      
          var body: some View {
              SubscriptionStoreView(groupID: groupID)
          }
      }
    • 21:09 - Simulated off-device purchase using StoreKitTest

      // Simulated off-device purchase using StoreKitTest
      import StoreKit
      import StoreKitTest
      
      func testSubscriptionRenewal() async throws {
          let session = try SKTestSession(configurationFileNamed: "Store")
      
          let oneYearInterval: TimeInterval = (365 * 24 * 60 * 60)
          let transaction = try await session.buyProduct(
              identifier: "birdpass.individual",
              options: [
                  .purchaseDate(Date.now - oneYearInterval)
              ]
          )
      
          // Inspect transaction
      }
    • 21:48 - Set a simulated purchase error when loading products

      // Set a simulated purchase error when loading products
      import StoreKit
      import StoreKitTest
      
      func testLoadProducts() async throws {
          let session = try SKTestSession(configurationFileNamed: "Store")
          let productIDs = [
              "acorns.individual",
              "nectar.cup"
          ]
      
          // Set a simulated error, then load products, expecting an error
          session.setSimulatedError(.generic(.networkError), forAPI: .loadProducts)
          do {
              _ = try await Product.products(for: productIDs)
              XCTFail("Expected a network error")
          }
          catch StoreKitError.networkError(_) {
              // Expected error thrown, continue...
          }
          // Disable simulated error
          session.setSimulatedError(nil, forAPI: .loadProducts)
      }
    • 22:24 - Set a faster subscription renewal rate in a test session

      // Set a faster subscription renewal rate in a test session
      import StoreKit
      import StoreKitTest
      
      func testSubscriptionRenewal() async throws {
          let session = try SKTestSession(configurationFileNamed: "Store")
      
          // Set renewals to expire every minute
          session.timeRate = .oneRenewalEveryMinute
      
          let transaction = try await session.buyProduct(identifier: "birdpass.individual")
      
          // Wait for renewals and inspect transactions
      }

Developer Footer

  • 비디오
  • WWDC23
  • StoreKit 2 및 Xcode 내 StoreKit Testing의 새로운 기능
  • 메뉴 열기 메뉴 닫기
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    메뉴 열기 메뉴 닫기
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    메뉴 열기 메뉴 닫기
    • 손쉬운 사용
    • 액세서리
    • 앱 확장 프로그램
    • App Store
    • 오디오 및 비디오(영문)
    • 증강 현실
    • 디자인
    • 배포
    • 교육
    • 서체(영문)
    • 게임
    • 건강 및 피트니스
    • 앱 내 구입
    • 현지화
    • 지도 및 위치
    • 머신 러닝
    • 오픈 소스(영문)
    • 보안
    • Safari 및 웹(영문)
    메뉴 열기 메뉴 닫기
    • 문서(영문)
    • 튜토리얼
    • 다운로드(영문)
    • 포럼(영문)
    • 비디오
    메뉴 열기 메뉴 닫기
    • 지원 문서
    • 문의하기
    • 버그 보고
    • 시스템 상태(영문)
    메뉴 열기 메뉴 닫기
    • Apple Developer
    • App Store Connect
    • 인증서, 식별자 및 프로파일(영문)
    • 피드백 지원
    메뉴 열기 메뉴 닫기
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(영문)
    • News Partner Program(영문)
    • Video Partner Program(영문)
    • Security Bounty Program(영문)
    • Security Research Device Program(영문)
    메뉴 열기 메뉴 닫기
    • Apple과의 만남
    • Apple Developer Center
    • App Store 어워드(영문)
    • Apple 디자인 어워드
    • Apple Developer Academy(영문)
    • WWDC
    Apple Developer 앱 받기
    Copyright © 2025 Apple Inc. 모든 권리 보유.
    약관 개인정보 처리방침 계약 및 지침