1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[StoreKit] Consumable Product の Ask to Buy 対応

Last updated at Posted at 2023-03-09

TL;DR

StoreKit の Consumable Product が Ask to Buy で購入された場合に検知するには、Transaction.updates の中で Transaction.unfinishedを監視するようにする。

Transaction.updates {
    guard
        case .verified(let transaction) = verificationResult,
        transaction.revocationDate == nil
    else { return }

    for await verificationResult in Transaction.unfinished {

        switch transaction.productType {
        case .consumable:
            // アプリ内の情報を更新する
        default:
            break
        }

        await transaction.finish()
    }
}

背景

以前 StoreKit 2 でのアプリ内課金の基本 という記事を書いたのですが、 Transaction.currentEntitlements について

これで consumable の購入個数を更新できるかと思ったが、transaction が finish() していない consumable があっても currentEntitlements で取得できなかった。

という問題がありました。記事の中ではワークアラウンドコードを仕込んだのですが、それだと Ask to Buy 機能を使った時に consumable product を購入できたことが検知できませんでした。

この問題について Apple Developer Forums で問い合わせていたのですが、回答が得られたので記事として残しておきます。

解決策

当初は Transaction.currentEntitlements でトランザクションが終了していない consumable product を取得しようとしていました(当時ドキュメントがそうなっていたので)
現在のTransaction.currentEntitlements のドキュメント を見ると、以下の情報が取得できると書いてあります。

  • それぞれの non-consumable product のトランザクション
  • 購読中かグレースピリオドの auto-renewable subscription の最新のトランザクション
  • 終了後も含めた non-renewing subscription の最新のトランザクション

そして、consumable product に関して以下の記載もありました。

To get transactions for unfinished consumables, use the unfinished or all sequences in Transaction.

なので、consumable product の終了していないトランザクションを取得するには、Transaction.unfinishedTransaction.all を使えば良さそうです。

  • Transaction.unfinishedfinish() が呼ばれていないトランザクションを取得できます。

  • Transaction.all は今までのトランザクションの履歴を取得でき、 finish() が呼ばれていない consumable product のトランザクションも含みます。しかし、以下のトランザクションは含まないようです:

    • 終了した consumable product, non-renewing subscription
    • 再購入された non-consumable product, auto-renewing subscription, non-renewing subscription
    • 購入の復元

今回は、フォーラムの回答でも提案されていたので、Transaction.unfinished を使うことにしました。

Transaction.updates {
    guard
        case .verified(let transaction) = verificationResult,
        transaction.revocationDate == nil
    else { return }

    for await verificationResult in Transaction.unfinished {

        switch transaction.productType {
        case .consumable:
            // アプリ内の情報を更新する
        default:
            break
        }

        await transaction.finish()
    }
}

Xcode で Ask to Buy を試すと、購入の承認後に無事アプリ内で購入処理のハンドリングができました:tada:

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?