🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

App Store

App Storeは、Apple社が運営する、iPhone、iPod touch、iPad向けアプリケーションソフトのダウンロードサービスです。携帯電話、Wi-Fiによる無線通信に対応しており、多くのアプリケーションをダウンロード、インストールすることができます。世界中の開発者によってアプリケーションが登録されており、有償のソフトもあればフリーソフトも多く登録されています。

Q&A

解決済

1回答

2769閲覧

iOS アプリの定期購入型課金機能の実装についてです

Hayato1201

総合スコア231

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

App Store

App Storeは、Apple社が運営する、iPhone、iPod touch、iPad向けアプリケーションソフトのダウンロードサービスです。携帯電話、Wi-Fiによる無線通信に対応しており、多くのアプリケーションをダウンロード、インストールすることができます。世界中の開発者によってアプリケーションが登録されており、有償のソフトもあればフリーソフトも多く登録されています。

1グッド

1クリップ

投稿2021/01/17 04:55

編集2021/01/20 13:17

現在 SwiftyStoreKit を使ってサブスクリプション型の App 内課金を実装しています。その過程でいくつか分からないことがあるのですが、

こちら のサイトなどで AppDelegate 内で起動時にトランザクションの監視を行っていますが、purchase.transaction.transactionState の値によって購入済みかどうか分かるという認識で正しいでしょうか?また、その場合サブスクの期間が切れていたら purchased や restored といった値は返ってこないという事でしょうか?

また SwiftyStoreKit.verifySubscription でサブスクリプションの状況が確認できる様ですが、SwiftyStoreKit.completeTransactions でサブスクの状況が確認できるのであればこちらの verifySubscription は必要ない気もするのでやはり completeTransactions の purchased や restored では現在のサブスクの状況は分からないという事なのでしょうか?

② 課金済みか、サブスク期間が切れていないかのチェックはアプリ起動時に AppDelegate で verifySubscription を行い UserDefault などのフラグを更新してアプリ内ではそのフラグを元に機能の出しわけをする様な作りにしようと思っているのですが通常サブスクモデルの課金機能はこの様な流れで問題ないのでしょうか?

③ SwiftyStoreKit.restorePurchases でリストアができる様ですが、こちらでリストアした場合、例えば一ヶ月プランで半月後にリストアした、という様な時には正しくさらに半月後にverifySubscription で expired とされるのでしょうか?

3つ質問を出してしまいましたが、どれか1つでも結構ですのでご存知の方いらっしゃいましたらご教授ください。

------- 追記 -----------

下記 verifySubscription を行うメソッドを追記しました。

Swift

1func verifyPurchase (with PRODUCT_ID:String) { 2 3 let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: "sharedSecret" ) 4 SwiftyStoreKit.verifyReceipt(using: appleValidator) {(result) in 5 6 switch result { 7 8 case .success(let receipt): 9 10 //自動更新 11 let purchaseResult = SwiftyStoreKit.verifySubscription(ofType: .autoRenewable, productId: PRODUCT_ID, inReceipt: receipt) 12 13 switch purchaseResult { 14 15 case .purchased: 16 UserDefaults.standard.set(1, forKey: PRODUCT_ID) 17 18 case .notPurchased: 19 break 20 21 case .expired( _, _): 22 UserDefaults.standard.set(nil, forKey: PRODUCT_ID) 23 } 24 25 case .error(let error): 26 print (error) 27 28 } 29 30 31 } 32} 33
tis👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

①. purchase.transaction.transactionStateは購入(purchaseProductもしくは、retrieveProductsInfo)から、
購入が完了または、失敗するまでの状態を把握するために使用します。
あとは、購読が更新された時も呼び出され、purchasedを通ります。
今購読中か、否かを確認したい時は、おっしゃる通りverifySubscription を使用します。

②. その場合の懸念点としては、リアルタイム購読状態が更新されないことですかね。
例えば、アプリを立ち上げてすぐに日付が変わって有効期限が切れた場合、しばらくは課金状態として使えてしまいますね。

フラグではなくて、有効期限をUserDefaultに保存しておいて、有効期限が過去だったら、verifySubscriptionを実行するのはどうでしょうか?

通常は、サーバーサイドでレシートの解析を行うことが多いと思いますが、
アプリ内でやるにしてもverifySubscriptionは、AppDelegateではなくて、
購読中かどうかを知りたいときに実行します。

③. その理解で良いと思います。
リストアは通常、機種変更やアプリの再インストール時をしたときに、
レシート情報を復元したいときに使用します。

sandbox環境や、Xcode12から追加されたStoreKit Testingで、
アプリ内課金の動作確認をしてみるのが一番理解につながるとおもいます。

投稿2021/01/19 14:25

ichi888

総合スコア81

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Hayato1201

2021/01/19 14:56

詳しいご回答ありがとうございます!! ①に関してですが、上記の記事などではアプリ起動時にトランザクションをこれによって監視する事を推奨していますがこれはなぜでしょうか?アプリ起動した瞬間に購入処理が動く事って基本ない気がするのですが、、、
Hayato1201

2021/01/19 15:23

度々すみません、また1つ思ったのですが、App内課金はAppleIDに紐づいていると思ったのですが、sandbox のアカウントをサインアウトしてもverifySubscriptionで値をとってきていました。これはなぜでしょう?もし仮にAppleIDに紐づいていなかったら他のIDでログインしても購入状態が引き継がれてしまうと思うのですがそういうものなのでしょうか?
ichi888

2021/01/19 15:41 編集

1. > 上記の記事などではアプリ起動時にトランザクションをこれによって監視する事を推奨していますがこれはなぜでしょうか? 翌月になってレシートが更新されたタイミングでその更新をアプリが検知する必要があるので、 アプリが起動している最中は常に監視しているべきかと思います。 2. > App内課金はAppleIDに紐づいていると思ったのですが、 AppleIDに紐づいているはずです。 > verifySubscriptionで値をとってきていました 値とは具体的にどういうことでしょう? 例えば、有効期限も未来のままでしょうか?
Hayato1201

2021/01/20 13:30

繰り返しのご返信誠にありがとうございます!!! >翌月になってレシートが更新されたタイミングでその更新をアプリが検知する 購読が更新された時も呼び出され、purchasedを通るとのことなのでレシートが更新され、そこで購読が切れたらtransactionStateがfailedになるということでしょうか?例えば購読状態かどうかをUserDefaultにフラグとして持っていた場合はレシートの更新タイミングでtransactionStateがfailedになったらそれをfalseにするといった対応をすべきという認識でよろしいですか?? また2に関してですが、verifySubscription部分の実装を追記しました。 事象としては、sandboxのアカウントで購入後、そのアカウントをサインアウトして、別のアカウントでサインインしました。そのアカウントでアプリを起動してverifySubscriptionのpurchaseResultは.purchasedとなっていました。このことからAppleIDに紐づいていないのかな?と思ったのですがどうなのでしょうか。。。?
Hayato1201

2021/01/20 13:39

五月雨式で申し訳ありませんが、 sandboxで課金をしたアカウントをサインアウトしてサブスクが切れるまで放置したところverifySubscriptionはしっかり.expiredだと判断していました。そもそもiPhoneの設定のiTunesStoreとAppStoreからSANDBOXアカウントをサインアウトしましたが、それは実際のサインアウトと違うという仕様なのでしょうか??
ichi888

2021/01/20 14:09

> 購読が更新された時も呼び出され、purchasedを通るとのことなのでレシートが更新され、そこで購読が切れたらtransactionStateがfailedになるということでしょうか? failedは確か通らないはずです。有効期限が切れた場合はtransactionStateが呼ばれないはずです。 sandboxで検証できないでしょうか? ブレークポイントfailedの箇所にを貼って検証するのが良いかと思います。 UserDefaultでフラグで持つと、有効期限が切れたかどうかがわからないので、 上述したように、verifySubscriptionをお実行して取得できるexpiredDate(添付されたリンクのブログのなかでこの変数名を使用していました。)を保存して、 日付が過去だったら、課金していないと考えるのが良いと思います。 > そもそもiPhoneの設定のiTunesStoreとAppStoreからSANDBOXアカウントをサインアウトしましたが、それは実際のサインアウトと違うという仕様なのでしょうか?? 自分の記憶では、更新されたきがしたのですが。。そこはよくわからないです。 ただ、通常はAppleIDを変更したら、今インストールされているアプリ事態が消える(AppleIDに紐づくため)ので、あまり意識しなくて良いのではないでしょうか?
Hayato1201

2021/01/20 14:47

何度も丁寧に返信していただきとても助かります。ありがとうございます! >通常はAppleIDを変更したら、今インストールされているアプリ事態が消える なるほどそうだったんですね、じゃあ問題無さそうです! すみません最後にもう1つ気になった事があったのですが、restorePurchasesでのリストア時に期限が切れているものもresults.restoredPurchasesとして取得している様なのですが、リンク先と同じ様に実装した場合、期限切れでも一度でも購入していればリストアできてしまう様です。そのためそれぞれのpurchase.productIdで再度verifySubscriptionをする必要があると思うのですが、それは仕方ないのでしょうか?そもそもresults.restoredPurchasesとなるものは期限内のものだけにはならないのでしょうか?
ichi888

2021/01/20 15:17 編集

そうですね。そもそもレシート情報を復元する機能になるので、今まで購入した期間分 (1か月更新で6ヶ月購読したら、6回) transactionStateのrestoredを通るのではないでしょうか。 それはStoreKitの仕様なので、しょうがないですね。 復元が完了した後に、verifySubscriptionをする必要があります。
Hayato1201

2021/01/20 15:33

繰り返しのフォロー大変ありがとうございました!! ベストアンサーとさせていただきます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問