android_in_app_purchases.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. .. _doc_android_in_app_purchases:
  2. Android in-app purchases
  3. ========================
  4. Godot offers a first-party ``GodotGooglePlayBilling`` Android plugin compatible with Godot 3.2.2 and higher.
  5. This plugin uses the `Google Play Billing library <https://developer.android.com/google/play/billing>`__
  6. instead of the now deprecated AIDL IAP implementation. For details of how to migrate from the older
  7. ``GodotPaymentsV3``, see the migration guide: `Migrating from Godot 3.2.1 and lower (GodotPaymentsV3)`_.
  8. If you learn better by looking at an example, you can find the demo project
  9. `here <https://github.com/godotengine/godot-demo-projects/tree/master/mobile/android_iap>`__.
  10. Usage
  11. -----
  12. Getting started
  13. ***************
  14. Make sure you have enabled and successfully set up :ref:`Android Custom Builds <doc_android_custom_build>`.
  15. Follow the compiling instructions on the ``GodotGooglePlayBilling`` `github page <https://github.com/godotengine/godot-google-play-billing>`__.
  16. .. note::
  17. If you use a custom build you possibly have to put your own `godot-lib.***.release.aar` file in the `./godot-google-play-billing/libs/` folder.
  18. Then put the files `./godot-google-play-billing/build/outputs/aar/GodotGooglePlayBilling.***.release.aar` and `./GodotGooglePlayBilling.gdap` into your project in the `res://android/plugins` folder.
  19. The plugin should now show up in the Android export settings, where you can enable it.
  20. Initialize the plugin
  21. *********************
  22. To use the ``GodotGooglePlayBilling`` API:
  23. 1. Obtain a reference to the ``GodotGooglePlayBilling`` singleton
  24. 2. Connect handlers for the plugin signals
  25. 3. Call ``startConnection``
  26. Initialization example:
  27. ::
  28. var payment
  29. func _ready():
  30. if Engine.has_singleton("GodotGooglePlayBilling"):
  31. payment = Engine.get_singleton("GodotGooglePlayBilling")
  32. # These are all signals supported by the API
  33. # You can drop some of these based on your needs
  34. payment.connect("billing_resume", self, "_on_billing_resume") # No params
  35. payment.connect("connected", self, "_on_connected") # No params
  36. payment.connect("disconnected", self, "_on_disconnected") # No params
  37. payment.connect("connect_error", self, "_on_connect_error") # Response ID (int), Debug message (string)
  38. payment.connect("price_change_acknowledged", self, "_on_price_acknowledged") # Response ID (int)
  39. payment.connect("purchases_updated", self, "_on_purchases_updated") # Purchases (Dictionary[])
  40. payment.connect("purchase_error", self, "_on_purchase_error") # Response ID (int), Debug message (string)
  41. payment.connect("sku_details_query_completed", self, "_on_sku_details_query_completed") # SKUs (Dictionary[])
  42. payment.connect("sku_details_query_error", self, "_on_sku_details_query_error") # Response ID (int), Debug message (string), Queried SKUs (string[])
  43. payment.connect("purchase_acknowledged", self, "_on_purchase_acknowledged") # Purchase token (string)
  44. payment.connect("purchase_acknowledgement_error", self, "_on_purchase_acknowledgement_error") # Response ID (int), Debug message (string), Purchase token (string)
  45. payment.connect("purchase_consumed", self, "_on_purchase_consumed") # Purchase token (string)
  46. payment.connect("purchase_consumption_error", self, "_on_purchase_consumption_error") # Response ID (int), Debug message (string), Purchase token (string)
  47. payment.connect("query_purchases_response", self, "_on_query_purchases_response") # Purchases (Dictionary[])
  48. payment.startConnection()
  49. else:
  50. print("Android IAP support is not enabled. Make sure you have enabled 'Custom Build' and the GodotGooglePlayBilling plugin in your Android export settings! IAP will not work.")
  51. The API must be in a connected state prior to use. The ``connected`` signal is sent
  52. when the connection process succeeds. You can also use ``isReady()`` to determine if the plugin
  53. is ready for use. The ``getConnectionState()`` function returns the current connection state
  54. of the plugin.
  55. Return values for ``getConnectionState()``:
  56. ::
  57. # Matches BillingClient.ConnectionState in the Play Billing Library
  58. enum ConnectionState {
  59. DISCONNECTED, # not yet connected to billing service or was already closed
  60. CONNECTING, # currently in process of connecting to billing service
  61. CONNECTED, # currently connected to billing service
  62. CLOSED, # already closed and shouldn't be used again
  63. }
  64. Query available items
  65. *********************
  66. Once the API has connected, query SKUs using ``querySkuDetails()``. You must successfully complete
  67. a SKU query before before calling the ``purchase()`` or ``queryPurchases()`` functions,
  68. or they will return an error. ``querySkuDetails()`` takes two parameters: an array
  69. of SKU name strings, and a string specifying the type of SKU being queried.
  70. The SKU type string should be ``"inapp"`` for normal in-app purchases or ``"subs"`` for subscriptions.
  71. The name strings in the array should match the SKU product ids defined in the Google Play Console entry
  72. for your app.
  73. Example use of ``querySkuDetails()``:
  74. ::
  75. func _on_connected():
  76. payment.querySkuDetails(["my_iap_item"], "inapp") # "subs" for subscriptions
  77. func _on_sku_details_query_completed(sku_details):
  78. for available_sku in sku_details:
  79. print(available_sku)
  80. func _on_sku_details_query_error(response_id, error_message, skus_queried):
  81. print("on_sku_details_query_error id:", response_id, " message: ",
  82. error_message, " skus: ", skus_queried)
  83. Query user purchases
  84. ********************
  85. To retrieve a user's purchases, call the ``queryPurchases()`` function passing
  86. a string with the type of SKU to query. The SKU type string should be
  87. ``"inapp"`` for normal in-app purchases or ``"subs"`` for subscriptions.
  88. The ``query_purchases_response`` signal is sent with the result.
  89. The signal has a single parameter: a :ref:`Dictionary <class_Dictionary>` with
  90. a status code and either an array of purchases or an error message.
  91. Only active subscriptions and non-consumed one-time purchases are
  92. included in the purchase array.
  93. Example use of ``queryPurchases()``:
  94. ::
  95. func _query_purchases():
  96. payment.queryPurchases("inapp") # Or "subs" for subscriptions
  97. func _on_query_purchases_response(query_result):
  98. if query_result.status == OK:
  99. for purchase in query_result.purchases:
  100. _process_purchase(purchase)
  101. else:
  102. print("queryPurchases failed, response code: ",
  103. query_result.response_code,
  104. " debug message: ", query_result.debug_message)
  105. You should query purchases during startup after successfully retrieving SKU details.
  106. Since the user may make a purchase or resolve a pending transaction from
  107. outside your app, you should recheck for purchases when resuming from the
  108. background. To accomplish this, you can use the ``billing_resume`` signal.
  109. Example use of ``billing_resume``:
  110. ::
  111. func _on_billing_resume():
  112. if payment.getConnectionState() == ConnectionState.CONNECTED:
  113. _query_purchases()
  114. For more information on processing the purchase items returned by
  115. ``queryPurchases()``, see `Processing a purchase item`_
  116. Purchase an item
  117. ****************
  118. To initiate the purchase flow for an item, call ``purchase()`` passing the
  119. product id string of the SKU you wish to purchase.
  120. Reminder: you **must** query the SKU details for an item before you can
  121. pass it to ``purchase()``.
  122. Example use of ``purchase()``:
  123. ::
  124. payment.purchase("my_iap_item")
  125. The payment flow will send a ``purchases_updated`` signal on success or a
  126. ``purchase_error`` signal on failure.
  127. ::
  128. func _on_purchases_updated(purchases):
  129. for purchase in purchases:
  130. _process_purchase(purchase)
  131. func _on_purchase_error(response_id, error_message):
  132. print("purchase_error id:", response_id, " message: ", error_message)
  133. Processing a purchase item
  134. **************************
  135. The ``query_purchases_response`` and ``purchases_updated`` signals provide an array
  136. of purchases in :ref:`Dictionary <class_Dictionary>` format. The purchase Dictionary
  137. includes keys that map to values of the Google Play Billing
  138. `Purchase <https://developer.android.com/reference/com/android/billingclient/api/Purchase>`_ class.
  139. Purchase fields:
  140. ::
  141. dictionary.put("order_id", purchase.getOrderId());
  142. dictionary.put("package_name", purchase.getPackageName());
  143. dictionary.put("purchase_state", purchase.getPurchaseState());
  144. dictionary.put("purchase_time", purchase.getPurchaseTime());
  145. dictionary.put("purchase_token", purchase.getPurchaseToken());
  146. dictionary.put("quantity", purchase.getQuantity());
  147. dictionary.put("signature", purchase.getSignature());
  148. // PBL V4 replaced getSku with getSkus to support multi-sku purchases,
  149. // use the first entry for "sku" and generate an array for "skus"
  150. ArrayList<String> skus = purchase.getSkus();
  151. dictionary.put("sku", skus.get(0));
  152. String[] skusArray = skus.toArray(new String[0]);
  153. dictionary.put("skus", skusArray);
  154. dictionary.put("is_acknowledged", purchase.isAcknowledged());
  155. dictionary.put("is_auto_renewing", purchase.isAutoRenewing());
  156. Check purchase state
  157. ********************
  158. Check the ``purchase_state`` value of a purchase to determine if a
  159. purchase was completed or is still pending.
  160. PurchaseState values:
  161. ::
  162. # Matches Purchase.PurchaseState in the Play Billing Library
  163. enum PurchaseState {
  164. UNSPECIFIED,
  165. PURCHASED,
  166. PENDING,
  167. }
  168. If a purchase is in a ``PENDING`` state, you should not award the contents of the
  169. purchase or do any further processing of the purchase until it reaches the
  170. ``PURCHASED`` state. If you have a store interface, you may wish to display
  171. information about pending purchases needing to be completed in the Google Play Store.
  172. For more details on pending purchases, see
  173. `Handling pending transactions <https://developer.android.com/google/play/billing/integrate#pending>`_
  174. in the Google Play Billing Library documentation.
  175. Consumables
  176. ***********
  177. If your in-app item is not a one-time purchase but a consumable item (e.g. coins) which can be purchased
  178. multiple times, you can consume an item by calling ``consumePurchase()`` passing
  179. the ``purchase_token`` value from the purchase dictionary.
  180. Calling ``consumePurchase()`` automatically acknowledges a purchase.
  181. Consuming a product allows the user to purchase it again, it will no longer appear
  182. in subsequent ``queryPurchases()`` calls unless it is repurchased.
  183. Example use of ``consumePurchase()``:
  184. ::
  185. func _process_purchase(purchase):
  186. if purchase.sku == "my_consumable_iap_item" and purchase.purchase_state == PurchaseState.PURCHASED:
  187. # Add code to store payment so we can reconcile the purchase token
  188. # in the completion callback against the original purchase
  189. payment.consumePurchase(purchase.purchase_token)
  190. func _on_purchase_consumed(purchase_token):
  191. _handle_purchase_token(purchase_token, true)
  192. func _on_purchase_consumption_error(response_id, error_message, purchase_token):
  193. print("_on_purchase_consumption_error id:", response_id,
  194. " message: ", error_message)
  195. _handle_purchase_token(purchase_token, false)
  196. # Find the sku associated with the purchase token and award the
  197. # product if successful
  198. func _handle_purchase_token(purchase_token, purchase_successful):
  199. # check/award logic, remove purchase from tracking list
  200. Acknowledging purchases
  201. ***********************
  202. If your in-app item is a one-time purchase, you must acknowledge the purchase by
  203. calling the ``acknowledgePurchase()`` function, passing the ``purchase_token``
  204. value from the purchase dictionary. If you do not acknowledge a purchase within
  205. three days, the user automatically receives a refund, and Google Play revokes the purchase.
  206. If you are calling ``comsumePurchase()`` it automatically acknowledges the purchase and
  207. you do not need to call ``acknowledgePurchase()``.
  208. Example use of ``acknowledgePurchase()``:
  209. ::
  210. func _process_purchase(purchase):
  211. if purchase.sku == "my_one_time_iap_item" and \
  212. purchase.purchase_state == PurchaseState.PURCHASED and \
  213. not purchase.is_acknowledged:
  214. # Add code to store payment so we can reconcile the purchase token
  215. # in the completion callback against the original purchase
  216. payment.acknowledgePurchase(purchase.purchase_token)
  217. func _on_purchase_acknowledged(purchase_token):
  218. _handle_purchase_token(purchase_token, true)
  219. func _on_purchase_acknowledgement_error(response_id, error_message, purchase_token):
  220. print("_on_purchase_acknowledgement_error id: ", response_id,
  221. " message: ", error_message)
  222. _handle_purchase_token(purchase_token, false)
  223. # Find the sku associated with the purchase token and award the
  224. # product if successful
  225. func _handle_purchase_token(purchase_token, purchase_successful):
  226. # check/award logic, remove purchase from tracking list
  227. Subscriptions
  228. *************
  229. Subscriptions work mostly like regular in-app items. Use ``"subs"`` as the second
  230. argument to ``querySkuDetails()`` to get subscription details. Pass ``"subs"``
  231. to ``queryPurchases()`` to get subscription purchase details.
  232. You can check ``is_auto_renewing`` in the a subscription purchase
  233. returned from ``queryPurchases()`` to see if a user has cancelled an
  234. auto-renewing subscription.
  235. You need to acknowledge new subscription purchases, but not automatic
  236. subscription renewals.
  237. If you support upgrading or downgrading between different subscription levels,
  238. you should use ``updateSubscription()`` to use the subscription update flow to
  239. change an active subscription. Like ``purchase()``, results are returned by the
  240. ``purchases_updated`` and ``purchase_error`` signals.
  241. There are three parameters to ``updateSubscription()``:
  242. 1. The purchase token of the currently active subscription
  243. 2. The product id string of the subscription SKU to change to
  244. 3. The proration mode to apply to the subscription.
  245. The proration values are defined as:
  246. ::
  247. enum SubscriptionProrationMode {
  248. # Replacement takes effect immediately, and the remaining time
  249. # will be prorated and credited to the user.
  250. IMMEDIATE_WITH_TIME_PRORATION = 1,
  251. # Replacement takes effect immediately, and the billing cycle remains the same.
  252. # The price for the remaining period will be charged.
  253. # This option is only available for subscription upgrade.
  254. IMMEDIATE_AND_CHARGE_PRORATED_PRICE,
  255. # Replacement takes effect immediately, and the new price will be charged on
  256. # next recurrence time. The billing cycle stays the same.
  257. IMMEDIATE_WITHOUT_PRORATION,
  258. # Replacement takes effect when the old plan expires, and the new price
  259. # will be charged at the same time.
  260. DEFERRED,
  261. # Replacement takes effect immediately, and the user is charged full price
  262. # of new plan and is given a full billing cycle of subscription,
  263. # plus remaining prorated time from the old plan.
  264. IMMEDIATE_AND_CHARGE_FULL_PRICE,
  265. }
  266. Default behavior is ``IMMEDIATE_WITH_TIME_PRORATION``.
  267. Example use of ``updateSubscription``:
  268. ::
  269. payment.updateSubscription(_active_subscription_purchase.purchase_token, \
  270. "new_sub_sku", SubscriptionProrationMode.IMMEDIATE_WITH_TIME_PRORATION)
  271. The ``confirmPriceChange()`` function can be used to launch price change confirmation flow
  272. for a subscription. Pass the product id of the subscription SKU subject to the price change.
  273. The result will be sent by the ``price_change_acknowledged`` signal.
  274. Example use of ``confirmPriceChange()``:
  275. ::
  276. enum BillingResponse {SUCCESS = 0, CANCELLED = 1}
  277. func confirm_price_change(product_id):
  278. payment.confirmPriceChange(product_id)
  279. func _on_price_acknowledged(response_id):
  280. if response_id == BillingResponse.SUCCESS:
  281. print("price_change_accepted")
  282. elif response_id == BillingResponse.CANCELED:
  283. print("price_change_canceled")
  284. Migrating from Godot 3.2.1 and lower (GodotPaymentsV3)
  285. ------------------------------------------------------
  286. The new ``GodotGooglePlayBilling`` API is not compatible with its predecessor ``GodotPaymentsV3``.
  287. Changes
  288. *******
  289. - You need to enable the Custom Build option in your Android export settings and install
  290. the ``GodotGooglePlayBilling`` plugin manually (see below for details)
  291. - All purchases have to be acknowledged by your app. This is a
  292. `requirement from Google <https://developer.android.com/google/play/billing/integrate#process>`__.
  293. Purchases that are not acknowledged by your app will be refunded.
  294. - Support for subscriptions
  295. - Signals (no polling or callback objects)