godotengine / godot-ios-plugins

MIT License
126 stars 48 forks source link

Documentation Doesn't explain how to consume a consumable in app purchase #18

Closed Tekuzo closed 3 years ago

Tekuzo commented 3 years ago

The documentation doesn't mention how to consume a consumable in app purchase.

I have an In App Purchase set up as a consumable in AppStoreConnect but when I try to purchase it multiple times it will not go through. There is a finish_transaction() function that the readme has, that is missing from the documentation on the Godot homepage.

I am confused about what to do. AppStoreConnect will not let me purchase this IAP a second time because I already have it, every time I click the button to initiate my purchase event, the receipt in the returned dictionary is always the same.

Thank you

naithar commented 3 years ago

Handling purchases should be done entirely by developer. It can be done either in application/game code or using server. You can use product_id field to check product identifier that user have purchased and handle it appropriately. Using finish_transaction is not necessary if you are calling set_auto_finish_transaction(true) when initializing the plugin.

You should be able to find more information about that in Apple's documentation or any other site that provide tutorials on iOS specific SDKs, for example: https://www.raywenderlich.com/1145-in-app-purchases-tutorial-consumables.

Tekuzo commented 3 years ago

Ok, well that isn't explained in the documentation.

The Store Kit API is accessible through the InAppStore singleton. It is initialized automatically.

naithar commented 3 years ago

Ok, well that isn't explained in the documentation

What exactly is not explained? If you mean that not every method is listed on documentation page, then yes - documentation should be updated, but you have already created an issue covering that: https://github.com/godotengine/godot-docs/issues/4900

Tekuzo commented 3 years ago

No, I am confused because your recommendation, which seems to be helping so thank you very much, directly contradicts the written explanation from the docs.

The docs say that the plugin is initialized automatically, and you were telling me to call set_auto_finish_transaction(true) during the init. This is a step that I didn't take because the docs said not to do it and it led to some problems.

naithar commented 3 years ago

The plugin is initialized automatically - you don't have to create it's singleton and delegates. set_auto_finish_transaction is on application initialization side so maybe it's better to call it a setup step.

mobiusstrip commented 4 months ago

@Tekuzo @naithar

could you also take a look at my code please i compiled my project and exported to xcode with the plugin enabled but i dont know how to proceed

on ui

func _on_buy_button_10_shards_pressed():
    Purchase.purchase("com.prism.spire.shards.ten","Shards 10")
    new_shard_value=GameDataManager.level_info[0]["shards"]+10
    GameDataManager.modify_dict(0,"shards",new_shard_value)

on purchase singleton


extends Node2D

signal purchase_confirmed
var _appstore = null

func check_events():
    while _appstore.get_pending_event_count() > 0:
        var event = _appstore.pop_pending_event()
        if event.result=="ok": # other possible values are "progress", "error", "unhandled", "completed"
                match event.type:
                    'product_info':
                # fields: titles, descriptions, prices, ids, localized_prices, currency_codes, invalid_ids
                        pass
                    'purchase':
                # fields: product_id, transaction_id, receipt
                        pass
                    'restore':
                        # fields: product_id, transaction_id, receipt
                        pass
                    'completed':
                        # Now the last in-app purchase restore has been sent,
                        # so if you didn't get any, the user doesn't have
                        # any purchases to restore.
                        pass

func purchase(product_id,reference_name):
    var result = _appstore.purchase({str(product_id): str(reference_name)})

func restore(): # such button is required by Apple for non-consumable products
    var result = _appstore.restore_purchases()

func _ready():
    if Engine.has_singleton("InAppStore"):
        _appstore = Engine.get_singleton('InAppStore')
    else:
        print("no app store plugin")
    var result = _appstore.request_product_info( { "product_ids": ["com.prism.spire.shards.ten", "com.prism.spire.shards.hundred", "com.prism.spire.shards.onethousand", "com.prism.spire.shards.twohundredfifty", "com.prism.spire.shards.fifty", "com.prism.spire.shards.fivehundred"] } )
    if result == OK:
        print("Successfully started product info request")
        _appstore.set_auto_finish_transaction(true)
        var timer = Timer.new()
        timer.wait_time = 1
#       timer.connect("timeout", self, 'check_events')
        await get_tree().create_timer(check_events()).timeout
        add_child(timer)
        timer.start()
    else:
        print("failed requesting product info")