+2 votes


I am currently trying to implement in-app-purchases on iOS. But the documentation ( https://docs.godotengine.org/en/3.1/tutorials/platform/services_for_ios.html ) seems to be lacking some infos. From various threads I gathered some infos and achieved the following simple wip helper class, which is working on Android so far:

extends Node

signal purchase_success(item_name)

enum modes {Android, iOS, Other}

var currentMode 
var payment
var timer

func _ready():
    # check for android
    if Engine.has_singleton("GodotPayments"):
        payment = Engine.get_singleton("GodotPayments")
        currentMode = modes.Android
        print("Using Android IAP")
    elif Engine.has_singleton("InAppStore"):
        payment = Engine.get_singleton("InAppStore")
        currentMode = modes.iOS
        print("Using iOS IAP")
        currentMode = modes.Other
        print("Using no IAP")

    if currentMode == modes.Android and payment:
        # set callback with this script instance

# purchase item
# callback : purchase_success, purchase_fail, purchase_cancel, purchase_owned
func purchase(item_name):
    if payment:
        if currentMode == modes.Android:
            # transaction_id could be any string that used for validation internally in java
            payment.purchase(item_name, "transaction_id")
        elif currentMode == modes.iOS:
            var result = payment.purchase({"product_id":  item_name})
            if result == OK:
                print('Ok, purchasing')
                return true
                print("Purchase Error")

func _listenForSuccess():
    timer = Timer.new()
    timer.autostart = true
    timer.one_shot = false
    timer.wait_time = 1.0
    timer.connect("timeout", self, "check_events")

# put this on a 1 second timer or something
func check_events():
    if currentMode == modes.iOS:
        while payment.get_pending_event_count() > 0:
            var event = payment.pop_pending_event()
            if event.type == "purchase":
                if event.result == "ok":
                    emit_signal("purchase_success", event.product_id)

func purchase_success(_receipt, _signature, sku):
    print("purchase_success : ", sku)
    emit_signal("purchase_success", sku)

I also tried to replace this line:

var result = payment.purchase({"product_id":  item_name})

with this:

var result = payment.purchase({"product_id": "com.company.game." + item_name})

The doc isn't clear about how the product id should look like.

I exported the project to xCode and uploaded it to the appstore from there. Afterwards I added the build to the internat test group and am running the app through TestFlight. When I get the the point where the function is called nothing happens.

I also don't know how to get some logs from apps running in testflight, so that would be helpful, too.

Any hints would be really appreciated, thanks in advance!

in Engine by (179 points)

I made my own logging with labels and found out, that the initial purchase call is successful and the event from the queue just stores the information that an error occured, nothing more.

Wait, which version of the product id worked?

Because mine are always said to be invalid.

1 Answer

0 votes

I can't get the purchases to work. I have created a purchase in the App store connect with an ID and followed the commands in the tutorial, but I always get this error:

Condition "!params.has("productid")" is true. Returned: ERRINVALID_PARAMETER

by (24 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.