Re: アプリ内課金v3におけるキャンセル通知について

2,572 views
Skip to first unread message

katsuki nakatani

unread,
Mar 17, 2013, 10:50:23 PM3/17/13
to android-...@googlegroups.com
こんにちは。
中谷と申します。

Playストアのアプリのデータ(キャッシュ?)を消去したり、端末を再起動したりしたら
所持していないようにステータスが変わったように思います。
トリガーがどのタイミングかは私もわからなかったのですが上記のような方法で
アイテムを所持していないことを確認することができるかと思います。


2013年3月18日月曜日 7時14分48秒 UTC+9 Maasa:
初めまして、まあさと申します。

今まで作成したアプリのアプリ内課金は、全てinAppBillingのv2を使用していたのですが、
この度、v3への入れ替え作業を行っております。

そこで質問なのですが、v2の場合は例えばアイテム購入後に、デベロッパー側でコンソール画面からユーザの購入をキャンセルした場合や、
ユーザ側のクレジット番号などの不備等で、ステータスが購入状態からキャンセルになった場合などの対策として
purchaseStateChangedにて非同期で受け取ったpurchaseStateがPurchaseState.CANCELEDであった場合に購入状態を未購入に設定していました。

ただ、v3の場合、デベロッパーコンソールで購入をキャンセルしても、アイテムの所有までは解除されないようなので、未購入状態に戻す事が出来ず困っています。
キャンセルが発生したかどうかを、アプリ起動時などのリストア処理にて判定して、その瞬間アイテム消費通知を送る事で解決出来るとは思うのですが、
v3でIabHelperを使用している場合、そのアイテムで購入のキャンセルがあったかどうかというのは判別できますでしょうか?
例えば、アイテムを購入し、デベロッパーコンソールにてその購入をキャンセル、その後アプリを起動し、リストア処理でIabHelper.QueryInventoryFinishedListenerで受け取った通知を見ても
すでに購入はキャンセルされているにも関わらず、アイテムの所有はユーザ側が持ったままだからかpurchaseStateにはPurchaseState.PURCHASEDが戻ってきてしまいます。

もしかすると、判定する部分が間違えているのかもしれませんが、よろしければご教唆頂けると幸いです。

Maasa

unread,
Mar 18, 2013, 12:27:59 AM3/18/13
to android-...@googlegroups.com
中谷様、ご返信ありがとうございます。

という事は、consumeAsyncでアイテムの消費通知を行わなくても、デベロッパーコンソールから購入をキャンセルするだけで
その後の何らかがトリガーとなってアイテムの所有も取り消されていたという事でしょうか?

そうすると、アイテムの所有管理はGoogle側で行っている事から、仰る通りコンソールから更なる操作が必要なのか、
もしくは購入キャンセルからアイテムの所有ステータスを変更するまでに時間がかかっているのかもしれないですね。

普通に考えても、購入をキャンセルしたらアイテムの所有権は消滅するのはずなので、アプリ側から通知を行わなくても
Google側でステータスの移行が行われるのが自然だと思うのですが、一体何がトリガーとなっているのでしょう?

もしかすると、購入代金のみ取り消しというパターンのために、デベロッパーコンソールからキャンセルを行っても、
アプリ側から個別にアイテムの消費通知を行わないと所有ステータスは変わらない…という可能性もあるのでしょうか。


2013年3月18日月曜日 11時50分23秒 UTC+9 katsuki nakatani:

Maasa

unread,
Mar 18, 2013, 6:04:41 PM3/18/13
to android-...@googlegroups.com
その後、色々と試してみた結果を記載致します。

まず、IabHelperを通してlaunchPurchaseFlowでアイテムを購入する事で、購入処理は完結し、ユーザは該当アイテムを所有する。
その後、管理画面よりデベロッパー側で購入をキャンセルする。
この時点でユーザ側にキャンセル通知のメールが届く。

通常、このタイミングでアイテムの所有も解除されているのが自然だと思ったのですが、ここで
queryInventoryAsyncを呼んでアイテムの所有状態を確認しても、QueryInventoryFinishedListenerに通知されるInventoryを参照すると、
inventory.hasPurchase(該当アイテムID)がtrueで戻ってきてしまいます。

これは15分間隔くらいで何度も試してみましたが、1日経過してもfalseで戻ってくる事はありませんでした。
デベロッパー側でキャンセルをしても、アイテムの所有まではキャンセルされないのかと思い、再テストを行うためにconsumeAsyncでアイテムの消費を行いました。
すると、OnConsumeFinishedListenerには、すでにアイテムを所有していないBILLING_RESPONSE_RESULT_ITEM_NOT_OWNEDが戻ってきました。

これは、キャンセル後すぐは正常に消費されるので、キャンセルから一定時間が経過したためにアイテムの所有状態もキャンセルされた証だと思うのですが、
そうすると、なぜinventory.hasPurchase(該当アイテムID)がtrueで戻ってきたのかが分かりません。
アイテムの所有、未所有を判定するためにinventory.hasPurchase(該当アイテムID)以外のメソッドがあるのでしょうか?
もし詳しい事をお知りの方がいらっしゃいましたら、ご教唆頂けると幸いです。

この処理を完結させたい理由として、非消耗型のアイテムを購入したユーザからのメールなどでのキャンセル要求に対して、管理画面からの操作で払い戻しする代わりに
アイテムの所有状態も未所有に戻したい、という事情があります。
何とぞよろしくお願い申し上げます。



2013年3月18日月曜日 13時27分59秒 UTC+9 Maasa:

katsuki nakatani

unread,
Mar 18, 2013, 7:51:13 PM3/18/13
to android-...@googlegroups.com
中谷です。

>という事は、consumeAsyncでアイテムの消費通知を行わなくても、デベロッパーコンソールから購入をキャンセルするだけで
>その後の何らかがトリガーとなってアイテムの所有も取り消されていたという事でしょうか?
管理型のアイテムについては消費する処理なくキャンセル処理後にqueryInventoryでリストを取得したら
管理型のキャンセルしたアイテムについては購入情報は送られてきていませんでした。
(購入→アプリ内で購入されたことを確認→キャンセル→Playストアアプリのキャッシュ、データを消去→queryInventoryで確認)
これについてはv3でアイテム情報はキャッシュして渡されるとどこかで見たので、おそらくPlayストアのデータ内で
キャッシュしてるんだろうなぁとそこまで深くは追及していませんでした。


2013年3月19日火曜日 7時04分41秒 UTC+9 Maasa:

Maasa

unread,
Mar 20, 2013, 7:34:23 AM3/20/13
to android-...@googlegroups.com
中谷様、ご返信ありがとうございます。

>管理型のキャンセルしたアイテムについては購入情報は送られてきていませんでした。

>(購入→アプリ内で購入されたことを確認→キャンセル→Playストアアプリのキャッシュ、データを消去→queryInventoryで確認)

仰る通り、まずPlayストアアプリのデータを確認して、そこに情報がなければGooglePlayに新たに問い合わせているようですね。
同じ手順でテストしてみたところ、全く同じ挙動となりました。
という事は、コンソールから払い戻しをした際などにユーザがキャッシュやデータをクリアせずにアプリ側にそれを知らせる方法としては、
queryInventoryでの参照をPlayストアアプリのデータではなく毎回GooglePlayに問い合わせるように改変する必要があるという事でしょうか。
キャッシュを参照するのは24時間以内程度とかであれば、そこまで焦る必要もなさそうですが、この辺り調べてみたいと思います。

ちなみに、コンソールから購入をキャンセルをしてPlayストアのデータを消去したりアプリを再インストールしたりしていると、データをクリアしたタイミング?によっては
Uncaught remote exceptionが吐き出される事がありました。

2013年3月19日火曜日 8時51分13秒 UTC+9 katsuki nakatani:
Reply all
Reply to author
Forward
0 new messages