question

studioalfredwalker avatar image
studioalfredwalker asked

LinkGoogleAccount Issue - already linked account error & already redeemed error

Hi there.

I am trying to use LinkGoogleAccount to link a Google Play Games account to the user's PlayFab account (logined by AndroidDeviceID already).

Attached codes include login with android device ID and linking in current project, and now I am in trouble in dealing with two errors.

1. already linked error

After first request in an the LinkGoogleAccount(), error message says that google account I choose to link is already linked.

  • There is only one player in the Players in "Players" of the game manager.
  • There was few players in past, but I deleted all the player excepts one. (yesterday)
    (Is this error related to dummay account left?)
  • Left only one player is now linked with android device only.
  • Is it necessary to unlink already linked android device before linking google account?
    like an image of below link says?
    (https://api.playfab.com/docs/tutorials/landing-players/account-linking)

2. Google API error code: invalid grant details: already redeemed

I get an API error code when I try to set forceLink to true at second request of LinkGoogleAccount().

  • As far as I know, PlayGamesPlatform.Instance.GetServerAuthCode() is for one time usage, so should I sign out before sending second request? or is there any way to get refreshed serverauthcode?

I'm not sure I described my problem correctly.

Please let me know if any additional information is required.

Thanks.

P.S. Is there any sample projects for beginner like Unicorn Battle project posted in last year? I cannot find recent sample projects excepts (https://api.playfab.com/docs/tutorials/landing-players/sign-in-with-google).

    /// <summary>
    /// Logins the with device identifier (Android only).
    /// </summary>
    public static void LoginWithDeviceId(bool createAccount)
    {
        if (GetDeviceId())
        {
            if (!string.IsNullOrEmpty(android_id))
            {
                var request = new LoginWithAndroidDeviceIDRequest
                {
                    AndroidDeviceId = android_id,
                    TitleId = PlayFabSettings.TitleId,
                    CreateAccount = createAccount
                };


                // Request loading prompt here (to be implemented)
                PlayFabClientAPI.LoginWithAndroidDeviceID(request, OnLoginWithDeviceIDResult, (PlayFabError error) =>
                {
                    if (error.Error == PlayFabErrorCode.AccountNotFound)
                    {
                        PopupUIController.Instance.ShowLogin();	// Users chooses auth method (guest, google)
                        PF_Bridge.RaiseCallbackError("Account not found, please select a login method to continue.", PlayFabAPIMethods.GenericLogin, MessageDisplayStyle.error);
                    }
                    else
                    {
                        RetryLoginWithDeviceID("No response from server.", createAccount);
                        // OnLoginError(error);
                    }
                });
            }
            else
            {
                PopupUIController.Instance.ShowLogin();
                PF_Bridge.RaiseCallbackError("Account not found. \nPlease select a login method to continue.", PlayFabAPIMethods.GenericLogin, MessageDisplayStyle.error);
            }
        }
        else
        {
            PopupUIController.Instance.ShowLogin();
            PF_Bridge.RaiseCallbackError("Device ID is not found. \nPlease select a login method to continue", PlayFabAPIMethods.GenericLogin, MessageDisplayStyle.error);
            // Debug.Log("Device ID is not found.");
        }
    }



    


/// <summary>
    /// Called on a successful login attempt
    /// </summary>
    /// <param name="result">Result object returned from PlayFab server</param>
    private static void OnLoginWithDeviceIDResult(PlayFab.ClientModels.LoginResult result) //LoginResult
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            LinkDeviceId();
            
            PlayerPrefs.SetString("AuthMethod", "AndroidDeviceID");

            PlayerPrefs.Save();
        }


        PopupUIController.Instance.HideLogin();  // Hide auth method selection


        PF_Bridge.RaiseCallbackSuccess(string.Empty, PlayFabAPIMethods.GenericLogin, MessageDisplayStyle.none);
        if (OnLoginSuccess != null)
            OnLoginSuccess(string.Format("SUCCESS: {0}", result.SessionTicket), MessageDisplayStyle.error);
    }


/// <summary>
    /// Links a mobile device to a PlayFab account via the unique device id (A device can only be linked to one account at a time)
    /// </summary>
    public static void LinkDeviceId()
    {
        if (!GetDeviceId())
            return;


        UnityAction<PlayFabError> onLinkError = error =>
        {
            PF_Bridge.PlayFabErrorCallback(error);
        };


        if (!string.IsNullOrEmpty(android_id))
        {
            // Request loading prompt here (to be implemented)
            var request = new LinkAndroidDeviceIDRequest { AndroidDeviceId = android_id };
            PF_Bridge.RaiseCallbackSuccess(string.Empty, PlayFabAPIMethods.LinkDeviceID, MessageDisplayStyle.none);
            PlayFabClientAPI.LinkAndroidDeviceID(request, OnAndroidDeviceIDLinkSuccessed, error => { onLinkError(error); });
        }
    }


public static void LinkGoogleAccount()
{
	Social.localUser.Authenticate((success) =>
        {
            if (success)
            {
                // Request loading prompt here (to be implemented)


#if UNITY_ANDROID
                var serverAuthCode = PlayGamesPlatform.Instance.GetServerAuthCode();
                var request = new LinkGoogleAccountRequest()
                {
                    ForceLink = false,
                    ServerAuthCode = serverAuthCode
                };


                PlayFabClientAPI.LinkGoogleAccount(request, OnGoogleAccountLinkSuccessed, error =>
                {
                    if (error.ErrorMessage.Contains("already linked"))
                    {
                       // Close loading prompt here (to be implemented)


                        Action<bool> afterConfirm = (bool response) =>
                        {
                            if (!response)
                                return;


                            // Request loading prompt here (to be impelmented)
                            request.ForceLink = true;
                            PlayFabClientAPI.LinkGoogleAccount(request, OnGoogleAccountLinkSuccessed, PF_Bridge.PlayFabErrorCallback);
                        };

                        DialogueCanvasController.RequestConfirmationPrompt("Caution!\nSelected google account is already linked to another play. Do you want to force-bind your google account to this play?", afterConfirm);
                    }
                    else
                    {
                        PF_Bridge.RaiseCallbackError(error.ErrorMessage, PlayFabAPIMethods.LinkGoogleAccount, MessageDisplayStyle.error);
                        return;
                    }
                });
#endif
            }
            else
            {
                PopupUIController.Instance.ShowSimpleInfo(-1, "Google Authentication failed.\n<");
            }
        });
    }


Account Management
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

1 Answer

·
brendan avatar image
brendan answered

No, the already linked error means exactly that - that the (Google, in this case) account you are attempting to link to the PlayFab account is already linked to another account. What's likely tripping you up is that the account is queued for deletion when you use that option - there's a more complete discussion on this here: https://community.playfab.com/questions/6720/deleting-users-from-playfab.html. We'll be making some changes to that process in the near future, to help simplify this.

And yes, Google server auth codes are one-time-use, so they cannot be re-used between attempts to link to the player account. So you'll need to request a new server auth code from Google, in that case.

For samples, and specifically related to your questions, I'd recommend our Google sign-in sample: https://github.com/PlayFab/PlayFab-Samples/tree/master/Recipes/GoogleSignInSample.

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image brendan ♦♦ commented ·

Correction and clarification:

When you use the delete player option, the player account is queued for deletion. The deletion process removes all title-specific aspects of the player - statistics, player data, title display name, inventory, etc.

However, the "core" of the player account lives at the Publisher ID level - that's where all the credentials live, as well as the Username. That's how you can have a player sign into one title, and then sign into another, and have all the data for that player be associated with a single PlayFab ID (and so, share data across titles using player publisher data).

Apologies for the confusion on this.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.