October 21, 2024
Chicago 12, Melborne City, USA
Android

Getting 401 Unauthorized response for Apple Developer API call


I have implemented subscription purchase using Plugin.InAppBilling package and its codes are below.

private async void PlanClicked(Object sender, EventArgs e)
{
    UserDialogs.Instance.ShowLoading("");
    if (IsBusy)
        return;

    IsBusy = true;
    try
    {
        // check internet first with Essentials
        if (Connectivity.NetworkAccess != NetworkAccess.Internet)
            return;

        // connect to the app store api
        var connected = await CrossInAppBilling.Current.ConnectAsync();
        if (!connected)
            return;

        UserDialogs.Instance.HideHud();
        //try to make purchase, this will return a purchase, empty, or throw an exception
        var purchase = await CrossInAppBilling.Current.PurchaseAsync(productId, ItemType.Subscription);

        if (purchase == null)
        {
            //nothing was purchased
            return;
        }

        if (purchase.State == PurchaseState.Purchased)
        {
            Debug.WriteLine("Purchase successfull");
            Debug.WriteLine("Purchase token:>>" + purchase.PurchaseToken);
            Debug.WriteLine("Purchase id:>>" + purchase.Id);
        }
        else
        {
            throw new InAppBillingPurchaseException(PurchaseError.GeneralError);
        }
    }
    catch (InAppBillingPurchaseException purchaseEx)
    {
        // Handle all the different error codes that can occure and do a pop up
        Debug.WriteLine("purchaseEx:>>" + purchaseEx);
    }
    catch (Exception ex)
    {
        // Handle a generic exception as something really went wrong
        Debug.WriteLine("exception:>>" + ex);
    }
    finally
    {
        await CrossInAppBilling.Current.DisconnectAsync();
        IsBusy = false;
    }
}

After successful purchase I get the PurchaseToken and ID from app store and play store.

Now using this I need to fetch the subscription details of a user. Which App Store Developer API and Play Store Developer API are suit for this?

I tried using this API from Apple and this API from Play Store. Is this the correct API to fetch the subscription details?

When I try the Apple API I am getting the 401 Unauthorized response.

Using below code I am generating the JWT token.

private string LoadPrivateKey()
{
    string fileName = "API key (.p8 file)";

    using var stream = FileSystem.OpenAppPackageFileAsync(fileName).Result;
    using var reader = new StreamReader(stream);
    var privateKey = reader.ReadToEnd();

    // Remove the header and footer lines
    privateKey = privateKey
        .Replace("-----BEGIN PRIVATE KEY-----", string.Empty)
        .Replace("-----END PRIVATE KEY-----", string.Empty)
        .Replace("\n", string.Empty)
        .Replace("\r", string.Empty);

    return privateKey;
}

public async void JWTGenerator(Object sender, EventArgs e)
{
    try
    {
        // Key ID from Apple Developer account
        string keyId = "keyId";

        // Team ID from Apple Developer account
        string teamId = "teamId";

        // Load your private key from the .p8 file
        string privateKey = LoadPrivateKey();

        // Call the GenerateToken method to create a JWT
        string jwtToken = AppleApiTokenGenerator.GenerateToken(keyId, teamId, privateKey);
        DisplayAlert("JWT Token", jwtToken, "OK");
    }
    catch (Exception ex)
    {
        Debug.WriteLine("JWTException:>" + ex);
    }

}

public class AppleApiTokenGenerator
{
    public static string GenerateToken(string keyId, string teamId, string privateKey)
    {
        byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = new SymmetricSecurityKey(Convert.FromBase64String(privateKey));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[]
            {
        new Claim(JwtRegisteredClaimNames.Iss, teamId),
        new Claim(JwtRegisteredClaimNames.Aud, "https://api.storekit-sandbox.itunes.apple.com/inApps/v1/subscriptions/{transactionId}"),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
    }),
            Expires = DateTime.UtcNow.AddMinutes(20),
            SigningCredentials = credentials
        };

        var token = tokenHandler.CreateToken(tokenDescriptor);
        Console.WriteLine($"JWT token:{tokenHandler.WriteToken(token)}");
        return tokenHandler.WriteToken(token);
    }
}

The .P8 file we have added under the Recourses/Row and set the build action as a MauAsset.

Can anyone provide a solution or guidance?

Thanks in advance for your help!



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video