nyancoder

WWDC 2021 - Meet StoreKit 2 본문

WWDC/WWDC 2021

WWDC 2021 - Meet StoreKit 2

nyancoder 2021. 7. 24. 20:16

원본 영상: https://developer.apple.com/videos/play/wwdc2021/10114/

 

Meet StoreKit2

  • 이 세션은 StoreKit을 이용하여 클라이언트 코드를 구현하고, 인앱 구매를 위한 서버를 구축하고, 고객을 지원과 환불을 처리하는 세 가지 세션 중 첫 번째입니다.

  • StoreKit 2는 iOS, macOS, tvOS 및 watchOS에서 앱 내 구매를 위한 새 Swift API입니다.
  • async/await을 지원합니다.
  • 인앱 구매 거래를 더 쉽고 더 높은 보안 수준으로 제공합니다.
  • 구독을 위한 API를 더 추가하였습니다.
  • StoreKit 2 API는 기존의 StoreKit 프레임워크 내에 존재합니다.

  • StoreKit 2 API는 제품, 구매, 거래 정보, 거래 내역, 구독 상태에 대한 기능을 제공합니다.

 

Products and purchases

  • StoreKit 2 제품 구조는 기존 StoreKit 제품 객체가 강화된 버전입니다.
  • 제품 유형 및 구독 정보와 데이터가 추가되었습니다.
  • StoreKit 2에서는 구독 정보를 이용해 고객이 구독 제안을 받을 수 있는지를 쉽게 확인할 수 있습니다.
  • BackingValue라는 래핑 유형을 추가하여 최신 버전의 StoreKit에서도 이전 버전의 데이터에 접근할 수 있도록 하였습니다.

  • StoreKit 2에서는 정적 함수를 호출하여 제품을 요청하면, 기존 SKProductsRequest와 동일하게 App Store에서 제품 메타 데이터를 얻어옵니다.
  • async/await 패턴으로 제품 요청과 구매가 한 줄의 코드로 작성될 수 있습니다.
  • 구매는 이제 제품 객체의 함수이기 때문에, 방금 검색한 제품을 가져와서 직접 구매를 호출할 수 있습니다.
  • 구매는 구매 옵션을 통해 설정할 수 있습니다.

  • 구매 옵션은 구매의 수량 및 할인 등의 속성을 결정할 수 있습 옵션입니다.
  • 또한 어떤 사용자 계정 이 거래를 시작하고 완료했는지 추적할 수 있는 앱 계정 토큰이 추가되었습니다.

  • 앱 계정 토큰은 UUID 형식이기 때문에 사용자가 쉽게 생성할 수 있습니다.
  • 구매 옵션으로 구매 시 앱 계정 토큰을 보내면 이 토큰이 해당 구매에 대한 거래 정보에 포함됩니다.
  • 앱 계정 토큰은 모든 기기의 거래 정보에 영원히 유지됩니다.

 

Transaction Info

  • 구매가 처리되면 StoreKit 2는 모든 트랜잭션에 대해 개별적으로 서명된 객체를 제공합니다.
  • 웹에서 공통 표준으로 사용되는 JSON 웹 서명을 사용한 JSON형식으로 제공됩니다.
  • 서명된 객체에 포함된 모든 정보는 기본 StoreKit API를 통해 사용할 수 있기 때문에 쉽게 데이터를 이용해 작업할 수 있습니다.

  • Xcode 프로젝트에서 판매하려는 제품을 정의하는 StoreKit 구성 파일을 만들 수 있습니다.

  • 각각의 제품을 구분하기 위해서 제품 식별자가 포함된 plist도 있습니다.

  • StoreKit 2를 사용하면 Product 구조체의 request 정적 함수를 통해 쉽게 상품 정보들을 가져올 수 있습니다.
  • 제품 정보에 포함된 type이 App Store 서버에 정의된 type에 대한 속성을 제공하기 때문에 쉽게 구매 유형을 분류할 수 있습니다.
  • consumable은 한번 사용하면 없어지는 형태의 제품입니다.
  • nonConsumable은 한번 구입하면 영원히 소유하는 속성의 제품입니다.
  • autoRenewable은 가입 후 정기적으로 요금이 청구되며, 원할 때 업그레이드나 다운그레이드 할 수 있는 제품입니다.

  • 구매를 할 때에는 해당 제품 객체에서 purchase를 호출하면 새 동시성 기능을 통해 PurchaseResult를 반환해줍니다.
  • PurchaseResult를 통해 구매가 성공했는지, 취소되었는지, 구매를 위해 은행의 추가 확인 등의 별도 상태로 전환되었는지를 알 수 있습니다.
  • PurchaseResult가 성공 상태인 경우에 확인 상태를 받을 수 있습니다.
  • 이 예제에서는 checkVerified함수를 통해, 결과가 확인되지 않으면 자체 failedVerification 오류가 리턴하는 예입니다.
  • 사용자가 콘텐츠를 얻은 후에는 StoreKit의 트랜잭션을 완료해야 합니다.
  • purchase함수를 호출할 때, appAccountToken을 옵션에 전달하여 현재 로그인한 사용자에 대한 토큰을 전달할 수 있습니다.

  • 때때로 고객은 구매가 일어날 때 부모의 승인과 같은 추가적인 처리가 필요합니다.
  • 이러한 경우 product.purchase()의 결과는 보류 상태가 됩니다.
  • 이러한 트랜젝션을 처리하기 위해서는 이후에 StoreKit에서 발생하는 이벤트를 무한 비동기 시퀀스를 통해서 지속적으로 확인해야 합니다.
  • 여기서는 거래의 결과가 오면 이전의 처리와 마찬가지로 기존에 구현한 checkVerified를 통해 결과가 확인되었는지를 검증하고 updatePurchasedIdentifiers를 통해 UI를 업데이트하고 트랜젝션을 마칩니다.

  • 이제 결제 사이트에서 구매를 하면 권한을 요청하는 팝업이 표시됩니다.

  • 테스트를 진행하기 위해서는 하단의 Xcode의 버튼을 눌러 StoreKit 테스트의 트랜잭션 관리자를 열 수 있습니다.

  • 해단 거래를 선택하고 우측 상단의 승인 버튼을 클릭하면 이전에 만든 트랜젝션을 처리하는 함수가 수행되고 UI가 업데이트됩니다.

  • 이러한 예제 코드에서는 제품을 요청하고, 구매를 시작하고, 다양한 구매 결과에 반응하고, 거래의 무결성을 확인하고, 업데이트를 받는 것이 쉽게 처리되는 것을 확인할 수 있습니다.

 

Transaction history

  • 완료된 트랜잭션을 얻기 위한 새로운 API가 추가되었으며, 단일 호출로 사용자의 모든 과거 트랜잭션에 접근할 수 있습니다.
  • 또한 가장 최근 거래 정보만 얻어올 수 있습니다.
  • 현재 제품 정보에 대한 거래 정보 또한 얻어올 수 있습니다.

  • CurrentEntitlements 함수를 통해서 사용자의 거래 내역의 모든 비소모품과 현재 활성화된 모든 구독 거래를 얻어올 수 있습니다.
  • 취소된 항목은 포함되지 않으므로 사용자가 현재 구매하여 활성화된 모든 정보를 얻어올 수 있게 됩니다.
  • 소모품은 거래 내역의 영구적인 요소가 아니기 때문에 때문에 포함되지 않습니다.

  • StoreKit 2를 사용하면 사용자가 새 기기에 앱을 설치할 때 바로 내역을 얻어올 수 있게 됩니다.
  • 고객이 한 기기에서 구매하면 앱이 설치된 다른 모든 기기에서 구매내역을 확인할 수 있습니다.
  • 실제로 다른 기기에서 구매할 때 앱이 실행 중인 경우 실시간으로 새 거래에 대한 알림을 받게 됩니다.

  • 드물게 사용자가 구매를 했다고 생각하지만 표시되지 않는 경우 App Store 동기화 API를 사용하여 모든 StoreKit 2 트랜잭션을 즉시 재동 기화할 수 있습니다.
  • 이는 restoreCompletedTransactions API를 대체하며 사용자가 동기화를 시작할 수 있도록 하는 UI를 앱에서 제공해야 합니다.
  • 사용자가 수동 동기화를 시작해야 하는 경우 계정을 인증해야 하기 때문에, 사용자 입력에 대한 응답으로만 이 API를 사용해야 합니다.

  • StoreKit 2 API를 사용하여 이루어진 트랜잭션은 원래 StoreKit API에서 사용할 수 있으며 그 반대의 경우도 마찬가지입니다.
  • 앱에 기존 트랜잭션이 있는 경우 즉시 StoreKit 2 API에서 볼 수 있습니다.
  • 통합 영수증 내에서도 StoreKit 2로 구매한 것을 사용할 수 있습니다.

 

Subscription status

  • 구독 상태는 세 부분으로 구성되며, 첫 번째는 최신 거래이기 때문에 구독에 대해 발생한 마지막 트랜잭션에 쉽게 접근할 수 있습니다.
  • 두 번째는 갱신 상태이며, 이것은 구독의 현재 상태가 현재 구독 중인지, 만료되었는지, 유예 중이를 알려줍니다.
  • 구독 상태의 마지막 부분은 갱신 정보이며, 사용자의 구독에 대한 모든 세부 정보를 볼 수 있습니다.
  • 이 데이터는 트랜잭션 없이 변경될 수 있기 때문에 트랜잭션 정보에 없는 모든 종류의 정보를 포함합니다.
  • 구독 API 호출 시에는 사용자가 동일한 제품에 대해 여러 구독을 가질 수 있기 때문에 상태 배열을 반환합니다.

  • 구독 상태 정보는 사용자가 자동 ​​갱신을 켰는지 여부를 가지고 있습니다.
  • 또한 구독에 대해. 자동 갱신이 설정된 제품 ID도 확인할 수 있기 때문에 다운그레이드 한 경우 이 값을 통해 확인할 수 있습니다.
  • 구독이 이미 만료된 경우 갱신 정보를 사용하여 만료 이유를 확인할 수 있습니다.
  • 전체 정보에는 중요한 데이터가 포함되어 있기 때문에 JWS를 사용하여 서명됩니다.

  • isPurchased 함수에 Transaction.latest(for:)를 호출하도록 하여 가장 최근 거래정보를 받아올 수 있습니다.
  • StoreKit 메서드는 트랜잭션이 StoreKit 2의 확인 검사를 통과했음을 얻을 수 있는 결과를 반환하며, 이는 이전의 checkVerified 함수를 통해서 결과를 얻어올 수 있도록 합니다.
  • revocationDate의 nil여부를 확인하여 환불된 거래인지를 알 수 있으며, 기간 중간에 고객이 업그레이드한 구독은 isUpgraded 플래그가 true로 설정되므로 업그레이드된 트랜잭션을 무시해야 합니다.

  • 위의 예에서는 updateSubscriptionStatus함수를 통해서 StoreKit에서 구독 상태를 가져와 사용자에게 표시할 수 있습니다.
  • 여러 구독 정보를 가지고 있을 수 있기 때문에, 가진 구독 정보를 순회하면서 제공할 수 있는 가장 높은 등급의 서비스를 얻어옵니다.
  • 구동의 상태가 만료되거나 취소되었는지를 확인해야 합니다.

  • currentEntitlements를 호출하면 사용자의 유효한 거래를 들을 가져올 수 있습니다.
  • 결과 목록에서 확인된 목록만을 필터링할 수 있으며, 이후 갱신 가능하거나 비소모성 제품에 대해서만 필터링해서 표시할 수 있습니다.

 

Signature validation

  • JSON 웹 서명은 세 부분으로 구성되며 첫 번째는 전체의 메타데이터를 포함하는 헤더입니다.
  • 헤더에는 서명에 사용되는 알고리즘과 서명을 확인하는 데 사용되는 인증서의 위치 같은 중요한 정보가 포함됩니다.
  • StoreKit 2는 현재 Swift의 CryptoKit에서 기본적으로 지원되는 ECDSA 알고리즘을 사용합니다.
  • 인증서는 추가적인 인터넷 연결이 필요하지 않도록 전체 인증서 체인이 JWS 데이터에 포함되어 있음을 나타내는 x5c 헤더를 사용합니다.
  • 두 번째 부분은 페이로드이며, 거래 ID, 상품 ID, 구매 날짜 등의 주요 정보를 담고 있습니다.
  • 마지막 부분은 서명 정보이며 헤더와 페이로드를 모두 사용하여 생성됩니다.

  • JWS 데이터에서 서명의 유효성을 검사한 후에도 서명된 정보 페이로드에 있는 번들 ID가 앱의 번들 ID와 일치하는지 확인해야 합니다.
  • 보안을 강화하려면 API 호출에 의존하기보다 앱의 번들 ID를 앱 어딘가에 포함하고 해당 값을 사용하여 페이로드의 번들 ID와 비교하는 것이 좋습니다.

  • 그리고 장치 유효성 검사를 수행해야 합니다.
  • 첫 번째 값은 AppStore.deviceVerificationID에서 장치 식별자를 가져온 다음 이를 서명된 정보에서의 deviceVerificationNonce와 합하고, 이를 SHA384 해시를 수행해서 해시값을 구합니다.
  • 이를 두 번째 값인 deviceVerification과 비교하여 유효성 검사를 완료할 수 있습니다.

 

목차: https://nyancoder.tistory.com/2

 

Comments