コネヒト開発者ブログ

コネヒト開発者ブログ

iOSDC2021で「知られざる課金ステータス」というタイトルで発表してきました

こんにちは!コネヒトでiOSアプリの開発をしている @ohayoukenchan です。
2021.9.17-9.19に開催されたiOSDC2021で発表してきました。

iOSDCとは?

iOS関連技術をコアのテーマとしたオンラインカンファレンスです。

今回はオンラインということで、トークは事前収録されニコ生で配信されました。 また、トークセッション後のAsk The SpeakerはDiscordにて行なわれました。 事前収録のおかげでトーク中もDiscordで質問にお答えする余裕があったりオンラインイベントならではの良さがありました。

コネヒトはシルバースポンサーとして協賛させていただきました!

自分のトーク内容

お試しオファーの無料期間中にプロモーションオファーを適用したり、プロモーションオファーの無料期間中にプロモーションオファーを適用したりすると、ユーザーの課金状態がどのようになるかについてお話しました。

オファーの比較

それぞれのオファーについて簡単な表にしてみました。 オファーコードに関しては省略しております

お試しオファー プロモーションオファー
主な用途 新規サブスクリプション利用者の獲得 既存のサブスクリプション利用者の維持と過去の利用者の再登録
利用資格 App内の新規サブスクリプション利用者 App内の既存または過去のサブスクリプション利用者
利用の限度 サブスクリプショングループごとに1件のお試しオファーを利用可能 デベロッパはユーザーが何件までオファーを利用できるか決定 する
オファーの限度 サブスクリプションごと、地域ごとに、1件のオファー サブスクリプションごとに、10件のアクティブなオファー
互換性(iOS) iOS 10以降 iOS 12.2以降

同一サブスクリプションのプロモーションオファーを適応する場合

プロモーションオファーはサブスクリプションに紐づく形で作成できます。
オファー適用前のサブスクリプションが適用するオファーに紐づく場合は、現在の無料期間終了後にプロモーションオファーが適用されます。

お試しオファー無料中の場合、お試しオファー終了後にプロモーションオファーが適用される

f:id:ohayoukenchan:20210928180731p:plain
プロモーションオファーが課金前のサブスクリプションに紐づく場合

課金中の場合、契約期間終了後にプロモーションオファーが適用される

f:id:ohayoukenchan:20210928181857p:plain
プロモーションオファーが課金前のサブスクリプションに紐づく場合(課金中)

クロスグレードが発生する場合

クロスグレードはユーザーが、同等のレベルのサブスクリプションに切り替えることを指します。詳しくはこちらをご確認ください。

プロモーションオファーが紐付いていない別のサブスクリプションからプロモーションオファーを適用させることも出来ます。 その場合、グレードと契約期間からクロスグレードの条件が決まります。 今回はすべて同一グレードのみの検証となっています。 グレードが異なる場合アップグレードやダウングレードの対象となりますのでご注意ください。

別のサブスクリプション(期間が同じ)のプロモーションオファーを適用する場合

別のサブスクリプションで期間が同じサブスクリプションからプロモーションオファーを適用する場合は現在の契約は即時終了します。

お試しオファー無料中の場合、お試しオファーは即終了しプロモーションオファーの無料期間になる

f:id:ohayoukenchan:20210928180836p:plain
プロモーションオファーが課金前のサブスクリプションに紐づかない場合(お試しオファー中)

課金中の場合、現在の契約は終了し、プロモーションオファーの無料期間になる。そして契約期間の差額分返金される

App 内課金が同じ期間のものである場合、前の App 内課金から比例配分された金額は、元の支払い方法で返金されます。

f:id:ohayoukenchan:20210928181239p:plain
プロモーションオファーが課金前のサブスクリプションに紐づかない場合(課金中)

別のサブスクリプション(期間が異なる)のプロモーションオファーを適用する場合

同じグレード、同じ期間の場合は現在適用中のオファーは即破棄されていましたが、期間が異なる場合は条件が異なります。 期間が異なる場合、オファー適用は現在の契約が終了した後の適用となります。

お試しオファー無料中の場合、お試しオファー終了後にプロモーションオファー適用になる

f:id:ohayoukenchan:20210928181315p:plain
プロモーションオファーが課金前のサブスクリプションに紐づかない場合(お試しオファー中)

課金中の場合、契約期間終了後にプロモーションオファー適用になる

App 内課金が異なる期間のものである場合、クロスグレードは、カスタマーの次の更新日に有効になります。 同一サブスクリプションのプロモーションオファーを適用する場合と同じ挙動となります。

f:id:ohayoukenchan:20210928181408p:plain
プロモーションオファーが課金前のサブスクリプションに紐づかない場合(課金中)

プロモーションオファー無料期間中にプロモーションオファー

プロモーションオファーの無料期間中に再度プロモーションオファーを適用させようとすると、現在適用中のオファーとは別に1件までペンディングさせることができます。ペンディング中のオファーはレシート情報のpending_renewal_infoに記録され、次回更新日に有効化することができます。 pending_renewal_infoは常に最新のオファーしか記録しないので複数のプロモーションオファーを適用待ちにできないので、プロモーションオファーを何回かけても最新のオファー一件のみしかペンディングさせることが出来ないことに注意してください。

f:id:ohayoukenchan:20210928181445p:plain
プロモーションオファー無料期間中にプロモーションオファーを適応させ、 再度プロモーションオファー

話さなかったこと

7日間無料状態で課金を試すときは鍛錬が必要

sandboxでの7日間は5分しかないので無料期間内にオファーを追加するのが大変だったりしました。 sandboxアカウント名を短くしたり、事前に課金開始画面を開いておいたり。DBでレシート検証するユーザーの情報を事前に用意したりすることでいかに早く処理を完了するかを鍛えることができました。

sandbox環境で何度やっても想定通り行かない日がある

私はexpire_dateを過ぎても全く更新されない地雷を踏みました 別の日に試すとすんなりうまくいったので、sandbox調子悪いなとおもったら別の日に試したほうがよさそうです。

ハマったこと

サーバー側で現在の自動継続課金の有効期限を、レシート内の一番未来のexpire_date_msでソートして取得していたが、お試しオファー1年無料の後に、6ヶ月無料を適用させた場合、有効期限が6ヶ月後を想定しているのに対して、破棄された1年無料の有効期限を取得してしまっていた。サーバー側で保持した有効期限はクライアント側で表示ロジックの制御に使用していたので、有効期限が異なり、ユーザーに適切な体験を提供できなくなりそうだった。最新のレシートの有効期限を取得することで回避しました。

終わりに

オファーの切り替えなどはユーザーが意図しないケースも多く、ユーザー体験を損ねてしまっているのではないかと感じています。 ママリでは購読開始前に現在の課金ステータスから、返金対象だったり契約が消えてしまう可能性のあるユーザーに注意文言を表示していますが、そもそも確認されているのかも怪しいと思っています。 StoreKit2の発表により、アプリ内で現在の課金状態を表示することが出来るようになったり、返金APIが追加されたりするのでユーザー体験を損ねないようなユーザー体験を提供できそうですね。