Implementation of subscriptions and example value for iap.google.notifications_endpoint_id

Hi everyone!

I’m currently implementing IAP’s for our game. I’ve got Google IAP’s working perfectly with additional logic running in “RegisterAfterValidatePurchaseGoogle”.

Now I’m trying to do the same with subscriptions but dealing with a few road blocks.

Issue 1: I don’t seem to have an equivalent to “RegisterAfterValidatePurchaseGoogle” but for subscriptions. I.E.: RegisterAfterValidateSubscriptionGoogle. As such how would I be able to know the user just subscribed?

Issue 2: What value should we use for iap.google.notifications_endpoint_id?
I’m pretty confident we have the setup from google play done correctly as I can see the messages when pressing pull in the Google Cloud Pub/Sub webpage.

The subscription name given by google has the following format (I anonimized these values):
projects/myapp-85069681/subscriptions/MASubs-sub
The value provided in the Nakama documentation is as follows:
/v2/console/google/subscriptions/<notifications_endpoint_id>
I see no overlap in either of these and end up having no idea what to use as notifications_endpoint_id.

Should it be:
/v2/console/google/subscriptions/projects/myapp-85069681/subscriptions/MASubs-sub
or
/v2/console/google/subscriptions/MASubs-sub
I tried both but had no success in having nakama identify the renewal of a subscription.

I’ve even added the iap.google.package_name and set the iap.google.refund_check_period_min to 1 in the config.yml but that doesn’t seem to fix anything either.

I’d really appreciate some help/guidance. We’re using Golang for the backend logic in Nakama 3.14.0 as we had to downgrade from 3.15.0 due to this bug.

To clarify, here is an anonimized version of the relevant part my current config.yml:

  apple:
    shared_password: ''
    notifications_endpoint_id: ''
  google:
    client_email: 'myappnakamabackend@api-2137238579647032880-116300.iam.gserviceaccount.com'
    private_key: "-----BEGIN PRIVATE KEY-----\nA_REALLY_LONG_AND_SECRET_KEY=\n-----END PRIVATE KEY-----\n"
    notifications_endpoint_id: 'MASubs-sub'
    package_name: 'com.company.myapp'
    refund_check_period_min: 1 

Hello @juliobds,

On issue 1: those hooks were omitted by an oversight on some versions of the server, I believe they are included in 3.15 but I see you had to downgrade, we’re close to releasing v3.16 which should solve the issues you’re having.

Issue 2: You can use whatever string is URL safe, the idea for the terminating URL path to be configurable is just so that not all Nakama deployments have the same endpoint set up automatically, and also act as a toggle to expose the endpoint. You could use a randomly generated string, or something like “notifications”. The full URL will be printed in the logs after server startup if the configuration is present. The full URL is then what you should configure in the Google console. Your current configured value of ‘MASubs-sub’ should work :+1:.

Unfortunately, while v3.15 introduced the regression you mentioned, it also fixed a lot of bugs around notification handling, which is likely why you aren’t seeing the renewals. As I mentioned, stay tuned, v3.16.0 should be out really soon. Alternatively, you can build the master branch from source.

Also bear in mind that the server will only handle renewals that have been previously validated using the corresponding API.

Best.

Hi sesposito, first and foremost, thank you for getting back to me.

I’ve been focusing on a different project waiting for the release of Nakama v3.16 and finally was able to focus back on the project I was having the issues with.

Issue 1: Solved by upgrading to v3.16. Great job guys! Thanks for all the effort!

Issue 2: I’m finding it very difficult to know if I have everything set up correctly and the feature isn’t working or if the feature is working but I didn’t configure everything correctly.

In my mind, I would ideally be able to run a piece of code when the subscription gets renewed. Perhaps this is not the way the system should work but I cannot find any further information on this topic anywhere else.

Long story short, how can I test if subscriptions are being renewed and can I run a piece of code when the server detects the renewal? At the moment I’d simply like to run a debug log in order to know that things are indeed working as expected.

Thank you very much for your time and attention.

Thanks for the kind words @juliobds,

If you run the server in debug, it should print a log when a notification is received (but it won’t specify whether a subscription was renewed or not).

The best way right now would be to see the expiry_time be updated for a given subscription after a renewal happens. You can see the current value of the expiry time in the Nakama console under a given account who has an active subscription (which was previously validated using the related API). The docs are a bit outdated so the subscriptions tab is not present there but you should see it in your Nakama version.

We haven’t yet implemented custom hooks for renewals, there are a few reasons for this, the main one being that it’s hard to streamline the API so that it’s the same for each provider, since the notifications are much different between them. However I’d suggest you create a Github issue with a feature request in the Nakama repo for it and we’ll consider it in a future release.

Best.

Hi Sesposito, thanks for your previous answer. I’ve been trying different things on and off but alas, no success.

I’ve been doing that as far as I know by passing the startup parameter “–logger.level DEBUG” and no message is ever triggered related to subscription renewals. I’ve also ran Nakama from source code and added additional log messages in core_subscription.go, in **"func googleNotificationHandler(logger *zap.Logger, db sql.DB, config IAPGoogleConfig) http.HandlerFunc {" to be more precise.

Unlike before, I am now very confident my setup on Google’s side is correct as I can read notifications from the subscription using the following code:

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"cloud.google.com/go/pubsub"
)

func main() {
	// Set your Google Cloud project ID and Pub/Sub subscription name
	projectID := "YOUR PROJECT ID"
	subscriptionName := "YOUR SUBSCRIPTION NAME"

	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
	defer cancel()

	// Create a new Pub/Sub client
	client, err := pubsub.NewClient(ctx, projectID)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}
	defer client.Close()

	// Get a handle for the specified subscription
	sub := client.Subscription(subscriptionName)

	// Receive messages and print them to the console
	err = sub.Receive(ctx, func(ctx context.Context, msg *pubsub.Message) {
		fmt.Printf("Received message: %s\n", msg.Data)
		msg.Ack()
	})
	if err != nil {
		log.Fatalf("Failed to receive messages: %v", err)
	}
}

To anyone that finds this code useful to test your Google backend setup you’ll have to create an environment variable pointing to your .json credentials. In a Mac this would be done with:

export GOOGLE_APPLICATION_CREDENTIALS="/Path/to/your/google/applications/credentials/appname-80122638-12431ff11581.json"

From this I’m concluding the setup on Google’s side is done correctly as I can see the notifications of the events being renewed, however the same doesn’t happen within Nakama. The expiry date displayed in the Nakama console is never updated (Neither are the additional debug logs I added directly to the source code).

I also tried to pass the contents of my .json credentials through the startup commands when starting Nakama, with the “–google_auth.credentials_json=” parameter. I made sure to add ““redirect_uris”: [“urn:ietf:wg:oauth:2.0:oob”]” to the json content as explained in this forum post. Not sure what that does or even why we need to add it manually, heck, I don’t even know what exactly to add between the square braces, there’s simply no documentation that I can find that explains this process step by step. It’s extremely frustrating to say the least.

At this point I’m stuck, not sure where to move or even what else to try to receive the notifications within Nakama.

Any help or direction would be greatly appreciated. :pray:

Hello @juliobds,

The google_auth.credentials_json config should be unrelated to the IAP notifications. The credentials the server uses (in the IAP config section) are the same that are used to validate a subscription using the API, so if validating a subscription receipt works, the notification should work as well.

The test you’ve set up seems to rely on pub/sub, I don’t think that will work the same as with the Nakama setup, as the latter relies on receiving the notifications via an HTTP hook, not a pub/sub socket connection (I’m assuming that’s what Google sdk is doing in your code).

We’ve had some users that were able to successfully receive and process Google’s subscription notifications, are you sure your Nakama endpoint is correctly configured, publicly accessible and behind HTTPS? Otherwise Google might not accept it as a valid endpoint.

Best.