mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 06:09:46 +03:00
Update Android IAP demo for 3.2.2
This commit is contained in:
@@ -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")
|
||||
@@ -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)
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user