mirror of
https://github.com/bitwarden/server.git
synced 2025-04-15 18:18:12 -05:00
update to apple iap service
This commit is contained in:
parent
ed7da76bac
commit
68b5ba6474
@ -1,15 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.Billing.Models;
|
||||||
|
|
||||||
namespace Bit.Core.Services
|
namespace Bit.Core.Services
|
||||||
{
|
{
|
||||||
public interface IAppleIapService
|
public interface IAppleIapService
|
||||||
{
|
{
|
||||||
Task<bool> VerifyReceiptAsync(string receiptData);
|
Task<AppleReceiptStatus> GetVerifiedReceiptStatusAsync(string receiptData);
|
||||||
Task<string> GetVerifiedLastTransactionIdAsync(string receiptData);
|
Task SaveReceiptAsync(AppleReceiptStatus receiptStatus);
|
||||||
Task<DateTime?> GetVerifiedLastExpiresDateAsync(string receiptData);
|
Task<Tuple<string, Guid?>> GetReceiptAsync(string originalTransactionId);
|
||||||
string HashReceipt(string receiptData);
|
|
||||||
Task SaveReceiptAsync(string receiptData);
|
|
||||||
Task<string> GetReceiptAsync(string hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,47 +34,7 @@ namespace Bit.Core.Services.Implementations
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> VerifyReceiptAsync(string receiptData)
|
public async Task<AppleReceiptStatus> GetVerifiedReceiptStatusAsync(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);
|
var receiptStatus = await GetReceiptStatusAsync(receiptData);
|
||||||
if(receiptStatus?.Status != 0)
|
if(receiptStatus?.Status != 0)
|
||||||
@ -86,13 +46,41 @@ namespace Bit.Core.Services.Implementations
|
|||||||
var validProductBundle = receiptStatus.Receipt.BundleId == "com.bitwarden.desktop" ||
|
var validProductBundle = receiptStatus.Receipt.BundleId == "com.bitwarden.desktop" ||
|
||||||
receiptStatus.Receipt.BundleId == "com.8bit.bitwarden";
|
receiptStatus.Receipt.BundleId == "com.8bit.bitwarden";
|
||||||
var validProduct = receiptStatus.LatestReceiptInfo.LastOrDefault()?.ProductId == "premium_annually";
|
var validProduct = receiptStatus.LatestReceiptInfo.LastOrDefault()?.ProductId == "premium_annually";
|
||||||
if(validEnvironment && validProductBundle && validProduct)
|
if(validEnvironment && validProductBundle && validProduct &&
|
||||||
|
receiptStatus.GetOriginalTransactionId() != null &&
|
||||||
|
receiptStatus.GetLastTransactionId() != null)
|
||||||
{
|
{
|
||||||
return receiptStatus;
|
return receiptStatus;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task SaveReceiptAsync(AppleReceiptStatus receiptStatus)
|
||||||
|
{
|
||||||
|
var originalTransactionId = receiptStatus.GetOriginalTransactionId();
|
||||||
|
if(string.IsNullOrWhiteSpace(originalTransactionId))
|
||||||
|
{
|
||||||
|
throw new Exception("OriginalTransactionId is null");
|
||||||
|
}
|
||||||
|
await _metaDataRespository.UpsertAsync("AppleReceipt", originalTransactionId,
|
||||||
|
new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
["Data"] = receiptStatus.GetReceiptData(),
|
||||||
|
["UserId"] = receiptStatus.GetReceiptData()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Tuple<string, Guid?>> GetReceiptAsync(string originalTransactionId)
|
||||||
|
{
|
||||||
|
var receipt = await _metaDataRespository.GetAsync("AppleReceipt", originalTransactionId);
|
||||||
|
if(receipt == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Tuple<string, Guid?>(receipt.ContainsKey("Data") ? receipt["Data"] : null,
|
||||||
|
receipt.ContainsKey("UserId") ? new Guid(receipt["UserId"]) : (Guid?)null);
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<AppleReceiptStatus> GetReceiptStatusAsync(string receiptData, bool prod = true,
|
private async Task<AppleReceiptStatus> GetReceiptStatusAsync(string receiptData, bool prod = true,
|
||||||
int attempt = 0, AppleReceiptStatus lastReceiptStatus = null)
|
int attempt = 0, AppleReceiptStatus lastReceiptStatus = null)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user