88 lines
3.3 KiB
C#
88 lines
3.3 KiB
C#
using System.Net.Http.Json;
|
|
using System.Reflection;
|
|
|
|
namespace LMEMappeCatastaliApp.Services;
|
|
|
|
public sealed class PlayPurchaseVerificationService
|
|
{
|
|
private const string EndpointMetadataKey = "PlayBillingVerificationUrl";
|
|
private const string RequiredMetadataKey = "PlayBillingVerificationRequired";
|
|
private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(20) };
|
|
|
|
public bool IsConfigured => VerificationEndpoint is not null;
|
|
public bool IsRequired => ReadMetadata(RequiredMetadataKey).Equals("true", StringComparison.OrdinalIgnoreCase);
|
|
|
|
private static Uri? VerificationEndpoint
|
|
{
|
|
get
|
|
{
|
|
var value = ReadMetadata(EndpointMetadataKey);
|
|
return Uri.TryCreate(value, UriKind.Absolute, out var endpoint)
|
|
&& endpoint.Scheme == Uri.UriSchemeHttps
|
|
? endpoint
|
|
: null;
|
|
}
|
|
}
|
|
|
|
public async Task<PlayPurchaseVerificationResult> VerifyAsync(
|
|
string purchaseToken,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var endpoint = VerificationEndpoint;
|
|
if (endpoint is null)
|
|
{
|
|
return PlayPurchaseVerificationResult.NotConfigured();
|
|
}
|
|
|
|
try
|
|
{
|
|
using var response = await _httpClient.PostAsJsonAsync(endpoint, new
|
|
{
|
|
packageName = AppInfo.Current.PackageName,
|
|
productId = EntitlementService.ProductId,
|
|
purchaseToken
|
|
}, cancellationToken);
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
return PlayPurchaseVerificationResult.Failed(
|
|
$"Verifica acquisto non disponibile ({(int)response.StatusCode}).");
|
|
}
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<VerificationResponse>(cancellationToken);
|
|
return result is null
|
|
? PlayPurchaseVerificationResult.Failed("Risposta di verifica acquisto non valida.")
|
|
: new(true, true, result.Active, result.ExpiresAt, result.Message ?? string.Empty);
|
|
}
|
|
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
|
|
{
|
|
return PlayPurchaseVerificationResult.Failed("Il server di verifica acquisti non ha risposto in tempo.");
|
|
}
|
|
catch (Exception error)
|
|
{
|
|
return PlayPurchaseVerificationResult.Failed(
|
|
$"Verifica acquisto non disponibile: {error.GetBaseException().Message}");
|
|
}
|
|
}
|
|
|
|
private static string ReadMetadata(string key) =>
|
|
typeof(PlayPurchaseVerificationService).Assembly
|
|
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
|
.FirstOrDefault(attribute => attribute.Key == key)?.Value?.Trim() ?? string.Empty;
|
|
|
|
private sealed record VerificationResponse(bool Active, DateTimeOffset? ExpiresAt, string? Message);
|
|
}
|
|
|
|
public sealed record PlayPurchaseVerificationResult(
|
|
bool Configured,
|
|
bool Verified,
|
|
bool Active,
|
|
DateTimeOffset? ExpiresAt,
|
|
string Message)
|
|
{
|
|
public static PlayPurchaseVerificationResult NotConfigured() =>
|
|
new(false, false, false, null, "Server di verifica acquisti non configurato.");
|
|
|
|
public static PlayPurchaseVerificationResult Failed(string message) =>
|
|
new(true, false, false, null, message);
|
|
}
|