I created a project to validate in-app purchase receipts using c# but I always get error 401, you don't have permission, I followed the instructions exactly but still failed, I created a private key in Certificates, IDs & Profiles and download the .p8 file but it still doesn't work, I also created and tried another key in Users and Access > Integrations > App Store Connect API and also In-App Purchase but it still doesn't work. When I try to put the created token on jwt.io, I always get an Invalid Signature error
using Jose; using System; using System.Collections.Generic; using System.Net.Http.Headers; using System.Net.Http; using System.Security.Cryptography; using System.Threading.Tasks; using System.IO; using System.Net;
namespace CheckIAP { internal class Program
{
static async Task Main(string[] args)
{
string jwtToken = GenerateAppStoreJwtToken();
string transactionId = "110002159078***";
Console.WriteLine(jwtToken);
string url = $"https://api.storekit.itunes.apple.com/inApps/v2/history/{transactionId}";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string responseData = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseData);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}, {response.ReasonPhrase}");
string responseData = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseData);
}
}
Console.ReadLine();
}
public static string GenerateAppStoreJwtToken()
{
string teamId = "PZG479xxxx";
string keyId = "JCXH26xxxx";
string issuerId = "7aa0c9c2-***-***-***-xxxx";
string bundleId = "com.***.***";
const string API_KEY = "MIGTAgEAMBMGByqGSM....";
var header = new Dictionary<string, object>()
{
{ "alg", "ES256" },
{ "kid", keyId },
{ "typ", "JWT" }
};
var payload = new Dictionary<string, object>
{
{ "iss", issuerId },
{ "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
{ "exp", DateTimeOffset.UtcNow.AddMinutes(15).ToUnixTimeSeconds() },
{ "aud", "appstoreconnect-v1" },
{ "sub", bundleId }
};
var key = CngKey.Import(Convert.FromBase64String(API_KEY),
CngKeyBlobFormat.Pkcs8PrivateBlob);
return Jose.JWT.Encode(payload, key, JwsAlgorithm.ES256, header);
}
}
}