App Store Server Java Library

repository·main·Indexed 42 days ago

https://github.com/apple/app-store-server-library-java

A client-side Java 11+ implementation for interacting with Apple's App Store Server APIs. The library provides tools for handling notifications, verifying signed data via SignedDataVerifier, managing promotional offers with PromotionalOfferSignatureCreator, and migrating legacy receipts using ReceiptUtility. Version 5.2.0.

Tokens
2.5K
Snippets
5
Records
7
Agent score
5%

What's inside App Store Server Library for Java

  1. Install the App Store Server Java Library

    main

    The library requires Java 11+. You can install it using Gradle or Maven.

    Gradle

    Add the following to your build.gradle file:

    Maven

    Add the following to your pom.xml file:

    implementation 'com.apple.itunes.storekit:app-store-server-library:5.2.0'
    <dependency>
        <groupId>com.apple.itunes.storekit</groupId>
        <artifactId>app-store-server-library</artifactId>
        <version>5.2.0</version>
    </dependency>
  2. Obtain App Store Server API credentials

    main

    To use the App Store Server API or create promotional offer signatures, you need a signing key from App Store Connect.

    1. Log in to App Store Connect with an Admin role.
    2. Navigate to Users and Access > Integrations > In-App Purchase.
    3. Create or manage keys to obtain your:
      • Signing Key (a .p8 file)
      • Key ID
      • Issuer ID
  3. Migrate legacy receipts to transaction history

    main

    Use ReceiptUtility to extract a transactionId from a legacy App Receipt. Once you have the ID, you can use AppStoreServerAPIClient.getTransactionHistory to retrieve the full transaction history using the V2 API.

    import com.apple.itunes.storekit.client.AppStoreServerAPIClient;
    import com.apple.itunes.storekit.client.GetTransactionHistoryVersion;
    import com.apple.itunes.storekit.migration.ReceiptUtility;
    import com.apple.itunes.storekit.model.Environment;
    import com.apple.itunes.storekit.model.HistoryResponse;
    import com.apple.itunes.storekit.model.TransactionHistoryRequest;
    import java.util.LinkedList;
    import java.util.List;
    
    // ... setup client ...
    String appReceipt = "MI...";
    ReceiptUtility receiptUtil = new ReceiptUtility();
    String transactionId = receiptUtil.extractTransactionIdFromAppReceipt(appReceipt);
    
    if (transactionId != null) {
        TransactionHistoryRequest request = new TransactionHistoryRequest()
                .sort(TransactionHistoryRequest.Order.ASCENDING)
                .revoked(false)
                .productTypes(List.of(TransactionHistoryRequest.ProductType.AUTO_RENEWABLE));
        
        HistoryResponse response = null;
        List<String> transactions = new LinkedList<>();
        do {
            String revision = response != null ? response.getRevision() : null;
            response = client.getTransactionHistory(transactionId, revision, request, GetTransactionHistoryVersion.V2);
            transactions.addAll(response.getSignedTransactions());
        } while (response.getHasMore());
        System.out.println(transactions);
    }
  4. Create promotional offer signatures

    main

    Use PromotionalOfferSignatureCreator to generate signatures for promotional offers. This requires the encoded signing key, key ID, and bundle ID. You must provide the product ID, subscription offer ID, app account token, a unique nonce, and a timestamp.

    import com.apple.itunes.storekit.offers.PromotionalOfferSignatureCreator;
    import java.util.UUID;
    
    // ... setup encodedKey, keyId, bundleId ...
    
    PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(encodedKey, keyId, bundleId);
    
    String productId = "<product_id>";
    String subscriptionOfferId = "<subscription_offer_id>";
    String appAccountToken = "<app_account_token>";
    UUID nonce = UUID.randomUUID();
    long timestamp = System.currentTimeMillis();
    
    String encodedSignature = signatureCreator.createSignature(productId, subscriptionOfferId, appAccountToken, nonce, timestamp);
    System.out.println(encodedSignature);
  5. Verify signed data with SignedDataVerifier

    main

    Use SignedDataVerifier to validate signed payloads (like App Store Server Notifications). You must provide a set of Apple Root CA InputStreams, the bundleId, and the Environment. If using the PRODUCTION environment, you must also provide the appAppleId.

    import com.apple.itunes.storekit.model.Environment;
    import com.apple.itunes.storekit.model.ResponseBodyV2DecodedPayload;
    import com.apple.itunes.storekit.verification.SignedDataVerifier;
    import com.apple.itunes.storekit.verification.VerificationException;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.Set;
    
    String bundleId = "com.example";
    Environment environment = Environment.SANDBOX;
    Set<InputStream> rootCAs = Set.of(
            new FileInputStream("/path/to/rootCA1"),
            new FileInputStream("/path/to/rootCA2")
    );
    Long appAppleId = null; // Required for Production
    
    SignedDataVerifier signedPayloadVerifier = new SignedDataVerifier(rootCAs, bundleId, appAppleId, environment, true);
    String notificationPayload = "ey...";
    
    try {
        ResponseBodyV2DecodedPayload payload = signedPayloadVerifier.verifyAndDecodeNotification(notificationPayload);
        System.out.println(payload);
    } catch (VerificationException e) {
        e.printStackTrace();
    }
  6. Use AppStoreServerAPIClient to call App Store APIs

    main

    The AppStoreServerAPIClient is the primary entry point for interacting with the App Store Server APIs. It requires the encoded signing key, key ID, issuer ID, bundle ID, and the target Environment (e.g., Environment.SANDBOX or Environment.PRODUCTION).

    import com.apple.itunes.storekit.client.AppStoreServerAPIClient;
    import com.apple.itunes.storekit.model.Environment;
    import com.apple.itunes.storekit.model.SendTestNotificationResponse;
    import java.nio.file.Files;
    import java.nio.file.Path;
    
    // ... setup variables ...
    String issuerId = "99b16628-15e4-4668-972b-eeff55eeff55";
    String keyId = "ABCDEFGHIJ";
    String bundleId = "com.example";
    Path filePath = Path.of("/path/to/key/SubscriptionKey_ABCDEFGHIJ.p8");
    String encodedKey = Files.readString(filePath);
    Environment environment = Environment.SANDBOX;
    
    AppStoreServerAPIClient client = new AppStoreServerAPIClient(encodedKey, keyId, issuerId, bundleId, environment);
    
    try {
        SendTestNotificationResponse response = client.requestTestNotification();
        System.out.println(response);
    } catch (Exception e) {
        e.printStackTrace();
    }