メインコンテンツまでスキップ

以前の AppCoins SDK バージョンからの更新

このガイドでは、以前のバージョンの AppCoins iOS SDK から現行バージョンへ更新する方法を説明します。新バージョンは StoreKit 2 の公開インターフェースに合わせて設計されており、そのためにいくつかのプロパティ名の変更、Purchase 型から Transaction への置き換え、および PurchaseIntent / Purchase.updates フローの完全な削除が必要となりました。

概要

現行 SDK バージョンにおける主な変更点は次のとおりです。

  • Purchase から Transaction への名称変更Purchase.allPurchase.unfinishedPurchase.latest は、それぞれ Transaction.allTransaction.unfinishedTransaction.latest(for:) になりました。
  • PurchaseIntentPurchase.updates の削除 — 旧来の Purchase.updates は、明示的な確認を必要とする PurchaseIntent オブジェクトを発行していました。購入結果は product.purchase() から VerificationResult<Transaction> として直接返されるようになりました。
  • Product のプロパティ名の変更skuidtitledisplayNamepriceLabeldisplayPrice
  • Product.products(domain:for:) の簡素化domain パラメータが削除されました。SDK がバンドル識別子を自動的に読み取ります。
  • 購入エラーが throw されるように変更.failed(let error) の結果ケースを、product.purchase() を囲む do/catch に置き換えてください。
  • transaction.finish() が throw しなくなったtry キーワードを削除してください。

互換性のない変更の一覧

旧 API新 API
product.skuproduct.id
product.titleproduct.displayName
product.priceLabelproduct.displayPrice
product.priceValueproduct.displayPrice(整形済み)または product.priceDecimal
Product.products(domain:for:)Product.products(for:) — domain は削除
PurchaseResult.failed(let error)throws AppCoinsSDKErrordo/catch を使用
try await purchase.finish()await transaction.finish() — throw しなくなりました
Purchase.unfinished()(async、throws)Transaction.unfinishedAsyncStream、throw なし
Purchase.all()(async、throws)Transaction.allAsyncStream
Purchase.latest(sku:)Transaction.latest(for: productID:)
Purchase.updatesPurchaseIntent のストリーム)削除 — product.purchase() の戻り値を使用
PurchaseIntent.confirm()削除
PurchaseIntent.reject()削除

Xcode の設定

Xcode のターゲットで次の設定が行われていることを確認してください。これらは SDK の動作に必須です。

  1. Keychain Sharing

    1. Project Navigator(左サイドバー)でプロジェクトを選択します。
    2. TARGETS でターゲットを選択します。
    3. Signing & Capabilities タブを開きます。
    4. + ボタンをクリックして新しい機能を追加します。
    5. Keychain Sharing を検索して選択します。
    6. Keychain Groups フィールドで、既定値を com.aptoide.appcoins-wallet に正確に置き換えます。
  2. URL スキーム

    1. TARGETS でターゲットを選択します。
    2. Info タブに移動します。
    3. URL Types セクションを展開し、+ をクリックします。
    4. URL Schemes$(PRODUCT_BUNDLE_IDENTIFIER).iapRoleEditor に設定します。
  3. MKSellsDigitalGoods

    1. Info タブで Custom iOS Target Properties セクションまでスクロールし、+ をクリックします。
    2. キー MKSellsDigitalGoods を追加し、値を YES(Boolean)に設定します。

1. 購入フローの更新

変更前:

let result = await product.purchase()

switch result {
case .success(let verificationResult):
switch verificationResult {
case .verified(let purchase):
try await purchase.finish()
case .unverified(let purchase, let error):
print("Unverified: \(error)")
}
case .pending:
break
case .userCancelled:
break
case .failed(let error):
print("Purchase failed: \(error)")
}

変更後:

do {
let result = try await product.purchase()

switch result {
case .success(let verificationResult):
switch verificationResult {
case .verified(let transaction):
await transaction.finish()
case .unverified(let transaction, let error):
print("Unverified: \(error)")
}
case .pending:
break
case .userCancelled:
break
}
} catch let error as AppCoinsSDKError {
print("Purchase failed: \(error)")
}

相違点は次の 2 点です。

  1. product.purchase()try await product.purchase() になりました。この呼び出しは throw する可能性があります。
  2. try await purchase.finish()await transaction.finish() になりました。この呼び出しは throw しなくなりました。

2. 未完了トランザクションの更新

変更前:

func processUnfinished() async {
do {
let purchases = try await Purchase.unfinished()
for purchase in purchases {
giveItem(for: purchase.sku)
try await purchase.finish()
}
} catch {
print("Error loading unfinished: \(error)")
}
}

変更後:

func processUnfinished() async {
if await AppcSDK.isAvailable() {
for await verificationResult in Transaction.unfinished {
if case .verified(let transaction) = verificationResult {
giveItem(for: transaction.productID)
await transaction.finish()
}
}
}
}

Transaction.unfinishedAsyncStream です。for await で反復処理してください。try は不要で、別途ループするためのラッパー配列もありません。

⚠️
これはアプリ起動のたびに呼び出してください。以前のセッションで支払ったユーザーは、そのトランザクションが完了するまでアイテムを受け取れません。購入は、消費されない場合 24 時間後に自動的に返金されます。

3. Transaction.allTransaction.latest の更新

変更前:

let purchases = try await Purchase.all()
let latest = try await Purchase.latest(sku: "gas")

変更後:

// Iterate all transactions
for await verificationResult in Transaction.all {
if case .verified(let transaction) = verificationResult {
// handle transaction
}
}

// Get the latest transaction for a product
if let verificationResult = await Transaction.latest(for: "gas") {
if case .verified(let transaction) = verificationResult {
// handle transaction
}
}

4. PurchaseIntent の処理を削除する

旧 SDK では、Purchase.updates が、明示的な確認または拒否を必要とする PurchaseIntent オブジェクトのストリームとして公開されていました。Purchase.updates を監視するコードはすべて削除してください。代替となるストリームはありません。購入結果は product.purchase() から直接返されます。

変更前:

for await intent in Purchase.updates {
if User.isSignedIn {
let result = await intent.confirm()
// handle result
}
}

変更後: この監視処理を完全に削除します。product.purchase() を呼び出す箇所で結果を処理してください。

let result = try await product.purchase()
switch result {
case .success(let verificationResult):
if case .verified(let transaction) = verificationResult {
giveItem(for: transaction.productID)
await transaction.finish()
}
case .pending, .userCancelled:
break
}

ユーザーが認証されるまで確認を遅らせる実装にしていた場合は、保留中の商品を保存しておき、ユーザーのログイン後に product.purchase() を呼び出してください。

5. エラー処理の変更

変更前:

switch result {
case .failed(let error):
switch error {
case .networkError:
showNetworkAlert()
case .purchaseNotAllowed:
showNotAllowedAlert()
default:
showGenericAlert()
}
// ...
}

変更後:

do {
let result = try await product.purchase()
// handle result
} catch let error as AppCoinsSDKError {
switch error {
case .networkError:
showNetworkAlert()
case .purchaseNotAllowed:
showNotAllowedAlert()
case .productUnavailable:
showUnavailableAlert()
case .notEntitled:
showEntitlementAlert()
case .systemError:
showSystemErrorAlert()
case .unknown:
showGenericAlert()
}
}

AppCoinsSDKError のケースはすべて変更ありません。変わったのは、結果のケースとして受け取るか、スローされたエラーとして受け取るかという受け取り方だけです。