mirror of
https://github.com/signalapp/Signal-Server
synced 2026-08-05 04:46:23 +01:00
Select only matching entitlements from storekit list
Co-authored-by: Jon Chambers <63609320+jon-signal@users.noreply.github.com>
This commit is contained in:
+22
-11
@@ -9,14 +9,18 @@ import com.apple.itunes.storekit.model.AutoRenewStatus;
|
||||
import com.apple.itunes.storekit.model.Status;
|
||||
import com.apple.itunes.storekit.model.StatusResponse;
|
||||
import com.apple.itunes.storekit.model.SubscriptionGroupIdentifierItem;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
|
||||
@@ -165,23 +169,20 @@ public class AppleAppStoreManager implements SubscriptionPaymentProcessor {
|
||||
|
||||
final List<AppleAppStoreDecodedTransaction> txs = item.getLastTransactions().stream()
|
||||
.map(txItem -> appleAppStoreClient.verify(statuses.getEnvironment(), txItem))
|
||||
.filter(tx -> tx.signedTransaction().getOriginalTransactionId().equals(originalTransactionId))
|
||||
.filter(decoded -> productIdToLevel.containsKey(decoded.transaction().getProductId()))
|
||||
.toList();
|
||||
|
||||
if (txs.isEmpty()) {
|
||||
throw new SubscriptionInvalidArgumentsException("transactionId did not include a paid subscription", null);
|
||||
}
|
||||
|
||||
if (txs.size() > 1) {
|
||||
logger.warn("Multiple matching product transactions found for transactionId {}, only considering first",
|
||||
originalTransactionId);
|
||||
}
|
||||
|
||||
if (!originalTransactionId.equals(txs.getFirst().signedTransaction().getOriginalTransactionId())) {
|
||||
// Get All Subscriptions only requires that the transaction be some transaction associated with the
|
||||
// subscription. This is too flexible, since we'd like to key on the originalTransactionId in the
|
||||
// SubscriptionManager.
|
||||
throw new SubscriptionInvalidArgumentsException("transactionId was not the transaction's originalTransactionId", null);
|
||||
throw new SubscriptionInvalidArgumentsException("transactionId did not include a paid subscription or the provided transactionId was not an originalTransactionId", null);
|
||||
}
|
||||
|
||||
if (txs.size() > 1) {
|
||||
logger.warn("Multiple matching product transactions found with a sha256(originalTransactionId)={}, only considering first",
|
||||
sha256(originalTransactionId));
|
||||
}
|
||||
return txs.getFirst();
|
||||
}
|
||||
@@ -210,4 +211,14 @@ public class AppleAppStoreManager implements SubscriptionPaymentProcessor {
|
||||
|| tx.signedTransaction().getStatus() == Status.BILLING_GRACE_PERIOD;
|
||||
}
|
||||
|
||||
private static String sha256(final String input) {
|
||||
final MessageDigest sha256;
|
||||
try {
|
||||
sha256 = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError("Every implementation of the Java platform is required to support SHA-256", e);
|
||||
}
|
||||
return Base64.getEncoder().encodeToString(sha256.digest(input.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+22
@@ -147,6 +147,28 @@ class AppleAppStoreManagerTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleLastTransactionsItems()
|
||||
throws VerificationException, APIException, IOException, SubscriptionPaymentRequiredException, SubscriptionInvalidArgumentsException, SubscriptionNotFoundException, RateLimitExceededException {
|
||||
when(apiClient.getAllSubscriptionStatuses(ORIGINAL_TX_ID, new Status[]{}))
|
||||
.thenReturn(new StatusResponse()
|
||||
.data(List.of(new SubscriptionGroupIdentifierItem()
|
||||
.subscriptionGroupIdentifier(SUBSCRIPTION_GROUP_ID)
|
||||
.addLastTransactionsItem(new LastTransactionsItem()
|
||||
.originalTransactionId(ORIGINAL_TX_ID + "-different")
|
||||
.status(Status.ACTIVE)
|
||||
.signedRenewalInfo(SIGNED_RENEWAL_INFO)
|
||||
.signedTransactionInfo(SIGNED_TX_INFO))
|
||||
.addLastTransactionsItem(new LastTransactionsItem()
|
||||
.originalTransactionId(ORIGINAL_TX_ID)
|
||||
.status(Status.ACTIVE)
|
||||
.signedRenewalInfo(SIGNED_RENEWAL_INFO)
|
||||
.signedTransactionInfo(SIGNED_TX_INFO))))
|
||||
.environment(Environment.PRODUCTION));
|
||||
mockDecode(AutoRenewStatus.ON);
|
||||
assertThat(appleAppStoreManager.validateTransaction(ORIGINAL_TX_ID)).isEqualTo(LEVEL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cancelRenewalDisabled() throws APIException, VerificationException, IOException {
|
||||
mockSubscription(Status.ACTIVE, AutoRenewStatus.OFF);
|
||||
|
||||
Reference in New Issue
Block a user