Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: vpavic/app-store-server-library-java
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: apple/app-store-server-library-java
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Loading
Showing with 2,447 additions and 464 deletions.
  1. +3 −3 .github/workflows/ci-prb.yml
  2. +4 −4 .github/workflows/ci-release-javadocs.yml
  3. +3 −3 .github/workflows/ci-release.yml
  4. +3 −3 .github/workflows/ci-snapshot.yml
  5. +2 −2 .github/workflows/gradle-wrapper-validation.yml
  6. +0 −29 CHANGELOG
  7. +67 −0 CHANGELOG.md
  8. +21 −11 README.md
  9. +7 −5 build.gradle
  10. +1 −1 gradle.properties
  11. +1 −1 gradle/wrapper/gradle-wrapper.properties
  12. +7 −7 gradlew
  13. +59 −0 src/main/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreator.java
  14. +37 −0 src/main/java/com/apple/itunes/storekit/client/APIError.java
  15. +43 −275 src/main/java/com/apple/itunes/storekit/client/AppStoreServerAPIClient.java
  16. +388 −0 src/main/java/com/apple/itunes/storekit/client/BaseAppStoreServerAPIClient.java
  17. +1 −2 src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticator.java
  18. +8 −0 src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorInterface.java
  19. +18 −0 src/main/java/com/apple/itunes/storekit/client/GetTransactionHistoryVersion.java
  20. +4 −0 src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInAppRequest.java
  21. +15 −0 src/main/java/com/apple/itunes/storekit/model/AppAccountTokenNullSerializer.java
  22. +59 −4 src/main/java/com/apple/itunes/storekit/model/AppTransaction.java
  23. +39 −2 src/main/java/com/apple/itunes/storekit/model/ConsumptionRequest.java
  24. +45 −0 src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestReason.java
  25. +36 −1 src/main/java/com/apple/itunes/storekit/model/Data.java
  26. +1 −0 src/main/java/com/apple/itunes/storekit/model/Environment.java
  27. +161 −0 src/main/java/com/apple/itunes/storekit/model/ExternalPurchaseToken.java
  28. +187 −23 src/main/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayload.java
  29. +57 −40 src/main/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayload.java
  30. +1 −0 src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponse.java
  31. +5 −3 src/main/java/com/apple/itunes/storekit/model/NotificationTypeV2.java
  32. +2 −1 src/main/java/com/apple/itunes/storekit/model/OfferType.java
  33. +1 −0 src/main/java/com/apple/itunes/storekit/model/OrderLookupResponse.java
  34. +44 −0 src/main/java/com/apple/itunes/storekit/model/PurchasePlatform.java
  35. +1 −0 src/main/java/com/apple/itunes/storekit/model/RefundHistoryResponse.java
  36. +44 −0 src/main/java/com/apple/itunes/storekit/model/RefundPreference.java
  37. +27 −3 src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayload.java
  38. +1 −0 src/main/java/com/apple/itunes/storekit/model/SubscriptionGroupIdentifierItem.java
  39. +4 −3 src/main/java/com/apple/itunes/storekit/model/Subtype.java
  40. +67 −0 src/main/java/com/apple/itunes/storekit/model/UpdateAppAccountTokenRequest.java
  41. +50 −0 src/main/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreator.java
  42. +3 −3 src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreator.java
  43. +52 −0 src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreator.java
  44. +65 −0 src/main/java/com/apple/itunes/storekit/signature/JWSSignatureCreator.java
  45. +57 −0 src/main/java/com/apple/itunes/storekit/verification/ChainVerifier.java
  46. +38 −4 src/main/java/com/apple/itunes/storekit/verification/SignedDataVerifier.java
  47. +82 −0 ...st/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreatorTest.java
  48. +188 −8 src/test/java/com/apple/itunes/storekit/client/AppStoreServerAPIClientTest.java
  49. +1 −0 src/test/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorTest.java
  50. +3 −0 src/test/java/com/apple/itunes/storekit/model/AppTransactionTest.java
  51. +11 −2 src/test/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayloadTest.java
  52. +3 −2 src/test/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayloadTest.java
  53. +100 −4 src/test/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayloadTest.java
  54. +65 −0 src/test/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreatorTest.java
  55. +2 −1 src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreatorTest.java
  56. +93 −0 src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreatorTest.java
  57. +0 −8 src/test/java/com/apple/itunes/storekit/util/SignedDataCreator.java
  58. +2 −0 src/test/java/com/apple/itunes/storekit/util/TestingUtility.java
  59. +90 −2 src/test/java/com/apple/itunes/storekit/verification/ChainVerifierTest.java
  60. +3 −1 src/test/resources/models/appTransaction.json
  61. +4 −0 src/test/resources/models/familyTransactionNotSupportedError.json
  62. +16 −0 src/test/resources/models/signedConsumptionRequestNotification.json
  63. +13 −0 src/test/resources/models/signedExternalPurchaseTokenNotification.json
  64. +13 −0 src/test/resources/models/signedExternalPurchaseTokenSandboxNotification.json
  65. +12 −2 src/test/resources/models/signedRenewalInfo.json
  66. +3 −1 src/test/resources/models/signedTransaction.json
  67. +4 −0 src/test/resources/models/transactionIdNotOriginalTransactionId.json
6 changes: 3 additions & 3 deletions .github/workflows/ci-prb.yml
Original file line number Diff line number Diff line change
@@ -14,9 +14,9 @@ jobs:
os: [ ubuntu-latest ]
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java }}
distribution: 'corretto'
@@ -31,7 +31,7 @@ jobs:
run: sudo -E env "PATH=$PATH" bash -c "ulimit -l 65536 && ulimit -a && ./gradlew --no-daemon --parallel clean test"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}-${{ matrix.java }}
path: '**/build/test-results/test/TEST-*.xml'
8 changes: 4 additions & 4 deletions .github/workflows/ci-release-javadocs.yml
Original file line number Diff line number Diff line change
@@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'corretto'
@@ -25,7 +25,7 @@ jobs:
- name: Build javadocs
run: ./gradlew --no-daemon --parallel javadoc
- name: Upload javadocs
uses: actions/upload-pages-artifact@v2
uses: actions/upload-pages-artifact@v3
with:
path: build/docs/javadoc
deploy:
@@ -38,4 +38,4 @@ jobs:
steps:
- name: Deploy
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
6 changes: 3 additions & 3 deletions .github/workflows/ci-release.yml
Original file line number Diff line number Diff line change
@@ -8,9 +8,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 17
distribution: 'corretto'
@@ -33,7 +33,7 @@ jobs:
./gradlew --no-daemon --parallel publish"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}-${{ matrix.java }}
path: '**/build/test-results/test/TEST-*.xml'
6 changes: 3 additions & 3 deletions .github/workflows/ci-snapshot.yml
Original file line number Diff line number Diff line change
@@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 21
distribution: 'corretto'
@@ -38,7 +38,7 @@ jobs:
|| exit 1) || exit 0"
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}-${{ matrix.java }}
path: '**/build/test-results/test/TEST-*.xml'
4 changes: 2 additions & 2 deletions .github/workflows/gradle-wrapper-validation.yml
Original file line number Diff line number Diff line change
@@ -5,5 +5,5 @@ jobs:
validation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1.1.0
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v3.5.0
29 changes: 0 additions & 29 deletions CHANGELOG

This file was deleted.

67 changes: 67 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Changelog

## Version 3.5.0
- Incorporate changes for App Store Server API v1.16 [https://github.com/apple/app-store-server-library-java/pull/165]

## Version 3.4.0
- Incorporate changes for App Store Server API v1.15 and App Store Server Notifications v2.15 [https://github.com/apple/app-store-server-library-java/pull/152]

## Version 3.3.0
- Update BaseAppStoreServerAPIClient to move URL selection to a method [https://github.com/apple/app-store-server-library-java/pull/136]

## Version 3.2.0
- Incorporate caching of validated certificate chains to prevent repetitive OCSP fetches [https://github.com/apple/app-store-server-library-java/pull/127]

## Version 3.1.0
- Incorporate changes for App Store Server API v1.13 and App Store Server Notifications v2.13 [https://github.com/apple/app-store-server-library-java/pull/116]
- Handle parsing empty or unexpected bodies on API exceptions without throwing a caused-by exception [https://github.com/apple/app-store-server-library-java/pull/119]

## Version 3.0.0
- Allow providing a custom bearer token provider and HTTP client implementation [https://github.com/apple/app-store-server-library-java/pull/109]
- This change refactors the internal implementation of the AppStoreServerAPIClient class. Users extending this class may see interface changes
- Rename applicationUsername to appAccountToken [https://github.com/apple/app-store-server-library-java/pull/104]

## Version 2.2.0
- Incorporate changes for App Store Server API v1.12 and App Store Server Notifications v2.12 [https://github.com/apple/app-store-server-library-java/pull/103]
- Handle null appAccountToken appropriately in PromotionalOfferSignatureCreator [https://github.com/apple/app-store-server-library-java/pull/100]

## Version 2.1.0
- Incorporate changes for App Store Server API v1.11 and App Store Server Notifications v2.11 [https://github.com/apple/app-store-server-library-java/pull/94]
- Add proxy authenticator support [https://github.com/apple/app-store-server-library-java/pull/93]
- Various documentation and quality of life improvements, including contributions from @hakusai22

## Version 2.0.0
- Incorporate changes for App Store Server API v1.10.1 [https://github.com/apple/app-store-server-library-java/pull/77]
- This change is a breaking change, as the datatype of the price field has changed from Integer to Long

## Version 1.1.0
- Support App Store Server Notifications v2.10 [https://github.com/apple/app-store-server-library-java/pull/74]
- Require appAppleId in SignedDataVerifier for the Production environment [https://github.com/apple/app-store-server-library-java/pull/68]

## Version 1.0.0
- Switch from GSON to Jackson for parsing [https://github.com/apple/app-store-server-library-java/pull/58]
- Rename Status to VerificationStatus [https://github.com/apple/app-store-server-library-java/pull/59]
- Add message to APIException and update JavaDocs [https://github.com/apple/app-store-server-library-java/pull/60]

## Version 0.2.0
- Significantly increase unit test coverage [https://github.com/apple/app-store-server-library-java/pull/51]
- Add support for Xcode and LocalTesting environments [https://github.com/apple/app-store-server-library-java/pull/49]
- Allow parsing unknown Enum values [https://github.com/apple/app-store-server-library-java/pull/50]
- Add support for testing in Java 21 [https://github.com/apple/app-store-server-library-java/pull/48]
- Add error codes from App Store Server API v1.9 [https://github.com/apple/app-store-server-library-java/pull/43]
- Add new fields from App Store Server API v1.10 [https://github.com/apple/app-store-server-library-java/pull/53]
- Fix private key parsing on Windows from @vpavic [https://github.com/apple/app-store-server-library-java/pull/41]

## Version 0.1.3

- Add status field to Data [https://github.com/apple/app-store-server-library-java/pull/34]
- Publish JavaDocs

## Version 0.1.2

- Make SignedDataVerifier::decodeSignedObject protected

## Version 0.1.1

- Move release to Maven Central
- The additional repository is no longer needed in a Gradle/Maven config
32 changes: 21 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,11 +2,10 @@
The Java server library for the [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi) and [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications). Also available in [Swift](https://github.com/apple/app-store-server-library-swift), [Python](https://github.com/apple/app-store-server-library-python), and [Node.js](https://github.com/apple/app-store-server-library-node).

## Table of Contents
1. [Beta](#-beta-)
2. [Installation](#installation)
3. [Documentation](#documentation)
4. [Usage](#usage)
5. [Support](#support)
1. [Installation](#installation)
2. [Documentation](#documentation)
3. [Usage](#usage)
4. [Support](#support)

## Installation

@@ -16,7 +15,7 @@ The Java server library for the [App Store Server API](https://developer.apple.c

### Gradle
```groovy
implementation 'com.apple.itunes.storekit:app-store-server-library:1.0.0'
implementation 'com.apple.itunes.storekit:app-store-server-library:3.5.0'
```

@@ -25,7 +24,7 @@ implementation 'com.apple.itunes.storekit:app-store-server-library:1.0.0'
<dependency>
<groupId>com.apple.itunes.storekit</groupId>
<artifactId>app-store-server-library</artifactId>
<version>1.0.0</version>
<version>3.5.0</version>
</dependency>
```

@@ -34,6 +33,15 @@ implementation 'com.apple.itunes.storekit:app-store-server-library:1.0.0'
[JavaDocs](https://apple.github.io/app-store-server-library-java/)

[WWDC Video](https://developer.apple.com/videos/play/wwdc2023/10143/)

### Obtaining an In-App Purchase key from App Store Connect

To use the App Store Server API or create promotional offer signatures, a signing key downloaded from App Store Connect is required. To obtain this key, you must have the Admin role. Go to Users and Access > Integrations > In-App Purchase. Here you can create and manage keys, as well as find your issuer ID. When using a key, you'll need the key ID and issuer ID as well.

### Obtaining Apple Root Certificates

Download and store the root certificates found in the Apple Root Certificates section of the [Apple PKI](https://www.apple.com/certificateauthority/) site. Provide these certificates as an array to a SignedDataVerifier to allow verifying the signed data comes from Apple.

## Usage

### API Usage
@@ -90,8 +98,9 @@ public class ExampleVerification {
new FileInputStream("/path/to/rootCA1"),
new FileInputStream("/path/to/rootCA2")
);
Long appAppleId = null; // appAppleId must be provided for the Production environment

SignedDataVerifier signedPayloadVerifier = new SignedDataVerifier(rootCAs, bundleId, null, environment, true);
SignedDataVerifier signedPayloadVerifier = new SignedDataVerifier(rootCAs, bundleId, appAppleId, environment, true);

String notificationPayload = "ey...";

@@ -109,6 +118,7 @@ public class ExampleVerification {

```java
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;
@@ -143,7 +153,7 @@ public class ExampleMigration {
List<String> transactions = new LinkedList<>();
do {
String revision = response != null ? response.getRevision() : null;
response = client.getTransactionHistory(transactionId, revision, request);
response = client.getTransactionHistory(transactionId, revision, request, GetTransactionHistoryVersion.V2);
transactions.addAll(response.getSignedTransactions());
} while (response.getHasMore());
System.out.println(transactions);
@@ -172,10 +182,10 @@ public class ExampleSignatureCreation {

String productId = "<product_id>";
String subscriptionOfferId = "<subscription_offer_id>";
String applicationUsername = "<application_username>";
String appAccountToken = "<app_account_token>";
UUID nonce = UUID.randomUUID();
long timestamp = System.currentTimeMillis();
String encodedSignature = signatureCreator.createSignature(productId, subscriptionOfferId, applicationUsername, nonce, timestamp);
String encodedSignature = signatureCreator.createSignature(productId, subscriptionOfferId, appAccountToken, nonce, timestamp);
System.out.println(encodedSignature);
}
}
12 changes: 7 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -6,12 +6,14 @@ sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.11.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.0'
implementation 'com.auth0:java-jwt:4.4.0'
implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1'
implementation 'com.auth0:java-jwt:4.5.0'
implementation 'org.bouncycastle:bcprov-jdk18on:1.81'

testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
testImplementation 'org.junit.jupiter:junit-jupiter:5.13.1'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'org.mockito:mockito-core:5.18.0'
}

repositories {
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version=1.0.0
version=3.5.0
group=com.apple.itunes.storekit
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
14 changes: 7 additions & 7 deletions gradlew
Original file line number Diff line number Diff line change
@@ -145,15 +145,15 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.

set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Loading