[WWDC2024]StoreKitとアプリ回課金の新機能
この記事は集まれSwift好き!Swift愛好会スピンオフ WWDC24セッション要約会 @ DeNAでの発表資料です
今回対象とするWWDC2024のセッションはWhat’s new in StoreKit and In-App Purchaseです
今回のセッションでも言及されている以前のWWDCでのStoreKitについてのセッションは以前の要約回でまとめています
今回WWDC2024のWhat’s new in StoreKit and In-App Purchaseのセッションは以下のセクションで構成されています
今回はセクションごとにそのサマリーをまとめます
Core API enhancements
- Info.plistの設定を変更することで、使用済みのconsumableな課金アイテムのtransactionも取得できるようになった
- SKIncludeConsumableInAppPurchaseHistoryをtrueに設定する
- App Store Server APIでも利用可能
- 色々新しいFieldが追加
- Transaction
- currency: 購入時の通貨
- currencyCodeがdeprecatedになりました
- price: AppStoreConnectで設定された金額
- currency: 購入時の通貨
- RenewalInfo
- currency: Locale.Currency型
- renewalPrice: Decimal型
- Transaction
- Xcode16でビルドしたアプリから利用が可能で、iOS15~のアプリから利用可能
- Win-back offersというAppStoreで新しくアプリの課金機能について訴求する仕組みが登場
- 詳しくはImplement App Store Offersのセッションを参照
Merchandise using SwiftUI
このセクションではWWDC2023で追加されたSwiftUIでの標準コンポーネントを使った課金画面(StoreKit views)の追加機能について説明されています
今回はStreaming Passというデモアプリを使って、月払い/年払いとBasic/Premiumのサブスクプランの4つ組み合わせのある課金体系のある課金画面の実装サンプルを紹介しています
グループごとに課金メニューをまとめる
既存のSubscriptionStoreViewで表示する課金アイテムをグループごとにまとめる機能として、SubscriptionOptionGroupSetが追加されました
以下のサンプルコードの場合、basic / premiumプランごとに自動でタブごとに分けられ、かつそれぞれに合ったタブ名とアピール用のコンテンツのUI(marketingContent)を表示するUIです
プランのカテゴリを表示するタブやプランの選択UIは、subscriptionStoreControlStyle modifierで調整することができます
このサンプルコードの場合は省スペースのcompactPickerかつbottomに表示するようにしています
選択できる表示方法については、プラットフォームにより異なります(セッション動画の紹介箇所)
また表示形式については、タブ以外にもsubscriptionStoreOptionGroupStyleのmodifierを使い、.linksを指定することで、タップすると表示UIを切り替えるように変更することもできます
import StoreKit
import SwiftUI
struct DestinationVideoShop: View {
var body: some View {
SubscriptionStoreView(groupID: Self.subscriptionGroupID) {
SubscriptionOptionGroupSet { product in
StreamingPassLevel(product) // Group by streaming pass level, e.g basic / premium
} label: { streamingPassLevel in
Text(streamingPassLevel.localizedTitle)
} marketingContent: { streamingPassLevel in
StreamingPassMarketingContent(level: streamingPassLevel)
StreamingPassFeatures(level: streamingPassLevel)
}
}
.subscriptionStoreControlStyle(.compactPicker, placement: .bottomBar)
}
}
Styleを自作する
この表示スタイルは自作することができます
既存のButtonStyleなど同様、SubscriptionStoreControlStyleを継承した自作のスタイルを実装すれば、カスタムUIを自作することも可能です
自作したスタイルは、subscriptionStoreControlStyleのmodifierで反映できます
import StoreKit
import SwiftUI
struct BadgedPickerControlStyle: SubscriptionStoreControlStyle {
func makeBody(configuration: Configuration) -> some View {
SubscriptionPicker(configuration) { pickerOption in
HStack(alignment: .top) {
VStack(alignment: .leading) {
Text(pickerOption.displayName)
.font(title2.bold())
Text(priceDisplay(for: pickerOption))
if pickerOption.isFamilyShareable {
FamilyShareableBadge()
}
Text(pickerOption.description)
}
Spacer()
SelectionIndicator(pickerOption.isSelected)
}
} confirmation: { option in
SubscribeButton(option)
}
}
}
struct DestinationVideoShop: View {
var body: some View {
SubscriptionStoreView(groupID: Self.subscriptionGroupID) {
SubscriptionPeriodGroupSet { _ in
StreamingPassMarketingContent()
}
}
.subscriptionStoreControlStyle(BadgedPickerControlStyle())
}
}
Test in Xcode
- StoreKit Configurationファイルから、以下の設定が追加可能になった
- App Policiesタブ
- Privacy Policy
- License Agreement(Terms of Service)
- Win-back offers
- ProductViewやStoreViewなどの画像
- 初期化時にprefersPromotionalIconをtrueに設定
- In-App Purchaseに関連したシステムのダイアログ表示時のオプション選択をコントールする設定
- disabledにしておくと、システムダイアログが表示された際に事前に設定した選択オプションで自動で処理が進められる
- UIテストなどで活用できる
- App Policiesタブ
- Transaction Manager(セッション動画の紹介箇所)
- Intent Purchaseの表示確認について、AppStoreなしにTransaction Managerから表示確認ができるようになった
- サブスクリプションの課金継続時に問題が生じた時のエラー内容を解決するためのsheetの表示確認ができるようになった
- 合わせて、StoreKit ConfigurationファイルのConfiguration Settings > Purchase Options > Billing RetryをEnabledに変更する設定変更も必要
Update to StoreKit 2
StoreKit1はiOS18~(今年リリースの新OSから)deprecatedになることが発表されました
しばらくは機能するが、今後のアップデートは発生しないとのことです
まだStoreKit1を利用している場合、StoreKit2へのリプレイスを進める必要があります
まとめ
去年に比べるとアップデートのボリュームやインパクトは小さいように感じたが、確実に課金機能やUIの実装の負担は少なくなってきている
また一部の実装は今年の最新のiOS18以前からも利用できるようになっているのもありがたい
またこのセッションでの一番重要な情報は一番最後のOriginalのStoreKitがdeprecatedになることかと思います
特に古いアプリやサービスの場合、StoreKit1で実装していて、かつ重要な課金機能のStoreKit2へのリプレイスはリスクがあり、なかなか着手できていないというサービスは多いと思います
StoreKit2の場合は、Swift Concurrencyベースで、StoreKit1に比べると仕組みや登場人物もシンプルで、かつテストの仕方も非常に豊富なので、早めにリプレイスするのがよさそうかなと思います
(ただ本当に古いサービスだと、Swift ConcurrencyベースのStoreKit2を導入するのも大変な場合もあるかもしれません…)