Update Android IAP demo for 3.2.2

This commit is contained in:
Timo Schwarzer
2020-06-14 13:57:18 +02:00
parent 5363f8a75a
commit 74924dd073
4 changed files with 154 additions and 262 deletions

View File

@@ -1,138 +0,0 @@
extends Node
signal purchase_success(item_name)
signal purchase_fail
signal purchase_cancel
signal purchase_owned(item_name)
signal has_purchased(item_name)
signal consume_success(item_name)
signal consume_fail
signal consume_not_required
signal sku_details_complete
signal sku_details_error
var payment
func _ready():
if Engine.has_singleton("GodotPayments"):
payment = Engine.get_singleton("GodotPayments")
else:
print("GodotPayment singleton is only available on Android devices.")
if payment:
# Set callback with this script instance.
payment.setPurchaseCallbackId(get_instance_id())
# Set consume purchased item automatically after purchase, default value is true.
func set_auto_consume(auto):
if payment:
payment.setAutoConsume(auto)
# Request user owned item, callback: has_purchased.
func request_purchased():
if payment:
payment.requestPurchased()
func has_purchased(_receipt, _signature, sku):
if sku == "":
print("has_purchased : nothing")
emit_signal("has_purchased", null)
else:
print("has_purchased : ", sku)
emit_signal("has_purchased", sku)
# purchase item
# callback : purchase_success, purchase_fail, purchase_cancel, purchase_owned
func purchase(item_name):
if payment:
# transaction_id could be any string that used for validation internally in java
payment.purchase(item_name, "transaction_id")
func purchase_success(_receipt, _signature, sku):
print("purchase_success : ", sku)
emit_signal("purchase_success", sku)
func purchase_fail():
print("purchase_fail")
emit_signal("purchase_fail")
func purchase_cancel():
print("purchase_cancel")
emit_signal("purchase_cancel")
func purchase_owned(sku):
print("purchase_owned : ", sku)
emit_signal("purchase_owned", sku)
# Consume purchased item.
# Callback: consume_success, consume_fail
func consume(item_name):
if payment:
payment.consume(item_name)
# Consume all purchased items.
func consume_all():
if payment:
payment.consumeUnconsumedPurchases()
func consume_success(_receipt, _signature, sku):
print("consume_success : ", sku)
emit_signal("consume_success", sku)
# If consume fails, need to call request_purchased() to get purchase token from Google.
# Then try to consume again.
func consume_fail():
emit_signal("consume_fail")
# No purchased item to consume.
func consume_not_required():
emit_signal("consume_not_required")
# Detail info of IAP items:
# sku_details = {
# product_id (String) : {
# type (String),
# product_id (String),
# title (String),
# description (String),
# price (String), # this can be used to display price for each country with their own currency
# price_currency_code (String),
# price_amount (float)
# },
# ...
# }
var sku_details = {}
# Query for details of IAP items.
# Callback: sku_details_complete
func sku_details_query(list):
if payment:
var sku_list = PoolStringArray(list)
payment.querySkuDetails(sku_list)
func sku_details_complete(result):
print("sku_details_complete : ", result)
for key in result.keys():
sku_details[key] = result[key]
emit_signal("sku_details_complete")
func sku_details_error(error_message):
print("error_sku_details = ", error_message)
emit_signal("sku_details_error")

View File

@@ -1,78 +1,117 @@
extends Control
onready var alert = get_node("alert")
const TEST_ITEM_SKU = "my_in_app_purchase_sku"
onready var alert_dialog = $AlertDialog
onready var label = $Label
var payment = null
var test_item_purchase_token = null
func _ready():
iap.set_auto_consume(false)
iap.connect("purchase_success", self, "on_purchase_success")
iap.connect("purchase_fail", self, "on_purchase_fail")
iap.connect("purchase_cancel", self, "on_purchase_cancel")
iap.connect("purchase_owned", self, "on_purchase_owned")
iap.connect("has_purchased", self, "on_has_purchased")
iap.connect("consume_success", self, "on_consume_success")
iap.connect("consume_fail", self, "on_consume_fail")
iap.connect("sku_details_complete", self, "on_sku_details_complete")
if Engine.has_singleton("GodotPayment"):
label.text += "\n\n\nTest item SKU: %s" % TEST_ITEM_SKU
get_node("purchase").connect("pressed", self, "button_purchase")
get_node("consume").connect("pressed", self, "button_consume")
get_node("request").connect("pressed", self, "button_request")
get_node("query").connect("pressed", self, "button_query")
func on_purchase_success(item_name):
alert.set_text("Purchase success : " + item_name)
alert.popup()
func on_purchase_fail():
alert.set_text("Purchase fail")
alert.popup()
func on_purchase_cancel():
alert.set_text("Purchase cancel")
alert.popup()
func on_purchase_owned(item_name):
alert.set_text("Purchase owned: " + item_name)
alert.popup()
func on_has_purchased(item_name):
if item_name == null:
alert.set_text("Don't have purchased item")
payment = Engine.get_singleton("GodotPayment")
payment.connect("connected", self, "_on_connected") # No params
payment.connect("disconnected", self, "_on_disconnected") # No params
payment.connect("connect_error", self, "_on_connect_error") # Response ID (int), Debug message (string)
payment.connect("purchases_updated", self, "_on_purchases_updated") # Purchases (Dictionary[])
payment.connect("purchase_error", self, "_on_purchase_error") # Response ID (int), Debug message (string)
payment.connect("sku_details_query_completed", self, "_on_sku_details_query_completed") # SKUs (Dictionary[])
payment.connect("sku_details_query_error", self, "_on_sku_details_query_error") # Response ID (int), Debug message (string), Queried SKUs (string[])
payment.connect("purchase_acknowledged", self, "_on_purchase_acknowledged") # Purchase token (string)
payment.connect("purchase_acknowledgement_error", self, "_on_purchase_acknowledgement_error") # Response ID (int), Debug message (string), Purchase token (string)
payment.connect("purchase_consumed", self, "_on_purchase_consumed") # Purchase token (string)
payment.connect("purchase_consumption_error", self, "_on_purchase_consumption_error") # Response ID (int), Debug message (string), Purchase token (string)
payment.startConnection()
else:
alert.set_text("Has purchased: " + item_name)
alert.popup()
show_alert("Android IAP support is not enabled. Make sure you have enabled 'Custom Build' and the GodotPayment plugin in your Android export settings! This application will not work.")
func on_consume_success(item_name):
alert.set_text("Consume success: " + item_name)
alert.popup()
func show_alert(text):
alert_dialog.dialog_text = text
alert_dialog.popup_centered()
func on_consume_fail():
alert.set_text("Try to request purchased first")
alert.popup()
func _on_connected():
print("PurchaseManager connected")
# We must acknowledge all puchases.
# See https://developer.android.com/google/play/billing/integrate#process for more information
var query = payment.queryPurchases("inapp") # Use "subs" for subscriptions
var purchase_token = null
if query.status == OK:
for purchase in query.purchases:
if !purchase.is_acknowledged:
print("Purchase " + str(purchase.sku) + " has not been acknowledged. Acknowledging...")
payment.acknowledgePurchase(purchase.purchase_token)
else:
print("Purchase query failed: %d" % query.status)
func on_sku_details_complete():
alert.set_text("Got detail info: " + to_json(iap.sku_details["item_test_a"]))
alert.popup()
func _on_sku_details_query_completed(sku_details):
for available_sku in sku_details:
show_alert(to_json(available_sku))
func button_purchase():
iap.purchase("item_tess")
func _on_purchases_updated(purchases):
print("Purchases updated: %s" % to_json(purchases))
# See _on_connected
for purchase in purchases:
if !purchase.is_acknowledged:
print("Purchase " + str(purchase.sku) + " has not been acknowledged. Acknowledging...")
payment.acknowledgePurchase(purchase.purchase_token)
if purchases.size() > 0:
test_item_purchase_token = purchases[purchases.size() - 1].purchase_token
func button_consume():
iap.consume("item_tess")
func _on_purchase_acknowledged(purchase_token):
print("Purchase acknowledged: %s" % purchase_token)
func button_request():
iap.request_purchased()
func _on_purchase_consumed(purchase_token):
show_alert("Purchase consumed successfully: %s" % purchase_token)
func button_query():
iap.sku_details_query(["item_test_a", "item_test_b"])
func _on_purchase_error(code, message):
show_alert("Purchase error %d: %s" % [code, message])
func _on_purchase_acknowledgement_error(code, message):
show_alert("Purchase acknowledgement error %d: %s" % [code, message])
func _on_purchase_consumption_error(code, message):
show_alert("Purchase consumption error %d: %s" % [code, message])
func _on_sku_details_query_error(code, message):
show_alert("SKU details query error %d: %s" % [code, message])
func _on_disconnected():
show_alert("GodotPayment disconnected. Will try to reconnect in 10s...")
yield(get_tree().create_timer(10), "timeout")
payment.startConnection()
# GUI
func _on_QuerySkuDetailsButton_pressed():
payment.querySkuDetails([TEST_ITEM_SKU])
func _on_PurchaseButton_pressed():
var response = payment.purchase(TEST_ITEM_SKU)
if response.status != OK:
show_alert("Purchase error %d: %s" % [response.response_code, response.debug_message])
func _on_ConsumeButton_pressed():
if test_item_purchase_token == null:
show_alert("You need to set 'test_item_purchase_token' first! (either by hand or in code)")
return
payment.consumePurchase(test_item_purchase_token)

View File

@@ -7,9 +7,9 @@ anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -512.0
margin_left = -512.711
margin_top = -300.0
margin_right = 512.0
margin_right = 511.289
margin_bottom = 300.0
size_flags_horizontal = 2
size_flags_vertical = 2
@@ -18,71 +18,66 @@ __meta__ = {
"_edit_use_anchors_": false
}
[node name="purchase" type="Button" parent="."]
margin_left = 40.0
margin_top = 40.0
margin_right = 250.0
margin_bottom = 120.0
size_flags_horizontal = 2
size_flags_vertical = 2
text = "Purchase in app"
[node name="consume" type="Button" parent="."]
margin_left = 40.0
margin_top = 150.0
margin_right = 250.0
margin_bottom = 230.0
size_flags_horizontal = 2
size_flags_vertical = 2
text = "Consume in app"
[node name="request" type="Button" parent="."]
margin_left = 40.0
margin_top = 260.0
margin_right = 250.0
margin_bottom = 340.0
size_flags_horizontal = 2
size_flags_vertical = 2
text = "Request purchased"
[node name="query" type="Button" parent="."]
margin_left = 40.0
margin_top = 370.0
margin_right = 250.0
margin_bottom = 450.0
size_flags_horizontal = 2
size_flags_vertical = 2
text = "Query in app items"
[node name="alert" type="AcceptDialog" parent="."]
margin_left = 290.0
margin_top = 60.0
margin_right = 700.0
margin_bottom = 290.0
size_flags_horizontal = 2
size_flags_vertical = 2
[node name="AlertDialog" type="AcceptDialog" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = 64.0
margin_top = 64.0
margin_right = -64.0
margin_bottom = -64.0
grow_horizontal = 2
grow_vertical = 2
rect_min_size = Vector2( 400, 0 )
size_flags_vertical = 4
popup_exclusive = true
dialog_autowrap = true
[node name="Label" type="Label" parent="."]
margin_left = 300.0
margin_top = 40.0
margin_right = 932.0
margin_bottom = 207.0
margin_right = 996.0
margin_bottom = 156.0
size_flags_horizontal = 2
size_flags_vertical = 0
text = "\"iap\" is located in Autoloads. See Project > Project Settings > AutoLoad
text = "To test in-app purchase on android device,
To enable IAP module
1. Project > Project Settings
2. write [Category : android] / [Property : modules] / [Type : String] and click Add
3. Click \"Android\" on left panel
4. double click on right filed of \"modules\"
5. write \"org/godotengine/godot/GodotPaymentV3\"
To test in-app purchase on android device,
1. Need to add \"com.android.vending.BILLING\" permission at Project > Export > Android > User Permissions
1. Make sure you have enabled \"Custom Build\" and the GodotPayment plugin in your Android export settings
2. Export APK and upload it as alpha or beta stage to Google Play Developer Console and publish it.
(It's not published to public, but you and tester can access it.)
3. There should be activated in-app item
4. Any changes on Developer console will take 2~3 hours to take effect"
(It's not published to public, but you and other testers can access it.)
3. There should be an activate in-app item. Copy its SKU into the TEST_ITEM_SKU constant in iap_demo.gd
4. Changes you make in the Play Console may take some time before taking effect"
[node name="QuerySkuDetailsButton" type="Button" parent="."]
margin_left = 40.5697
margin_top = 39.9347
margin_right = 221.57
margin_bottom = 91.9347
text = "Query SKU details"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="PurchaseButton" type="Button" parent="."]
margin_left = 40.5697
margin_top = 101.203
margin_right = 221.57
margin_bottom = 153.203
text = "Purchase"
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ConsumeButton" type="Button" parent="."]
margin_left = 40.5697
margin_top = 162.142
margin_right = 221.57
margin_bottom = 214.142
text = "Consume"
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="pressed" from="QuerySkuDetailsButton" to="." method="_on_QuerySkuDetailsButton_pressed"]
[connection signal="pressed" from="PurchaseButton" to="." method="_on_PurchaseButton_pressed"]
[connection signal="pressed" from="ConsumeButton" to="." method="_on_ConsumeButton_pressed"]

View File

@@ -23,10 +23,6 @@ config/name="Android in-app purchases"
run/main_scene="res://main.tscn"
config/icon="res://icon.png"
[autoload]
iap="*res://iap.gd"
[debug]
gdscript/warnings/return_value_discarded=false