iOSアプリ内課金の開発におけるテストパターンについてまとめました。

はじめに

 

こんにちは!

 

私は2021年4月からEMoshUに入社致しました。新人エンジニアのしゅんたです。

 

現在、研修にて、消耗型のiOS課金アプリの実装に奮闘しており、課金機能を実装するために、様々な調査や実装テストを行いました。

 

その中で、iOS課金の実装方法の解説はインターネット上にたくさんありますが、どんなテスト検証を行ったのかを紹介したサイトはあまり見かけません。

 

そこで、エンジニアブログ第3弾では、iOSアプリ内課金の開発におけるテストパターンについて書かせていただきます。

 

是非、最後までご覧ください!

 

 

 

取り挙げる内容

  • iOSアプリ内課金の概要
  • テスト環境について
  • テストパターン
  • まとめ

 

 

 

 

 

iOSアプリ内課金の概要

 

まずは、課金の種類を見ていきましょう。

 

種類 詳細
消耗型 一度使うとなくなる ゲーム内で使用する、宝石や投げ銭
非消耗型 一度の購入で無制限に利用可能 広告非表示
自動サブスクリプション ユーザーが解約するまで利用可能 月額サービス
非更新サブスクリプション 一定期間、無制限に利用可能 ストリーミングコンテンツ

 

 

主にアプリ内課金には4つの種類が存在します。

 

今回、開発したアプリは消耗型を採用したため、本稿は消耗型課金についてフォーカスした内容となっています。

 

 

 

StoreKitについて

StoreKitは、アプリ内課金におけるAppStoreとのやり取りをサポートするフレームワークです。

アプリ内課金を実装する際、StoreKitを使用し課金処理を行います。

 

 

実装に必要となる主なクラスを一部ご紹介します。

 

 

SKProductsRequest

課金アイテムの情報をリクエストし、ユーザーが実際に課金できるプロダクトをAppStoreから取得します。

 

 

 

SKPaymentQueue

AppStoreと通信し、ユーザーが課金処理を行うためのインターフェースを表示します。

 

 

 

SKPaymentTransaction

現在のトランザクションの状態を表すクラスです。

 

 

 

SKPaymentTransactionObserver

処理されたトランザクションの結果を受け取るクラスです。

 

 

 

 

 

 

テスト環境について

 

課金機能を実装するにあたって、2種類のテスト環境で動作確認を実施しました。

 

 

 

ローカルテスト

 

まず、課金機能を実装したあとは、ローカルテストを行いました。

XcodeのConfiguration.storekitを使用すれば、ローカル環境で課金機能の動作確認が簡単にできます。

 

 

 

ローカルテストでできること

 

Appleの公式サイトによると以下の項目が挙げられています。

 

  • 開発の初期段階、またはAppStoreConnectでアプリ内課金を構成する前のテスト
  • ネットワーク接続が利用できない場合のローカルテスト
  • Sandbox環境で設定が難しい、アプリ内課金のデバッグ(プロモーション特典の利用資格など)
  • 支払いシートにローカライズされた製品情報の表示
  • 失敗したトランザクションを含め、様々なトランザクションのテスト
  • StoreKitテストの自動化

 

 

開発初期段階で、動作確認ができるのはとても便利な機能でした。

今後、課金の実装をする時は、積極的に採用していきたいですね。

 

 

 

Sandbox環境

 

デバイス上のStoreKitと、AppStoreConnectから実際のプロダクト情報を使ってアプリ内課金の動作確認ができます。

先ほどのローカルテストと比べ、より本番に近い状態で動作確認することができます。

 

詳しく知りたい方はAppleの公式サイトに詳細が掲載されていますので、チェックしてみてください。

 

 

 

 

 

 

テストパターン

 

では、ここからは実際に行ったテストパターンについて触れていきます。

 

 

そもそも、なぜテストする必要があるのか?

 

例えば、ユーザーが課金ボタンを押した後、通信エラーで課金処理が中断したときのことを考えてみてください。

 

ユーザーは課金ができているか不安になってしまって、課金ボタンをもう一度押してしまい、重複して課金処理をしてしまうかもしれません。

 

そうなっては、大変ですよね...

 

そうならないためにも、失敗の可能性を考慮した実装にすると同時に、その実装が正常に動くかをテストする必要があります。

 

少しわかりにくいと思いますので、想定される課金処理のパターンを見ていきましょう。

 

 

 

課金処理では、A〜Iのようなパターン(アクティビティ)が想定されます。

 

 

A:アイテムが無効だった場合
 

 

B:設定で課金機能が無効であった場合
 

 

C:課金の処理中だった場合
 

 

D:中断された課金処理がある場合
 

 

E:ネットワークの接続がない場合
 

 

F:課金処理を途中でキャンセルした場合

 

 

G:課金が完了して、アプリ固有の処理がエラーになった場合

 

 

H:課金処理が終了した場合

 

 

 I:アプリ起動時に中断されたトランザクションがある場合
 


それぞれの流れをまとめると、以下のようなアクティビティ図になります。

なお、以下のアクティビティ図では課金アイテムの取得件数および同時に課金できるアイテムは1件を想定しています。

アクティビティ図 .png

アクティビティ図2.png

 

 

 

簡単な流れを説明しますと、まず課金アイテム取得のための識別子をAppStoreに問い合わせて、課金アイテムの取得を行います。

 

その後、取得したアイテム情報をもとに、AppStoreとやりとりしながら課金処理を行っています。

 

 

それでは、実際にテストした内容について、深堀していきます。

 

以下の内容はSandbox環境でテストしています。

 

 

 

 

1. 課金処理が終了した場合

アクティビティ図でいうと"H"のパターンになります。

こちらのテストが一番わかりやすいですかね。

 

今回、開発したアプリでは課金処理が成功した場合は、アプリ固有の処理として、課金が完了したことを示すダイアログを表示させています。

課金ボタンを押して課金処理が正常に完了することと、ダイアログが表示されるかのテストを行いました。

 

H.png

 

 

 

2. 課金処理を途中でキャンセルした場合

アクティビティ図でいうと"F"のパターンになります。

 

今回、開発したアプリでは課金処理が失敗した場合もアプリ固有の処理として、ユーザーに課金がキャンセルされたことを示すダイアログを表示させています。

課金処理がキャンセルされた時に、正常に課金処理が終了することと、ダイアログが表示されるのかのテストを行いました。

 

F,E.png

 

 

 

3. アイテムが無効だった場合

アクティビティ図でいうと"A"のパターンになります。

 

課金アイテムが無効だった場合もテストが必要です。

AppStoreConnectの課金アイテムの設定で、一時的に配信を止めることができるので、その状態で動かしてみてエラー処理が正常に実行されるのかのテストをしました。

 

A.png

 

 

 

4. 設定で課金機能が無効であった場合

アクティビティ図でいうと"B"のパターンになります。

 

今回、開発したアプリでは、ユーザーが課金ボタンを押した時に、iPhoneの設定で課金機能が無効な場合は、ユーザーにそのことを伝えるダイアログを表示させています。

実際に、iPhoneの設定でアプリ内課金を無効し、ダイアログが表示されるのかのテストをしました。

 

B.C.png

 

 

 

5. 課金の処理中だった場合

アクティビティ図でいうと"C"のパターンになります。

 

場合によっては、ユーザーが課金ボタンを何度も押してしまう可能性があります。

その場合でも、重複して課金しないような処理にする必要があるのと同時に、ユーザーが連続で課金ボタンを押した場合は、"課金の処理中です"というようなダイアログを表示させるとユーザーにとってわかりやすい設計になると思います。

 

実際に課金ボタンを連続で押した場合、二回目以降の課金処理が進行しないことと、ダイアログが表示されるのかのテストをしました。

 

B.C.png

 

 

 

6. 中断された課金処理がある場合

アクティビティ図でいうと"D"のパターンになります。

 

中断された課金処理というのは、課金が完了して、アプリ固有の処理中にエラー(アクティビティ図"G")となりfinishTransactionが実行されなかったときの状態を指します。

その状態で、再度課金ボタンを押した場合は、重複して課金処理が実行されずに、中断された課金処理が正常に終了する必要があります。

 

実際にテストするときは、1度目の課金処理が完了した後、finishTransactionだけ呼ばれないような処理にします。

その処理を実行後、2度目の課金ボタンを押した時、重複して課金処理が実行されないことと、中断されていた課金処理が正常に終了するかどうかのテストをしました。

 

D.png

 

 

 

7. ネットワークの接続がない場合

アクティビティ図でいうと"E"のパターンになります。

 

ユーザーが課金ボタンを押した時に、ネットワークの接続がない場合は、課金処理をキャンセルさせ、ネットワークの接続がないことを示すダイアログを表示させる実装になっている必要があります。

 

実際にテストするときは、iPhoneを機内モードに設定してテストすると簡単に検証でき、ネットワークの接続がない場合は、課金処理がキャンセルし、ダイアログが表示されるかのテストをしました。

 

F,E.png

 

 

 

8. アプリ起動時に中断されたトランザクションがある場合

アクティビティ図でいうと"I"のパターンになります。

 

課金が完了して、アプリ固有の処理がエラー(アクティビティ図"G")となりfinishTransactionが実行されなかった、かつ、その後アプリを終了させた場合、アプリを再起動すると中断されたトランザクションの処理を検知し、再度課金処理が実行されるように実装する必要があります。

 

実際にテストするときは、課金ボタンを押し課金処理を実行している状態で、finishTransactionが呼ばれる前にアプリを終了させます。

その後、再度アプリ起動後に、中断されたトランザクションの処理を検知し、正常に課金処理が終了するかどうかのテストをしました。

 

アクティビティ図2.png

 

 

 

 

 

まとめ

 

今回は、iOSアプリ内課金の開発におけるテストパターンについて共有させていただきました。

 

もし、課金機能にバグがあったら、それだけで売上の機会損失になりますし、

 

アプリの規模が大きくなればなるほど、ユーザーに多大なる迷惑をかけてしまいます。

 

以上のことを踏まえて、特に課金周りの実装は、責任感を持って開発しなければならないということを学ぶことができました。

 

そのため、テストパターンを理解しておくことで、バグを未然に防いだり、ユーザーにとって優しい設計になると思ったので、今回、記事にさせていただきました。

 

また、この課金アプリの実装は、入社して初めて開発した成果物なので、とても思い入れがあります。

 

この苦労して実装できた気持ちをいつまでも忘れず、そして開発をサポートしてくださった人達の感謝はもっと忘れず、

 

エンジニアとして一人前になれるように、日々、邁進していきます!

 

最後までご覧いただきありがとうございました。

 

 

 

さいごに

EMoshUは、仕事にたいして情熱がある方、メンバー同士で切磋琢磨しながら、一緒に会社を大きくしていける、そんな仲間を募っています。

 

一緒に同じ志を持って試行錯誤しながら成長したいという方は、ぜひ募集要項をご確認の上、ご連絡いただければと思います。

 

 

 

参考文献

 

 

 

募集要項

 

 

 

まずは話を聞いてみたいという方へ