1
0
mirror of https://github.com/bitwarden/server.git synced 2025-02-28 03:51:23 +01:00

apple iap service

This commit is contained in:
Kyle Spearrin 2019-09-17 19:48:40 -04:00
parent 7a2e86c2ba
commit 8290ddbb94
2 changed files with 72 additions and 2 deletions

View File

@ -1,9 +1,15 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace Bit.Core.Services
{
public interface IAppleIapService
{
Task<bool> VerifyReceiptAsync(string receiptData);
Task<string> GetVerifiedLastTransactionIdAsync(string receiptData);
Task<DateTime?> GetVerifiedLastExpiresDateAsync(string receiptData);
string HashReceipt(string receiptData);
Task SaveReceiptAsync(string receiptData);
Task<string> GetReceiptAsync(string hash);
}
}

View File

@ -1,7 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Bit.Billing.Models;
using Bit.Core.Repositories;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -13,20 +18,79 @@ namespace Bit.Core.Services.Implementations
private readonly HttpClient _httpClient = new HttpClient();
private readonly GlobalSettings _globalSettings;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IMetaDataRespository _metaDataRespository;
private readonly ILogger<AppleIapService> _logger;
public AppleIapService(
GlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IMetaDataRespository metaDataRespository,
ILogger<AppleIapService> logger)
{
_globalSettings = globalSettings;
_hostingEnvironment = hostingEnvironment;
_metaDataRespository = metaDataRespository;
_logger = logger;
}
public async Task<bool> VerifyReceiptAsync(string receiptData)
{
var receiptStatus = await GetVerifiedReceiptStatusAsync(receiptData);
return receiptStatus != null;
}
public async Task<string> GetVerifiedLastTransactionIdAsync(string receiptData)
{
var receiptStatus = await GetVerifiedReceiptStatusAsync(receiptData);
return receiptStatus?.LatestReceiptInfo?.LastOrDefault()?.TransactionId;
}
public async Task<DateTime?> GetVerifiedLastExpiresDateAsync(string receiptData)
{
var receiptStatus = await GetVerifiedReceiptStatusAsync(receiptData);
return receiptStatus?.LatestReceiptInfo?.LastOrDefault()?.ExpiresDate;
}
public string HashReceipt(string receiptData)
{
using(var sha256 = SHA256.Create())
{
var hash = sha256.ComputeHash(Convert.FromBase64String(receiptData));
return BitConverter.ToString(hash).Replace("-", string.Empty);
}
}
public async Task SaveReceiptAsync(string receiptData)
{
var hash = HashReceipt(receiptData);
await _metaDataRespository.UpsertAsync("appleReceipt", hash,
new KeyValuePair<string, string>("data", receiptData));
}
public async Task<string> GetReceiptAsync(string hash)
{
var receipt = await _metaDataRespository.GetAsync("appleReceipt", hash);
return receipt != null && receipt.ContainsKey("data") ? receipt["data"] : null;
}
private async Task<AppleReceiptStatus> GetVerifiedReceiptStatusAsync(string receiptData)
{
var receiptStatus = await GetReceiptStatusAsync(receiptData);
return receiptStatus?.Status == 0;
if(receiptStatus?.Status != 0)
{
return null;
}
var validEnvironment = (!_hostingEnvironment.IsProduction() && receiptStatus.Environment == "Sandbox") ||
(_hostingEnvironment.IsProduction() && receiptStatus.Environment != "Sandbox");
var validProductBundle = receiptStatus.Receipt.BundleId == "com.bitwarden.desktop" ||
receiptStatus.Receipt.BundleId == "com.8bit.bitwarden";
var validProduct = receiptStatus.LatestReceiptInfo.LastOrDefault()?.ProductId == "premium_annually";
if(validEnvironment && validProductBundle && validProduct)
{
return receiptStatus;
}
return null;
}
private async Task<AppleReceiptStatus> GetReceiptStatusAsync(string receiptData, bool prod = true,