diff --git a/CHANGELOG.md b/CHANGELOG.md index 35e2ae12..8ac19a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - Incorporate changes for Retention Messaging API v1.3 and 1.4 [https://github.com/apple/app-store-server-library-java/pull/242] ## Version 5.0.0 -- Incorporate changes for App Store Server API v1.19 [https://github.com/apple/app-store-server-library-java/pull/219] from @riyazpanjwani +- Incorporate changes for App Store Server API v1.19 [https://github.com/apple/app-store-server-library-java/pull/220] from @riyazpanjwani - This changes ConsumptionRequest and several dependent types to the V2 variant, while the V1 version was created as a new type, to align with documentation, which is a breaking change ## Version 4.0.0 @@ -49,7 +49,7 @@ ## 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] +- Handle null appAccountToken appropriately in ConsumptionRequest [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] diff --git a/README.md b/README.md index bdb722d7..640dc46e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Apple App Store Server Java Library -The Java server library for the [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi), [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications), [Retention Messaging API](https://developer.apple.com/documentation/retentionmessaging), and [Advanced Commerce API](https://developer.apple.com/documentation/AdvancedCommerceAPI). 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). +The Java server library for the [App Store Server API](https://developer.apple.com/documentation/appstoreserverapi), [App Store Server Notifications](https://developer.apple.com/documentation/appstoreservernotifications), [Retention Messaging API](https://developer.apple.com/documentation/retentionmessaging), and [Advanced Commerce API](https://developer.apple.com/documentation/advancedcommerceapi). 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. [Installation](#installation) @@ -40,7 +40,7 @@ To use the App Store Server API or create promotional offer signatures, a signin ### 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. +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 a Set of InputStreams to a SignedDataVerifier to allow verifying the signed data comes from Apple. ## Usage @@ -91,7 +91,7 @@ import java.io.InputStream; import java.util.Set; public class ExampleVerification { - public static void main(String[] args) { + public static void main(String[] args) throws Exception { String bundleId = "com.example"; Environment environment = Environment.SANDBOX; Set rootCAs = Set.of( diff --git a/build.gradle b/build.gradle index c886785f..cb371291 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,9 @@ apply plugin: 'maven-publish' apply plugin: 'signing' dependencies { - implementation 'com.squareup.okhttp3:okhttp:5.5.0' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.22.2' - implementation 'com.auth0:java-jwt:4.5.2' + api 'com.squareup.okhttp3:okhttp:5.5.0' + api 'com.fasterxml.jackson.core:jackson-databind:2.22.2' + api 'com.auth0:java-jwt:4.5.2' implementation 'org.bouncycastle:bcprov-jdk18on:1.85.2' testImplementation 'org.junit.jupiter:junit-jupiter:6.1.3' @@ -55,7 +55,7 @@ publishing { from components.java pom { name = "App Store Server Library" - description = "The Java server library for the App Store Server API and App Store Server Notifications" + description = "The Java server library for the App Store Server API, App Store Server Notifications, Retention Messaging API, and Advanced Commerce API" url = "https://github.com/apple/app-store-server-library-java/" licenses { license { diff --git a/src/main/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreator.java b/src/main/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreator.java index 1727248a..f07e4102 100644 --- a/src/main/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreator.java +++ b/src/main/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreator.java @@ -5,6 +5,7 @@ import com.apple.itunes.storekit.model.AdvancedCommerceInAppRequest; import com.apple.itunes.storekit.signature.JWSSignatureCreator; import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; @@ -36,6 +37,7 @@ public AdvancedCommerceInAppSignatureCreator(String signingKey, String keyId, St .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) .withSetterVisibility(JsonAutoDetect.Visibility.NONE) .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + objectMapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_NULL); } /** diff --git a/src/main/java/com/apple/itunes/storekit/client/APIError.java b/src/main/java/com/apple/itunes/storekit/client/APIError.java index 92225258..515cd425 100644 --- a/src/main/java/com/apple/itunes/storekit/client/APIError.java +++ b/src/main/java/com/apple/itunes/storekit/client/APIError.java @@ -2,166 +2,174 @@ package com.apple.itunes.storekit.client; - import java.util.Arrays; /** - * An error returned by the App Store Server API indicating an issue with processing a request. - * See the specific documentation for each endpoint to learn more about what codes are possible from each endpoint. - */ + * Understand the error codes that App Store Server API responses return. + * + * @see Error codes + **/ public enum APIError { /** * An error that indicates an invalid request. * * @see GeneralBadRequestError - */ + **/ GENERAL_BAD_REQUEST(4000000L), /** * An error that indicates an invalid app identifier. * * @see InvalidAppIdentifierError - */ + **/ INVALID_APP_IDENTIFIER(4000002L), + /** + * An error that indicates the request limit is invalid. + * + * @see InvalidLimitError + **/ + INVALID_LIMIT(4000004L), + /** * An error that indicates an invalid request revision. * * @see InvalidRequestRevisionError - */ + **/ INVALID_REQUEST_REVISION(4000005L), /** * An error that indicates an invalid transaction identifier. * * @see InvalidTransactionIdError - */ + **/ INVALID_TRANSACTION_ID(4000006L), /** * An error that indicates an invalid original transaction identifier. * * @see InvalidOriginalTransactionIdError - */ + **/ INVALID_ORIGINAL_TRANSACTION_ID(4000008L), /** * An error that indicates an invalid extend-by-days value. * * @see InvalidExtendByDaysError - */ + **/ INVALID_EXTEND_BY_DAYS(4000009L), /** * An error that indicates an invalid reason code. * * @see InvalidExtendReasonCodeError - */ + **/ INVALID_EXTEND_REASON_CODE(4000010L), /** * An error that indicates an invalid request identifier. * * @see InvalidRequestIdentifierError - */ + **/ INVALID_REQUEST_IDENTIFIER(4000011L), /** - * An error that indicates that the start date is earlier than the earliest allowed date. + * An error that indicates the start date is earlier than the earliest allowed date. * * @see StartDateTooFarInPastError - */ + **/ START_DATE_TOO_FAR_IN_PAST(4000012L), /** - * An error that indicates that the end date precedes the start date, or the two dates are equal. + * An error that indicates the end date precedes the start date, or the two dates are equal. * * @see StartDateAfterEndDateError - */ + **/ START_DATE_AFTER_END_DATE(4000013L), /** * An error that indicates the pagination token is invalid. * * @see InvalidPaginationTokenError - */ + **/ INVALID_PAGINATION_TOKEN(4000014L), /** * An error that indicates the start date is invalid. * * @see InvalidStartDateError - */ + **/ INVALID_START_DATE(4000015L), /** * An error that indicates the end date is invalid. * * @see InvalidEndDateError - */ + **/ INVALID_END_DATE(4000016L), /** * An error that indicates the pagination token expired. * * @see PaginationTokenExpiredError - */ + **/ PAGINATION_TOKEN_EXPIRED(4000017L), /** * An error that indicates the notification type or subtype is invalid. * * @see InvalidNotificationTypeError - */ + **/ INVALID_NOTIFICATION_TYPE(4000018L), /** - * An error that indicates the request is invalid because it has too many constraints applied. + * An error that indicates the request is invalid because it has too many applied constraints. * * @see MultipleFiltersSuppliedError - */ + **/ MULTIPLE_FILTERS_SUPPLIED(4000019L), /** * An error that indicates the test notification token is invalid. * * @see InvalidTestNotificationTokenError - */ + **/ INVALID_TEST_NOTIFICATION_TOKEN(4000020L), /** - * An error that indicates an invalid sort parameter. + * An error that indicates the sort parameter is invalid. * * @see InvalidSortError - */ + **/ INVALID_SORT(4000021L), /** - * An error that indicates an invalid product type parameter. + * An error that indicates the product type parameter is invalid. * * @see InvalidProductTypeError - */ + **/ INVALID_PRODUCT_TYPE(4000022L), /** * An error that indicates the product ID parameter is invalid. * * @see InvalidProductIdError - */ + **/ INVALID_PRODUCT_ID(4000023L), /** - * An error that indicates an invalid subscription group identifier. + * An error that indicates the subscription group identifier is invalid. * * @see InvalidSubscriptionGroupIdentifierError - */ + **/ INVALID_SUBSCRIPTION_GROUP_IDENTIFIER(4000024L), /** * An error that indicates the query parameter exclude-revoked is invalid. * * @see InvalidExcludeRevokedError - */ + * @deprecated Use {@link #INVALID_REVOKED} instead. + **/ @Deprecated INVALID_EXCLUDE_REVOKED(4000025L), @@ -169,457 +177,1381 @@ public enum APIError { * An error that indicates an invalid in-app ownership type parameter. * * @see InvalidInAppOwnershipTypeError - */ + **/ INVALID_IN_APP_OWNERSHIP_TYPE(4000026L), /** * An error that indicates a required storefront country code is empty. * * @see InvalidEmptyStorefrontCountryCodeListError - */ + **/ INVALID_EMPTY_STOREFRONT_COUNTRY_CODE_LIST(4000027L), /** * An error that indicates a storefront code is invalid. * * @see InvalidStorefrontCountryCodeError - */ + **/ INVALID_STOREFRONT_COUNTRY_CODE(4000028L), /** * An error that indicates the revoked parameter contains an invalid value. * * @see InvalidRevokedError - */ + **/ INVALID_REVOKED(4000030L), /** * An error that indicates the status parameter is invalid. * * @see InvalidStatusError - */ + **/ INVALID_STATUS(4000031L), /** * An error that indicates the value of the account tenure field is invalid. * * @see InvalidAccountTenureError - */ + **/ INVALID_ACCOUNT_TENURE(4000032L), /** * An error that indicates the value of the app account token field is invalid. * * @see InvalidAppAccountTokenError - */ + **/ INVALID_APP_ACCOUNT_TOKEN(4000033L), /** * An error that indicates the value of the consumption status field is invalid. * * @see InvalidConsumptionStatusError - */ + **/ INVALID_CONSUMPTION_STATUS(4000034L), /** * An error that indicates the customer consented field is invalid or doesn’t indicate that the customer consented. * * @see InvalidCustomerConsentedError - */ + **/ INVALID_CUSTOMER_CONSENTED(4000035L), /** * An error that indicates the value in the delivery status field is invalid. * * @see InvalidDeliveryStatusError - */ + **/ INVALID_DELIVERY_STATUS(4000036L), /** * An error that indicates the value in the lifetime dollars purchased field is invalid. * * @see InvalidLifetimeDollarsPurchasedError - */ + **/ INVALID_LIFETIME_DOLLARS_PURCHASED(4000037L), /** * An error that indicates the value in the lifetime dollars refunded field is invalid. * * @see InvalidLifetimeDollarsRefundedError - */ + **/ INVALID_LIFETIME_DOLLARS_REFUNDED(4000038L), /** * An error that indicates the value in the platform field is invalid. * * @see InvalidPlatformError - */ + **/ INVALID_PLATFORM(4000039L), /** * An error that indicates the value in the playtime field is invalid. * * @see InvalidPlayTimeError - */ + **/ INVALID_PLAY_TIME(4000040L), /** * An error that indicates the value in the sample content provided field is invalid. * * @see InvalidSampleContentProvidedError - */ + **/ INVALID_SAMPLE_CONTENT_PROVIDED(4000041L), /** * An error that indicates the value in the user status field is invalid. * * @see InvalidUserStatusError - */ + **/ INVALID_USER_STATUS(4000042L), /** - * An error that indicates the transaction identifier doesn’t represent a consumable in-app purchase. + * An error that indicates the transaction identifier doesn’t represent a consumable In-App Purchase. * * @see InvalidTransactionNotConsumableError - */ + * @deprecated Use {@link #INVALID_TRANSACTION_TYPE_NOT_SUPPORTED} instead. + **/ @Deprecated INVALID_TRANSACTION_NOT_CONSUMABLE(4000043L), /** - * An error that indicates the transaction identifier represents an unsupported in-app purchase type. + * An error that indicates an invalid refund preference value. + * + * @see InvalidRefundPreferenceError + **/ + INVALID_REFUND_PREFERENCE(4000044L), + + /** + * An error that indicates the transaction identifier represents an unsupported In-App Purchase type. * * @see InvalidTransactionTypeNotSupportedError - */ + **/ INVALID_TRANSACTION_TYPE_NOT_SUPPORTED(4000047L), - /** - * An error that indicates the endpoint doesn't support an app transaction ID. + * An error that indicates the endpoint doesn’t support an app transaction ID. * * @see AppTransactionIdNotSupportedError - */ - APP_TRANSACTION_ID_NOT_SUPPORTED_ERROR(4000048L), + **/ + APP_TRANSACTION_ID_NOT_SUPPORTED(4000048L), + + /** + * The currency value is invalid. + * + * @see InvalidCurrencyError + **/ + INVALID_CURRENCY(4000053L), + + /** + * At least one type of change must be provided in a modify subscription request. + * + * @see OneItemNeededInModifyError + **/ + ONE_ITEM_NEEDED_IN_MODIFY(4000063L), + + /** + * The required field, requestInfo, is missing. + * + * @see NullRequestInfoError + **/ + NULL_REQUEST_INFO(4000079L), + + /** + * The required field, requestReferenceId, is missing. + * + * @see NullRequestReferenceIDError + **/ + NULL_REQUEST_REFERENCE_ID(4000080L), + + /** + * The requestReferenceId value is invalid. + * + * @see InvalidRequestReferenceIDError + **/ + INVALID_REQUEST_REFERENCE_ID(4000081L), + + /** + * The consistencyToken value is invalid. + * + * @see InvalidConsistencyTokenError + **/ + INVALID_CONSISTENCY_TOKEN(4000082L), + + /** + * The required field, version, is missing. + * + * @see NullVersionError + **/ + NULL_VERSION(4000083L), + + /** + * The value of version is invalid. + * + * @see UnexpectedVersionError + **/ + UNEXPECTED_VERSION(4000084L), + + /** + * The required field, transactionId, is missing. + * + * @see NullTransactionIdError + **/ + NULL_TRANSACTION_ID(4000085L), + + /** + * The price field must contain a positive number. + * + * @see NegativePriceError + **/ + NEGATIVE_PRICE(4000086L), + + /** + * Exceeds the maximum length of the SKU field. + * + * @see SKULengthExceededError + **/ + SKU_LENGTH_EXCEEDED(4000087L), + + /** + * Exceeds the maximum length of the description field. + * + * @see DescriptionLengthExceededError + **/ + DESCRIPTION_LENGTH_EXCEEDED(4000088L), + + /** + * Exceeds the maximum length of the displayName field. + * + * @see DisplayNameLengthExceededError + **/ + DISPLAY_NAME_LENGTH_EXCEEDED(4000089L), + + /** + * The proratedPrice field must contain a positive number. + * + * @see NegativeProratedPriceError + **/ + NEGATIVE_PRORATED_PRICE(4000091L), + + /** + * The required field, offer period, is missing. + * + * @see NullOfferPeriodError + **/ + NULL_OFFER_PERIOD(4000092L), + + /** + * The required field, periodCount, is missing. + * + * @see NullPeriodCountError + **/ + NULL_PERIOD_COUNT(4000093L), + + /** + * Period count must be a positive number. + * + * @see PeriodCountNotPositiveError + **/ + PERIOD_COUNT_NOT_POSITIVE(4000094L), + + /** + * The required field, reason, is missing. + * + * @see NullReasonError + **/ + NULL_REASON(4000095L), + + /** + * Previous original transaction id is invalid. + * + * @see InvalidPreviousTransactionIDError + **/ + INVALID_PREVIOUS_TRANSACTION_ID(4000096L), + + /** + * The requestReferenceId was repeated. + * + * @see RepeatedRequestReferenceIdError + **/ + REPEATED_REQUEST_REFERENCE_ID(4000097L), + + /** + * The required field, currency, is missing. + * + * @see NullCurrencyError + **/ + NULL_CURRENCY(4000098L), + + /** + * The required field, taxCode, is missing. + * + * @see NullTaxCodeError + **/ + NULL_TAX_CODE(4000099L), + + /** + * The required field, storefront, is missing. + * + * @see NullStorefrontError + **/ + NULL_STOREFRONT(4000100L), + + /** + * The required field, items, is missing. + * + * @see NullItemsError + **/ + NULL_ITEMS(4000101L), + + /** + * The required field, item, is missing. + * + * @see NullItemError + **/ + NULL_ITEM(4000102L), + + /** + * The required field, descriptors, is missing. + * + * @see NullDescriptorsError + **/ + NULL_DESCRIPTORS(4000103L), + + /** + * The required field, period, is missing. + * + * @see NullPeriodError + **/ + NULL_PERIOD(4000104L), + + /** + * The required field, SKU, is missing. + * + * @see NullSKUError + **/ + NULL_SKU(4000105L), + + /** + * The required field, displayName, is missing. + * + * @see NullDisplayNameError + **/ + NULL_DISPLAY_NAME(4000106L), + + /** + * The required field, description, is missing. + * + * @see NullDescriptionError + **/ + NULL_DESCRIPTION(4000107L), + + /** + * The required field, price, is missing. + * + * @see NullPriceError + **/ + NULL_PRICE(4000109L), /** - * An error that indicates the image that's uploading is invalid. + * The required field, retainBillingCycle, is missing. + * + * @see NullRetainBillingCycleError + **/ + NULL_RETAIN_BILLING_CYCLE(4000110L), + + /** + * The required field, effective, is missing. + * + * @see NullEffectiveError + **/ + NULL_EFFECTIVE(4000111L), + + /** + * The required field, SKU in changeItems, is missing. + * + * @see NullNewSKUError + **/ + NULL_NEW_SKU(4000112L), + + /** + * The previous subscription targeted is invalid. + * + * @see InvalidPreviousSubscriptionError + **/ + INVALID_PREVIOUS_SUBSCRIPTION(4000113L), + + /** + * Provided SKU is already owned. + * + * @see ProductAlreadyExistsError + **/ + PRODUCT_ALREADY_EXISTS(4000114L), + + /** + * Product changes are invalid. + * + * @see InvalidProductChangesError + **/ + INVALID_PRODUCT_CHANGES(4000115L), + + /** + * The targeted salable isn't configured as a generic salable. + * + * @see InvalidSalableError + **/ + INVALID_SALABLE(4000116L), + + /** + * The salable duration is invalid. + * + * @see InvalidSalableDurationError + **/ + INVALID_SALABLE_DURATION(4000117L), + + /** + * The displayName is invalid. + * + * @see InvalidDisplayNameError + **/ + INVALID_DISPLAY_NAME(4000118L), + + /** + * The description is invalid. + * + * @see InvalidDescriptionError + **/ + INVALID_DESCRIPTION(4000119L), + + /** + * The requested product to change doesn't exist. + * + * @see InvalidProductError + **/ + INVALID_PRODUCT(4000121L), + + /** + * The SKU was invalid. + * + * @see InvalidSKUError + **/ + INVALID_SKU(4000122L), + + /** + * The refundType is invalid. + * + * @see InvalidRefundTypeError + **/ + INVALID_REFUND_TYPE(4000123L), + + /** + * The refundReason is invalid. + * + * @see InvalidRefundReasonError + **/ + INVALID_REFUND_REASON(4000124L), + + /** + * The change reason is invalid. + * + * @see InvalidChangeReasonError + **/ + INVALID_CHANGE_REASON(4000125L), + + /** + * The offer reason is invalid. + * + * @see InvalidOfferReasonError + **/ + INVALID_OFFER_REASON(4000126L), + + /** + * The taxCode is invalid. + * + * @see InvalidTaxProductCodeError + **/ + INVALID_TAX_PRODUCT_CODE(4000127L), + + /** + * The offer period is invalid. + * + * @see InvalidOfferPeriodError + **/ + INVALID_OFFER_PERIOD(4000128L), + + /** + * The offer periodCount is invalid. + * + * @see InvalidOfferPeriodCountError + **/ + INVALID_OFFER_PERIOD_COUNT(4000129L), + + /** + * The renewal period is invalid. + * + * @see InvalidRenewalPeriodError + **/ + INVALID_RENEWAL_PERIOD(4000130L), + + /** + * The renewal price is invalid. + * + * @see InvalidRenewalPriceError + **/ + INVALID_RENEWAL_PRICE(4000131L), + + /** + * The amount is invalid. + * + * @see InvalidAmountError + **/ + INVALID_AMOUNT(4000132L), + + /** + * The storefronts mismatch. + * + * @see MismatchedStorefrontError + **/ + MISMATCHED_STOREFRONT(4000133L), + + /** + * Pricing isn't configured for the storefront. + * + * @see MissingPricingConfigForStorefrontError + **/ + MISSING_PRICING_CONFIG_FOR_STOREFRONT(4000134L), + + /** + * The operation isn't allowed. + * + * @see OperationNotAllowedError + **/ + OPERATION_NOT_ALLOWED(4000135L), + + /** + * More items were provided than allowed. + * + * @see MoreItemsThanAllowedError + **/ + MORE_ITEMS_THAN_ALLOWED(4000136L), + + /** + * More offers were provided than allowed. + * + * @see MoreOffersThanAllowedError + **/ + MORE_OFFERS_THAN_ALLOWED(4000137L), + + /** + * The addItems and changeItems entries cannot be empty. + * + * @see EmptyAddChangeItemsError + **/ + EMPTY_ADD_CHANGE_ITEMS(4000139L), + + /** + * All items must be updated on a period change. + * + * @see MissingUpdatedItemsWithPeriodChangeError + **/ + MISSING_UPDATED_ITEMS_WITH_PERIOD_CHANGE(4000140L), + + /** + * Period reset conflicts with retaining billing cycle. + * + * @see PeriodResetWithRetainBillingCycleError + **/ + PERIOD_RESET_WITH_RETAIN_BILLING_CYCLE(4000141L), + + /** + * A period change at next cycle conflicts with addition at the current period. + * + * @see PeriodChangeEffectiveConflictError + **/ + PERIOD_CHANGE_EFFECTIVE_CONFLICT(4000142L), + + /** + * Multiple operations on a single SKU isn't allowed. + * + * @see MultipleOperationsOnSingleSKUError + **/ + MULTIPLE_OPERATIONS_ON_SINGLE_SKU(4000143L), + + /** + * The removeItems object was present without addItems or changeItems. + * + * @see RemoveItemsWithoutAddOrChangeItemsError + **/ + REMOVE_ITEMS_WITHOUT_ADD_OR_CHANGE_ITEMS(4000144L), + + /** + * A product in removeItems wasn't found for the given subscription. + * + * @see RemoveItemNotFoundError + **/ + REMOVE_ITEM_NOT_FOUND(4000145L), + + /** + * The targeted item in changeItems wasn't found. + * + * @see ChangeItemNotFoundError + **/ + CHANGE_ITEM_NOT_FOUND(4000146L), + + /** + * The request contains a billing period that doesn't align with the subscription's billing cycle. + * + * @see MisalignedBillingCycleError + **/ + MISALIGNED_BILLING_CYCLE(4000147L), + + /** + * Bill cycle reset with effective later. + * + * @see BillingCycleResetWithEffectiveLaterError + **/ + BILLING_CYCLE_RESET_WITH_EFFECTIVE_LATER(4000148L), + + /** + * Period change immediately with effective later. + * + * @see PeriodChangeImmediateWithEffectiveAtNextBillingCycleError + **/ + PERIOD_CHANGE_IMMEDIATE_WITH_EFFECTIVE_AT_NEXT_BILLING_CYCLE(4000149L), + + /** + * Prorated price and offer price are mutually exclusive. + * + * @see MultiplePricesError + **/ + MULTIPLE_PRICES(4000150L), + + /** + * The prorated price was invalid. + * + * @see InvalidProratedPriceError + **/ + INVALID_PRORATED_PRICE(4000151L), + + /** + * The subscription offer price is higher than the regular subscription price. + * + * @see InvalidOfferPriceError + **/ + INVALID_OFFER_PRICE(4000152L), + + /** + * The refundAmount value is invalid. + * + * @see NullRefundAmountError + **/ + NULL_REFUND_AMOUNT(4000153L), + + /** + * The refundAmount must be a positive number. + * + * @see NegativeRefundAmountError + **/ + NEGATIVE_REFUND_AMOUNT(4000154L), + + /** + * Can't provide the refund amount because the refundType isn't CUSTOM. + * + * @see RefundAmountWithoutCustomError + **/ + REFUND_AMOUNT_WITHOUT_CUSTOM(4000155L), + + /** + * The required field, refundReason, is missing. + * + * @see NullRefundReasonError + **/ + NULL_REFUND_REASON(4000156L), + + /** + * The required field, refundType, is missing. + * + * @see NullRefundTypeError + **/ + NULL_REFUND_TYPE(4000157L), + + /** + * The type SIMULATE_REFUND_DECLINE is only valid in Sandbox. + * + * @see SimulateRefundDeclineOnlyInSandboxError + **/ + SIMULATE_REFUND_DECLINE_ONLY_IN_SANDBOX(4000158L), + + /** + * The required field, refundRiskingPreference, is missing. + * + * @see NullRefundRiskingError + **/ + NULL_REFUND_RISKING(4000159L), + + /** + * When included, provide at least one item in items. + * + * @see AtLeastOneItemError + **/ + AT_LEAST_ONE_ITEM(4000160L), + + /** + * An error that indicates the image that’s uploading is invalid. * * @see InvalidImageError - */ + **/ INVALID_IMAGE(4000161L), /** * An error that indicates the header text is too long. * * @see HeaderTooLongError - */ + **/ HEADER_TOO_LONG(4000162L), /** * An error that indicates the body text is too long. * * @see BodyTooLongError - */ + **/ BODY_TOO_LONG(4000163L), /** * An error that indicates the locale is invalid. * * @see InvalidLocaleError - */ + **/ INVALID_LOCALE(4000164L), + /** + * Provide either the displayName or a description. + * + * @see AtLeastOneOfDisplayNameOrDescriptionError + **/ + AT_LEAST_ONE_OF_DISPLAY_NAME_OR_DESCRIPTION(4000165L), + + /** + * The required field, targetProductID, is missing. + * + * @see NullTargetProductIDError + **/ + NULL_TARGET_PRODUCT_ID(4000166L), + + /** + * The targetProductID value is invalid. + * + * @see InvalidTargetProductIDError + **/ + INVALID_TARGET_PRODUCT_ID(4000167L), + + /** + * The active subscription must contain at least one item and cannot be completely empty. + * + * @see RemovalAllNotAllowedError + **/ + REMOVAL_ALL_NOT_ALLOWED(4000168L), + + /** + * The required field, currentSKU, is missing. + * + * @see NullCurrentSKUError + **/ + NULL_CURRENT_SKU(4000169L), + + /** + * Exceeds the maximum length of the currentSKU field. + * + * @see CurrentSKULengthExceededError + **/ + CURRENT_SKU_LENGTH_EXCEEDED(4000170L), + + /** + * The required field, advancedCommerceData, was null. + * + * @see NullAdvancedCommerceDataError + **/ + NULL_ADVANCED_COMMERCE_DATA(4000171L), + + /** + * The operation is invalid. + * + * @see InvalidOperationError + **/ + INVALID_OPERATION(4000172L), + + /** + * The payload is malformed. + * + * @see MalformedPayloadError + **/ + MALFORMED_PAYLOAD(4000173L), + + /** + * The signature is invalid. + * + * @see InvalidSignatureError + **/ + INVALID_SIGNATURE(4000174L), + /** * An error that indicates the alternative text for an image is too long. * * @see AltTextTooLongError - */ + **/ ALT_TEXT_TOO_LONG(4000175L), + /** + * The subscription was already migrated. + * + * @see SubscriptionAlreadyMigratedError + **/ + SUBSCRIPTION_ALREADY_MIGRATED(4000176L), + + /** + * An active or pending offer prevents changes to the item mid-cycle. + * + * @see OfferPreventsItemMidCycleChangeError + **/ + OFFER_PREVENTS_ITEM_MID_CYCLE_CHANGE(4000177L), + + /** + * Price change is not allowed through plan modification. + * + * @see PriceChangeNotSupportedThroughModifyItemsError + **/ + PRICE_CHANGE_NOT_SUPPORTED_THROUGH_MODIFY_ITEMS(4000178L), + + /** + * The number of items in subscription exceeds the limit. + * + * @see ItemLimitExceededError + **/ + ITEM_LIMIT_EXCEEDED(4000179L), + + /** + * Pending subscription changes must specify a renewalItem, and if there are no pending changes, a renewalItem cannot be specified. + * + * @see PendingChangesMismatchError + **/ + PENDING_CHANGES_MISMATCH(4000180L), + + /** + * The transaction has pending refunds. + * + * @see PendingRefundError + **/ + PENDING_REFUND(4000181L), + + /** + * Only requests against the latest transaction can have a PRORATED refundType value. + * + * @see ProratedOnlyLatestTransactionError + **/ + PRORATED_ONLY_LATEST_TRANSACTION(4000182L), + /** * An error that indicates the app account token value is not a valid UUID. * * @see InvalidAppAccountTokenUUIDError - */ - INVALID_APP_ACCOUNT_TOKEN_UUID_ERROR(4000183L), + **/ + INVALID_APP_ACCOUNT_TOKEN_UUID(4000183L), + + /** + * If one item has a refundReason value of SIMULATE_REFUND_DECLINE, all items must have a refundReason value of SIMULATE_REFUND_DECLINE. + * + * @see PartialSimulateRefundDeclineError + **/ + PARTIAL_SIMULATE_REFUND_DECLINE(4000184L), /** * An error that indicates the transaction is for a product the customer obtains through Family Sharing, which the endpoint doesn’t support. * * @see FamilyTransactionNotSupportedError - */ - FAMILY_TRANSACTION_NOT_SUPPORTED_ERROR(4000185L), + **/ + FAMILY_TRANSACTION_NOT_SUPPORTED(4000185L), + + /** + * Only active subscriptions are revocable. + * + * @see RevokeOnInactiveSubscriptionError + **/ + REVOKE_ON_INACTIVE_SUBSCRIPTION(4000186L), /** * An error that indicates the endpoint expects an original transaction identifier. * * @see TransactionIdIsNotOriginalTransactionIdError - */ - TRANSACTION_ID_IS_NOT_ORIGINAL_TRANSACTION_ID_ERROR(4000187L), + **/ + TRANSACTION_ID_IS_NOT_ORIGINAL_TRANSACTION_ID(4000187L), + + /** + * Invalid request. dependentSKUs can't be shared between multiple SKUs. + * + * @see DependentSKUsCannotBeSharedError + **/ + DEPENDENT_SKUS_CANNOT_BE_SHARED(4000192L), + + /** + * Invalid request. dependentSKUs can't be chained. + * + * @see DependentSKUsCannotBeChainedError + **/ + DEPENDENT_SKUS_CANNOT_BE_CHAINED(4000193L), + + /** + * Invalid request. The same SKU can't be repeated in this request. + * + * @see ItemCannotBeSpecifiedMultipleTimesError + **/ + ITEM_CANNOT_BE_SPECIFIED_MULTIPLE_TIMES(4000194L), + + /** + * Invalid request. A price change can't be issued when the price increase has already been communicated. + * + * @see PriceChangeCannotBeIssuedWhenAlreadyCommunicatedError + **/ + PRICE_CHANGE_CANNOT_BE_ISSUED_WHEN_ALREADY_COMMUNICATED(4000205L), + + /** + * An error that indicates the consumption percentage is outside the valid range. + * + * @see ConsumptionPercentageOutOfRangeError + **/ + CONSUMPTION_PERCENTAGE_OUT_OF_RANGE(4000207L), + + /** + * An error that indicates the consumption percentage must be zero for the provided delivery status. + * + * @see UndeliveredConsumptionPercentageNonZeroError + **/ + UNDELIVERED_CONSUMPTION_PERCENTAGE_NON_ZERO(4000208L), + + /** + * An error that indicates the consumption percentage field is unsupported for auto-renewable subscription transactions. + * + * @see ConsumptionPercentageAutoRenewableSubscriptionError + **/ + CONSUMPTION_PERCENTAGE_AUTO_RENEWABLE_SUBSCRIPTION(4000209L), + + /** + * An error that indicates Advanced Commerce API transactions are not supported by the endpoint. + * + * @see AdvancedCommerceTransactionNotSupportedError + **/ + ADVANCED_COMMERCE_TRANSACTION_NOT_SUPPORTED(4000210L), /** * An error the API returns that indicates the performance test request is invalid. * * @see InvalidPerformanceTestRequestError - */ + **/ INVALID_PERFORMANCE_TEST_REQUEST(4000211L), /** * An error that indicates the request ID is invalid. * * @see InvalidRequestIdError - */ + **/ INVALID_REQUEST_ID(4000212L), /** * An error that indicates an error with an existing test. * * @see ExistingPerformanceTestRunError - */ + **/ EXISTING_PERFORMANCE_TEST_RUN(4000213L), + /** + * Invalid request. Price provided for a changed item with an offer while subject to a price increase was invalid. + * + * @see InvalidPriceForChangeItemInPriceIncreaseError + **/ + INVALID_PRICE_FOR_CHANGE_ITEM_IN_PRICE_INCREASE(4000214L), + /** * An error that indicates the URL is invalid. * * @see BadRequestRealtimeUrlError - */ + **/ BAD_REQUEST_REALTIME_URL(4000215L), /** * An error that indicates the image size provided is invalid. * * @see BadRequestImageSizeError - */ + **/ BAD_REQUEST_IMAGE_SIZE(4000216L), /** * An error that indicates there are too many bullet points. * * @see BadRequestTooManyBulletPointsError - */ + **/ BAD_REQUEST_TOO_MANY_BULLET_POINTS(4000218L), /** * An error that indicates the text for a bullet point is too long. * * @see BadRequestBulletPointTextTooLongError - */ + **/ BAD_REQUEST_BULLET_POINT_TEXT_TOO_LONG(4000219L), + /** + * Invalid request. SKU values provided in request must be a SKU that will renew. + * + * @see InvalidSKUProvidedMustBeCurrentSKUSetToRenewError + **/ + INVALID_SKU_PROVIDED_MUST_BE_CURRENT_SKU_SET_TO_RENEW(4000220L), + + /** + * Advanced Commerce API Price Increase mechanism is not currently supported in India. + * + * @see ACAPriceIncreaseIsNotCurrentlySupportedInIndiaError + **/ + ACA_PRICE_INCREASE_IS_NOT_CURRENTLY_SUPPORTED_IN_INDIA(4000221L), + + /** + * Invalid request. A prorated price shouldn't be present to change items with the change taking effect later. + * + * @see InvalidProratedPriceForChangeItemWithEffectiveLaterError + **/ + INVALID_PRORATED_PRICE_FOR_CHANGE_ITEM_WITH_EFFECTIVE_LATER(4000222L), + + /** + * Invalid request. The subscription offer configuration is invalid; free trial offers must use a period count of 1. + * + * @see FreeTrialOfferMustUsePeriodCountOfOneError + **/ + FREE_TRIAL_OFFER_MUST_USE_PERIOD_COUNT_OF_ONE(4000223L), + /** * An error that indicates that no image object is included, but the request indicates that the header should be placed above the image. * * @see BadRequestAboveImageRequiresAnImageError - */ + **/ BAD_REQUEST_ABOVE_IMAGE_REQUIRES_AN_IMAGE(4000224L), /** - * An error that indicates the subscription doesn't qualify for a renewal-date extension due to its subscription state. + * An error that indicates the group identifier is invalid. + * + * @see InvalidGroupIdError + **/ + INVALID_GROUP_ID(4000225L), + + /** + * An error that indicates the transaction is one that an organization or group assigns to the customer, which the endpoint doesn’t support. + * + * @see InvalidAssignedTransactionNotSupportedError + **/ + INVALID_ASSIGNED_TRANSACTION_NOT_SUPPORTED(4000227L), + + /** + * Unauthorized. + * + * @see UnauthorizedError + **/ + UNAUTHORIZED(4010000L), + + /** + * An error that indicates the subscription doesn’t qualify for a renewal-date extension due to its subscription state. * * @see SubscriptionExtensionIneligibleError - */ + **/ SUBSCRIPTION_EXTENSION_INELIGIBLE(4030004L), /** * An error that indicates the subscription doesn’t qualify for a renewal-date extension because it has already received the maximum extensions. * * @see SubscriptionMaxExtensionError - */ + **/ SUBSCRIPTION_MAX_EXTENSION(4030005L), /** - * An error that indicates a subscription isn't directly eligible for a renewal date extension because the user obtained it through Family Sharing. + * An error that indicates a subscription isn’t directly eligible for a renewal date extension because the customer obtained it through Family Sharing. * * @see FamilySharedSubscriptionExtensionIneligibleError - */ + **/ FAMILY_SHARED_SUBSCRIPTION_EXTENSION_INELIGIBLE(4030007L), + /** + * The subscription doesn't exist. + * + * @see SubscriptionDoesNotExistError + **/ + SUBSCRIPTION_DOES_NOT_EXIST(4030008L), + + /** + * The subscription already exists. + * + * @see SubscriptionAlreadyExistsError + **/ + SUBSCRIPTION_ALREADY_EXISTS(4030009L), + + /** + * The subscription isn't eligible for the requested changes. + * + * @see SubscriptionNotEligibleError + **/ + SUBSCRIPTION_NOT_ELIGIBLE(4030010L), + + /** + * The subscription is already active, and cannot be reactivated or renewed at this time. + * + * @see SubscriptionAlreadyActiveError + **/ + SUBSCRIPTION_ALREADY_ACTIVE(4030011L), + + /** + * The customer doesn't own the product. + * + * @see ProductNotOwnedError + **/ + PRODUCT_NOT_OWNED(4030013L), + /** * An error that indicates when you reach the maximum number of uploaded images. * * @see MaximumNumberOfImagesReachedError - */ + **/ MAXIMUM_NUMBER_OF_IMAGES_REACHED(4030014L), + /** + * The subscription is not active. + * + * @see InactiveACASubError + **/ + INACTIVE_ACA_SUB(4030015L), + /** * An error that indicates when you reach the maximum number of uploaded messages. * * @see MaximumNumberOfMessagesReachedError - */ + **/ MAXIMUM_NUMBER_OF_MESSAGES_REACHED(4030016L), /** - * An error that indicates the message isn't in the approved state, so you can't configure it as a default message. + * An error that indicates the message isn’t in the approved state, so you can’t configure it as a default message. * * @see MessageNotApprovedError - */ + **/ MESSAGE_NOT_APPROVED(4030017L), /** - * An error that indicates the image isn't in the approved state, so you can't configure it as part of a default message. + * An error that indicates the image isn’t in the approved state, so you can’t configure it as part of a default message. * * @see ImageNotApprovedError - */ + **/ IMAGE_NOT_APPROVED(4030018L), /** - * An error that indicates the image is currently in use as part of a message, so you can't delete it. + * An error that indicates the image is currently in use as part of a message, so you can’t delete it. * * @see ImageInUseError - */ + **/ IMAGE_IN_USE(4030019L), + /** + * Insufficient funds for refund. + * + * @see InsufficientFundsError + **/ + INSUFFICIENT_FUNDS(4030020L), + + /** + * The transaction was already refunded. + * + * @see AlreadyRefundedError + **/ + ALREADY_REFUNDED(4030021L), + + /** + * The storefront changed. + * + * @see StorefrontChangeError + **/ + STOREFRONT_CHANGE(4030022L), + + /** + * The product isn't eligible for the requested operation. + * + * @see ProductNotEligibleError + **/ + PRODUCT_NOT_ELIGIBLE(4030023L), + + /** + * The transaction is not refundable. + * + * @see TransactionNotRefundableError + **/ + TRANSACTION_NOT_REFUNDABLE(4030024L), + + /** + * The transaction can't be refunded; customer can contact Apple Support for assistance. + * + * @see TransactionCannotBeRefundedContactSupportError + **/ + TRANSACTION_CANNOT_BE_REFUNDED_CONTACT_SUPPORT(4030025L), + /** * An error that indicates that passing a performance test is required before you can set a URL for the production environment. * * @see ForbiddenNoPassingTestError - */ + **/ FORBIDDEN_NO_PASSING_TEST(4030026L), /** - * An error that indicates the App Store account wasn't found. + * The subscription isn't eligible for migration because a price increase has already been communicated to the customer. + * + * @see MigrationNotAllowedWhenPriceIncreaseCommunicatedError + **/ + MIGRATION_NOT_ALLOWED_WHEN_PRICE_INCREASE_COMMUNICATED(4030027L), + + /** + * An error that indicates a subscription isn’t eligible for a renewal date extension because the customer has access through an organization or group. + * + * @see AssignedSubscriptionExtensionIneligibleError + **/ + ASSIGNED_SUBSCRIPTION_EXTENSION_INELIGIBLE(4030028L), + + /** + * An error that indicates the App Store account wasn’t found. * * @see AccountNotFoundError - */ + **/ ACCOUNT_NOT_FOUND(4040001L), /** * An error response that indicates the App Store account wasn’t found, but you can try again. * * @see AccountNotFoundRetryableError - */ + **/ ACCOUNT_NOT_FOUND_RETRYABLE(4040002L), /** * An error that indicates the app wasn’t found. * * @see AppNotFoundError - */ + **/ APP_NOT_FOUND(4040003L), /** * An error response that indicates the app wasn’t found, but you can try again. * * @see AppNotFoundRetryableError - */ + **/ APP_NOT_FOUND_RETRYABLE(4040004L), /** - * An error that indicates an original transaction identifier wasn't found. + * An error that indicates an original transaction identifier wasn’t found. * * @see OriginalTransactionIdNotFoundError - */ + **/ ORIGINAL_TRANSACTION_ID_NOT_FOUND(4040005L), /** * An error response that indicates the original transaction identifier wasn’t found, but you can try again. * * @see OriginalTransactionIdNotFoundRetryableError - */ + **/ ORIGINAL_TRANSACTION_ID_NOT_FOUND_RETRYABLE(4040006L), /** - * An error that indicates that the App Store server couldn’t find a notifications URL for your app in this environment. + * An error that indicates the App Store server couldn’t find a notifications URL for your app in the environment. * - * @see ServerNotificationUrlNotFoundError - */ + * @see ServerNotificationURLNotFoundError + **/ SERVER_NOTIFICATION_URL_NOT_FOUND(4040007L), /** - * An error that indicates that the test notification token is expired or the test notification status isn’t available. + * An error that indicates the test notification token is expired or the test notification status isn’t available. * * @see TestNotificationNotFoundError - */ + **/ TEST_NOTIFICATION_NOT_FOUND(4040008L), /** - * An error that indicates the server didn't find a subscription-renewal-date extension request for the request identifier and product identifier you provided. + * An error that indicates the server didn’t find a subscription-renewal-date extension request for the request identifier and product identifier you provided. * * @see StatusRequestNotFoundError - */ + **/ STATUS_REQUEST_NOT_FOUND(4040009L), /** - * An error that indicates a transaction identifier wasn't found. + * An error that indicates a transaction identifier wasn’t found. * * @see TransactionIdNotFoundError - */ + **/ TRANSACTION_ID_NOT_FOUND(4040010L), /** - * An error that indicates the system can't find the image identifier. + * An error that indicates the system can’t find the image identifier. * * @see ImageNotFoundError - */ + **/ IMAGE_NOT_FOUND(4040014L), /** - * An error that indicates the system can't find the message identifier. + * An error that indicates the system can’t find the message identifier. * * @see MessageNotFoundError - */ + **/ MESSAGE_NOT_FOUND(4040015L), + /** + * Product not found. + * + * @see ProductNotFoundError + **/ + PRODUCT_NOT_FOUND(4040016L), + /** * An error the API returns if the service can’t find the specified test run. * * @see PerformanceTestRunNotFoundError - */ + **/ PERFORMANCE_TEST_RUN_NOT_FOUND(4040018L), /** * An error response that indicates an app transaction doesn’t exist for the specified customer. * * @see AppTransactionDoesNotExistError - */ - APP_TRANSACTION_DOES_NOT_EXIST_ERROR(4040019L), + **/ + APP_TRANSACTION_DOES_NOT_EXIST(4040019L), /** * An error that indicates a default message isn’t configured. * * @see DefaultMessageNotFoundError - */ + **/ DEFAULT_MESSAGE_NOT_FOUND(4040020L), /** * An error that indicates that the URL for your endpoint isn’t configured. * * @see RealtimeUrlNotFoundError - */ + **/ REALTIME_URL_NOT_FOUND(4040021L), + /** + * An error that indicates the group wasn’t found. + * + * @see GroupNotFoundError + **/ + GROUP_NOT_FOUND(4040022L), + /** * An error that indicates the image identifier already exists. * * @see ImageAlreadyExistsError - */ + **/ IMAGE_ALREADY_EXISTS(4090000L), /** * An error that indicates the message identifier already exists. * * @see MessageAlreadyExistsError - */ + **/ MESSAGE_ALREADY_EXISTS(4090001L), /** - * An error that indicates that the request exceeded the rate limit. + * An error that indicates the request exceeded the rate limit. * * @see RateLimitExceededError - */ + **/ RATE_LIMIT_EXCEEDED(4290000L), /** * An error that indicates a general internal error. * * @see GeneralInternalError - */ + **/ GENERAL_INTERNAL(5000000L), /** * An error response that indicates an unknown error occurred, but you can try again. * * @see GeneralInternalRetryableError - */ + **/ GENERAL_INTERNAL_RETRYABLE(5000001L); private final long errorCode; diff --git a/src/main/java/com/apple/itunes/storekit/client/BaseAppStoreServerAPIClient.java b/src/main/java/com/apple/itunes/storekit/client/BaseAppStoreServerAPIClient.java index d6ebc09d..41f3f8ec 100644 --- a/src/main/java/com/apple/itunes/storekit/client/BaseAppStoreServerAPIClient.java +++ b/src/main/java/com/apple/itunes/storekit/client/BaseAppStoreServerAPIClient.java @@ -24,6 +24,8 @@ import com.apple.itunes.storekit.model.ErrorPayload; import com.apple.itunes.storekit.model.ExtendRenewalDateRequest; import com.apple.itunes.storekit.model.ExtendRenewalDateResponse; +import com.apple.itunes.storekit.model.GetCustomerGroupsResponse; +import com.apple.itunes.storekit.model.GetGroupMembersResponse; import com.apple.itunes.storekit.model.GetImageListResponse; import com.apple.itunes.storekit.model.GetMessageListResponse; import com.apple.itunes.storekit.model.HistoryResponse; @@ -54,11 +56,13 @@ import java.io.Closeable; import java.io.IOException; import java.io.Reader; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; @@ -170,6 +174,9 @@ protected T makeHttpCall(String path, String method, Map T makeHttpCall(String path, String method, Map T makeHttpCall(String path, String method, MapExtend Subscription Renewal Dates for All Active Subscribers + * @see Extend Subscription Renewal Dates for All Active Subscribers */ public MassExtendRenewalDateResponse extendRenewalDateForAllActiveSubscribers(MassExtendRenewalDateRequest massExtendRenewalDateRequest) throws APIException, IOException { return makeHttpCall("/inApps/v1/subscriptions/extend/mass", "POST", Map.of(), massExtendRenewalDateRequest, MassExtendRenewalDateResponse.class, JSON); @@ -203,10 +230,10 @@ public MassExtendRenewalDateResponse extendRenewalDateForAllActiveSubscribers(Ma * @return A response that indicates whether an individual renewal-date extension succeeded, and related details. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Extend a Subscription Renewal Date + * @see Extend a Subscription Renewal Date */ public ExtendRenewalDateResponse extendSubscriptionRenewalDate(String originalTransactionId, ExtendRenewalDateRequest extendRenewalDateRequest) throws APIException, IOException { - return makeHttpCall("/inApps/v1/subscriptions/extend/" + originalTransactionId, "PUT", Map.of(), extendRenewalDateRequest, ExtendRenewalDateResponse.class, JSON); + return makeHttpCall(path("/inApps/v1/subscriptions/extend/{}", originalTransactionId), "PUT", Map.of(), extendRenewalDateRequest, ExtendRenewalDateResponse.class, JSON); } /** @@ -217,14 +244,14 @@ public ExtendRenewalDateResponse extendSubscriptionRenewalDate(String originalTr * @return A response that contains status information for all of a customer’s auto-renewable subscriptions in your app. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get All Subscription Statuses + * @see Get All Subscription Statuses */ public StatusResponse getAllSubscriptionStatuses(String anyTransactionId, Status[] status) throws APIException, IOException { Map> queryParameters = new HashMap<>(); if (status != null) { queryParameters.put("status", Arrays.stream(status).map(s -> s.getValue().toString()).collect(Collectors.toList())); } - return makeHttpCall("/inApps/v1/subscriptions/" + anyTransactionId, "GET", queryParameters, null, StatusResponse.class, null); + return makeHttpCall(path("/inApps/v1/subscriptions/{}", anyTransactionId), "GET", queryParameters, null, StatusResponse.class, null); } /** @@ -232,17 +259,17 @@ public StatusResponse getAllSubscriptionStatuses(String anyTransactionId, Status * * @param anyTransactionId Any transactionId, originalTransactionId, or appTransactionId that belongs to the customer for your app. * @param revision A token you provide to get the next set of up to 20 transactions. All responses include a revision token. Use the revision token from the previous RefundHistoryResponse. - * @return A response that contains status information for all of a customer’s auto-renewable subscriptions in your app. + * @return A response that contains an array of signed JSON Web Signature (JWS) refunded transactions, and paging information. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Refund History + * @see Get Refund History */ public RefundHistoryResponse getRefundHistory(String anyTransactionId, String revision) throws APIException, IOException { Map> queryParameters = new HashMap<>(); if (revision != null) { queryParameters.put("revision", List.of(revision)); } - return makeHttpCall("/inApps/v2/refund/lookup/" + anyTransactionId, "GET", queryParameters, null, RefundHistoryResponse.class, null); + return makeHttpCall(path("/inApps/v2/refund/lookup/{}", anyTransactionId), "GET", queryParameters, null, RefundHistoryResponse.class, null); } /** @@ -253,10 +280,10 @@ public RefundHistoryResponse getRefundHistory(String anyTransactionId, String re * @return A response that indicates the current status of a request to extend the subscription renewal date to all eligible subscribers. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Status of Subscription Renewal Date Extensions + * @see Get Status of Subscription Renewal Date Extensions */ public MassExtendRenewalDateStatusResponse getStatusOfSubscriptionRenewalDateExtensions(String requestIdentifier, String productId) throws APIException, IOException { - return makeHttpCall("/inApps/v1/subscriptions/extend/mass/" + productId + "/" + requestIdentifier, "GET", Map.of(), null, MassExtendRenewalDateStatusResponse.class, null); + return makeHttpCall(path("/inApps/v1/subscriptions/extend/mass/{}/{}", productId, requestIdentifier), "GET", Map.of(), null, MassExtendRenewalDateStatusResponse.class, null); } /** @@ -266,10 +293,10 @@ public MassExtendRenewalDateStatusResponse getStatusOfSubscriptionRenewalDateExt * @return A response that contains the contents of the test notification sent by the App Store server and the result from your server. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Test Notification Status + * @see Get Test Notification Status */ public CheckTestNotificationResponse getTestNotificationStatus(String testNotificationToken) throws APIException, IOException { - return makeHttpCall("/inApps/v1/notifications/test/" + testNotificationToken, "GET", Map.of(), null, CheckTestNotificationResponse.class, null); + return makeHttpCall(path("/inApps/v1/notifications/test/{}", testNotificationToken), "GET", Map.of(), null, CheckTestNotificationResponse.class, null); } /** @@ -280,7 +307,7 @@ public CheckTestNotificationResponse getTestNotificationStatus(String testNotifi * @return A response that contains the App Store Server Notifications history for your app. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Notification History + * @see Get Notification History */ public NotificationHistoryResponse getNotificationHistory(String paginationToken, NotificationHistoryRequest notificationHistoryRequest) throws APIException, IOException { Map> queryParameters = new HashMap<>(); @@ -292,6 +319,7 @@ public NotificationHistoryResponse getNotificationHistory(String paginationToken /** * @see #getTransactionHistory(String, String, TransactionHistoryRequest, GetTransactionHistoryVersion) + * @deprecated Use {@link #getTransactionHistory(String, String, TransactionHistoryRequest, GetTransactionHistoryVersion)} instead */ @Deprecated(since = "2.2.0") public HistoryResponse getTransactionHistory(String anyTransactionId, String revision, TransactionHistoryRequest transactionHistoryRequest) throws APIException, IOException { @@ -307,9 +335,10 @@ public HistoryResponse getTransactionHistory(String anyTransactionId, String rev * @return A response that contains the customer’s transaction history for an app. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Transaction History + * @see Get Transaction History */ public HistoryResponse getTransactionHistory(String anyTransactionId, String revision, TransactionHistoryRequest transactionHistoryRequest, GetTransactionHistoryVersion version) throws APIException, IOException { + Objects.requireNonNull(transactionHistoryRequest, "transactionHistoryRequest cannot be null"); Map> queryParameters = new HashMap<>(); if (revision != null) { queryParameters.put("revision", List.of(revision)); @@ -332,13 +361,13 @@ public HistoryResponse getTransactionHistory(String anyTransactionId, String rev if (transactionHistoryRequest.getSubscriptionGroupIdentifiers() != null) { queryParameters.put("subscriptionGroupIdentifier", transactionHistoryRequest.getSubscriptionGroupIdentifiers()); } - if (transactionHistoryRequest.getInAppOwnershipType() != null) { - queryParameters.put("inAppOwnershipType", List.of(transactionHistoryRequest.getInAppOwnershipType().name())); + if (transactionHistoryRequest.getRawInAppOwnershipType() != null) { + queryParameters.put("inAppOwnershipType", List.of(transactionHistoryRequest.getRawInAppOwnershipType())); } if (transactionHistoryRequest.getRevoked() != null) { queryParameters.put("revoked", List.of(transactionHistoryRequest.getRevoked().toString())); } - return makeHttpCall("/inApps/" + version.getUrlVersion() + "/history/" + anyTransactionId, "GET", queryParameters, null, HistoryResponse.class, null); + return makeHttpCall(path("/inApps/{}/history/{}", version.getUrlVersion(), anyTransactionId), "GET", queryParameters, null, HistoryResponse.class, null); } /** @@ -348,10 +377,10 @@ public HistoryResponse getTransactionHistory(String anyTransactionId, String rev * @return A response that contains signed transaction information for a single transaction. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Get Transaction Info + * @see Get Transaction Info */ public TransactionInfoResponse getTransactionInfo(String transactionId) throws APIException, IOException { - return makeHttpCall("/inApps/v1/transactions/" + transactionId, "GET", Map.of(), null, TransactionInfoResponse.class, null); + return makeHttpCall(path("/inApps/v1/transactions/{}", transactionId), "GET", Map.of(), null, TransactionInfoResponse.class, null); } /** @@ -361,10 +390,10 @@ public TransactionInfoResponse getTransactionInfo(String transactionId) throws A * @return A response that includes the order lookup status and an array of signed transactions for the in-app purchases in the order. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Look Up Order ID + * @see Look Up Order ID */ public OrderLookupResponse lookUpOrderId(String orderId) throws APIException, IOException { - return makeHttpCall("/inApps/v1/lookup/" + orderId, "GET", Map.of(), null, OrderLookupResponse.class, null); + return makeHttpCall(path("/inApps/v1/lookup/{}", orderId), "GET", Map.of(), null, OrderLookupResponse.class, null); } /** @@ -373,7 +402,7 @@ public OrderLookupResponse lookUpOrderId(String orderId) throws APIException, IO * @return A response that contains the test notification token. * @throws APIException If a response was returned indicating the request could not be processed * @throws IOException If an exception was thrown while making the request - * @see Request a Test Notification + * @see Request a Test Notification */ public SendTestNotificationResponse requestTestNotification() throws APIException, IOException { return makeHttpCall("/inApps/v1/notifications/test", "POST", Map.of(), null, SendTestNotificationResponse.class, null); @@ -391,7 +420,7 @@ public SendTestNotificationResponse requestTestNotification() throws APIExceptio */ @Deprecated public void sendConsumptionData(String transactionId, ConsumptionRequestV1 consumptionRequest) throws APIException, IOException { - makeHttpCall("/inApps/v1/transactions/consumption/" + transactionId, "PUT", Map.of(), consumptionRequest, Void.class, JSON); + makeHttpCall(path("/inApps/v1/transactions/consumption/{}", transactionId), "PUT", Map.of(), consumptionRequest, Void.class, JSON); } /** @@ -404,7 +433,7 @@ public void sendConsumptionData(String transactionId, ConsumptionRequestV1 consu * @see Send Consumption Information */ public void sendConsumptionInformation(String transactionId, ConsumptionRequest consumptionRequest) throws APIException, IOException { - makeHttpCall("/inApps/v2/transactions/consumption/" + transactionId, "PUT", Map.of(), consumptionRequest, Void.class, JSON); + makeHttpCall(path("/inApps/v2/transactions/consumption/{}", transactionId), "PUT", Map.of(), consumptionRequest, Void.class, JSON); } @@ -418,15 +447,7 @@ public void sendConsumptionInformation(String transactionId, ConsumptionRequest * @see Set App Account Token */ public void setAppAccountToken(String originalTransactionId, UpdateAppAccountTokenRequest updateAppAccountTokenRequest) throws APIException, IOException { - makeHttpCall("/inApps/v1/transactions/" + originalTransactionId + "/appAccountToken", "PUT", Map.of(), updateAppAccountTokenRequest, Void.class, JSON); - } - - /** - * @see #uploadImage(UUID, byte[], ImageSize) - */ - @Deprecated(since = "5.1.0") - public void uploadImage(UUID imageIdentifier, byte[] image) throws APIException, IOException { - uploadImage(imageIdentifier, image, null); + makeHttpCall(path("/inApps/v1/transactions/{}/appAccountToken", originalTransactionId), "PUT", Map.of(), updateAppAccountTokenRequest, Void.class, JSON); } /** @@ -444,7 +465,7 @@ public void uploadImage(UUID imageIdentifier, byte[] image, ImageSize imageSize) if (imageSize != null) { queryParameters.put("imageSize", List.of(imageSize.name())); } - makeHttpCall("/inApps/v1/messaging/image/" + imageIdentifier, "PUT", queryParameters, image, Void.class, PNG); + makeHttpCall(path("/inApps/v1/messaging/image/{}", imageIdentifier.toString()), "PUT", queryParameters, image, Void.class, PNG); } /** @@ -456,7 +477,7 @@ public void uploadImage(UUID imageIdentifier, byte[] image, ImageSize imageSize) * @see Delete Image */ public void deleteImage(UUID imageIdentifier) throws APIException, IOException { - makeHttpCall("/inApps/v1/messaging/image/" + imageIdentifier, "DELETE", Map.of(), null, Void.class, null); + makeHttpCall(path("/inApps/v1/messaging/image/{}", imageIdentifier.toString()), "DELETE", Map.of(), null, Void.class, null); } /** @@ -481,7 +502,7 @@ public GetImageListResponse getImageList() throws APIException, IOException { * @see Upload Message */ public void uploadMessage(UUID messageIdentifier, UploadMessageRequestBody uploadMessageRequestBody) throws APIException, IOException { - makeHttpCall("/inApps/v1/messaging/message/" + messageIdentifier, "PUT", Map.of(), uploadMessageRequestBody, Void.class, JSON); + makeHttpCall(path("/inApps/v1/messaging/message/{}", messageIdentifier.toString()), "PUT", Map.of(), uploadMessageRequestBody, Void.class, JSON); } /** @@ -493,7 +514,7 @@ public void uploadMessage(UUID messageIdentifier, UploadMessageRequestBody uploa * @see Delete Message */ public void deleteMessage(UUID messageIdentifier) throws APIException, IOException { - makeHttpCall("/inApps/v1/messaging/message/" + messageIdentifier, "DELETE", Map.of(), null, Void.class, null); + makeHttpCall(path("/inApps/v1/messaging/message/{}", messageIdentifier.toString()), "DELETE", Map.of(), null, Void.class, null); } /** @@ -519,7 +540,7 @@ public GetMessageListResponse getMessageList() throws APIException, IOException * @see Configure Default Message */ public void configureDefaultMessage(String productId, String locale, DefaultConfigurationRequest defaultConfigurationRequest) throws APIException, IOException { - makeHttpCall("/inApps/v1/messaging/default/" + productId + "/" + locale, "PUT", Map.of(), defaultConfigurationRequest, Void.class, JSON); + makeHttpCall(path("/inApps/v1/messaging/default/{}/{}", productId, locale), "PUT", Map.of(), defaultConfigurationRequest, Void.class, JSON); } /** @@ -532,7 +553,7 @@ public void configureDefaultMessage(String productId, String locale, DefaultConf * @see Delete Default Message */ public void deleteDefaultMessage(String productId, String locale) throws APIException, IOException { - makeHttpCall("/inApps/v1/messaging/default/" + productId + "/" + locale, "DELETE", Map.of(), null, Void.class, null); + makeHttpCall(path("/inApps/v1/messaging/default/{}/{}", productId, locale), "DELETE", Map.of(), null, Void.class, null); } /** @@ -546,7 +567,7 @@ public void deleteDefaultMessage(String productId, String locale) throws APIExce * @see Get Default Message */ public DefaultConfigurationResponse getDefaultMessage(String productId, String locale) throws APIException, IOException { - return makeHttpCall("/inApps/v1/messaging/default/" + productId + "/" + locale, "GET", Map.of(), null, DefaultConfigurationResponse.class, null); + return makeHttpCall(path("/inApps/v1/messaging/default/{}/{}", productId, locale), "GET", Map.of(), null, DefaultConfigurationResponse.class, null); } /** @@ -606,8 +627,8 @@ public PerformanceTestResponse initiatePerformanceTest(PerformanceTestRequest pe * @throws IOException If an exception was thrown while making the request * @see Get Performance Test Results */ - public PerformanceTestResultResponse getPerformanceTestResults(String requestId) throws APIException, IOException { - return makeHttpCall("/inApps/v1/messaging/performanceTest/result/" + requestId, "GET", Map.of(), null, PerformanceTestResultResponse.class, null); + public PerformanceTestResultResponse getPerformanceTestResults(UUID requestId) throws APIException, IOException { + return makeHttpCall(path("/inApps/v1/messaging/performanceTest/result/{}", requestId.toString()), "GET", Map.of(), null, PerformanceTestResultResponse.class, null); } /** @@ -620,7 +641,7 @@ public PerformanceTestResultResponse getPerformanceTestResults(String requestId) * @see Get App Transaction Info */ public AppTransactionInfoResponse getAppTransactionInfo(String anyTransactionId) throws APIException, IOException { - return makeHttpCall("/inApps/v1/transactions/appTransactions/" + anyTransactionId, "GET", Map.of(), null, AppTransactionInfoResponse.class, null); + return makeHttpCall(path("/inApps/v1/transactions/appTransactions/{}", anyTransactionId), "GET", Map.of(), null, AppTransactionInfoResponse.class, null); } /** @@ -632,7 +653,7 @@ public AppTransactionInfoResponse getAppTransactionInfo(String anyTransactionId) * @see Finish Transaction */ public void finishTransaction(String transactionId) throws APIException, IOException { - makeHttpCall("/inApps/v1/transactions/" + transactionId + "/finish", "POST", Map.of(), null, Void.class, null); + makeHttpCall(path("/inApps/v1/transactions/{}/finish", transactionId), "POST", Map.of(), null, Void.class, null); } /** @@ -646,7 +667,7 @@ public void finishTransaction(String transactionId) throws APIException, IOExcep * @see Change Subscription Price */ public AdvancedCommerceSubscriptionPriceChangeResponse changeSubscriptionPrice(String transactionId, AdvancedCommerceSubscriptionPriceChangeRequest subscriptionPriceChangeRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/subscription/changePrice/" + transactionId, "POST", Map.of(), subscriptionPriceChangeRequest, AdvancedCommerceSubscriptionPriceChangeResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/subscription/changePrice/{}", transactionId), "POST", Map.of(), subscriptionPriceChangeRequest, AdvancedCommerceSubscriptionPriceChangeResponse.class, JSON); } /** @@ -660,7 +681,7 @@ public AdvancedCommerceSubscriptionPriceChangeResponse changeSubscriptionPrice(S * @see Cancel a Subscription */ public AdvancedCommerceSubscriptionCancelResponse cancelSubscription(String transactionId, AdvancedCommerceSubscriptionCancelRequest subscriptionCancelRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/subscription/cancel/" + transactionId, "POST", Map.of(), subscriptionCancelRequest, AdvancedCommerceSubscriptionCancelResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/subscription/cancel/{}", transactionId), "POST", Map.of(), subscriptionCancelRequest, AdvancedCommerceSubscriptionCancelResponse.class, JSON); } /** @@ -674,7 +695,7 @@ public AdvancedCommerceSubscriptionCancelResponse cancelSubscription(String tran * @see Revoke Subscription */ public AdvancedCommerceSubscriptionRevokeResponse revokeSubscription(String transactionId, AdvancedCommerceSubscriptionRevokeRequest subscriptionRevokeRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/subscription/revoke/" + transactionId, "POST", Map.of(), subscriptionRevokeRequest, AdvancedCommerceSubscriptionRevokeResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/subscription/revoke/{}", transactionId), "POST", Map.of(), subscriptionRevokeRequest, AdvancedCommerceSubscriptionRevokeResponse.class, JSON); } /** @@ -688,7 +709,7 @@ public AdvancedCommerceSubscriptionRevokeResponse revokeSubscription(String tran * @see Request Transaction Refund */ public AdvancedCommerceRequestRefundResponse requestTransactionRefund(String transactionId, AdvancedCommerceRequestRefundRequest requestRefundRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/transaction/requestRefund/" + transactionId, "POST", Map.of(), requestRefundRequest, AdvancedCommerceRequestRefundResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/transaction/requestRefund/{}", transactionId), "POST", Map.of(), requestRefundRequest, AdvancedCommerceRequestRefundResponse.class, JSON); } /** @@ -702,7 +723,7 @@ public AdvancedCommerceRequestRefundResponse requestTransactionRefund(String tra * @see Change Subscription Metadata */ public AdvancedCommerceSubscriptionChangeMetadataResponse changeSubscriptionMetadata(String transactionId, AdvancedCommerceSubscriptionChangeMetadataRequest subscriptionChangeMetadataRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/subscription/changeMetadata/" + transactionId, "POST", Map.of(), subscriptionChangeMetadataRequest, AdvancedCommerceSubscriptionChangeMetadataResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/subscription/changeMetadata/{}", transactionId), "POST", Map.of(), subscriptionChangeMetadataRequest, AdvancedCommerceSubscriptionChangeMetadataResponse.class, JSON); } /** @@ -716,7 +737,42 @@ public AdvancedCommerceSubscriptionChangeMetadataResponse changeSubscriptionMeta * @see Migrate a Subscription to Advanced Commerce API */ public AdvancedCommerceSubscriptionMigrateResponse migrateSubscriptionToAdvancedCommerceAPI(String transactionId, AdvancedCommerceSubscriptionMigrateRequest subscriptionMigrateRequest) throws APIException, IOException { - return makeHttpCall("/advancedCommerce/v1/subscription/migrate/" + transactionId, "POST", Map.of(), subscriptionMigrateRequest, AdvancedCommerceSubscriptionMigrateResponse.class, JSON); + return makeHttpCall(path("/advancedCommerce/v1/subscription/migrate/{}", transactionId), "POST", Map.of(), subscriptionMigrateRequest, AdvancedCommerceSubscriptionMigrateResponse.class, JSON); + } + + /** + * Get the groups that a customer belongs to, and their role in each group. + * + * @param anyTransactionId Any originalTransactionId, transactionId, or appTransactionId that belongs to the customer for your app. + * @return A response that contains the groups a customer belongs to, and their role in each group. + * @throws APIException If a response was returned indicating the request could not be processed + * @throws IOException If an exception was thrown while making the request + * @see Get Customer Groups + */ + public GetCustomerGroupsResponse getCustomerGroups(String anyTransactionId) throws APIException, IOException { + return makeHttpCall(path("/groups/v1/currentGroups/{}", anyTransactionId), "GET", Map.of(), null, GetCustomerGroupsResponse.class, null); + } + + /** + * Get a paginated list of the customers that belong to a group. + * + * @param groupId The identifier of a group in your app, which the Get Customer Groups endpoint returns. + * @param paginationToken An optional token you use to get the next set of members. Responses that have more members available include a paginationToken. Omit this parameter the first time you call this endpoint. + * @param limit An optional maximum number of members to return in a single response. + * @return A response that contains a page of the customers that belong to a group. + * @throws APIException If a response was returned indicating the request could not be processed + * @throws IOException If an exception was thrown while making the request + * @see Get Group Members + */ + public GetGroupMembersResponse getGroupMembers(String groupId, String paginationToken, Integer limit) throws APIException, IOException { + Map> queryParameters = new HashMap<>(); + if (paginationToken != null) { + queryParameters.put("paginationToken", List.of(paginationToken)); + } + if (limit != null) { + queryParameters.put("limit", List.of(limit.toString())); + } + return makeHttpCall(path("/groups/v1/group/{}", groupId), "GET", queryParameters, null, GetGroupMembersResponse.class, null); } protected interface HttpResponseInterface extends Closeable { diff --git a/src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticator.java b/src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticator.java index d79d6480..32964114 100644 --- a/src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticator.java +++ b/src/main/java/com/apple/itunes/storekit/client/BearerTokenAuthenticator.java @@ -45,9 +45,11 @@ public BearerTokenAuthenticator(String signingKey, String keyId, String issuerId } public String generateToken() { + Instant now = Instant.now(); return JWT.create() .withAudience(APP_STORE_CONNECT_AUDIENCE) - .withExpiresAt(Instant.now().plus(ChronoUnit.MINUTES.getDuration().multipliedBy(5))) + .withIssuedAt(now) + .withExpiresAt(now.plus(ChronoUnit.MINUTES.getDuration().multipliedBy(5))) .withIssuer(issuerId) .withKeyId(keyId) .withPayload(Map.of(BUNDLE_ID_KEY, bundleId)) diff --git a/src/main/java/com/apple/itunes/storekit/client/GetTransactionHistoryVersion.java b/src/main/java/com/apple/itunes/storekit/client/GetTransactionHistoryVersion.java index 6ec8b2c7..472931b8 100644 --- a/src/main/java/com/apple/itunes/storekit/client/GetTransactionHistoryVersion.java +++ b/src/main/java/com/apple/itunes/storekit/client/GetTransactionHistoryVersion.java @@ -1,7 +1,12 @@ +// Copyright (c) 2024 Apple Inc. Licensed under MIT License. + package com.apple.itunes.storekit.client; public enum GetTransactionHistoryVersion { + /** + * @deprecated Use {@link #V2} instead. + */ @Deprecated(since = "2.2.0") V1("v1"), V2("v2"); diff --git a/src/main/java/com/apple/itunes/storekit/migration/ReceiptUtility.java b/src/main/java/com/apple/itunes/storekit/migration/ReceiptUtility.java index b37b1ba5..2797b84e 100644 --- a/src/main/java/com/apple/itunes/storekit/migration/ReceiptUtility.java +++ b/src/main/java/com/apple/itunes/storekit/migration/ReceiptUtility.java @@ -15,6 +15,9 @@ import org.bouncycastle.asn1.pkcs.SignedData; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.CodingErrorAction; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; @@ -26,6 +29,7 @@ public class ReceiptUtility { private static final int IN_APP_TYPE_ID = 17; private static final int TRANSACTION_IDENTIFIER_TYPE_ID = 1703; private static final int ORIGINAL_TRANSACTION_IDENTIFIER_TYPE_ID = 1705; + private static final Pattern BASE64_PATTERN = Pattern.compile("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"); /** * Extracts a transaction id from an encoded App Receipt. Throws if the receipt does not match the expected format. @@ -33,12 +37,23 @@ public class ReceiptUtility { * * @param appReceipt The unmodified app receipt * @return A transaction id from the array of in-app purchases, null if the receipt contains no in-app purchases. - * @throws IOException If the receipt was malformed + * @throws IOException Not thrown for a malformed receipt, which throws IllegalArgumentException; declared for source compatibility * @throws IllegalArgumentException If the receipt could not be parsed or did not match the expected format */ public String extractTransactionIdFromAppReceipt(String appReceipt) throws IOException { + byte[] decodedAppReceipt = decodeBase64(appReceipt, "Invalid App Receipt"); + try { + return extractTransactionIdFromDecodedAppReceipt(decodedAppReceipt); + } catch (IllegalArgumentException e) { + throw e; + } catch (IOException | RuntimeException e) { + throw new IllegalArgumentException("Invalid App Receipt", e); + } + } + + private String extractTransactionIdFromDecodedAppReceipt(byte[] decodedAppReceipt) throws IOException { // PKCS#7 - try (ASN1InputStream in = new ASN1InputStream(Base64.getDecoder().decode(appReceipt))) { + try (ASN1InputStream in = new ASN1InputStream(decodedAppReceipt)) { ASN1Primitive root = in.readObject(); if (root instanceof ASN1Sequence) { ASN1Sequence seq = (ASN1Sequence) root; @@ -95,7 +110,7 @@ public String extractTransactionIdFromAppReceipt(String appReceipt) throws IOExc } } - return null; + throw new IllegalArgumentException("Invalid App Receipt"); } /** @@ -107,16 +122,35 @@ public String extractTransactionIdFromAppReceipt(String appReceipt) throws IOExc * @throws IllegalArgumentException If the receipt could not be parsed or did not match the expected format */ public String extractTransactionIdFromTransactionReceipt(String transactionReceipt) { - byte[] decodedTopLevelContainer = Base64.getDecoder().decode(transactionReceipt); - String topLevel = new String(decodedTopLevelContainer, StandardCharsets.UTF_8); + byte[] decodedTopLevelContainer = decodeBase64(transactionReceipt, null); + String topLevel = decodeUTF8(decodedTopLevelContainer, null); Matcher topLevelMatcher = Pattern.compile("\"purchase-info\"\\s+=\\s+\"([a-zA-Z0-9+/=]+)\";").matcher(topLevel); String encodedPurchaseInfo = topLevelMatcher.find() && topLevelMatcher.groupCount() == 1 ? topLevelMatcher.group(1) : null; if (encodedPurchaseInfo == null) { throw new IllegalArgumentException("Invalid purchase-info"); } - byte[] decodedPurchaseInfoContainer = Base64.getDecoder().decode(encodedPurchaseInfo); - String purchaseInfo = new String(decodedPurchaseInfoContainer, StandardCharsets.UTF_8); + byte[] decodedPurchaseInfoContainer = decodeBase64(encodedPurchaseInfo, "Invalid purchase-info"); + String purchaseInfo = decodeUTF8(decodedPurchaseInfoContainer, "Invalid purchase-info"); Matcher purchaseInfoMatcher = Pattern.compile("\"transaction-id\"\\s+=\\s+\"([a-zA-Z0-9+/=]+)\";").matcher(purchaseInfo); return purchaseInfoMatcher.find() && purchaseInfoMatcher.groupCount() == 1 ? purchaseInfoMatcher.group(1) : null; } + + private static byte[] decodeBase64(String value, String errorMessage) { + if (!BASE64_PATTERN.matcher(value).matches()) { + throw new IllegalArgumentException(errorMessage); + } + return Base64.getDecoder().decode(value); + } + + private static String decodeUTF8(byte[] value, String errorMessage) { + try { + return StandardCharsets.UTF_8.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + .decode(ByteBuffer.wrap(value)) + .toString(); + } catch (CharacterCodingException e) { + throw new IllegalArgumentException(errorMessage, e); + } + } } diff --git a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceBaseItem.java b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceBaseItem.java index fbdc6a7f..8aa2648b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceBaseItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceBaseItem.java @@ -1,8 +1,12 @@ // Copyright (c) 2026 Apple Inc. Licensed under MIT License. package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_NULL) public abstract class AbstractAdvancedCommerceBaseItem { private static final String SERIALIZED_NAME_SKU = "SKU"; @@ -12,13 +16,13 @@ public abstract class AbstractAdvancedCommerceBaseItem { protected AbstractAdvancedCommerceBaseItem() {} protected AbstractAdvancedCommerceBaseItem(String sku) { - this.sku = HelperValidationUtils.validateSku(sku); + this.sku = HelperValidationUtils.validateSku(Objects.requireNonNull(sku)); } protected abstract AbstractAdvancedCommerceBaseItem self(); public AbstractAdvancedCommerceBaseItem sku(String sku) { - this.sku = HelperValidationUtils.validateSku(sku); + this.sku = HelperValidationUtils.validateSku(Objects.requireNonNull(sku)); return self(); } @@ -33,7 +37,20 @@ public String getSku() { } public void setSku(String sku) { - this.sku = HelperValidationUtils.validateSku(sku); + this.sku = HelperValidationUtils.validateSku(Objects.requireNonNull(sku)); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractAdvancedCommerceBaseItem that = (AbstractAdvancedCommerceBaseItem) o; + return Objects.equals(sku, that.sku); + } + + @Override + public int hashCode() { + return Objects.hashCode(sku); } } diff --git a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceInAppRequest.java b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceInAppRequest.java index 01e25c75..546af9bf 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceInAppRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceInAppRequest.java @@ -2,10 +2,12 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +@JsonInclude(JsonInclude.Include.NON_NULL) public abstract class AbstractAdvancedCommerceInAppRequest> extends AdvancedCommerceRequest implements AdvancedCommerceInAppRequest { private static final String SERIALIZED_NAME_OPERATION = "operation"; @@ -27,6 +29,25 @@ protected AbstractAdvancedCommerceInAppRequest(String operation, String version, this.version = Objects.requireNonNull(version); } + /** + * The constant that represents the operation of this request. + * + * @return operation + **/ + public String getOperation() { + return operation; + } + + /** + * A number that represents the version of the data structure or Advanced Commerce API. + * + * @return version + * @see version + **/ + public String getVersion() { + return version; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceItem.java b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceItem.java index 92617e09..120e5360 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceItem.java @@ -3,11 +3,13 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; import java.util.Objects; +@JsonInclude(JsonInclude.Include.NON_NULL) public abstract class AbstractAdvancedCommerceItem extends AbstractAdvancedCommerceBaseItem { private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; diff --git a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceResponse.java b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceResponse.java index d2e02a63..44f2d152 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AbstractAdvancedCommerceResponse.java @@ -15,7 +15,7 @@ public abstract class AbstractAdvancedCommerceResponse { @JsonProperty(SERIALIZED_NAME_SIGNED_RENEWAL_INFO) private String signedRenewalInfo; - @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) + @JsonProperty(value = SERIALIZED_NAME_SIGNED_TRANSACTION_INFO, required = true) private String signedTransactionInfo; @JsonAnySetter private Map unknownFields; @@ -38,7 +38,7 @@ public AbstractAdvancedCommerceResponse signedRenewalInfo(String signedRenewalIn * Subscription renewal information, signed by the App Store, in JSON Web Signature (JWS) format. * * @return signedRenewalInfo - * @see JWSRenewalInfo + * @see JWSRenewalInfo **/ public String getSignedRenewalInfo() { return signedRenewalInfo; @@ -57,7 +57,7 @@ public AbstractAdvancedCommerceResponse signedTransactionInfo(String signedTrans * Transaction information signed by the App Store, in JSON Web Signature (JWS) Compact Serialization format. * * @return signedTransactionInfo - * @see JWSTransaction + * @see JWSTransaction **/ public String getSignedTransactionInfo() { return signedTransactionInfo; diff --git a/src/main/java/com/apple/itunes/storekit/model/AccountTenure.java b/src/main/java/com/apple/itunes/storekit/model/AccountTenure.java index ca5491ce..18b2a32d 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AccountTenure.java +++ b/src/main/java/com/apple/itunes/storekit/model/AccountTenure.java @@ -8,16 +8,40 @@ * The age of the customer’s account. * * @see accountTenure - */ + **/ public enum AccountTenure { + /** + * Account age is undeclared. + **/ UNDECLARED(0), + /** + * Account age is between 0–3 days. + **/ ZERO_TO_THREE_DAYS(1), + /** + * Account age is between 3–10 days. + **/ THREE_DAYS_TO_TEN_DAYS(2), + /** + * Account age is between 10–30 days. + **/ TEN_DAYS_TO_THIRTY_DAYS(3), + /** + * Account age is between 30–90 days. + **/ THIRTY_DAYS_TO_NINETY_DAYS(4), + /** + * Account age is between 90–180 days. + **/ NINETY_DAYS_TO_ONE_HUNDRED_EIGHTY_DAYS(5), + /** + * Account age is between 180–365 days. + **/ ONE_HUNDRED_EIGHTY_DAYS_TO_THREE_HUNDRED_SIXTY_FIVE_DAYS(6), + /** + * Account age is over 365 days. + **/ GREATER_THAN_THREE_HUNDRED_SIXTY_FIVE_DAYS(7); private final Integer value; @@ -39,5 +63,9 @@ public static AccountTenure fromValue(Integer value) { public Integer getValue() { return value; } -} + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceDescriptors.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceDescriptors.java index 27974a9c..44292d39 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceDescriptors.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceDescriptors.java @@ -3,6 +3,8 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -10,23 +12,29 @@ /** * The display name and description of a subscription product. - * + * * @see Descriptors - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceDescriptors { private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; @JsonProperty(value = SERIALIZED_NAME_DESCRIPTION, required = true) - protected String description; + private String description; @JsonProperty(value = SERIALIZED_NAME_DISPLAY_NAME, required = true) - protected String displayName; + private String displayName; @JsonAnySetter private Map unknownFields; - protected AdvancedCommerceDescriptors() {} + protected AdvancedCommerceDescriptors() { + } - protected AdvancedCommerceDescriptors(String description, String displayName) { + @JsonCreator + public AdvancedCommerceDescriptors( + @JsonProperty(value = SERIALIZED_NAME_DESCRIPTION, required = true) String description, + @JsonProperty(value = SERIALIZED_NAME_DISPLAY_NAME, required = true) String displayName + ) { this.description = HelperValidationUtils.validateDescription(description); this.displayName = HelperValidationUtils.validateDisplayName(displayName); } @@ -37,8 +45,8 @@ public AdvancedCommerceDescriptors description(String description) { } /** - * A string you provide that describes a SKU. - * + * A string that contains a description of the product. + * * @return description * @see description **/ @@ -56,8 +64,8 @@ public AdvancedCommerceDescriptors displayName(String displayName) { } /** - * A string with a product name that you can localize and is suitable for display to customers. - * + * A string that contains the name of the product, suitable for display to customers. + * * @return displayName * @see displayName **/ @@ -74,6 +82,11 @@ public AdvancedCommerceDescriptors unknownFields(Map unknownFiel return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -84,10 +97,16 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceDescriptors that = (AdvancedCommerceDescriptors) o; - return Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceDescriptors advancedCommerceDescriptors = (AdvancedCommerceDescriptors) o; + return Objects.equals(this.description, advancedCommerceDescriptors.description) && + Objects.equals(this.displayName, advancedCommerceDescriptors.displayName) && + Objects.equals(this.unknownFields, advancedCommerceDescriptors.unknownFields); } @Override @@ -103,4 +122,4 @@ public String toString() { ", unknownFields=" + unknownFields + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceEffective.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceEffective.java index a66e61d1..316bdea7 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceEffective.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceEffective.java @@ -8,10 +8,16 @@ * A string value that indicates when a requested change to an auto-renewable subscription goes into effect. * * @see effective - */ + **/ public enum AdvancedCommerceEffective { + /** + * The requested change goes into effect immediately. + **/ IMMEDIATELY("IMMEDIATELY"), + /** + * The requested change goes into effect at the start of the next billing cycle. + **/ NEXT_BILL_CYCLE("NEXT_BILL_CYCLE"); private final String value; @@ -38,4 +44,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInAppRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInAppRequest.java index d03db53c..9f1175f6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInAppRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInAppRequest.java @@ -1,3 +1,5 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + package com.apple.itunes.storekit.model; public interface AdvancedCommerceInAppRequest { diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInfo.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInfo.java index 90d49e33..e6ed5810 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceInfo.java @@ -12,16 +12,15 @@ * A response object you provide to present an offer or switch-plan recommendation message. * * @see advancedCommerceInfo - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceInfo { - private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; private static final String SERIALIZED_NAME_ADVANCED_COMMERCE_DATA = "advancedCommerceData"; - @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER) + @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIER) private UUID messageIdentifier; - @JsonProperty(value = SERIALIZED_NAME_ADVANCED_COMMERCE_DATA) + @JsonProperty(SERIALIZED_NAME_ADVANCED_COMMERCE_DATA) private String advancedCommerceData; public AdvancedCommerceInfo() { @@ -67,10 +66,15 @@ public void setAdvancedCommerceData(String advancedCommerceData) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceInfo that = (AdvancedCommerceInfo) o; - return Objects.equals(messageIdentifier, that.messageIdentifier) && Objects.equals(advancedCommerceData, that.advancedCommerceData); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceInfo advancedCommerceInfo = (AdvancedCommerceInfo) o; + return Objects.equals(this.messageIdentifier, advancedCommerceInfo.messageIdentifier) && + Objects.equals(this.advancedCommerceData, advancedCommerceInfo.advancedCommerceData); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOffer.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOffer.java index 0c4e6370..0d2fbb77 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOffer.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOffer.java @@ -3,6 +3,8 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -12,9 +14,9 @@ * A discount offer for an auto-renewable subscription. * * @see Offer - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceOffer { - private static final String SERIALIZED_NAME_PERIOD = "period"; private static final String SERIALIZED_NAME_PERIOD_COUNT = "periodCount"; private static final String SERIALIZED_NAME_PRICE = "price"; @@ -31,21 +33,32 @@ public class AdvancedCommerceOffer { @JsonAnySetter private Map unknownFields; - protected AdvancedCommerceOffer() {} + protected AdvancedCommerceOffer() { + } - public AdvancedCommerceOffer(String rawPeriod, Integer periodCount, Long price, String rawReason) { - this.period = Objects.requireNonNull(rawPeriod); + public AdvancedCommerceOffer( + AdvancedCommerceOfferPeriod period, + Integer periodCount, + Long price, + AdvancedCommerceOfferReason reason + ) { + this.period = Objects.requireNonNull(period).getValue(); this.periodCount = HelperValidationUtils.validatePeriodCount(periodCount); this.price = Objects.requireNonNull(price); - this.reason = Objects.requireNonNull(rawReason); + this.reason = Objects.requireNonNull(reason).getValue(); } - - public AdvancedCommerceOffer(AdvancedCommerceOfferPeriod period, Integer periodCount, Long price, AdvancedCommerceOfferReason reason) { - this.period = Objects.requireNonNull(period).getValue(); + @JsonCreator + public AdvancedCommerceOffer( + @JsonProperty(value = SERIALIZED_NAME_PERIOD, required = true) String rawPeriod, + @JsonProperty(value = SERIALIZED_NAME_PERIOD_COUNT, required = true) Integer periodCount, + @JsonProperty(value = SERIALIZED_NAME_PRICE, required = true) Long price, + @JsonProperty(value = SERIALIZED_NAME_REASON, required = true) String rawReason + ) { + this.period = Objects.requireNonNull(rawPeriod); this.periodCount = HelperValidationUtils.validatePeriodCount(periodCount); this.price = Objects.requireNonNull(price); - this.reason = Objects.requireNonNull(reason).getValue(); + this.reason = Objects.requireNonNull(rawReason); } public AdvancedCommerceOffer period(AdvancedCommerceOfferPeriod period) { @@ -55,16 +68,17 @@ public AdvancedCommerceOffer period(AdvancedCommerceOfferPeriod period) { /** * The period of the offer. - * + * * @return period + * @see Offer **/ public AdvancedCommerceOfferPeriod getPeriod() { return AdvancedCommerceOfferPeriod.fromValue(period); } - /** + /** * @see #getPeriod() - */ + **/ public String getRawPeriod() { return period; } @@ -82,10 +96,11 @@ public AdvancedCommerceOffer periodCount(Integer periodCount) { return this; } - /** + /** * The number of periods the offer is active. - * + * * @return periodCount + * @see Offer **/ public Integer getPeriodCount() { return periodCount; @@ -102,9 +117,9 @@ public AdvancedCommerceOffer price(Long price) { /** * The offer price, in milliunits. - * + * * @return price - * @see Price + * @see price **/ public Long getPrice() { return price; @@ -121,8 +136,9 @@ public AdvancedCommerceOffer reason(AdvancedCommerceOfferReason reason) { /** * The reason for the offer. - * + * * @return reason + * @see Offer **/ public AdvancedCommerceOfferReason getReason() { return AdvancedCommerceOfferReason.fromValue(reason); @@ -130,7 +146,7 @@ public AdvancedCommerceOfferReason getReason() { /** * @see #getReason() - */ + **/ public String getRawReason() { return reason; } @@ -148,6 +164,11 @@ public AdvancedCommerceOffer unknownFields(Map unknownFields) { return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -158,10 +179,18 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceOffer that = (AdvancedCommerceOffer) o; - return Objects.equals(period, that.period) && Objects.equals(periodCount, that.periodCount) && Objects.equals(price, that.price) && Objects.equals(reason, that.reason) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceOffer advancedCommerceOffer = (AdvancedCommerceOffer) o; + return Objects.equals(this.period, advancedCommerceOffer.period) && + Objects.equals(this.periodCount, advancedCommerceOffer.periodCount) && + Objects.equals(this.price, advancedCommerceOffer.price) && + Objects.equals(this.reason, advancedCommerceOffer.reason) && + Objects.equals(this.unknownFields, advancedCommerceOffer.unknownFields); } @Override @@ -179,4 +208,4 @@ public String toString() { ", unknownFields=" + unknownFields + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferPeriod.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferPeriod.java index 2836b423..9ce0d777 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferPeriod.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferPeriod.java @@ -8,7 +8,7 @@ * The period of the offer. * * @see Offer - */ + **/ public enum AdvancedCommerceOfferPeriod { P3D("P3D"), @@ -45,4 +45,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferReason.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferReason.java index 34882109..45766a03 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOfferReason.java @@ -8,7 +8,7 @@ * The reason for the offer. * * @see Offer - */ + **/ public enum AdvancedCommerceOfferReason { ACQUISITION("ACQUISITION"), @@ -39,4 +39,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeCreateRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeCreateRequest.java index 4cc18b8c..a22fa5f0 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeCreateRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeCreateRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,16 +11,10 @@ * The request data your app provides when a customer purchases a one-time-charge product. * * @see OneTimeChargeCreateRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceOneTimeChargeCreateRequest extends AbstractAdvancedCommerceInAppRequest { - - /** - * The constant that represents the operation of this request. - */ private static final String OPERATION = "CREATE_ONE_TIME_CHARGE"; - /** - * The version number of the API. - */ private static final String VERSION = "1"; private static final String SERIALIZED_NAME_CURRENCY = "currency"; @@ -41,9 +36,9 @@ protected AdvancedCommerceOneTimeChargeCreateRequest() { } public AdvancedCommerceOneTimeChargeCreateRequest( + AdvancedCommerceRequestInfo requestInfo, String currency, AdvancedCommerceOneTimeChargeItem item, - AdvancedCommerceRequestInfo requestInfo, String taxCode ) { super(OPERATION, VERSION, requestInfo); @@ -57,6 +52,39 @@ protected AdvancedCommerceOneTimeChargeCreateRequest self() { return this; } + /** + * The constant that represents the operation of this request. + * + * @return operation + * @see OneTimeChargeCreateRequest + **/ + @Override + public String getOperation() { + return super.getOperation(); + } + + /** + * The version number of the API. + * + * @return version + * @see version + **/ + @Override + public String getVersion() { + return super.getVersion(); + } + + /** + * The metadata of the request. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceOneTimeChargeCreateRequest currency(String currency) { this.currency = Objects.requireNonNull(currency); return this; @@ -123,7 +151,7 @@ public AdvancedCommerceOneTimeChargeCreateRequest taxCode(String taxCode) { * The tax code for this product. * * @return taxCode - * @see taxCode + * @see taxCode **/ public String getTaxCode() { return taxCode; @@ -135,11 +163,20 @@ public void setTaxCode(String taxCode) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceOneTimeChargeCreateRequest that = (AdvancedCommerceOneTimeChargeCreateRequest) o; - return Objects.equals(currency, that.currency) && Objects.equals(item, that.item) && Objects.equals(storefront, that.storefront) && Objects.equals(taxCode, that.taxCode); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceOneTimeChargeCreateRequest advancedCommerceOneTimeChargeCreateRequest = (AdvancedCommerceOneTimeChargeCreateRequest) o; + return Objects.equals(this.currency, advancedCommerceOneTimeChargeCreateRequest.currency) && + Objects.equals(this.item, advancedCommerceOneTimeChargeCreateRequest.item) && + Objects.equals(this.storefront, advancedCommerceOneTimeChargeCreateRequest.storefront) && + Objects.equals(this.taxCode, advancedCommerceOneTimeChargeCreateRequest.taxCode); } @Override @@ -149,12 +186,14 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "currency='" + currency + '\'' + - ", item=" + item + + return "AdvancedCommerceOneTimeChargeCreateRequest{" + + "operation='" + getOperation() + '\'' + + ", version='" + getVersion() + '\'' + ", requestInfo=" + getRequestInfo() + + ", currency='" + currency + '\'' + + ", item=" + item + ", storefront='" + storefront + '\'' + ", taxCode='" + taxCode + '\'' + - "}"; + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeItem.java index 6e8f986a..5a3e29f2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceOneTimeChargeItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,25 +11,74 @@ * The details of a one-time charge product, including its display name, price, SKU, and metadata. * * @see OneTimeChargeItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceOneTimeChargeItem extends AbstractAdvancedCommerceItem { private static final String SERIALIZED_NAME_PRICE = "price"; - + @JsonProperty(value = SERIALIZED_NAME_PRICE, required = true) private Long price; - + protected AdvancedCommerceOneTimeChargeItem() { super(); } + public AdvancedCommerceOneTimeChargeItem(String description, String displayName, String sku, Long price) { + super(sku, description, displayName); + this.price = Objects.requireNonNull(price); + } + @Override protected AdvancedCommerceOneTimeChargeItem self() { return this; } - public AdvancedCommerceOneTimeChargeItem(String description, String displayName, String sku, Long price) { - super(sku, description, displayName); - this.price = Objects.requireNonNull(price); + @Override + public AdvancedCommerceOneTimeChargeItem sku(String sku) { + return (AdvancedCommerceOneTimeChargeItem) super.sku(sku); + } + + @Override + public AdvancedCommerceOneTimeChargeItem description(String description) { + return (AdvancedCommerceOneTimeChargeItem) super.description(description); + } + + @Override + public AdvancedCommerceOneTimeChargeItem displayName(String displayName) { + return (AdvancedCommerceOneTimeChargeItem) super.displayName(displayName); + } + + /** + * The product identifier. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + /** + * A description of the product that doesn’t display to customers. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * The product name, suitable for display to customers. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); } public AdvancedCommerceOneTimeChargeItem price(Long price) { @@ -42,21 +92,27 @@ public AdvancedCommerceOneTimeChargeItem price(Long price) { * @return price * @see price **/ - public Long getPrice() { - return price; - } + public Long getPrice() { + return price; + } - public void setPrice(Long price) { - this.price = Objects.requireNonNull(price); - } + public void setPrice(Long price) { + this.price = Objects.requireNonNull(price); + } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceOneTimeChargeItem that = (AdvancedCommerceOneTimeChargeItem) o; - return Objects.equals(price, that.price); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceOneTimeChargeItem advancedCommerceOneTimeChargeItem = (AdvancedCommerceOneTimeChargeItem) o; + return Objects.equals(this.price, advancedCommerceOneTimeChargeItem.price); } @Override @@ -66,11 +122,11 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + + return "AdvancedCommerceOneTimeChargeItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + ", price=" + price + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePeriod.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePeriod.java index f5dca799..943efb9f 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePeriod.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePeriod.java @@ -8,14 +8,32 @@ * The duration of a single cycle of an auto-renewable subscription. * * @see period - */ + **/ public enum AdvancedCommercePeriod { + /** + * A period that is 1 week in duration. + **/ P1W("P1W"), + /** + * A period that is 1 month in duration. + **/ P1M("P1M"), + /** + * A period that is 2 months in duration. + **/ P2M("P2M"), + /** + * A period that is 3 months in duration. + **/ P3M("P3M"), + /** + * A period that is 6 months in duration. + **/ P6M("P6M"), + /** + * A period that is 1 year in duration. + **/ P1Y("P1Y"); private final String value; @@ -42,4 +60,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfo.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfo.java index 145f56ac..075738b5 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfo.java @@ -12,9 +12,8 @@ /** * @see advancedCommercePriceIncreaseInfo - */ + **/ public class AdvancedCommercePriceIncreaseInfo { - private static final String SERIALIZED_NAME_DEPENDENT_SKUS = "dependentSKUs"; private static final String SERIALIZED_NAME_PRICE = "price"; private static final String SERIALIZED_NAME_STATUS = "status"; @@ -37,6 +36,7 @@ public AdvancedCommercePriceIncreaseInfo dependentSKUs(List dependentSKU } public AdvancedCommercePriceIncreaseInfo addDependentSKU(String dependentSKU) { + Objects.requireNonNull(dependentSKU); if (this.dependentSKUs == null) { this.dependentSKUs = new ArrayList<>(); } @@ -83,12 +83,12 @@ public AdvancedCommercePriceIncreaseInfo status(AdvancedCommercePriceIncreaseInf * @see advancedCommercePriceIncreaseInfoStatus **/ public AdvancedCommercePriceIncreaseInfoStatus getStatus() { - return status != null ? AdvancedCommercePriceIncreaseInfoStatus.fromValue(status) : null; + return AdvancedCommercePriceIncreaseInfoStatus.fromValue(status); } /** * @see #getStatus() - */ + **/ public String getRawStatus() { return status; } @@ -106,6 +106,11 @@ public AdvancedCommercePriceIncreaseInfo unknownFields(Map unkno return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -116,10 +121,17 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommercePriceIncreaseInfo that = (AdvancedCommercePriceIncreaseInfo) o; - return Objects.equals(dependentSKUs, that.dependentSKUs) && Objects.equals(price, that.price) && Objects.equals(status, that.status) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommercePriceIncreaseInfo advancedCommercePriceIncreaseInfo = (AdvancedCommercePriceIncreaseInfo) o; + return Objects.equals(this.dependentSKUs, advancedCommercePriceIncreaseInfo.dependentSKUs) && + Objects.equals(this.price, advancedCommercePriceIncreaseInfo.price) && + Objects.equals(this.status, advancedCommercePriceIncreaseInfo.status) && + Objects.equals(this.unknownFields, advancedCommercePriceIncreaseInfo.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfoStatus.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfoStatus.java index c288f3c9..478ccb33 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfoStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommercePriceIncreaseInfoStatus.java @@ -5,8 +5,8 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * @see advancedCommercePriceIncreaseInfoStatus - */ + * @see advancedCommercePriceIncreaseInfoStatus + **/ public enum AdvancedCommercePriceIncreaseInfoStatus { SCHEDULED("SCHEDULED"), diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceReason.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceReason.java index 46f53c1d..87bbd479 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceReason.java @@ -5,11 +5,10 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * The data your app provides to change an item of an auto-renewable subscription. - * * @see SubscriptionModifyChangeItem - */ + **/ public enum AdvancedCommerceReason { + UPGRADE("UPGRADE"), DOWNGRADE("DOWNGRADE"), APPLY_OFFER("APPLY_OFFER"); @@ -38,4 +37,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefund.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefund.java index 77027f4c..466d91cd 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefund.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefund.java @@ -10,9 +10,8 @@ /** * @see advancedCommerceRefund - */ + **/ public class AdvancedCommerceRefund { - private static final String SERIALIZED_NAME_REFUND_AMOUNT = "refundAmount"; private static final String SERIALIZED_NAME_REFUND_DATE = "refundDate"; private static final String SERIALIZED_NAME_REFUND_REASON = "refundReason"; @@ -76,12 +75,12 @@ public AdvancedCommerceRefund refundReason(AdvancedCommerceRefundReason refundRe * @see advancedCommerceRefundReason **/ public AdvancedCommerceRefundReason getRefundReason() { - return refundReason != null ? AdvancedCommerceRefundReason.fromValue(refundReason) : null; + return AdvancedCommerceRefundReason.fromValue(refundReason); } /** * @see #getRefundReason() - */ + **/ public String getRawRefundReason() { return refundReason; } @@ -104,12 +103,12 @@ public AdvancedCommerceRefund refundType(AdvancedCommerceRefundType refundType) * @see advancedCommerceRefundType **/ public AdvancedCommerceRefundType getRefundType() { - return refundType != null ? AdvancedCommerceRefundType.fromValue(refundType) : null; + return AdvancedCommerceRefundType.fromValue(refundType); } /** * @see #getRefundType() - */ + **/ public String getRawRefundType() { return refundType; } @@ -127,6 +126,11 @@ public AdvancedCommerceRefund unknownFields(Map unknownFields) { return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -137,10 +141,18 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceRefund that = (AdvancedCommerceRefund) o; - return Objects.equals(refundAmount, that.refundAmount) && Objects.equals(refundDate, that.refundDate) && Objects.equals(refundReason, that.refundReason) && Objects.equals(refundType, that.refundType) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceRefund advancedCommerceRefund = (AdvancedCommerceRefund) o; + return Objects.equals(this.refundAmount, advancedCommerceRefund.refundAmount) && + Objects.equals(this.refundDate, advancedCommerceRefund.refundDate) && + Objects.equals(this.refundReason, advancedCommerceRefund.refundReason) && + Objects.equals(this.refundType, advancedCommerceRefund.refundType) && + Objects.equals(this.unknownFields, advancedCommerceRefund.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundReason.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundReason.java index ab864e51..5a70e841 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundReason.java @@ -6,17 +6,38 @@ /** * A reason to request a refund. - * + * * @see refundReason - */ + **/ public enum AdvancedCommerceRefundReason { + /** + * The customer didn’t intend to make the Apple In-App Purchase. + **/ UNINTENDED_PURCHASE("UNINTENDED_PURCHASE"), + /** + * The customer had issues with receiving or using the Apple In-App Purchase. + **/ FULFILLMENT_ISSUE("FULFILLMENT_ISSUE"), + /** + * The customer wasn’t satisfied with the Apple In-App Purchase. + **/ UNSATISFIED_WITH_PURCHASE("UNSATISFIED_WITH_PURCHASE"), + /** + * The customer requested a refund based on a legal reason. + **/ LEGAL("LEGAL"), + /** + * The customer requested a refund for other reasons. + **/ OTHER("OTHER"), + /** + * The customer modified one or more items in the subscription, which results in a refund. + **/ MODIFY_ITEMS_REFUND("MODIFY_ITEMS_REFUND"), + /** + * For testing purposes only, a simulation of a refund that the App Store declines. + **/ SIMULATE_REFUND_DECLINE("SIMULATE_REFUND_DECLINE"); private final String value; @@ -43,4 +64,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundType.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundType.java index 14e0e9f3..e62911c3 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundType.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRefundType.java @@ -5,10 +5,10 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * Information about the refund request for an item, such as its SKU, the refund amount, reason, and type. + * The type of refund requested. * * @see RequestRefundItem - */ + **/ public enum AdvancedCommerceRefundType { FULL("FULL"), @@ -39,4 +39,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalInfo.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalInfo.java index 5aa993a7..abc71142 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalInfo.java @@ -5,15 +5,15 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /** * @see advancedCommerceRenewalInfo - */ + **/ public class AdvancedCommerceRenewalInfo { - private static final String SERIALIZED_NAME_CONSISTENCY_TOKEN = "consistencyToken"; private static final String SERIALIZED_NAME_DESCRIPTORS = "descriptors"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -78,9 +78,18 @@ public AdvancedCommerceRenewalInfo items(List items return this; } + public AdvancedCommerceRenewalInfo addItem(AdvancedCommerceRenewalItem item) { + Objects.requireNonNull(item); + if (this.items == null) { + this.items = new ArrayList<>(); + } + this.items.add(item); + return this; + } + /** * @return items - * @see advancedCommerceRenewalItem + * @see advancedCommerceRenewalItems **/ public List getItems() { return items; @@ -100,12 +109,12 @@ public AdvancedCommerceRenewalInfo period(AdvancedCommercePeriod period) { * @see advancedCommercePeriod **/ public AdvancedCommercePeriod getPeriod() { - return period != null ? AdvancedCommercePeriod.fromValue(period) : null; + return AdvancedCommercePeriod.fromValue(period); } /** * @see #getPeriod() - */ + **/ public String getRawPeriod() { return period; } @@ -157,6 +166,11 @@ public AdvancedCommerceRenewalInfo unknownFields(Map unknownFiel return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -167,10 +181,20 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceRenewalInfo that = (AdvancedCommerceRenewalInfo) o; - return Objects.equals(consistencyToken, that.consistencyToken) && Objects.equals(descriptors, that.descriptors) && Objects.equals(items, that.items) && Objects.equals(period, that.period) && Objects.equals(requestReferenceId, that.requestReferenceId) && Objects.equals(taxCode, that.taxCode) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceRenewalInfo advancedCommerceRenewalInfo = (AdvancedCommerceRenewalInfo) o; + return Objects.equals(this.consistencyToken, advancedCommerceRenewalInfo.consistencyToken) && + Objects.equals(this.descriptors, advancedCommerceRenewalInfo.descriptors) && + Objects.equals(this.items, advancedCommerceRenewalInfo.items) && + Objects.equals(this.period, advancedCommerceRenewalInfo.period) && + Objects.equals(this.requestReferenceId, advancedCommerceRenewalInfo.requestReferenceId) && + Objects.equals(this.taxCode, advancedCommerceRenewalInfo.taxCode) && + Objects.equals(this.unknownFields, advancedCommerceRenewalInfo.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalItem.java index 75dd71b1..5f21f405 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRenewalItem.java @@ -10,9 +10,8 @@ /** * @see advancedCommerceRenewalItem - */ + **/ public class AdvancedCommerceRenewalItem { - private static final String SERIALIZED_NAME_SKU = "SKU"; private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; @@ -44,7 +43,7 @@ public AdvancedCommerceRenewalItem sku(String sku) { } /** - * @return sku + * @return SKU * @see advancedCommerceSKU **/ public String getSku() { @@ -145,6 +144,11 @@ public AdvancedCommerceRenewalItem unknownFields(Map unknownFiel return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -155,10 +159,20 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceRenewalItem that = (AdvancedCommerceRenewalItem) o; - return Objects.equals(sku, that.sku) && Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName) && Objects.equals(offer, that.offer) && Objects.equals(price, that.price) && Objects.equals(priceIncreaseInfo, that.priceIncreaseInfo) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceRenewalItem advancedCommerceRenewalItem = (AdvancedCommerceRenewalItem) o; + return Objects.equals(this.sku, advancedCommerceRenewalItem.sku) && + Objects.equals(this.description, advancedCommerceRenewalItem.description) && + Objects.equals(this.displayName, advancedCommerceRenewalItem.displayName) && + Objects.equals(this.offer, advancedCommerceRenewalItem.offer) && + Objects.equals(this.price, advancedCommerceRenewalItem.price) && + Objects.equals(this.priceIncreaseInfo, advancedCommerceRenewalItem.priceIncreaseInfo) && + Objects.equals(this.unknownFields, advancedCommerceRenewalItem.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequest.java index 21fa12de..0b68ce24 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequest.java @@ -2,10 +2,12 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; +@JsonInclude(JsonInclude.Include.NON_NULL) public abstract class AdvancedCommerceRequest> { protected static final String SERIALIZED_NAME_REQUEST_INFO = "requestInfo"; diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestInfo.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestInfo.java index 2bb06228..96aad4b8 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestInfo.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -11,7 +12,8 @@ * The metadata to include in server requests. * * @see RequestInfo - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceRequestInfo { private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; private static final String SERIALIZED_NAME_CONSISTENCY_TOKEN = "consistencyToken"; @@ -24,7 +26,8 @@ public class AdvancedCommerceRequestInfo { @JsonProperty(value = SERIALIZED_NAME_REQUEST_REFERENCE_ID, required = true) private UUID requestReferenceId; - protected AdvancedCommerceRequestInfo() {} + protected AdvancedCommerceRequestInfo() { + } public AdvancedCommerceRequestInfo(UUID requestReferenceId) { this.requestReferenceId = Objects.requireNonNull(requestReferenceId); @@ -37,8 +40,9 @@ public AdvancedCommerceRequestInfo appAccountToken(UUID appAccountToken) { /** * A UUID that represents an app account token, to associate with the transaction in the request. - * + * * @return appAccountToken + * @see RequestInfo **/ public UUID getAppAccountToken() { return appAccountToken; @@ -54,12 +58,12 @@ public AdvancedCommerceRequestInfo consistencyToken(String consistencyToken) { } /** - * The value of the advancedCommerceConsistencyToken that you receive in the JWSRenewalInfo renewal information for a subscription. Don’t generate this value. - * + * The value of the advancedCommerceConsistencyToken that you receive in the JWSRenewalInfo renewal information for a subscription. + * * @return consistencyToken - * @see advancedCommerceConsistencyToken + * @see RequestInfo **/ - public String consistencyToken() { + public String getConsistencyToken() { return consistencyToken; } @@ -73,9 +77,10 @@ public AdvancedCommerceRequestInfo requestReferenceId(UUID requestReferenceId) { } /** - * A UUID that you provide to uniquely identify each request. If the request times out, you can use the same requestReferenceId value to retry the request. Otherwise, provide a unique value. - * + * A UUID that you provide to uniquely identify each request. + * * @return requestReferenceId + * @see RequestInfo **/ public UUID getRequestReferenceId() { return requestReferenceId; @@ -87,10 +92,16 @@ public void setRequestReferenceId(UUID requestReferenceId) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceRequestInfo that = (AdvancedCommerceRequestInfo) o; - return Objects.equals(appAccountToken, that.appAccountToken) && Objects.equals(consistencyToken, that.consistencyToken) && Objects.equals(requestReferenceId, that.requestReferenceId); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceRequestInfo advancedCommerceRequestInfo = (AdvancedCommerceRequestInfo) o; + return Objects.equals(this.appAccountToken, advancedCommerceRequestInfo.appAccountToken) && + Objects.equals(this.consistencyToken, advancedCommerceRequestInfo.consistencyToken) && + Objects.equals(this.requestReferenceId, advancedCommerceRequestInfo.requestReferenceId); } @Override @@ -100,10 +111,10 @@ public int hashCode() { @Override public String toString() { - return "RequestInfo{" + + return "AdvancedCommerceRequestInfo{" + "appAccountToken=" + appAccountToken + ", consistencyToken='" + consistencyToken + '\'' + ", requestReferenceId=" + requestReferenceId + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundItem.java index 617b9bb9..f8a11800 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * Information about the refund request for an item, such as its SKU, the refund amount, reason, and type. * * @see RequestRefundItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceRequestRefundItem extends AbstractAdvancedCommerceBaseItem { private static final String SERIALIZED_NAME_REFUND_AMOUNT = "refundAmount"; private static final String SERIALIZED_NAME_REFUND_REASON = "refundReason"; @@ -18,7 +20,7 @@ public class AdvancedCommerceRequestRefundItem extends AbstractAdvancedCommerceB private static final String SERIALIZED_NAME_REVOKE = "revoke"; @JsonProperty(SERIALIZED_NAME_REFUND_AMOUNT) - private Integer refundAmount; + private Long refundAmount; @JsonProperty(value = SERIALIZED_NAME_REFUND_REASON, required = true) private String refundReason; @JsonProperty(value = SERIALIZED_NAME_REFUND_TYPE, required = true) @@ -30,18 +32,6 @@ protected AdvancedCommerceRequestRefundItem() { super(); } - public AdvancedCommerceRequestRefundItem( - String sku, - String rawRefundReason, - String rawRefundType, - Boolean revoke - ) { - super(sku); - this.refundReason = Objects.requireNonNull(rawRefundReason); - this.refundType = Objects.requireNonNull(rawRefundType); - this.revoke = Objects.requireNonNull(revoke); - } - public AdvancedCommerceRequestRefundItem( String sku, AdvancedCommerceRefundReason refundReason, @@ -54,12 +44,35 @@ public AdvancedCommerceRequestRefundItem( this.revoke = Objects.requireNonNull(revoke); } + public AdvancedCommerceRequestRefundItem(String sku, String rawRefundReason, String rawRefundType, Boolean revoke) { + super(sku); + this.refundReason = Objects.requireNonNull(rawRefundReason); + this.refundType = Objects.requireNonNull(rawRefundType); + this.revoke = Objects.requireNonNull(revoke); + } + @Override protected AdvancedCommerceRequestRefundItem self() { return this; } - public AdvancedCommerceRequestRefundItem refundAmount(Integer refundAmount) { + @Override + public AdvancedCommerceRequestRefundItem sku(String sku) { + return (AdvancedCommerceRequestRefundItem) super.sku(sku); + } + + /** + * The product identifier. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + public AdvancedCommerceRequestRefundItem refundAmount(Long refundAmount) { this.refundAmount = refundAmount; return this; } @@ -70,11 +83,11 @@ public AdvancedCommerceRequestRefundItem refundAmount(Integer refundAmount) { * @return refundAmount * @see refundAmount **/ - public Integer getRefundAmount() { + public Long getRefundAmount() { return refundAmount; } - public void setRefundAmount(Integer refundAmount) { + public void setRefundAmount(Long refundAmount) { this.refundAmount = refundAmount; } @@ -93,6 +106,13 @@ public AdvancedCommerceRefundReason getRefundReason() { return AdvancedCommerceRefundReason.fromValue(refundReason); } + /** + * @see #getRefundReason() + **/ + public String getRawRefundReason() { + return refundReason; + } + public void setRefundReason(AdvancedCommerceRefundReason refundReason) { this.refundReason = Objects.requireNonNull(refundReason).getValue(); } @@ -110,6 +130,7 @@ public AdvancedCommerceRequestRefundItem refundType(AdvancedCommerceRefundType r * The type of refund requested. * * @return refundType + * @see RequestRefundItem **/ public AdvancedCommerceRefundType getRefundType() { return AdvancedCommerceRefundType.fromValue(refundType); @@ -117,7 +138,7 @@ public AdvancedCommerceRefundType getRefundType() { /** * @see #getRefundType() - */ + **/ public String getRawRefundType() { return refundType; } @@ -137,6 +158,7 @@ public AdvancedCommerceRequestRefundItem revoke(Boolean revoke) { /** * @return revoke + * @see RequestRefundItem **/ public Boolean getRevoke() { return revoke; @@ -148,25 +170,35 @@ public void setRevoke(Boolean revoke) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceRequestRefundItem that = (AdvancedCommerceRequestRefundItem) o; - return Objects.equals(sku, that.sku) && Objects.equals(refundAmount, that.refundAmount) && Objects.equals(refundReason, that.refundReason) && Objects.equals(refundType, that.refundType) && Objects.equals(revoke, that.revoke); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceRequestRefundItem advancedCommerceRequestRefundItem = (AdvancedCommerceRequestRefundItem) o; + return Objects.equals(this.refundAmount, advancedCommerceRequestRefundItem.refundAmount) && + Objects.equals(this.refundReason, advancedCommerceRequestRefundItem.refundReason) && + Objects.equals(this.refundType, advancedCommerceRequestRefundItem.refundType) && + Objects.equals(this.revoke, advancedCommerceRequestRefundItem.revoke); } @Override public int hashCode() { - return Objects.hash(sku, refundAmount, refundReason, refundType, revoke); + return Objects.hash(super.hashCode(), refundAmount, refundReason, refundType, revoke); } @Override public String toString() { return "AdvancedCommerceRequestRefundItem{" + - "sku='" + sku + '\'' + + "sku='" + getSku() + '\'' + ", refundAmount=" + refundAmount + - ", refundReason=" + refundReason + + ", refundReason='" + refundReason + '\'' + ", refundType='" + refundType + '\'' + ", revoke=" + revoke + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundRequest.java index c78760f4..cf78da0e 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; @@ -11,7 +12,8 @@ * The request body for requesting a refund for a transaction. * * @see RequestRefundRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceRequestRefundRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_CURRENCY = "currency"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -32,12 +34,12 @@ protected AdvancedCommerceRequestRefundRequest() { } public AdvancedCommerceRequestRefundRequest( + AdvancedCommerceRequestInfo requestInfo, List items, - Boolean refundRiskingPreference, - AdvancedCommerceRequestInfo requestInfo + Boolean refundRiskingPreference ) { super(requestInfo); - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); this.refundRiskingPreference = Objects.requireNonNull(refundRiskingPreference); } @@ -46,8 +48,19 @@ protected AdvancedCommerceRequestRefundRequest self() { return this; } + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceRequestRefundRequest currency(String currency) { - this.currency = Objects.requireNonNull(currency); + this.currency = currency; return this; } @@ -62,11 +75,11 @@ public String getCurrency() { } public void setCurrency(String currency) { - this.currency = Objects.requireNonNull(currency); + this.currency = currency; } public AdvancedCommerceRequestRefundRequest items(List items) { - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); return this; } @@ -77,6 +90,8 @@ public AdvancedCommerceRequestRefundRequest addItem(AdvancedCommerceRequestRefun } /** + * Information about the refund request for an item, such as its SKU, the refund amount, reason, and type. + * * @return items * @see RequestRefundItem **/ @@ -85,7 +100,7 @@ public List getItems() { } public void setItems(List items) { - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); } public AdvancedCommerceRequestRefundRequest refundRiskingPreference(Boolean refundRiskingPreference) { @@ -94,8 +109,10 @@ public AdvancedCommerceRequestRefundRequest refundRiskingPreference(Boolean refu } /** + * A Boolean value that indicates whether the App Store asks you for consumption data to help inform the refund decision. + * * @return refundRiskingPreference - * @see RefundRiskingPreference + * @see refundRiskingPreference **/ public Boolean getRefundRiskingPreference() { return refundRiskingPreference; @@ -105,13 +122,14 @@ public void setRefundRiskingPreference(Boolean refundRiskingPreference) { this.refundRiskingPreference = Objects.requireNonNull(refundRiskingPreference); } - public AdvancedCommerceRequestRefundRequest storefront(String storefront) { this.storefront = storefront; return this; } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -125,14 +143,20 @@ public void setStorefront(String storefront) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceRequestRefundRequest that = (AdvancedCommerceRequestRefundRequest) o; - return Objects.equals(currency, that.currency) && - Objects.equals(items, that.items) && - Objects.equals(refundRiskingPreference, that.refundRiskingPreference) && - Objects.equals(storefront, that.storefront); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceRequestRefundRequest advancedCommerceRequestRefundRequest = (AdvancedCommerceRequestRefundRequest) o; + return Objects.equals(this.currency, advancedCommerceRequestRefundRequest.currency) && + Objects.equals(this.items, advancedCommerceRequestRefundRequest.items) && + Objects.equals(this.refundRiskingPreference, advancedCommerceRequestRefundRequest.refundRiskingPreference) && + Objects.equals(this.storefront, advancedCommerceRequestRefundRequest.storefront); } @Override @@ -142,12 +166,12 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "currency='" + currency + '\'' + + return "AdvancedCommerceRequestRefundRequest{" + + "requestInfo=" + getRequestInfo() + + ", currency='" + currency + '\'' + ", items=" + items + ", refundRiskingPreference=" + refundRiskingPreference + - ", requestInfo=" + getRequestInfo() + ", storefront='" + storefront + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundResponse.java index 64dd6478..a508d718 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceRequestRefundResponse.java @@ -2,19 +2,26 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * The response body for a transaction refund request. * * @see RequestRefundResponse - */ + **/ public class AdvancedCommerceRequestRefundResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceRequestRefundResponse() { super(); } - public AdvancedCommerceRequestRefundResponse(String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceRequestRefundResponse( + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(null, Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +30,11 @@ protected AdvancedCommerceRequestRefundResponse self() { return this; } + @Override + public AdvancedCommerceRequestRefundResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceRequestRefundResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceRequestRefundResponse signedTransactionInfo(String signedTransactionInfo) { Objects.requireNonNull(signedTransactionInfo); @@ -35,10 +47,36 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JWS Compact Serialization format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } return super.equals(o); } @@ -47,12 +85,12 @@ public int hashCode() { return super.hashCode(); } - @Override public String toString() { - return getClass().getSimpleName() + "{" + + return "AdvancedCommerceRequestRefundResponse{" + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelRequest.java index 748a2024..9105141b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * The request body for turning off automatic renewal of a subscription. * * @see SubscriptionCancelRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionCancelRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_STOREFRONT = "storefront"; @@ -25,12 +27,30 @@ public AdvancedCommerceSubscriptionCancelRequest(AdvancedCommerceRequestInfo req super(requestInfo); } + @Override + protected AdvancedCommerceSubscriptionCancelRequest self() { + return this; + } + + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionCancelRequest storefront(String storefront) { this.storefront = storefront; return this; } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -42,21 +62,19 @@ public void setStorefront(String storefront) { this.storefront = storefront; } - @Override - protected AdvancedCommerceSubscriptionCancelRequest self() { - return this; - } - @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; - if (!super.equals(o)) + } + if (!super.equals(o)) { return false; - AdvancedCommerceSubscriptionCancelRequest that = (AdvancedCommerceSubscriptionCancelRequest) o; - return Objects.equals(storefront, that.storefront); + } + AdvancedCommerceSubscriptionCancelRequest advancedCommerceSubscriptionCancelRequest = (AdvancedCommerceSubscriptionCancelRequest) o; + return Objects.equals(this.storefront, advancedCommerceSubscriptionCancelRequest.storefront); } @Override @@ -71,4 +89,4 @@ public String toString() { ", storefront='" + storefront + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelResponse.java index 6b72f0b7..f1737900 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCancelResponse.java @@ -2,19 +2,27 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * The response body for a successful subscription cancellation. * * @see SubscriptionCancelResponse - */ + **/ public class AdvancedCommerceSubscriptionCancelResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceSubscriptionCancelResponse() { super(); } - public AdvancedCommerceSubscriptionCancelResponse(String signedRenewalInfo, String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceSubscriptionCancelResponse( + @JsonProperty(value = "signedRenewalInfo", required = true) String signedRenewalInfo, + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(Objects.requireNonNull(signedRenewalInfo), Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +31,11 @@ protected AdvancedCommerceSubscriptionCancelResponse self() { return this; } + @Override + public AdvancedCommerceSubscriptionCancelResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionCancelResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceSubscriptionCancelResponse signedRenewalInfo(String signedRenewalInfo) { Objects.requireNonNull(signedRenewalInfo); @@ -47,11 +60,50 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JWS Compact Serialization format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + + return "AdvancedCommerceSubscriptionCancelResponse{" + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataDescriptors.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataDescriptors.java index 40f30c20..1cd3b9e3 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataDescriptors.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataDescriptors.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,42 +11,29 @@ * The subscription metadata to change, specifically the description and display name. * * @see SubscriptionChangeMetadataDescriptors - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionChangeMetadataDescriptors { - private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; + private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; - @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) - private AdvancedCommerceEffective effective; @JsonProperty(SERIALIZED_NAME_DESCRIPTION) private String description; @JsonProperty(SERIALIZED_NAME_DISPLAY_NAME) private String displayName; + @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) + private String effective; - protected AdvancedCommerceSubscriptionChangeMetadataDescriptors() {} - - public AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); - } - - public AdvancedCommerceSubscriptionChangeMetadataDescriptors effective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); - return this; + protected AdvancedCommerceSubscriptionChangeMetadataDescriptors() { } - /** - * The string that determines when the metadata change goes into effect. - * - * @return effective - * @see Effective - **/ - public AdvancedCommerceEffective getEffective() { - return effective; + public AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); } - public void setEffective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + public AdvancedCommerceSubscriptionChangeMetadataDescriptors(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); } public AdvancedCommerceSubscriptionChangeMetadataDescriptors description(String description) { @@ -55,7 +43,7 @@ public AdvancedCommerceSubscriptionChangeMetadataDescriptors description(String /** * The new description for the subscription. - * + * * @return description * @see description **/ @@ -74,7 +62,7 @@ public AdvancedCommerceSubscriptionChangeMetadataDescriptors displayName(String /** * The new display name for the subscription. - * + * * @return displayName * @see displayName **/ @@ -86,25 +74,61 @@ public void setDisplayName(String displayName) { this.displayName = displayName == null ? null : HelperValidationUtils.validateDisplayName(displayName); } + public AdvancedCommerceSubscriptionChangeMetadataDescriptors effective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); + return this; + } + + /** + * The string that determines when the metadata change goes into effect. + * + * @return effective + * @see effective + **/ + public AdvancedCommerceEffective getEffective() { + return AdvancedCommerceEffective.fromValue(effective); + } + + /** + * @see #getEffective() + **/ + public String getRawEffective() { + return effective; + } + + public void setEffective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); + } + + public void setRawEffective(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceSubscriptionChangeMetadataDescriptors that = (AdvancedCommerceSubscriptionChangeMetadataDescriptors) o; - return Objects.equals(effective, that.effective) && Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceSubscriptionChangeMetadataDescriptors advancedCommerceSubscriptionChangeMetadataDescriptors = (AdvancedCommerceSubscriptionChangeMetadataDescriptors) o; + return Objects.equals(this.description, advancedCommerceSubscriptionChangeMetadataDescriptors.description) && + Objects.equals(this.displayName, advancedCommerceSubscriptionChangeMetadataDescriptors.displayName) && + Objects.equals(this.effective, advancedCommerceSubscriptionChangeMetadataDescriptors.effective); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), effective, description, displayName); + return Objects.hash(description, displayName, effective); } @Override public String toString() { - return getClass().getSimpleName() + "{" + - "effective=" + effective + - ", description='" + description + '\'' + + return "AdvancedCommerceSubscriptionChangeMetadataDescriptors{" + + "description='" + description + '\'' + ", displayName='" + displayName + '\'' + + ", effective='" + effective + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataItem.java index f4863ecd..d9a77f20 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,68 +11,75 @@ * The metadata to change for an item, specifically its SKU, description, and display name. * * @see SubscriptionChangeMetadataItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionChangeMetadataItem { + private static final String SERIALIZED_NAME_SKU = "SKU"; private static final String SERIALIZED_NAME_CURRENT_SKU = "currentSKU"; - private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; - private static final String SERIALIZED_NAME_SKU = "SKU"; + private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; + @JsonProperty(SERIALIZED_NAME_SKU) + private String sku; @JsonProperty(value = SERIALIZED_NAME_CURRENT_SKU, required = true) private String currentSku; - @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) - private AdvancedCommerceEffective effective; @JsonProperty(SERIALIZED_NAME_DESCRIPTION) private String description; @JsonProperty(SERIALIZED_NAME_DISPLAY_NAME) private String displayName; - @JsonProperty(SERIALIZED_NAME_SKU) - private String sku; + @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) + private String effective; - protected AdvancedCommerceSubscriptionChangeMetadataItem() {} + protected AdvancedCommerceSubscriptionChangeMetadataItem() { + } - public AdvancedCommerceSubscriptionChangeMetadataItem(String currentSKU, AdvancedCommerceEffective effective) { - this.currentSku = HelperValidationUtils.validateSku(currentSKU); - this.effective = Objects.requireNonNull(effective); + public AdvancedCommerceSubscriptionChangeMetadataItem(String currentSku, AdvancedCommerceEffective effective) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); + this.effective = Objects.requireNonNull(effective).getValue(); } - public AdvancedCommerceSubscriptionChangeMetadataItem currentSku(String currentSku) { - this.currentSku = HelperValidationUtils.validateSku(currentSku); + public AdvancedCommerceSubscriptionChangeMetadataItem(String currentSku, String rawEffective) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); + this.effective = Objects.requireNonNull(rawEffective); + } + + public AdvancedCommerceSubscriptionChangeMetadataItem sku(String sku) { + this.sku = HelperValidationUtils.validateSku(sku); return this; } /** - * The original SKU of the item. + * The new SKU of the item. * - * @return currentSku + * @return SKU * @see SKU **/ - public String getCurrentSku() { - return currentSku; + public String getSku() { + return sku; } - public void setCurrentSku(String currentSku) { - this.currentSku = HelperValidationUtils.validateSku(currentSku); + public void setSku(String sku) { + this.sku = HelperValidationUtils.validateSku(sku); } - public AdvancedCommerceSubscriptionChangeMetadataItem effective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + public AdvancedCommerceSubscriptionChangeMetadataItem currentSku(String currentSku) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); return this; } /** - * The string that determines when the metadata change goes into effect. + * The original SKU of the item. * - * @return effective - * @see effective + * @return currentSKU + * @see SKU **/ - public AdvancedCommerceEffective getEffective() { - return effective; + public String getCurrentSku() { + return currentSku; } - public void setEffective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + public void setCurrentSku(String currentSku) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); } public AdvancedCommerceSubscriptionChangeMetadataItem description(String description) { @@ -81,7 +89,7 @@ public AdvancedCommerceSubscriptionChangeMetadataItem description(String descrip /** * The new description for the item. - * + * * @return description * @see description **/ @@ -100,7 +108,7 @@ public AdvancedCommerceSubscriptionChangeMetadataItem displayName(String display /** * The new display name for the item. - * + * * @return displayName * @see displayName **/ @@ -112,36 +120,55 @@ public void setDisplayName(String displayName) { this.displayName = displayName == null ? null : HelperValidationUtils.validateDisplayName(displayName); } - public AdvancedCommerceSubscriptionChangeMetadataItem sku(String sku) { - this.sku = HelperValidationUtils.validateSku(sku); + public AdvancedCommerceSubscriptionChangeMetadataItem effective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); return this; } /** - * The new SKU of the item. - * - * @return SKU - * @see SKU + * The string that determines when the metadata change goes into effect. + * + * @return effective + * @see effective **/ - public String getSku() { - return sku; + public AdvancedCommerceEffective getEffective() { + return AdvancedCommerceEffective.fromValue(effective); } - public void setSku(String sku) { - this.sku = sku == null ? null : HelperValidationUtils.validateSku(sku); - } + /** + * @see #getEffective() + **/ + public String getRawEffective() { + return effective; + } + + public void setEffective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); + } + + public void setRawEffective(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); + } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceSubscriptionChangeMetadataItem that = (AdvancedCommerceSubscriptionChangeMetadataItem) o; - return Objects.equals(effective, that.effective) && Objects.equals(currentSku, that.currentSku) && Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName) && Objects.equals(sku, that.sku); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceSubscriptionChangeMetadataItem advancedCommerceSubscriptionChangeMetadataItem = (AdvancedCommerceSubscriptionChangeMetadataItem) o; + return Objects.equals(this.sku, advancedCommerceSubscriptionChangeMetadataItem.sku) && + Objects.equals(this.currentSku, advancedCommerceSubscriptionChangeMetadataItem.currentSku) && + Objects.equals(this.description, advancedCommerceSubscriptionChangeMetadataItem.description) && + Objects.equals(this.displayName, advancedCommerceSubscriptionChangeMetadataItem.displayName) && + Objects.equals(this.effective, advancedCommerceSubscriptionChangeMetadataItem.effective); } @Override public int hashCode() { - return Objects.hash(effective, currentSku, description, displayName, sku); + return Objects.hash(sku, currentSku, description, displayName, effective); } @Override @@ -151,7 +178,7 @@ public String toString() { ", currentSku='" + currentSku + '\'' + ", description='" + description + '\'' + ", displayName='" + displayName + '\'' + - ", effective=" + effective + + ", effective='" + effective + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataRequest.java index 6732e52a..8ac0ad47 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -12,7 +13,8 @@ * The request body you provide to change the metadata of a subscription. * * @see SubscriptionChangeMetadataRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionChangeMetadataRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_DESCRIPTORS = "descriptors"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -28,7 +30,9 @@ public class AdvancedCommerceSubscriptionChangeMetadataRequest extends AdvancedC @JsonProperty(SERIALIZED_NAME_TAX_CODE) private String taxCode; - protected AdvancedCommerceSubscriptionChangeMetadataRequest() {} + protected AdvancedCommerceSubscriptionChangeMetadataRequest() { + super(); + } public AdvancedCommerceSubscriptionChangeMetadataRequest(AdvancedCommerceRequestInfo requestInfo) { super(requestInfo); @@ -39,12 +43,25 @@ protected AdvancedCommerceSubscriptionChangeMetadataRequest self() { return this; } + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionChangeMetadataRequest descriptors(AdvancedCommerceSubscriptionChangeMetadataDescriptors descriptors) { this.descriptors = descriptors; return this; } /** + * The subscription metadata to change, specifically the description and display name. + * * @return descriptors * @see SubscriptionChangeMetadataDescriptors **/ @@ -57,7 +74,7 @@ public void setDescriptors(AdvancedCommerceSubscriptionChangeMetadataDescriptors } public AdvancedCommerceSubscriptionChangeMetadataRequest items(List items) { - this.items = items; + this.items = items != null ? HelperValidationUtils.validateItems(items) : null; return this; } @@ -71,6 +88,8 @@ public AdvancedCommerceSubscriptionChangeMetadataRequest addItem(AdvancedCommerc } /** + * The metadata to change for an item, specifically its SKU, description, and display name. + * * @return items * @see SubscriptionChangeMetadataItem **/ @@ -79,51 +98,63 @@ public List getItems() { } public void setItems(List items) { - this.items = items; + this.items = items != null ? HelperValidationUtils.validateItems(items) : null; } - - public AdvancedCommerceSubscriptionChangeMetadataRequest taxCode(String taxCode) { - this.taxCode = taxCode; + public AdvancedCommerceSubscriptionChangeMetadataRequest storefront(String storefront) { + this.storefront = storefront; return this; } /** - * @return taxCode - * @see TaxCode + * A three-letter code that represents the country or region associated with the App Store storefront. + * + * @return storefront + * @see storefront **/ - public String getTaxCode() { - return taxCode; + public String getStorefront() { + return storefront; } - public void setTaxCode(String taxCode) { - this.taxCode = taxCode; + public void setStorefront(String storefront) { + this.storefront = storefront; } - public AdvancedCommerceSubscriptionChangeMetadataRequest storefront(String storefront) { - this.storefront = storefront; + public AdvancedCommerceSubscriptionChangeMetadataRequest taxCode(String taxCode) { + this.taxCode = taxCode; return this; } /** - * @return storefront - * @see storefront + * A tax code that applies to a SKU. + * + * @return taxCode + * @see taxCode **/ - public String getStorefront() { - return storefront; + public String getTaxCode() { + return taxCode; } - public void setStorefront(String storefront) { - this.storefront = storefront; + public void setTaxCode(String taxCode) { + this.taxCode = taxCode; } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionChangeMetadataRequest that = (AdvancedCommerceSubscriptionChangeMetadataRequest) o; - return Objects.equals(descriptors, that.descriptors) && Objects.equals(items, that.items) && Objects.equals(taxCode, that.taxCode) && Objects.equals(storefront, that.storefront); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionChangeMetadataRequest advancedCommerceSubscriptionChangeMetadataRequest = (AdvancedCommerceSubscriptionChangeMetadataRequest) o; + return Objects.equals(this.descriptors, advancedCommerceSubscriptionChangeMetadataRequest.descriptors) && + Objects.equals(this.items, advancedCommerceSubscriptionChangeMetadataRequest.items) && + Objects.equals(this.storefront, advancedCommerceSubscriptionChangeMetadataRequest.storefront) && + Objects.equals(this.taxCode, advancedCommerceSubscriptionChangeMetadataRequest.taxCode); } @Override @@ -133,12 +164,12 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "descriptors=" + descriptors + '\'' + - ", items=" + items + '\'' + - ", requestInfo=" + getRequestInfo() + '\'' + + return "AdvancedCommerceSubscriptionChangeMetadataRequest{" + + "requestInfo=" + getRequestInfo() + + ", descriptors=" + descriptors + + ", items=" + items + ", storefront='" + storefront + '\'' + ", taxCode='" + taxCode + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataResponse.java index 6076659e..1208d224 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionChangeMetadataResponse.java @@ -2,19 +2,27 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * The response body for a successful subscription metadata change. * * @see SubscriptionChangeMetadataResponse - */ + **/ public class AdvancedCommerceSubscriptionChangeMetadataResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceSubscriptionChangeMetadataResponse() { super(); } - public AdvancedCommerceSubscriptionChangeMetadataResponse(String signedRenewalInfo, String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceSubscriptionChangeMetadataResponse( + @JsonProperty(value = "signedRenewalInfo", required = true) String signedRenewalInfo, + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(Objects.requireNonNull(signedRenewalInfo), Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +31,11 @@ protected AdvancedCommerceSubscriptionChangeMetadataResponse self() { return this; } + @Override + public AdvancedCommerceSubscriptionChangeMetadataResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionChangeMetadataResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceSubscriptionChangeMetadataResponse signedRenewalInfo(String signedRenewalInfo) { Objects.requireNonNull(signedRenewalInfo); @@ -47,11 +60,50 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JWS Compact Serialization format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + + return "AdvancedCommerceSubscriptionChangeMetadataResponse{" + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateItem.java index e6b3c095..fee4db3c 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * The data that describes a subscription item. * * @see SubscriptionCreateItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionCreateItem extends AbstractAdvancedCommerceItem { private static final String SERIALIZED_NAME_OFFER = "offer"; private static final String SERIALIZED_NAME_PRICE = "price"; @@ -24,22 +26,72 @@ protected AdvancedCommerceSubscriptionCreateItem() { super(); } - @Override - protected AbstractAdvancedCommerceItem self() { - return this; - } - public AdvancedCommerceSubscriptionCreateItem(String sku, String description, String displayName, Long price) { super(sku, description, displayName); this.price = Objects.requireNonNull(price); } - + + @Override + protected AdvancedCommerceSubscriptionCreateItem self() { + return this; + } + + @Override + public AdvancedCommerceSubscriptionCreateItem sku(String sku) { + return (AdvancedCommerceSubscriptionCreateItem) super.sku(sku); + } + + @Override + public AdvancedCommerceSubscriptionCreateItem description(String description) { + return (AdvancedCommerceSubscriptionCreateItem) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionCreateItem displayName(String displayName) { + return (AdvancedCommerceSubscriptionCreateItem) super.displayName(displayName); + } + + /** + * The item’s product identifier, which you define. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + /** + * A string you provide that describes a SKU. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * A string with a product name that you can localize and is suitable for display to customers. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + public AdvancedCommerceSubscriptionCreateItem offer(AdvancedCommerceOffer offer) { this.offer = offer; return this; } /** + * A discount offer for an auto-renewable subscription. + * * @return offer * @see Offer **/ @@ -57,6 +109,8 @@ public AdvancedCommerceSubscriptionCreateItem price(Long price) { } /** + * A price, in milliunits of a currency, for an Advanced Commerce API SKU. + * * @return price * @see price **/ @@ -70,11 +124,18 @@ public void setPrice(Long price) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionCreateItem that = (AdvancedCommerceSubscriptionCreateItem) o; - return Objects.equals(offer, that.offer) && Objects.equals(price, that.price); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionCreateItem advancedCommerceSubscriptionCreateItem = (AdvancedCommerceSubscriptionCreateItem) o; + return Objects.equals(this.offer, advancedCommerceSubscriptionCreateItem.offer) && + Objects.equals(this.price, advancedCommerceSubscriptionCreateItem.price); } @Override @@ -84,12 +145,12 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + - ", offer=" + offer + '\'' + + return "AdvancedCommerceSubscriptionCreateItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + ", offer=" + offer + ", price=" + price + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateRequest.java index e15d1d9a..d20ed942 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionCreateRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; @@ -11,7 +12,8 @@ * The request data your app provides when a customer purchases an auto-renewable subscription. * * @see SubscriptionCreateRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionCreateRequest extends AbstractAdvancedCommerceInAppRequest { private static final String OPERATION = "CREATE_SUBSCRIPTION"; private static final String VERSION = "1"; @@ -31,7 +33,7 @@ public class AdvancedCommerceSubscriptionCreateRequest extends AbstractAdvancedC @JsonProperty(value = SERIALIZED_NAME_ITEMS, required = true) private List items; @JsonProperty(value = SERIALIZED_NAME_PERIOD, required = true) - private AdvancedCommercePeriod period; + private String period; @JsonProperty(SERIALIZED_NAME_PREVIOUS_TRANSACTION_ID) private String previousTransactionId; @JsonProperty(SERIALIZED_NAME_STOREFRONT) @@ -44,18 +46,34 @@ protected AdvancedCommerceSubscriptionCreateRequest() { } public AdvancedCommerceSubscriptionCreateRequest( + AdvancedCommerceRequestInfo requestInfo, String currency, AdvancedCommerceDescriptors descriptors, List items, AdvancedCommercePeriod period, + String taxCode + ) { + super(OPERATION, VERSION, requestInfo); + this.currency = Objects.requireNonNull(currency); + this.descriptors = Objects.requireNonNull(descriptors); + this.items = HelperValidationUtils.validateItems(items); + this.period = Objects.requireNonNull(period).getValue(); + this.taxCode = Objects.requireNonNull(taxCode); + } + + public AdvancedCommerceSubscriptionCreateRequest( AdvancedCommerceRequestInfo requestInfo, + String currency, + AdvancedCommerceDescriptors descriptors, + List items, + String rawPeriod, String taxCode ) { super(OPERATION, VERSION, requestInfo); this.currency = Objects.requireNonNull(currency); this.descriptors = Objects.requireNonNull(descriptors); this.items = HelperValidationUtils.validateItems(items); - this.period = Objects.requireNonNull(period); + this.period = Objects.requireNonNull(rawPeriod); this.taxCode = Objects.requireNonNull(taxCode); } @@ -64,12 +82,45 @@ protected AdvancedCommerceSubscriptionCreateRequest self() { return this; } + /** + * @return operation + * @see SubscriptionCreateRequest + **/ + @Override + public String getOperation() { + return super.getOperation(); + } + + /** + * A number that represents the version of the data structure or Advanced Commerce API. + * + * @return version + * @see version + **/ + @Override + public String getVersion() { + return super.getVersion(); + } + + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionCreateRequest currency(String currency) { this.currency = Objects.requireNonNull(currency); return this; } /** + * The three-letter ISO 4217 currency code for the price of a product. + * * @return currency * @see currency **/ @@ -87,6 +138,8 @@ public AdvancedCommerceSubscriptionCreateRequest descriptors(AdvancedCommerceDes } /** + * The display name and description of a subscription product. + * * @return descriptors * @see Descriptors **/ @@ -110,6 +163,8 @@ public AdvancedCommerceSubscriptionCreateRequest addItem(AdvancedCommerceSubscri } /** + * The data that describes a subscription item. + * * @return items * @see SubscriptionCreateItem **/ @@ -122,20 +177,33 @@ public void setItems(List items) { } public AdvancedCommerceSubscriptionCreateRequest period(AdvancedCommercePeriod period) { - this.period = Objects.requireNonNull(period); + this.period = Objects.requireNonNull(period).getValue(); return this; } /** + * The duration of a single cycle of an auto-renewable subscription. + * * @return period * @see period **/ public AdvancedCommercePeriod getPeriod() { + return AdvancedCommercePeriod.fromValue(period); + } + + /** + * @see #getPeriod() + **/ + public String getRawPeriod() { return period; } public void setPeriod(AdvancedCommercePeriod period) { - this.period = Objects.requireNonNull(period); + this.period = Objects.requireNonNull(period).getValue(); + } + + public void setRawPeriod(String rawPeriod) { + this.period = Objects.requireNonNull(rawPeriod); } public AdvancedCommerceSubscriptionCreateRequest previousTransactionId(String previousTransactionId) { @@ -144,6 +212,8 @@ public AdvancedCommerceSubscriptionCreateRequest previousTransactionId(String pr } /** + * A unique identifier that the App Store generates for a transaction. + * * @return previousTransactionId * @see transactionId **/ @@ -161,6 +231,8 @@ public AdvancedCommerceSubscriptionCreateRequest storefront(String storefront) { } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -178,8 +250,10 @@ public AdvancedCommerceSubscriptionCreateRequest taxCode(String taxCode) { } /** + * A tax code that applies to a SKU. + * * @return taxCode - * @see taxCode + * @see taxCode **/ public String getTaxCode() { return taxCode; @@ -191,11 +265,23 @@ public void setTaxCode(String taxCode) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionCreateRequest that = (AdvancedCommerceSubscriptionCreateRequest) o; - return Objects.equals(currency, that.currency) && Objects.equals(descriptors, that.descriptors) && Objects.equals(items, that.items) && Objects.equals(period, that.period) && Objects.equals(previousTransactionId, that.previousTransactionId) && Objects.equals(storefront, that.storefront) && Objects.equals(taxCode, that.taxCode); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionCreateRequest advancedCommerceSubscriptionCreateRequest = (AdvancedCommerceSubscriptionCreateRequest) o; + return Objects.equals(this.currency, advancedCommerceSubscriptionCreateRequest.currency) && + Objects.equals(this.descriptors, advancedCommerceSubscriptionCreateRequest.descriptors) && + Objects.equals(this.items, advancedCommerceSubscriptionCreateRequest.items) && + Objects.equals(this.period, advancedCommerceSubscriptionCreateRequest.period) && + Objects.equals(this.previousTransactionId, advancedCommerceSubscriptionCreateRequest.previousTransactionId) && + Objects.equals(this.storefront, advancedCommerceSubscriptionCreateRequest.storefront) && + Objects.equals(this.taxCode, advancedCommerceSubscriptionCreateRequest.taxCode); } @Override @@ -205,15 +291,17 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "currency='" + currency + '\'' + + return "AdvancedCommerceSubscriptionCreateRequest{" + + "operation='" + getOperation() + '\'' + + ", version='" + getVersion() + '\'' + + ", requestInfo=" + getRequestInfo() + + ", currency='" + currency + '\'' + ", descriptors=" + descriptors + ", items=" + items + - ", period=" + period + + ", period='" + period + '\'' + ", previousTransactionId='" + previousTransactionId + '\'' + - ", requestInfo=" + getRequestInfo() + ", storefront='" + storefront + '\'' + ", taxCode='" + taxCode + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateDescriptors.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateDescriptors.java index fbc481ec..b5c51107 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateDescriptors.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateDescriptors.java @@ -2,11 +2,16 @@ package com.apple.itunes.storekit.model; -/* +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.Map; + +/** * The description and display name of the subscription to migrate to that you manage. - * + * * @see SubscriptionMigrateDescriptors - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionMigrateDescriptors extends AdvancedCommerceDescriptors { protected AdvancedCommerceSubscriptionMigrateDescriptors() { super(); @@ -16,10 +21,51 @@ public AdvancedCommerceSubscriptionMigrateDescriptors(String description, String super(description, displayName); } + @Override + public AdvancedCommerceSubscriptionMigrateDescriptors description(String description) { + return (AdvancedCommerceSubscriptionMigrateDescriptors) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionMigrateDescriptors displayName(String displayName) { + return (AdvancedCommerceSubscriptionMigrateDescriptors) super.displayName(displayName); + } + + @Override + public AdvancedCommerceSubscriptionMigrateDescriptors unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionMigrateDescriptors) super.unknownFields(unknownFields); + } + + /** + * The description of the subscription to migrate to. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * The display name of the subscription to migrate to. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } return super.equals(o); } @@ -27,13 +73,13 @@ public boolean equals(Object o) { public int hashCode() { return super.hashCode(); } - + @Override public String toString() { - return getClass().getSimpleName() + "{" + - "description='" + description + '\'' + - ", displayName='" + displayName + '\'' + + return "AdvancedCommerceSubscriptionMigrateDescriptors{" + + "description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } - } diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateItem.java index 4a6d05ec..57c3ed7a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateItem.java @@ -2,11 +2,14 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * The SKU, description, and display name to use for a migrated subscription item. * * @see SubscriptionMigrateItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionMigrateItem extends AbstractAdvancedCommerceItem { protected AdvancedCommerceSubscriptionMigrateItem() { super(); @@ -21,12 +24,76 @@ protected AdvancedCommerceSubscriptionMigrateItem self() { return this; } + @Override + public AdvancedCommerceSubscriptionMigrateItem sku(String sku) { + return (AdvancedCommerceSubscriptionMigrateItem) super.sku(sku); + } + + @Override + public AdvancedCommerceSubscriptionMigrateItem description(String description) { + return (AdvancedCommerceSubscriptionMigrateItem) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionMigrateItem displayName(String displayName) { + return (AdvancedCommerceSubscriptionMigrateItem) super.displayName(displayName); + } + + /** + * The SKU to use for the migrated item. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + /** + * The description of the SKU. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * The display name of the SKU. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + " {" + - " sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + - " }"; + return "AdvancedCommerceSubscriptionMigrateItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRenewalItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRenewalItem.java index 18a90b9e..59741dec 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRenewalItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRenewalItem.java @@ -2,11 +2,14 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * The item information that replaces a migrated subscription item when the subscription renews. * * @see SubscriptionMigrateRenewalItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionMigrateRenewalItem extends AbstractAdvancedCommerceItem { protected AdvancedCommerceSubscriptionMigrateRenewalItem() { super(); @@ -21,24 +24,76 @@ protected AdvancedCommerceSubscriptionMigrateRenewalItem self() { return this; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - return super.equals(o); - } + @Override + public AdvancedCommerceSubscriptionMigrateRenewalItem sku(String sku) { + return (AdvancedCommerceSubscriptionMigrateRenewalItem) super.sku(sku); + } + + @Override + public AdvancedCommerceSubscriptionMigrateRenewalItem description(String description) { + return (AdvancedCommerceSubscriptionMigrateRenewalItem) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionMigrateRenewalItem displayName(String displayName) { + return (AdvancedCommerceSubscriptionMigrateRenewalItem) super.displayName(displayName); + } + + /** + * The SKU that the subscription item renews to at the next renewal period. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + /** + * The description of the renewing SKU. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } - @Override + /** + * The display name of the renewing SKU. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { - return getClass().getSimpleName() + " {" + - " sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + - " }"; + return "AdvancedCommerceSubscriptionMigrateRenewalItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRequest.java index 8fefefd4..76a74507 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -9,10 +10,11 @@ import java.util.Objects; /** - * The subscription details you provide to migrate a subscription from In-App Purchase to the Advanced Commerce API, such as descriptors, items, storefront, and more. + * The subscription details you provide to migrate a subscription from Apple In-App Purchase to the Advanced Commerce API, such as descriptors, items, storefront, and more. * * @see SubscriptionMigrateRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionMigrateRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_DESCRIPTORS = "descriptors"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -34,12 +36,17 @@ public class AdvancedCommerceSubscriptionMigrateRequest extends AdvancedCommerce @JsonProperty(value = SERIALIZED_NAME_TAX_CODE, required = true) private String taxCode; - protected AdvancedCommerceSubscriptionMigrateRequest() { super(); } - public AdvancedCommerceSubscriptionMigrateRequest(AdvancedCommerceRequestInfo requestInfo, AdvancedCommerceSubscriptionMigrateDescriptors descriptors, List items, String targetProductId, String taxCode) { + public AdvancedCommerceSubscriptionMigrateRequest( + AdvancedCommerceRequestInfo requestInfo, + AdvancedCommerceSubscriptionMigrateDescriptors descriptors, + List items, + String targetProductId, + String taxCode + ) { super(requestInfo); this.descriptors = Objects.requireNonNull(descriptors); this.items = HelperValidationUtils.validateItems(items); @@ -47,12 +54,30 @@ public AdvancedCommerceSubscriptionMigrateRequest(AdvancedCommerceRequestInfo re this.taxCode = Objects.requireNonNull(taxCode); } + @Override + protected AdvancedCommerceSubscriptionMigrateRequest self() { + return this; + } + + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionMigrateRequest descriptors(AdvancedCommerceSubscriptionMigrateDescriptors descriptors) { this.descriptors = Objects.requireNonNull(descriptors); return this; } /** + * The description and display name of the subscription to migrate to that you manage. + * * @return descriptors * @see SubscriptionMigrateDescriptors **/ @@ -77,7 +102,7 @@ public AdvancedCommerceSubscriptionMigrateRequest addItem(AdvancedCommerceSubscr /** * An array of one or more SKUs, along with descriptions and display names, that are included in the subscription. - * + * * @return items * @see SubscriptionMigrateItem **/ @@ -117,6 +142,24 @@ public void setRenewalItems(List this.renewalItems = renewalItems != null ? HelperValidationUtils.validateItems(renewalItems) : null; } + public AdvancedCommerceSubscriptionMigrateRequest storefront(String storefront) { + this.storefront = storefront; + return this; + } + + /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * + * @return storefront + * @see storefront + **/ + public String getStorefront() { + return storefront; + } + + public void setStorefront(String storefront) { + this.storefront = storefront; + } public AdvancedCommerceSubscriptionMigrateRequest targetProductId(String targetProductId) { this.targetProductId = Objects.requireNonNull(targetProductId); @@ -125,9 +168,9 @@ public AdvancedCommerceSubscriptionMigrateRequest targetProductId(String targetP /** * Your generic product ID for an auto-renewable subscription. - * + * * @return targetProductId - * @see targetProductId + * @see targetProductId **/ public String getTargetProductId() { return targetProductId; @@ -143,6 +186,8 @@ public AdvancedCommerceSubscriptionMigrateRequest taxCode(String taxCode) { } /** + * A tax code that applies to a SKU. + * * @return taxCode * @see taxCode **/ @@ -154,23 +199,6 @@ public void setTaxCode(String taxCode) { this.taxCode = Objects.requireNonNull(taxCode); } - public AdvancedCommerceSubscriptionMigrateRequest storefront(String storefront) { - this.storefront = storefront; - return this; - } - - /** - * @return storefront - * @see storefront - **/ - public String getStorefront() { - return storefront; - } - - public void setStorefront(String storefront) { - this.storefront = storefront; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -182,13 +210,13 @@ public boolean equals(Object o) { if (!super.equals(o)) { return false; } - AdvancedCommerceSubscriptionMigrateRequest that = (AdvancedCommerceSubscriptionMigrateRequest) o; - return Objects.equals(this.descriptors, that.descriptors) && - Objects.equals(this.items, that.items) && - Objects.equals(this.renewalItems, that.renewalItems) && - Objects.equals(this.storefront, that.storefront) && - Objects.equals(this.targetProductId, that.targetProductId) && - Objects.equals(this.taxCode, that.taxCode); + AdvancedCommerceSubscriptionMigrateRequest advancedCommerceSubscriptionMigrateRequest = (AdvancedCommerceSubscriptionMigrateRequest) o; + return Objects.equals(this.descriptors, advancedCommerceSubscriptionMigrateRequest.descriptors) && + Objects.equals(this.items, advancedCommerceSubscriptionMigrateRequest.items) && + Objects.equals(this.renewalItems, advancedCommerceSubscriptionMigrateRequest.renewalItems) && + Objects.equals(this.storefront, advancedCommerceSubscriptionMigrateRequest.storefront) && + Objects.equals(this.targetProductId, advancedCommerceSubscriptionMigrateRequest.targetProductId) && + Objects.equals(this.taxCode, advancedCommerceSubscriptionMigrateRequest.taxCode); } @Override @@ -196,21 +224,16 @@ public int hashCode() { return Objects.hash(super.hashCode(), descriptors, items, renewalItems, storefront, targetProductId, taxCode); } - @Override - protected AdvancedCommerceSubscriptionMigrateRequest self() { - return this; - } - @Override public String toString() { - return getClass().getSimpleName() + "{" + - "descriptors=" + descriptors + + return "AdvancedCommerceSubscriptionMigrateRequest{" + + "requestInfo=" + getRequestInfo() + + ", descriptors=" + descriptors + ", items=" + items + ", renewalItems=" + renewalItems + ", storefront='" + storefront + '\'' + ", targetProductId='" + targetProductId + '\'' + ", taxCode='" + taxCode + '\'' + - ", requestInfo=" + getRequestInfo() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateResponse.java index aff2bc43..a84afa02 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionMigrateResponse.java @@ -2,19 +2,27 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * A response that contains signed renewal and transaction information after a subscription successfully migrates to the Advanced Commerce API. * * @see SubscriptionMigrateResponse - */ + **/ public class AdvancedCommerceSubscriptionMigrateResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceSubscriptionMigrateResponse() { super(); } - public AdvancedCommerceSubscriptionMigrateResponse(String signedRenewalInfo, String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceSubscriptionMigrateResponse( + @JsonProperty(value = "signedRenewalInfo", required = true) String signedRenewalInfo, + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(Objects.requireNonNull(signedRenewalInfo), Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +31,11 @@ protected AdvancedCommerceSubscriptionMigrateResponse self() { return this; } + @Override + public AdvancedCommerceSubscriptionMigrateResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionMigrateResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceSubscriptionMigrateResponse signedRenewalInfo(String signedRenewalInfo) { Objects.requireNonNull(signedRenewalInfo); @@ -47,10 +60,36 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format, for the migrated subscription. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JSON Web Signature (JWS) Compact Serialization format, for the migrated subscription. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } return super.equals(o); } @@ -59,12 +98,12 @@ public int hashCode() { return super.hashCode(); } - @Override public String toString() { - return getClass().getSimpleName() + "{" + + return "AdvancedCommerceSubscriptionMigrateResponse{" + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyAddItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyAddItem.java index 7434d3c2..bdfb0e8b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyAddItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyAddItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * The data your app provides to add items when it makes changes to an auto-renewable subscription. * * @see SubscriptionModifyAddItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyAddItem extends AbstractAdvancedCommerceItem { private static final String SERIALIZED_NAME_OFFER = "offer"; private static final String SERIALIZED_NAME_PRICE = "price"; @@ -27,15 +29,64 @@ protected AdvancedCommerceSubscriptionModifyAddItem() { super(); } - protected AbstractAdvancedCommerceItem self() { - return this; - } - - public AdvancedCommerceSubscriptionModifyAddItem(String sku, String description, String displayName, long price) { + public AdvancedCommerceSubscriptionModifyAddItem(String sku, String description, String displayName, Long price) { super(sku, description, displayName); this.price = Objects.requireNonNull(price); } + @Override + protected AdvancedCommerceSubscriptionModifyAddItem self() { + return this; + } + + @Override + public AdvancedCommerceSubscriptionModifyAddItem sku(String sku) { + return (AdvancedCommerceSubscriptionModifyAddItem) super.sku(sku); + } + + @Override + public AdvancedCommerceSubscriptionModifyAddItem description(String description) { + return (AdvancedCommerceSubscriptionModifyAddItem) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionModifyAddItem displayName(String displayName) { + return (AdvancedCommerceSubscriptionModifyAddItem) super.displayName(displayName); + } + + /** + * The product identifier of an Apple In-App Purchase product you manage in your own system. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + /** + * A string you provide that describes a SKU. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * A string with a product name that you can localize and is suitable for display to customers. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + public AdvancedCommerceSubscriptionModifyAddItem offer(AdvancedCommerceOffer offer) { this.offer = offer; return this; @@ -55,12 +106,14 @@ public void setOffer(AdvancedCommerceOffer offer) { this.offer = offer; } - public AdvancedCommerceSubscriptionModifyAddItem price(long price) { + public AdvancedCommerceSubscriptionModifyAddItem price(Long price) { this.price = Objects.requireNonNull(price); return this; } /** + * A price, in milliunits of a currency, for an Advanced Commerce API SKU. + * * @return price * @see price **/ @@ -78,6 +131,8 @@ public AdvancedCommerceSubscriptionModifyAddItem proratedPrice(Long proratedPric } /** + * A prorated price, in milliunits of a currency, for an Advanced Commerce API SKU. + * * @return proratedPrice * @see proratedPrice **/ @@ -91,11 +146,19 @@ public void setProratedPrice(Long proratedPrice) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionModifyAddItem that = (AdvancedCommerceSubscriptionModifyAddItem) o; - return Objects.equals(offer, that.offer) && Objects.equals(price, that.price) && Objects.equals(proratedPrice, that.proratedPrice); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionModifyAddItem advancedCommerceSubscriptionModifyAddItem = (AdvancedCommerceSubscriptionModifyAddItem) o; + return Objects.equals(this.offer, advancedCommerceSubscriptionModifyAddItem.offer) && + Objects.equals(this.price, advancedCommerceSubscriptionModifyAddItem.price) && + Objects.equals(this.proratedPrice, advancedCommerceSubscriptionModifyAddItem.proratedPrice); } @Override @@ -103,15 +166,15 @@ public int hashCode() { return Objects.hash(super.hashCode(), offer, price, proratedPrice); } - @Override + @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + - ", offer=" + offer + '\'' + - ", price=" + price + '\'' + - ", proratedPrice=" + proratedPrice + '\'' + + return "AdvancedCommerceSubscriptionModifyAddItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + ", offer=" + offer + + ", price=" + price + + ", proratedPrice=" + proratedPrice + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyChangeItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyChangeItem.java index ce50315e..01f9e37c 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyChangeItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyChangeItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * The data your app provides to change an item of an auto-renewable subscription. * * @see SubscriptionModifyChangeItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyChangeItem extends AbstractAdvancedCommerceItem { private static final String SERIALIZED_NAME_CURRENT_SKU = "currentSKU"; private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; @@ -20,9 +22,9 @@ public class AdvancedCommerceSubscriptionModifyChangeItem extends AbstractAdvanc private static final String SERIALIZED_NAME_REASON = "reason"; @JsonProperty(value = SERIALIZED_NAME_CURRENT_SKU, required = true) - private String currentSKU; + private String currentSku; @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) - private AdvancedCommerceEffective effective; + private String effective; @JsonProperty(SERIALIZED_NAME_OFFER) private AdvancedCommerceOffer offer; @JsonProperty(value = SERIALIZED_NAME_PRICE, required = true) @@ -30,55 +32,144 @@ public class AdvancedCommerceSubscriptionModifyChangeItem extends AbstractAdvanc @JsonProperty(SERIALIZED_NAME_PRORATED_PRICE) private Long proratedPrice; @JsonProperty(value = SERIALIZED_NAME_REASON, required = true) - private AdvancedCommerceReason reason; + private String reason; - protected AdvancedCommerceSubscriptionModifyChangeItem() {} + protected AdvancedCommerceSubscriptionModifyChangeItem() { + super(); + } - @Override - protected AdvancedCommerceSubscriptionModifyChangeItem self() { - return this; + public AdvancedCommerceSubscriptionModifyChangeItem( + String sku, + String description, + String displayName, + String currentSku, + AdvancedCommerceEffective effective, + Long price, + AdvancedCommerceReason reason + ) { + super(sku, description, displayName); + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); + this.effective = Objects.requireNonNull(effective).getValue(); + this.price = Objects.requireNonNull(price); + this.reason = Objects.requireNonNull(reason).getValue(); } - public AdvancedCommerceSubscriptionModifyChangeItem(String currentSKU, String description, String displayName, AdvancedCommerceEffective effective, Long price, AdvancedCommerceReason reason, String sku) { + public AdvancedCommerceSubscriptionModifyChangeItem( + String sku, + String description, + String displayName, + String currentSku, + String rawEffective, + Long price, + String rawReason + ) { super(sku, description, displayName); - this.currentSKU = HelperValidationUtils.validateSku(currentSKU); - this.effective = Objects.requireNonNull(effective); + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); + this.effective = Objects.requireNonNull(rawEffective); this.price = Objects.requireNonNull(price); - this.reason = Objects.requireNonNull(reason); + this.reason = Objects.requireNonNull(rawReason); } - public AdvancedCommerceSubscriptionModifyChangeItem currentSKU(String currentSKU) { - this.currentSKU = HelperValidationUtils.validateSku(currentSKU); + @Override + protected AdvancedCommerceSubscriptionModifyChangeItem self() { return this; } + @Override + public AdvancedCommerceSubscriptionModifyChangeItem sku(String sku) { + return (AdvancedCommerceSubscriptionModifyChangeItem) super.sku(sku); + } + + @Override + public AdvancedCommerceSubscriptionModifyChangeItem description(String description) { + return (AdvancedCommerceSubscriptionModifyChangeItem) super.description(description); + } + + @Override + public AdvancedCommerceSubscriptionModifyChangeItem displayName(String displayName) { + return (AdvancedCommerceSubscriptionModifyChangeItem) super.displayName(displayName); + } + + /** + * The product identifier of an Apple In-App Purchase product you manage in your own system. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + /** + * A string you provide that describes a SKU. + * + * @return description + * @see description + **/ + @Override + public String getDescription() { + return super.getDescription(); + } + + /** + * A string with a product name that you can localize and is suitable for display to customers. + * + * @return displayName + * @see displayName + **/ + @Override + public String getDisplayName() { + return super.getDisplayName(); + } + + public AdvancedCommerceSubscriptionModifyChangeItem currentSku(String currentSku) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); + return this; + } + + /** + * The product identifier of an Apple In-App Purchase product you manage in your own system. + * * @return currentSKU * @see SKU - */ - public String getCurrentSKU() { - return currentSKU; + **/ + public String getCurrentSku() { + return currentSku; } - public void setCurrentSKU(String currentSKU) { - this.currentSKU = HelperValidationUtils.validateSku(currentSKU); + public void setCurrentSku(String currentSku) { + this.currentSku = HelperValidationUtils.validateSku(Objects.requireNonNull(currentSku)); } public AdvancedCommerceSubscriptionModifyChangeItem effective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + this.effective = Objects.requireNonNull(effective).getValue(); return this; } /** + * A string value that indicates when a requested change to an auto-renewable subscription goes into effect. + * * @return effective * @see effective **/ public AdvancedCommerceEffective getEffective() { + return AdvancedCommerceEffective.fromValue(effective); + } + + /** + * @see #getEffective() + **/ + public String getRawEffective() { return effective; } public void setEffective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + this.effective = Objects.requireNonNull(effective).getValue(); + } + + public void setRawEffective(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); } public AdvancedCommerceSubscriptionModifyChangeItem offer(AdvancedCommerceOffer offer) { @@ -87,6 +178,8 @@ public AdvancedCommerceSubscriptionModifyChangeItem offer(AdvancedCommerceOffer } /** + * A discount offer for an auto-renewable subscription. + * * @return offer * @see Offer **/ @@ -104,6 +197,8 @@ public AdvancedCommerceSubscriptionModifyChangeItem price(Long price) { } /** + * A price, in milliunits of a currency, for an Advanced Commerce API SKU. + * * @return price * @see price **/ @@ -121,6 +216,8 @@ public AdvancedCommerceSubscriptionModifyChangeItem proratedPrice(Long proratedP } /** + * A prorated price, in milliunits of a currency, for an Advanced Commerce API SKU. + * * @return proratedPrice * @see proratedPrice **/ @@ -133,47 +230,70 @@ public void setProratedPrice(Long proratedPrice) { } public AdvancedCommerceSubscriptionModifyChangeItem reason(AdvancedCommerceReason reason) { - this.reason = Objects.requireNonNull(reason); + this.reason = Objects.requireNonNull(reason).getValue(); return this; } /** * @return reason - */ + * @see SubscriptionModifyChangeItem + **/ public AdvancedCommerceReason getReason() { + return AdvancedCommerceReason.fromValue(reason); + } + + /** + * @see #getReason() + **/ + public String getRawReason() { return reason; } public void setReason(AdvancedCommerceReason reason) { - this.reason = Objects.requireNonNull(reason); + this.reason = Objects.requireNonNull(reason).getValue(); + } + + public void setRawReason(String rawReason) { + this.reason = Objects.requireNonNull(rawReason); } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionModifyChangeItem that = (AdvancedCommerceSubscriptionModifyChangeItem) o; - return Objects.equals(currentSKU, that.currentSKU) && Objects.equals(effective, that.effective) && Objects.equals(offer, that.offer) && Objects.equals(price, that.price) && Objects.equals(proratedPrice, that.proratedPrice) && Objects.equals(reason, that.reason); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionModifyChangeItem advancedCommerceSubscriptionModifyChangeItem = (AdvancedCommerceSubscriptionModifyChangeItem) o; + return Objects.equals(this.currentSku, advancedCommerceSubscriptionModifyChangeItem.currentSku) && + Objects.equals(this.effective, advancedCommerceSubscriptionModifyChangeItem.effective) && + Objects.equals(this.offer, advancedCommerceSubscriptionModifyChangeItem.offer) && + Objects.equals(this.price, advancedCommerceSubscriptionModifyChangeItem.price) && + Objects.equals(this.proratedPrice, advancedCommerceSubscriptionModifyChangeItem.proratedPrice) && + Objects.equals(this.reason, advancedCommerceSubscriptionModifyChangeItem.reason); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), currentSKU, effective, offer, price, proratedPrice, reason); + return Objects.hash(super.hashCode(), currentSku, effective, offer, price, proratedPrice, reason); } @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + - ", description='" + description + '\'' + - ", displayName='" + displayName + '\'' + - ", currentSKU='" + currentSKU + '\'' + - ", effective=" + effective + '\'' + - ", offer=" + offer + '\'' + - ", price=" + price + '\'' + - ", proratedPrice=" + proratedPrice + '\'' + - ", reason=" + reason + '\'' + + return "AdvancedCommerceSubscriptionModifyChangeItem{" + + "sku='" + getSku() + '\'' + + ", description='" + getDescription() + '\'' + + ", displayName='" + getDisplayName() + '\'' + + ", currentSku='" + currentSku + '\'' + + ", effective='" + effective + '\'' + + ", offer=" + offer + + ", price=" + price + + ", proratedPrice=" + proratedPrice + + ", reason='" + reason + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyDescriptors.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyDescriptors.java index 3c85d492..df55be5d 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyDescriptors.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyDescriptors.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,40 +11,29 @@ * The data your app provides to change the description and display name of an auto-renewable subscription. * * @see SubscriptionModifyDescriptors - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyDescriptors { - private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; - - @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) - private AdvancedCommerceEffective effective; + private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; + @JsonProperty(SERIALIZED_NAME_DESCRIPTION) private String description; @JsonProperty(SERIALIZED_NAME_DISPLAY_NAME) private String displayName; + @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) + private String effective; - protected AdvancedCommerceSubscriptionModifyDescriptors() {} - - public AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); - } - - public AdvancedCommerceSubscriptionModifyDescriptors effective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); - return this; + protected AdvancedCommerceSubscriptionModifyDescriptors() { } - /** - * @return effective - * @see effective - **/ - public AdvancedCommerceEffective getEffective() { - return effective; + public AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); } - public void setEffective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + public AdvancedCommerceSubscriptionModifyDescriptors(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); } public AdvancedCommerceSubscriptionModifyDescriptors description(String description) { @@ -52,6 +42,8 @@ public AdvancedCommerceSubscriptionModifyDescriptors description(String descript } /** + * A string you provide that describes a SKU. + * * @return description * @see description **/ @@ -69,6 +61,8 @@ public AdvancedCommerceSubscriptionModifyDescriptors displayName(String displayN } /** + * A string with a product name that you can localize and is suitable for display to customers. + * * @return displayName * @see displayName **/ @@ -80,25 +74,61 @@ public void setDisplayName(String displayName) { this.displayName = displayName == null ? null : HelperValidationUtils.validateDisplayName(displayName); } + public AdvancedCommerceSubscriptionModifyDescriptors effective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); + return this; + } + + /** + * A string value that indicates when a requested change to an auto-renewable subscription goes into effect. + * + * @return effective + * @see effective + **/ + public AdvancedCommerceEffective getEffective() { + return AdvancedCommerceEffective.fromValue(effective); + } + + /** + * @see #getEffective() + **/ + public String getRawEffective() { + return effective; + } + + public void setEffective(AdvancedCommerceEffective effective) { + this.effective = Objects.requireNonNull(effective).getValue(); + } + + public void setRawEffective(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceSubscriptionModifyDescriptors that = (AdvancedCommerceSubscriptionModifyDescriptors) o; - return Objects.equals(effective, that.effective) && Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceSubscriptionModifyDescriptors advancedCommerceSubscriptionModifyDescriptors = (AdvancedCommerceSubscriptionModifyDescriptors) o; + return Objects.equals(this.description, advancedCommerceSubscriptionModifyDescriptors.description) && + Objects.equals(this.displayName, advancedCommerceSubscriptionModifyDescriptors.displayName) && + Objects.equals(this.effective, advancedCommerceSubscriptionModifyDescriptors.effective); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), effective, description, displayName); + return Objects.hash(description, displayName, effective); } @Override public String toString() { - return getClass().getSimpleName() + "{" + - "effective=" + effective + '\'' + - ", description='" + description + '\'' + + return "AdvancedCommerceSubscriptionModifyDescriptors{" + + "description='" + description + '\'' + ", displayName='" + displayName + '\'' + + ", effective='" + effective + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyInAppRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyInAppRequest.java index cf975ac9..b91f6ced 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyInAppRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyInAppRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -12,7 +13,8 @@ * The request data your app provides to make changes to an auto-renewable subscription. * * @see SubscriptionModifyInAppRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyInAppRequest extends AbstractAdvancedCommerceInAppRequest { private static final String OPERATION = "MODIFY_SUBSCRIPTION"; private static final String VERSION = "1"; @@ -55,12 +57,12 @@ protected AdvancedCommerceSubscriptionModifyInAppRequest() { public AdvancedCommerceSubscriptionModifyInAppRequest( AdvancedCommerceRequestInfo requestInfo, - String transactionId, - Boolean retainBillingCycle + Boolean retainBillingCycle, + String transactionId ) { super(OPERATION, VERSION, requestInfo); - this.transactionId = Objects.requireNonNull(transactionId); this.retainBillingCycle = Objects.requireNonNull(retainBillingCycle); + this.transactionId = Objects.requireNonNull(transactionId); } @Override @@ -68,6 +70,37 @@ protected AdvancedCommerceSubscriptionModifyInAppRequest self() { return this; } + /** + * @return operation + * @see SubscriptionModifyInAppRequest + **/ + @Override + public String getOperation() { + return super.getOperation(); + } + + /** + * A number that represents the version of the data structure or Advanced Commerce API. + * + * @return version + * @see version + **/ + @Override + public String getVersion() { + return super.getVersion(); + } + + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionModifyInAppRequest addItems(List addItems) { this.addItems = addItems != null ? HelperValidationUtils.validateItems(addItems) : null; return this; @@ -83,6 +116,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest addAddItem(AdvancedCommerc } /** + * The data your app provides to add items when it makes changes to an auto-renewable subscription. + * * @return addItems * @see SubscriptionModifyAddItem **/ @@ -109,6 +144,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest addChangeItem(AdvancedComm } /** + * The data your app provides to change an item of an auto-renewable subscription. + * * @return changeItems * @see SubscriptionModifyChangeItem **/ @@ -126,6 +163,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest currency(String currency) } /** + * The three-letter ISO 4217 currency code for the price of a product. + * * @return currency * @see currency **/ @@ -143,6 +182,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest descriptors(AdvancedCommer } /** + * The data your app provides to change the description and display name of an auto-renewable subscription. + * * @return descriptors * @see SubscriptionModifyDescriptors **/ @@ -160,6 +201,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest periodChange(AdvancedComme } /** + * The data your app provides to change the period of an auto-renewable subscription. + * * @return periodChange * @see SubscriptionModifyPeriodChange **/ @@ -172,7 +215,7 @@ public void setPeriodChange(AdvancedCommerceSubscriptionModifyPeriodChange perio } public AdvancedCommerceSubscriptionModifyInAppRequest removeItems(List removeItems) { - this.removeItems = removeItems; + this.removeItems = removeItems != null ? HelperValidationUtils.validateItems(removeItems) : null; return this; } @@ -186,6 +229,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest addRemoveItem(AdvancedComm } /** + * The data your app provides to remove an item from an auto-renewable subscription. + * * @return removeItems * @see SubscriptionModifyRemoveItem **/ @@ -194,7 +239,7 @@ public List getRemoveItems() { } public void setRemoveItems(List removeItems) { - this.removeItems = removeItems; + this.removeItems = removeItems != null ? HelperValidationUtils.validateItems(removeItems) : null; } public AdvancedCommerceSubscriptionModifyInAppRequest retainBillingCycle(Boolean retainBillingCycle) { @@ -203,6 +248,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest retainBillingCycle(Boolean } /** + * A Boolean value that determines whether to keep the existing billing cycle with the change you request. + * * @return retainBillingCycle * @see retainBillingCycle **/ @@ -220,6 +267,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest storefront(String storefro } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -237,6 +286,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest taxCode(String taxCode) { } /** + * A tax code that applies to a SKU. + * * @return taxCode * @see taxCode **/ @@ -254,6 +305,8 @@ public AdvancedCommerceSubscriptionModifyInAppRequest transactionId(String trans } /** + * A unique identifier that the App Store generates for a transaction. + * * @return transactionId * @see transactionId **/ @@ -267,11 +320,26 @@ public void setTransactionId(String transactionId) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionModifyInAppRequest that = (AdvancedCommerceSubscriptionModifyInAppRequest) o; - return Objects.equals(addItems, that.addItems) && Objects.equals(changeItems, that.changeItems) && Objects.equals(currency, that.currency) && Objects.equals(descriptors, that.descriptors) && Objects.equals(periodChange, that.periodChange) && Objects.equals(removeItems, that.removeItems) && Objects.equals(retainBillingCycle, that.retainBillingCycle) && Objects.equals(storefront, that.storefront) && Objects.equals(taxCode, that.taxCode) && Objects.equals(transactionId, that.transactionId); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionModifyInAppRequest advancedCommerceSubscriptionModifyInAppRequest = (AdvancedCommerceSubscriptionModifyInAppRequest) o; + return Objects.equals(this.addItems, advancedCommerceSubscriptionModifyInAppRequest.addItems) && + Objects.equals(this.changeItems, advancedCommerceSubscriptionModifyInAppRequest.changeItems) && + Objects.equals(this.currency, advancedCommerceSubscriptionModifyInAppRequest.currency) && + Objects.equals(this.descriptors, advancedCommerceSubscriptionModifyInAppRequest.descriptors) && + Objects.equals(this.periodChange, advancedCommerceSubscriptionModifyInAppRequest.periodChange) && + Objects.equals(this.removeItems, advancedCommerceSubscriptionModifyInAppRequest.removeItems) && + Objects.equals(this.retainBillingCycle, advancedCommerceSubscriptionModifyInAppRequest.retainBillingCycle) && + Objects.equals(this.storefront, advancedCommerceSubscriptionModifyInAppRequest.storefront) && + Objects.equals(this.taxCode, advancedCommerceSubscriptionModifyInAppRequest.taxCode) && + Objects.equals(this.transactionId, advancedCommerceSubscriptionModifyInAppRequest.transactionId); } @Override @@ -281,18 +349,20 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "addItems=" + addItems + + return "AdvancedCommerceSubscriptionModifyInAppRequest{" + + "operation='" + getOperation() + '\'' + + ", version='" + getVersion() + '\'' + + ", requestInfo=" + getRequestInfo() + + ", addItems=" + addItems + ", changeItems=" + changeItems + ", currency='" + currency + '\'' + ", descriptors=" + descriptors + ", periodChange=" + periodChange + ", removeItems=" + removeItems + ", retainBillingCycle=" + retainBillingCycle + - ", requestInfo=" + getRequestInfo() + ", storefront='" + storefront + '\'' + ", taxCode='" + taxCode + '\'' + ", transactionId='" + transactionId + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyPeriodChange.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyPeriodChange.java index e49284bf..01e54003 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyPeriodChange.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyPeriodChange.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,71 +11,104 @@ * The data your app provides to change the period of an auto-renewable subscription. * * @see SubscriptionModifyPeriodChange - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyPeriodChange { private static final String SERIALIZED_NAME_EFFECTIVE = "effective"; private static final String SERIALIZED_NAME_PERIOD = "period"; @JsonProperty(value = SERIALIZED_NAME_EFFECTIVE, required = true) - private AdvancedCommerceEffective effective; + private String effective; @JsonProperty(value = SERIALIZED_NAME_PERIOD, required = true) - private AdvancedCommercePeriod period; + private String period; - protected AdvancedCommerceSubscriptionModifyPeriodChange() {} + protected AdvancedCommerceSubscriptionModifyPeriodChange() { + } public AdvancedCommerceSubscriptionModifyPeriodChange( AdvancedCommerceEffective effective, AdvancedCommercePeriod period ) { - this.effective = Objects.requireNonNull(effective); - this.period = Objects.requireNonNull(period); + this.effective = Objects.requireNonNull(effective).getValue(); + this.period = Objects.requireNonNull(period).getValue(); } public AdvancedCommerceSubscriptionModifyPeriodChange(String rawEffective, String rawPeriod) { - this.effective = AdvancedCommerceEffective.fromValue(rawEffective); - this.period = AdvancedCommercePeriod.fromValue(rawPeriod); + this.effective = Objects.requireNonNull(rawEffective); + this.period = Objects.requireNonNull(rawPeriod); } public AdvancedCommerceSubscriptionModifyPeriodChange effective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + this.effective = Objects.requireNonNull(effective).getValue(); return this; } /** + * A string value that indicates when a requested change to an auto-renewable subscription goes into effect. + * * @return effective * @see effective **/ public AdvancedCommerceEffective getEffective() { + return AdvancedCommerceEffective.fromValue(effective); + } + + /** + * @see #getEffective() + **/ + public String getRawEffective() { return effective; } public void setEffective(AdvancedCommerceEffective effective) { - this.effective = Objects.requireNonNull(effective); + this.effective = Objects.requireNonNull(effective).getValue(); + } + + public void setRawEffective(String rawEffective) { + this.effective = Objects.requireNonNull(rawEffective); } public AdvancedCommerceSubscriptionModifyPeriodChange period(AdvancedCommercePeriod period) { - this.period = Objects.requireNonNull(period); + this.period = Objects.requireNonNull(period).getValue(); return this; } /** + * The duration of a single cycle of an auto-renewable subscription. + * * @return period - * @see Period + * @see period **/ public AdvancedCommercePeriod getPeriod() { + return AdvancedCommercePeriod.fromValue(period); + } + + /** + * @see #getPeriod() + **/ + public String getRawPeriod() { return period; } public void setPeriod(AdvancedCommercePeriod period) { - this.period = Objects.requireNonNull(period); + this.period = Objects.requireNonNull(period).getValue(); + } + + public void setRawPeriod(String rawPeriod) { + this.period = Objects.requireNonNull(rawPeriod); } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceSubscriptionModifyPeriodChange that = (AdvancedCommerceSubscriptionModifyPeriodChange) o; - return Objects.equals(effective, that.effective) && Objects.equals(period, that.period); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceSubscriptionModifyPeriodChange advancedCommerceSubscriptionModifyPeriodChange = (AdvancedCommerceSubscriptionModifyPeriodChange) o; + return Objects.equals(this.effective, advancedCommerceSubscriptionModifyPeriodChange.effective) && + Objects.equals(this.period, advancedCommerceSubscriptionModifyPeriodChange.period); } @Override @@ -85,8 +119,8 @@ public int hashCode() { @Override public String toString() { return "AdvancedCommerceSubscriptionModifyPeriodChange{" + - "effective=" + effective + - ", period=" + period + + "effective='" + effective + '\'' + + ", period='" + period + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyRemoveItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyRemoveItem.java index 15ad885c..09fdfdcb 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyRemoveItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionModifyRemoveItem.java @@ -2,11 +2,14 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; + /** * The data your app provides to remove an item from an auto-renewable subscription. * * @see SubscriptionModifyRemoveItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionModifyRemoveItem extends AbstractAdvancedCommerceBaseItem { protected AdvancedCommerceSubscriptionModifyRemoveItem() { super(); @@ -17,14 +20,46 @@ public AdvancedCommerceSubscriptionModifyRemoveItem(String sku) { } @Override - protected AbstractAdvancedCommerceBaseItem self() { + protected AdvancedCommerceSubscriptionModifyRemoveItem self() { return this; } + @Override + public AdvancedCommerceSubscriptionModifyRemoveItem sku(String sku) { + return (AdvancedCommerceSubscriptionModifyRemoveItem) super.sku(sku); + } + + /** + * The product identifier of an Apple In-App Purchase product you manage in your own system. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + + return "AdvancedCommerceSubscriptionModifyRemoveItem{" + + "sku='" + getSku() + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeItem.java index f3b2d4c6..664ccf15 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeItem.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -12,15 +13,16 @@ * The data your app provides to change a subscription price. * * @see SubscriptionPriceChangeItem - */ -public class AdvancedCommerceSubscriptionPriceChangeItem extends AbstractAdvancedCommerceBaseItem{ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AdvancedCommerceSubscriptionPriceChangeItem extends AbstractAdvancedCommerceBaseItem { + private static final String SERIALIZED_NAME_DEPENDENT_SKUS = "dependentSKUs"; private static final String SERIALIZED_NAME_PRICE = "price"; - private static final String SERIALIZED_DEPENDENT_SKUS = "dependentSKUs"; + @JsonProperty(SERIALIZED_NAME_DEPENDENT_SKUS) + private List dependentSKUs; @JsonProperty(value = SERIALIZED_NAME_PRICE, required = true) private Long price; - @JsonProperty(SERIALIZED_DEPENDENT_SKUS) - private List dependentSKUs; protected AdvancedCommerceSubscriptionPriceChangeItem() { super(); @@ -36,21 +38,20 @@ protected AdvancedCommerceSubscriptionPriceChangeItem self() { return this; } - public AdvancedCommerceSubscriptionPriceChangeItem price(Long price) { - this.price = Objects.requireNonNull(price); - return this; + @Override + public AdvancedCommerceSubscriptionPriceChangeItem sku(String sku) { + return (AdvancedCommerceSubscriptionPriceChangeItem) super.sku(sku); } /** - * @return price - * @see price + * The product identifier of an Apple In-App Purchase product you manage in your own system. + * + * @return SKU + * @see SKU **/ - public Long getPrice() { - return price; - } - - public void setPrice(Long price) { - this.price = Objects.requireNonNull(price); + @Override + public String getSku() { + return super.getSku(); } public AdvancedCommerceSubscriptionPriceChangeItem dependentSKUs(List dependentSKUs) { @@ -70,6 +71,8 @@ public AdvancedCommerceSubscriptionPriceChangeItem addDependentSKU(String depend } /** + * The product identifier of a dependent SKU in a subscription price change. + * * @return dependentSKUs * @see dependentSKU **/ @@ -90,26 +93,52 @@ private void validateDependentSKUs(List dependentSKUs) { } } + public AdvancedCommerceSubscriptionPriceChangeItem price(Long price) { + this.price = Objects.requireNonNull(price); + return this; + } + + /** + * A price, in milliunits of a currency, for an Advanced Commerce API SKU. + * + * @return price + * @see price + **/ + public Long getPrice() { + return price; + } + + public void setPrice(Long price) { + this.price = Objects.requireNonNull(price); + } + @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionPriceChangeItem that = (AdvancedCommerceSubscriptionPriceChangeItem) o; - return Objects.equals(price, that.price) && Objects.equals(dependentSKUs, that.dependentSKUs); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionPriceChangeItem advancedCommerceSubscriptionPriceChangeItem = (AdvancedCommerceSubscriptionPriceChangeItem) o; + return Objects.equals(this.dependentSKUs, advancedCommerceSubscriptionPriceChangeItem.dependentSKUs) && + Objects.equals(this.price, advancedCommerceSubscriptionPriceChangeItem.price); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), price, dependentSKUs); + return Objects.hash(super.hashCode(), dependentSKUs, price); } @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + - ", price=" + price + + return "AdvancedCommerceSubscriptionPriceChangeItem{" + + "sku='" + getSku() + '\'' + ", dependentSKUs=" + dependentSKUs + + ", price=" + price + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeRequest.java index 118b5f8c..08ab70b6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; @@ -11,7 +12,8 @@ * The request body you use to change the price of an auto-renewable subscription. * * @see SubscriptionPriceChangeRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionPriceChangeRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_CURRENCY = "currency"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -23,14 +25,17 @@ public class AdvancedCommerceSubscriptionPriceChangeRequest extends AdvancedComm private List items; @JsonProperty(SERIALIZED_NAME_STOREFRONT) private String storefront; - public AdvancedCommerceSubscriptionPriceChangeRequest() {} + + protected AdvancedCommerceSubscriptionPriceChangeRequest() { + super(); + } public AdvancedCommerceSubscriptionPriceChangeRequest( AdvancedCommerceRequestInfo requestInfo, List items ) { super(requestInfo); - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); } @Override @@ -38,6 +43,17 @@ protected AdvancedCommerceSubscriptionPriceChangeRequest self() { return this; } + /** + * Metadata that identifies the request. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionPriceChangeRequest currency(String currency) { this.currency = currency; return this; @@ -58,7 +74,7 @@ public void setCurrency(String currency) { } public AdvancedCommerceSubscriptionPriceChangeRequest items(List items) { - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); return this; } @@ -79,7 +95,7 @@ public List getItems() { } public void setItems(List items) { - this.items = Objects.requireNonNull(items); + this.items = HelperValidationUtils.validateItems(items); } public AdvancedCommerceSubscriptionPriceChangeRequest storefront(String storefront) { @@ -89,7 +105,7 @@ public AdvancedCommerceSubscriptionPriceChangeRequest storefront(String storefro /** * The App Store storefront of the subscription. - * + * * @return storefront * @see storefront **/ @@ -103,13 +119,19 @@ public void setStorefront(String storefront) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionPriceChangeRequest that = (AdvancedCommerceSubscriptionPriceChangeRequest) o; - return Objects.equals(currency, that.currency) && - Objects.equals(items, that.items) && - Objects.equals(storefront, that.storefront); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionPriceChangeRequest advancedCommerceSubscriptionPriceChangeRequest = (AdvancedCommerceSubscriptionPriceChangeRequest) o; + return Objects.equals(this.currency, advancedCommerceSubscriptionPriceChangeRequest.currency) && + Objects.equals(this.items, advancedCommerceSubscriptionPriceChangeRequest.items) && + Objects.equals(this.storefront, advancedCommerceSubscriptionPriceChangeRequest.storefront); } @Override @@ -119,11 +141,11 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "currency='" + currency + '\'' + + return "AdvancedCommerceSubscriptionPriceChangeRequest{" + + "requestInfo=" + getRequestInfo() + + ", currency='" + currency + '\'' + ", items=" + items + - ", requestInfo=" + getRequestInfo() + ", storefront='" + storefront + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeResponse.java index 12e2b2a0..b2b84f9d 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionPriceChangeResponse.java @@ -2,19 +2,27 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * A response that contains signed JWS renewal and JWS transaction information after a subscription price change request. * * @see SubscriptionPriceChangeResponse - */ + **/ public class AdvancedCommerceSubscriptionPriceChangeResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceSubscriptionPriceChangeResponse() { super(); } - public AdvancedCommerceSubscriptionPriceChangeResponse(String signedRenewalInfo, String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceSubscriptionPriceChangeResponse( + @JsonProperty(value = "signedRenewalInfo", required = true) String signedRenewalInfo, + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(Objects.requireNonNull(signedRenewalInfo), Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +31,11 @@ protected AdvancedCommerceSubscriptionPriceChangeResponse self() { return this; } + @Override + public AdvancedCommerceSubscriptionPriceChangeResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionPriceChangeResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceSubscriptionPriceChangeResponse signedRenewalInfo(String signedRenewalInfo) { Objects.requireNonNull(signedRenewalInfo); @@ -47,11 +60,50 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JWS Compact Serialization format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + - "signedRenewalInfo='" + getSignedRenewalInfo() + - ", signedTransactionInfo='" + getSignedTransactionInfo() + + return "AdvancedCommerceSubscriptionPriceChangeResponse{" + + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateInAppRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateInAppRequest.java index bba13e23..cd81dbcd 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateInAppRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateInAppRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.ArrayList; @@ -12,7 +13,8 @@ * The request your app provides to reactivate a subscription that has automatic renewal turned off. * * @see SubscriptionReactivateInAppRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionReactivateInAppRequest extends AbstractAdvancedCommerceInAppRequest { private static final String OPERATION = "REACTIVATE_SUBSCRIPTION"; private static final String VERSION = "1"; @@ -45,14 +47,45 @@ protected AdvancedCommerceSubscriptionReactivateInAppRequest self() { return this; } + /** + * @return operation + * @see SubscriptionReactivateInAppRequest + **/ + @Override + public String getOperation() { + return super.getOperation(); + } + + /** + * A number that represents the version of the data structure or Advanced Commerce API. + * + * @return version + * @see version + **/ + @Override + public String getVersion() { + return super.getVersion(); + } + + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionReactivateInAppRequest items(List items) { - this.items = items; + this.items = items != null ? HelperValidationUtils.validateItems(items) : null; return this; } public AdvancedCommerceSubscriptionReactivateInAppRequest addItem(AdvancedCommerceSubscriptionReactivateItem item) { - Objects.requireNonNull(item); - if (this.items == null) { + Objects.requireNonNull(item); + if (this.items == null) { this.items = new ArrayList<>(); } this.items.add(item); @@ -60,6 +93,8 @@ public AdvancedCommerceSubscriptionReactivateInAppRequest addItem(AdvancedCommer } /** + * An item in a subscription to reactivate. + * * @return items * @see SubscriptionReactivateItem **/ @@ -68,7 +103,7 @@ public List getItems() { } public void setItems(List items) { - this.items = items; + this.items = items != null ? HelperValidationUtils.validateItems(items) : null; } public AdvancedCommerceSubscriptionReactivateInAppRequest storefront(String storefront) { @@ -77,6 +112,8 @@ public AdvancedCommerceSubscriptionReactivateInAppRequest storefront(String stor } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -94,6 +131,8 @@ public AdvancedCommerceSubscriptionReactivateInAppRequest transactionId(String t } /** + * A unique identifier that the App Store generates for a transaction. + * * @return transactionId * @see transactionId **/ @@ -107,11 +146,19 @@ public void setTransactionId(String transactionId) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - AdvancedCommerceSubscriptionReactivateInAppRequest that = (AdvancedCommerceSubscriptionReactivateInAppRequest) o; - return Objects.equals(items, that.items) && Objects.equals(storefront, that.storefront) && Objects.equals(transactionId, that.transactionId); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + if (!super.equals(o)) { + return false; + } + AdvancedCommerceSubscriptionReactivateInAppRequest advancedCommerceSubscriptionReactivateInAppRequest = (AdvancedCommerceSubscriptionReactivateInAppRequest) o; + return Objects.equals(this.items, advancedCommerceSubscriptionReactivateInAppRequest.items) && + Objects.equals(this.storefront, advancedCommerceSubscriptionReactivateInAppRequest.storefront) && + Objects.equals(this.transactionId, advancedCommerceSubscriptionReactivateInAppRequest.transactionId); } @Override @@ -121,11 +168,13 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "items=" + items + + return "AdvancedCommerceSubscriptionReactivateInAppRequest{" + + "operation='" + getOperation() + '\'' + + ", version='" + getVersion() + '\'' + ", requestInfo=" + getRequestInfo() + + ", items=" + items + ", storefront='" + storefront + '\'' + ", transactionId='" + transactionId + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateItem.java index 41df789a..f3505409 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionReactivateItem.java @@ -2,13 +2,15 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; + /** - * An item in a subscription to reactive. + * An item in a subscription to reactivate. * * @see SubscriptionReactivateItem - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionReactivateItem extends AbstractAdvancedCommerceBaseItem { - protected AdvancedCommerceSubscriptionReactivateItem() { super(); } @@ -18,14 +20,46 @@ public AdvancedCommerceSubscriptionReactivateItem(String sku) { } @Override - protected AbstractAdvancedCommerceBaseItem self() { + protected AdvancedCommerceSubscriptionReactivateItem self() { return this; } + @Override + public AdvancedCommerceSubscriptionReactivateItem sku(String sku) { + return (AdvancedCommerceSubscriptionReactivateItem) super.sku(sku); + } + + /** + * The SKU of the item to reactivate. + * + * @return SKU + * @see SKU + **/ + @Override + public String getSku() { + return super.getSku(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + - "sku='" + sku + '\'' + + return "AdvancedCommerceSubscriptionReactivateItem{" + + "sku='" + getSku() + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeRequest.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeRequest.java index 0a59d77b..adf8dc75 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeRequest.java @@ -2,6 +2,7 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Objects; @@ -10,7 +11,8 @@ * The request body you provide to terminate a subscription and all its items immediately. * * @see SubscriptionRevokeRequest - */ + **/ +@JsonInclude(JsonInclude.Include.NON_NULL) public class AdvancedCommerceSubscriptionRevokeRequest extends AdvancedCommerceRequest { private static final String SERIALIZED_NAME_REFUND_REASON = "refundReason"; private static final String SERIALIZED_NAME_REFUND_RISKING_PREFERENCE = "refundRiskingPreference"; @@ -18,7 +20,7 @@ public class AdvancedCommerceSubscriptionRevokeRequest extends AdvancedCommerceR private static final String SERIALIZED_NAME_STOREFRONT = "storefront"; @JsonProperty(value = SERIALIZED_NAME_REFUND_REASON, required = true) - private AdvancedCommerceRefundReason refundReason; + private String refundReason; @JsonProperty(value = SERIALIZED_NAME_REFUND_RISKING_PREFERENCE, required = true) private Boolean refundRiskingPreference; @JsonProperty(value = SERIALIZED_NAME_REFUND_TYPE, required = true) @@ -32,14 +34,26 @@ protected AdvancedCommerceSubscriptionRevokeRequest() { public AdvancedCommerceSubscriptionRevokeRequest( AdvancedCommerceRequestInfo requestInfo, - Boolean refundRiskingPreference, AdvancedCommerceRefundReason refundReason, - String refundType - ) { + Boolean refundRiskingPreference, + AdvancedCommerceRefundType refundType + ) { + super(requestInfo); + this.refundReason = Objects.requireNonNull(refundReason).getValue(); + this.refundRiskingPreference = Objects.requireNonNull(refundRiskingPreference); + this.refundType = Objects.requireNonNull(refundType).getValue(); + } + + public AdvancedCommerceSubscriptionRevokeRequest( + AdvancedCommerceRequestInfo requestInfo, + String rawRefundReason, + Boolean refundRiskingPreference, + String rawRefundType + ) { super(requestInfo); - this.refundReason = Objects.requireNonNull(refundReason); + this.refundReason = Objects.requireNonNull(rawRefundReason); this.refundRiskingPreference = Objects.requireNonNull(refundRiskingPreference); - this.refundType = Objects.requireNonNull(refundType); + this.refundType = Objects.requireNonNull(rawRefundType); } @Override @@ -47,21 +61,45 @@ protected AdvancedCommerceSubscriptionRevokeRequest self() { return this; } + /** + * The metadata to include in server requests. + * + * @return requestInfo + * @see RequestInfo + **/ + @Override + public AdvancedCommerceRequestInfo getRequestInfo() { + return super.getRequestInfo(); + } + public AdvancedCommerceSubscriptionRevokeRequest refundReason(AdvancedCommerceRefundReason refundReason) { - this.refundReason = Objects.requireNonNull(refundReason); + this.refundReason = Objects.requireNonNull(refundReason).getValue(); return this; } /** + * A reason to request a refund. + * * @return refundReason * @see refundReason **/ public AdvancedCommerceRefundReason getRefundReason() { + return AdvancedCommerceRefundReason.fromValue(refundReason); + } + + /** + * @see #getRefundReason() + **/ + public String getRawRefundReason() { return refundReason; } public void setRefundReason(AdvancedCommerceRefundReason refundReason) { - this.refundReason = Objects.requireNonNull(refundReason); + this.refundReason = Objects.requireNonNull(refundReason).getValue(); + } + + public void setRawRefundReason(String rawRefundReason) { + this.refundReason = Objects.requireNonNull(rawRefundReason); } public AdvancedCommerceSubscriptionRevokeRequest refundRiskingPreference(Boolean refundRiskingPreference) { @@ -70,6 +108,8 @@ public AdvancedCommerceSubscriptionRevokeRequest refundRiskingPreference(Boolean } /** + * A Boolean value that indicates whether the App Store asks you for consumption data to help inform the refund decision. + * * @return refundRiskingPreference * @see refundRiskingPreference **/ @@ -81,17 +121,32 @@ public void setRefundRiskingPreference(Boolean refundRiskingPreference) { this.refundRiskingPreference = Objects.requireNonNull(refundRiskingPreference); } - public AdvancedCommerceSubscriptionRevokeRequest refundType(String refundType) { - this.refundType = Objects.requireNonNull(refundType); + public AdvancedCommerceSubscriptionRevokeRequest refundType(AdvancedCommerceRefundType refundType) { + this.refundType = Objects.requireNonNull(refundType).getValue(); return this; } - public String getRefundType() { + /** + * @return refundType + * @see SubscriptionRevokeRequest + **/ + public AdvancedCommerceRefundType getRefundType() { + return AdvancedCommerceRefundType.fromValue(refundType); + } + + /** + * @see #getRefundType() + **/ + public String getRawRefundType() { return refundType; } - public void setRefundType(String refundType) { - this.refundType = Objects.requireNonNull(refundType); + public void setRefundType(AdvancedCommerceRefundType refundType) { + this.refundType = Objects.requireNonNull(refundType).getValue(); + } + + public void setRawRefundType(String rawRefundType) { + this.refundType = Objects.requireNonNull(rawRefundType); } public AdvancedCommerceSubscriptionRevokeRequest storefront(String storefront) { @@ -100,6 +155,8 @@ public AdvancedCommerceSubscriptionRevokeRequest storefront(String storefront) { } /** + * A three-letter code that represents the country or region associated with the App Store storefront. + * * @return storefront * @see storefront **/ @@ -113,17 +170,20 @@ public void setStorefront(String storefront) { @Override public boolean equals(Object o) { - if (this == o) + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; - if (!super.equals(o)) + } + if (!super.equals(o)) { return false; - AdvancedCommerceSubscriptionRevokeRequest that = (AdvancedCommerceSubscriptionRevokeRequest) o; - return Objects.equals(refundReason, that.refundReason) - && Objects.equals(refundRiskingPreference, that.refundRiskingPreference) - && Objects.equals(refundType, that.refundType) - && Objects.equals(storefront, that.storefront); + } + AdvancedCommerceSubscriptionRevokeRequest advancedCommerceSubscriptionRevokeRequest = (AdvancedCommerceSubscriptionRevokeRequest) o; + return Objects.equals(this.refundReason, advancedCommerceSubscriptionRevokeRequest.refundReason) && + Objects.equals(this.refundRiskingPreference, advancedCommerceSubscriptionRevokeRequest.refundRiskingPreference) && + Objects.equals(this.refundType, advancedCommerceSubscriptionRevokeRequest.refundType) && + Objects.equals(this.storefront, advancedCommerceSubscriptionRevokeRequest.storefront); } @Override @@ -133,12 +193,12 @@ public int hashCode() { @Override public String toString() { - return getClass().getSimpleName() + "{" + - "refundReason=" + refundReason + + return "AdvancedCommerceSubscriptionRevokeRequest{" + + "requestInfo=" + getRequestInfo() + + ", refundReason='" + refundReason + '\'' + ", refundRiskingPreference=" + refundRiskingPreference + ", refundType='" + refundType + '\'' + - ", requestInfo=" + getRequestInfo() + ", storefront='" + storefront + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeResponse.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeResponse.java index b570eafb..46f063d7 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceSubscriptionRevokeResponse.java @@ -2,19 +2,27 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; import java.util.Objects; /** * The response body for a successful revoke-subscription request. * * @see SubscriptionRevokeResponse - */ + **/ public class AdvancedCommerceSubscriptionRevokeResponse extends AbstractAdvancedCommerceResponse { protected AdvancedCommerceSubscriptionRevokeResponse() { super(); } - public AdvancedCommerceSubscriptionRevokeResponse(String signedRenewalInfo, String signedTransactionInfo) { + @JsonCreator + public AdvancedCommerceSubscriptionRevokeResponse( + @JsonProperty(value = "signedRenewalInfo", required = true) String signedRenewalInfo, + @JsonProperty(value = "signedTransactionInfo", required = true) String signedTransactionInfo + ) { super(Objects.requireNonNull(signedRenewalInfo), Objects.requireNonNull(signedTransactionInfo)); } @@ -23,6 +31,11 @@ protected AdvancedCommerceSubscriptionRevokeResponse self() { return this; } + @Override + public AdvancedCommerceSubscriptionRevokeResponse unknownFields(Map unknownFields) { + return (AdvancedCommerceSubscriptionRevokeResponse) super.unknownFields(unknownFields); + } + @Override public AdvancedCommerceSubscriptionRevokeResponse signedRenewalInfo(String signedRenewalInfo) { Objects.requireNonNull(signedRenewalInfo); @@ -47,11 +60,50 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { super.setSignedTransactionInfo(signedTransactionInfo); } + /** + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedRenewalInfo + * @see JWSRenewalInfo + **/ + @Override + public String getSignedRenewalInfo() { + return super.getSignedRenewalInfo(); + } + + /** + * Transaction information signed by the App Store, in JWS Compact Serialization format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + @Override + public String getSignedTransactionInfo() { + return super.getSignedTransactionInfo(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + @Override public String toString() { - return getClass().getSimpleName() + "{" + + return "AdvancedCommerceSubscriptionRevokeResponse{" + "signedRenewalInfo='" + getSignedRenewalInfo() + '\'' + ", signedTransactionInfo='" + getSignedTransactionInfo() + '\'' + + ", unknownFields=" + getUnknownFields() + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionInfo.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionInfo.java index 8b2a5a43..ee8c327b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionInfo.java @@ -5,15 +5,15 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /** * @see advancedCommerceTransactionInfo - */ + **/ public class AdvancedCommerceTransactionInfo { - private static final String SERIALIZED_NAME_DESCRIPTORS = "descriptors"; private static final String SERIALIZED_NAME_ESTIMATED_TAX = "estimatedTax"; private static final String SERIALIZED_NAME_ITEMS = "items"; @@ -84,9 +84,18 @@ public AdvancedCommerceTransactionInfo items(List(); + } + this.items.add(item); + return this; + } + /** * @return items - * @see advancedCommerceTransactionItem + * @see advancedCommerceTransactionItems **/ public List getItems() { return items; @@ -106,12 +115,12 @@ public AdvancedCommerceTransactionInfo period(AdvancedCommercePeriod period) { * @see advancedCommercePeriod **/ public AdvancedCommercePeriod getPeriod() { - return period != null ? AdvancedCommercePeriod.fromValue(period) : null; + return AdvancedCommercePeriod.fromValue(period); } /** * @see #getPeriod() - */ + **/ public String getRawPeriod() { return period; } @@ -197,6 +206,11 @@ public AdvancedCommerceTransactionInfo unknownFields(Map unknown return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -207,10 +221,22 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceTransactionInfo that = (AdvancedCommerceTransactionInfo) o; - return Objects.equals(descriptors, that.descriptors) && Objects.equals(estimatedTax, that.estimatedTax) && Objects.equals(items, that.items) && Objects.equals(period, that.period) && Objects.equals(requestReferenceId, that.requestReferenceId) && Objects.equals(taxCode, that.taxCode) && Objects.equals(taxExclusivePrice, that.taxExclusivePrice) && Objects.equals(taxRate, that.taxRate) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceTransactionInfo advancedCommerceTransactionInfo = (AdvancedCommerceTransactionInfo) o; + return Objects.equals(this.descriptors, advancedCommerceTransactionInfo.descriptors) && + Objects.equals(this.estimatedTax, advancedCommerceTransactionInfo.estimatedTax) && + Objects.equals(this.items, advancedCommerceTransactionInfo.items) && + Objects.equals(this.period, advancedCommerceTransactionInfo.period) && + Objects.equals(this.requestReferenceId, advancedCommerceTransactionInfo.requestReferenceId) && + Objects.equals(this.taxCode, advancedCommerceTransactionInfo.taxCode) && + Objects.equals(this.taxExclusivePrice, advancedCommerceTransactionInfo.taxExclusivePrice) && + Objects.equals(this.taxRate, advancedCommerceTransactionInfo.taxRate) && + Objects.equals(this.unknownFields, advancedCommerceTransactionInfo.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionItem.java b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionItem.java index ba3b415d..64dd9d55 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/AdvancedCommerceTransactionItem.java @@ -5,15 +5,15 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /** * @see advancedCommerceTransactionItem - */ + **/ public class AdvancedCommerceTransactionItem { - private static final String SERIALIZED_NAME_SKU = "SKU"; private static final String SERIALIZED_NAME_DESCRIPTION = "description"; private static final String SERIALIZED_NAME_DISPLAY_NAME = "displayName"; @@ -48,7 +48,7 @@ public AdvancedCommerceTransactionItem sku(String sku) { } /** - * @return sku + * @return SKU * @see advancedCommerceSKU **/ public String getSku() { @@ -132,6 +132,15 @@ public AdvancedCommerceTransactionItem refunds(List refu return this; } + public AdvancedCommerceTransactionItem addRefund(AdvancedCommerceRefund refund) { + Objects.requireNonNull(refund); + if (this.refunds == null) { + this.refunds = new ArrayList<>(); + } + this.refunds.add(refund); + return this; + } + /** * @return refunds * @see advancedCommerceRefunds @@ -150,6 +159,8 @@ public AdvancedCommerceTransactionItem revocationDate(Long revocationDate) { } /** + * The UNIX time, in milliseconds, that the App Store refunded the transaction or revoked it from Family Sharing. + * * @return revocationDate * @see revocationDate **/ @@ -166,6 +177,11 @@ public AdvancedCommerceTransactionItem unknownFields(Map unknown return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -176,10 +192,21 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AdvancedCommerceTransactionItem that = (AdvancedCommerceTransactionItem) o; - return Objects.equals(sku, that.sku) && Objects.equals(description, that.description) && Objects.equals(displayName, that.displayName) && Objects.equals(offer, that.offer) && Objects.equals(price, that.price) && Objects.equals(refunds, that.refunds) && Objects.equals(revocationDate, that.revocationDate) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AdvancedCommerceTransactionItem advancedCommerceTransactionItem = (AdvancedCommerceTransactionItem) o; + return Objects.equals(this.sku, advancedCommerceTransactionItem.sku) && + Objects.equals(this.description, advancedCommerceTransactionItem.description) && + Objects.equals(this.displayName, advancedCommerceTransactionItem.displayName) && + Objects.equals(this.offer, advancedCommerceTransactionItem.offer) && + Objects.equals(this.price, advancedCommerceTransactionItem.price) && + Objects.equals(this.refunds, advancedCommerceTransactionItem.refunds) && + Objects.equals(this.revocationDate, advancedCommerceTransactionItem.revocationDate) && + Objects.equals(this.unknownFields, advancedCommerceTransactionItem.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/AlternateProduct.java b/src/main/java/com/apple/itunes/storekit/model/AlternateProduct.java index c31aeda0..6a6e1683 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AlternateProduct.java +++ b/src/main/java/com/apple/itunes/storekit/model/AlternateProduct.java @@ -12,25 +12,30 @@ * A switch-plan message and product ID you provide in a real-time response to your Get Retention Message endpoint. * * @see alternateProduct - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class AlternateProduct { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; private static final String SERIALIZED_NAME_BILLING_PLAN_TYPE = "billingPlanType"; - @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER) + + @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER, required = true) private UUID messageIdentifier; - @JsonProperty(value = SERIALIZED_NAME_PRODUCT_ID) + @JsonProperty(value = SERIALIZED_NAME_PRODUCT_ID, required = true) private String productId; - @JsonProperty(value = SERIALIZED_NAME_BILLING_PLAN_TYPE) + @JsonProperty(SERIALIZED_NAME_BILLING_PLAN_TYPE) private String billingPlanType; + protected AlternateProduct() { + } - public AlternateProduct() { + public AlternateProduct(UUID messageIdentifier, String productId) { + this.messageIdentifier = Objects.requireNonNull(messageIdentifier); + this.productId = Objects.requireNonNull(productId); } public AlternateProduct messageIdentifier(UUID messageIdentifier) { - this.messageIdentifier = messageIdentifier; + this.messageIdentifier = Objects.requireNonNull(messageIdentifier); return this; } @@ -45,11 +50,11 @@ public UUID getMessageIdentifier() { } public void setMessageIdentifier(UUID messageIdentifier) { - this.messageIdentifier = messageIdentifier; + this.messageIdentifier = Objects.requireNonNull(messageIdentifier); } public AlternateProduct productId(String productId) { - this.productId = productId; + this.productId = Objects.requireNonNull(productId); return this; } @@ -64,7 +69,7 @@ public String getProductId() { } public void setProductId(String productId) { - this.productId = productId; + this.productId = Objects.requireNonNull(productId); } public AlternateProduct billingPlanType(BillingPlanType billingPlanType) { @@ -77,12 +82,12 @@ public AlternateProduct billingPlanType(BillingPlanType billingPlanType) { * @see billingPlanType **/ public BillingPlanType getBillingPlanType() { - return billingPlanType != null ? BillingPlanType.fromValue(billingPlanType) : null; + return BillingPlanType.fromValue(billingPlanType); } /** * @see #getBillingPlanType() - */ + **/ public String getRawBillingPlanType() { return billingPlanType; } @@ -97,12 +102,16 @@ public void setRawBillingPlanType(String rawBillingPlanType) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AlternateProduct that = (AlternateProduct) o; - return Objects.equals(messageIdentifier, that.messageIdentifier) && - Objects.equals(productId, that.productId) && - Objects.equals(billingPlanType, that.billingPlanType); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AlternateProduct alternateProduct = (AlternateProduct) o; + return Objects.equals(this.messageIdentifier, alternateProduct.messageIdentifier) && + Objects.equals(this.productId, alternateProduct.productId) && + Objects.equals(this.billingPlanType, alternateProduct.billingPlanType); } @Override @@ -118,4 +127,4 @@ public String toString() { ", billingPlanType='" + billingPlanType + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AppAccountTokenNullSerializer.java b/src/main/java/com/apple/itunes/storekit/model/AppAccountTokenNullSerializer.java index d1b5f443..bea1bd2b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AppAccountTokenNullSerializer.java +++ b/src/main/java/com/apple/itunes/storekit/model/AppAccountTokenNullSerializer.java @@ -1,3 +1,5 @@ +// Copyright (c) 2024 Apple Inc. Licensed under MIT License. + package com.apple.itunes.storekit.model; import com.fasterxml.jackson.core.JsonGenerator; diff --git a/src/main/java/com/apple/itunes/storekit/model/AppData.java b/src/main/java/com/apple/itunes/storekit/model/AppData.java index 795d4cd0..ec383928 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AppData.java +++ b/src/main/java/com/apple/itunes/storekit/model/AppData.java @@ -12,12 +12,13 @@ * The object that contains the app metadata and signed app transaction information. * * @see appData - */ + **/ public class AppData { private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; private static final String SERIALIZED_NAME_SIGNED_APP_TRANSACTION_INFO = "signedAppTransactionInfo"; + @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) private Long appAppleId; @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) @@ -29,7 +30,6 @@ public class AppData { @JsonAnySetter private Map unknownFields; - public AppData() { } @@ -83,12 +83,12 @@ public AppData environment(Environment environment) { * @see environment **/ public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + return Environment.fromValue(environment); } /** * @see #getEnvironment() - */ + **/ public String getRawEnvironment() { return environment; } @@ -126,10 +126,10 @@ public AppData unknownFields(Map unknownFields) { } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -169,4 +169,4 @@ public String toString() { ", unknownFields=" + unknownFields + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AppTransaction.java b/src/main/java/com/apple/itunes/storekit/model/AppTransaction.java index 1e1429ce..3d3769fa 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AppTransaction.java +++ b/src/main/java/com/apple/itunes/storekit/model/AppTransaction.java @@ -1,3 +1,5 @@ +// Copyright (c) 2023 Apple Inc. Licensed under MIT License. + package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; @@ -9,117 +11,100 @@ import java.util.UUID; /** - A decoded payload that contains app transaction information. - - @see AppTransaction - @see JWSAppTransactionDecodedPayload - */ + * A decoded payload that contains app transaction information. + * + * @see AppTransaction + * @see JWSAppTransactionDecodedPayload + **/ public class AppTransaction implements DecodedSignedData { - - private static final String SERIALIZED_NAME_RECEIPT_TYPE = "receiptType"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; + private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; + private static final String SERIALIZED_NAME_ORIGINAL_APPLICATION_VERSION = "originalApplicationVersion"; + private static final String SERIALIZED_NAME_ORIGINAL_PLATFORM = "originalPlatform"; + private static final String SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE = "originalPurchaseDate"; + private static final String SERIALIZED_NAME_PREORDER_DATE = "preorderDate"; + private static final String SERIALIZED_NAME_RECEIPT_CREATION_DATE = "receiptCreationDate"; + private static final String SERIALIZED_NAME_RECEIPT_TYPE = "receiptType"; + private static final String SERIALIZED_NAME_STORE_TYPE = "storeType"; private static final String SERIALIZED_NAME_APPLICATION_VERSION = "applicationVersion"; private static final String SERIALIZED_NAME_VERSION_EXTERNAL_IDENTIFIER = "versionExternalIdentifier"; - private static final String SERIALIZED_NAME_RECEIPT_CREATION_DATE = "receiptCreationDate"; - private static final String SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE = "originalPurchaseDate"; - private static final String SERIALIZED_NAME_ORIGINAL_APPLICATION_VERSION = "originalApplicationVersion"; private static final String SERIALIZED_NAME_DEVICE_VERIFICATION = "deviceVerification"; private static final String SERIALIZED_NAME_DEVICE_VERIFICATION_NONCE = "deviceVerificationNonce"; - private static final String SERIALIZED_NAME_PREORDER_DATE = "preorderDate"; - private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; - private static final String SERIALIZED_NAME_ORIGINAL_PLATFORM = "originalPlatform"; - @JsonProperty(SERIALIZED_NAME_RECEIPT_TYPE) - private String receiptType; @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) private Long appAppleId; + @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) + private String appTransactionId; @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) private String bundleId; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_APPLICATION_VERSION) + private String originalApplicationVersion; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_PLATFORM) + private String originalPlatform; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long originalPurchaseDate; + @JsonProperty(SERIALIZED_NAME_PREORDER_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long preorderDate; + @JsonProperty(SERIALIZED_NAME_RECEIPT_CREATION_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long receiptCreationDate; + @JsonProperty(SERIALIZED_NAME_RECEIPT_TYPE) + private String receiptType; + @JsonProperty(SERIALIZED_NAME_STORE_TYPE) + private String storeType; @JsonProperty(SERIALIZED_NAME_APPLICATION_VERSION) private String applicationVersion; @JsonProperty(SERIALIZED_NAME_VERSION_EXTERNAL_IDENTIFIER) private Long versionExternalIdentifier; - @JsonProperty(SERIALIZED_NAME_RECEIPT_CREATION_DATE) - @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) - private Long receiptCreationDate; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE) - @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) - private Long originalPurchaseDate; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_APPLICATION_VERSION) - private String originalApplicationVersion; @JsonProperty(SERIALIZED_NAME_DEVICE_VERIFICATION) private String deviceVerification; @JsonProperty(SERIALIZED_NAME_DEVICE_VERIFICATION_NONCE) private UUID deviceVerificationNonce; - @JsonProperty(SERIALIZED_NAME_PREORDER_DATE) - @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) - private Long preorderDate; - @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) - private String appTransactionId; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_PLATFORM) - private String originalPlatform; @JsonAnySetter private Map unknownFields; - /** - The date that the App Store signed the JWS app transaction. - - @see environment - */ - public Environment getReceiptType() { - return this.receiptType != null ? Environment.fromValue(this.receiptType) : null; + public AppTransaction() { } - /** - * @see #getReceiptType() - */ - public String getRawReceiptType() { - return this.receiptType; - } - - public void setReceiptType(Environment receiptType) { - this.receiptType = receiptType != null ? receiptType.getValue() : null; - } - - public void setRawReceiptType(String rawReceiptType) { - this.receiptType = rawReceiptType; - } - - public AppTransaction receiptType(Environment receiptType) { - this.receiptType = receiptType != null ? receiptType.getValue() : null; + public AppTransaction appAppleId(Long appAppleId) { + this.appAppleId = appAppleId; return this; } /** - The unique identifier the App Store uses to identify the app. - - @see appId - */ + * The unique identifier the App Store uses to identify the app. + * + * @return appAppleId + * @see appAppleId + **/ public Long getAppAppleId() { - return this.appAppleId; + return appAppleId; } public void setAppAppleId(Long appAppleId) { this.appAppleId = appAppleId; } - public AppTransaction appAppleId(Long appAppleId) { - this.appAppleId = appAppleId; + public AppTransaction appTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; return this; } /** - The bundle identifier that the app transaction applies to. - - @see bundleId - */ - public String getBundleId() { - return this.bundleId; + * The unique identifier of the app download transaction. + * + * @return appTransactionId + * @see appTransactionId + **/ + public String getAppTransactionId() { + return appTransactionId; } - public void setBundleId(String bundleId) { - this.bundleId = bundleId; + public void setAppTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; } public AppTransaction bundleId(String bundleId) { @@ -128,204 +113,271 @@ public AppTransaction bundleId(String bundleId) { } /** - The app version that the app transaction applies to. - - @see appVersion - */ - public String getApplicationVersion() { - return this.applicationVersion; + * The bundle identifier that the app transaction applies to. + * + * @return bundleId + * @see bundleId + **/ + public String getBundleId() { + return bundleId; } - public void setApplicationVersion(String applicationVersion) { - this.applicationVersion = applicationVersion; + public void setBundleId(String bundleId) { + this.bundleId = bundleId; } - public AppTransaction applicationVersion(String applicationVersion) { - this.applicationVersion = applicationVersion; + public AppTransaction originalApplicationVersion(String originalApplicationVersion) { + this.originalApplicationVersion = originalApplicationVersion; return this; } /** - The version external identifier of the app - - @see appVersionID - */ - public Long getVersionExternalIdentifier() { - return this.versionExternalIdentifier; + * The app version that the customer originally purchased from the App Store. + * + * @return originalApplicationVersion + * @see originalApplicationVersion + **/ + public String getOriginalApplicationVersion() { + return originalApplicationVersion; } - public void setVersionExternalIdentifier(Long versionExternalIdentifier) { - this.versionExternalIdentifier = versionExternalIdentifier; + public void setOriginalApplicationVersion(String originalApplicationVersion) { + this.originalApplicationVersion = originalApplicationVersion; } - public AppTransaction versionExternalIdentifier(Long versionExternalIdentifier) { - this.versionExternalIdentifier = versionExternalIdentifier; + public AppTransaction originalPlatform(PurchasePlatform originalPlatform) { + this.originalPlatform = originalPlatform != null ? originalPlatform.getValue() : null; return this; } /** - The date that the App Store signed the JWS app transaction. + * The platform on which the customer originally purchased the app. + * + * @return originalPlatform + * @see originalPlatform + **/ + public PurchasePlatform getOriginalPlatform() { + return PurchasePlatform.fromValue(originalPlatform); + } - @see receiptCreationDate - */ - public Long getReceiptCreationDate() { - return this.receiptCreationDate; + /** + * @see #getOriginalPlatform() + **/ + public String getRawOriginalPlatform() { + return originalPlatform; } - public void setReceiptCreationDate(Long receiptCreationDate) { - this.receiptCreationDate = receiptCreationDate; + public void setOriginalPlatform(PurchasePlatform originalPlatform) { + this.originalPlatform = originalPlatform != null ? originalPlatform.getValue() : null; } - public AppTransaction receiptCreationDate(Long receiptCreationDate) { - this.receiptCreationDate = receiptCreationDate; + public void setRawOriginalPlatform(String rawOriginalPlatform) { + this.originalPlatform = rawOriginalPlatform; + } + + public AppTransaction originalPurchaseDate(Long originalPurchaseDate) { + this.originalPurchaseDate = originalPurchaseDate; return this; } /** - The date the customer originally purchased the app from the App Store. - - @see originalPurchaseDate - */ + * The date the customer originally purchased the app from the App Store. + * + * @return originalPurchaseDate + * @see originalPurchaseDate + **/ public Long getOriginalPurchaseDate() { - return this.originalPurchaseDate; + return originalPurchaseDate; } public void setOriginalPurchaseDate(Long originalPurchaseDate) { this.originalPurchaseDate = originalPurchaseDate; } - public AppTransaction originalPurchaseDate(Long originalPurchaseDate) { - this.originalPurchaseDate = originalPurchaseDate; + public AppTransaction preorderDate(Long preorderDate) { + this.preorderDate = preorderDate; return this; } /** - The app version that the user originally purchased from the App Store. - - @see originalAppVersion - */ - public String getOriginalApplicationVersion() { - return this.originalApplicationVersion; + * The date the customer placed an order for the app before it’s available in the App Store. + * + * @return preorderDate + * @see preorderDate + **/ + public Long getPreorderDate() { + return preorderDate; } - public void setOriginalApplicationVersion(String originalApplicationVersion) { - this.originalApplicationVersion = originalApplicationVersion; + public void setPreorderDate(Long preorderDate) { + this.preorderDate = preorderDate; } - public AppTransaction originalApplicationVersion(String originalApplicationVersion) { - this.originalApplicationVersion = originalApplicationVersion; + public AppTransaction receiptCreationDate(Long receiptCreationDate) { + this.receiptCreationDate = receiptCreationDate; return this; } /** - The Base64 device verification value to use to verify whether the app transaction belongs to the device. - - @see deviceVerification - */ - public String getDeviceVerification() { - return this.deviceVerification; + * The date that the App Store signed the JWS app transaction. + * + * @return receiptCreationDate + * @see receiptCreationDate + **/ + public Long getReceiptCreationDate() { + return receiptCreationDate; } - - public void setDeviceVerification(String deviceVerification) { - this.deviceVerification = deviceVerification; + + public void setReceiptCreationDate(Long receiptCreationDate) { + this.receiptCreationDate = receiptCreationDate; } - - public AppTransaction deviceVerification(String deviceVerification) { - this.deviceVerification = deviceVerification; + + public AppTransaction receiptType(Environment receiptType) { + this.receiptType = receiptType != null ? receiptType.getValue() : null; return this; } /** - The UUID used to compute the device verification value. + * The server environment, production or sandbox, that signed the app transaction. + * + * @return receiptType + * @see environment + **/ + public Environment getReceiptType() { + return Environment.fromValue(receiptType); + } - @see deviceVerificationNonce - */ - public UUID getDeviceVerificationNonce() { - return deviceVerificationNonce; + /** + * @see #getReceiptType() + **/ + public String getRawReceiptType() { + return receiptType; } - - public void setDeviceVerificationNonce(UUID deviceVerificationNonce) { - this.deviceVerificationNonce = deviceVerificationNonce; + + public void setReceiptType(Environment receiptType) { + this.receiptType = receiptType != null ? receiptType.getValue() : null; } - - public AppTransaction deviceVerificationNonce(UUID deviceVerificationNonce) { - this.deviceVerificationNonce = deviceVerificationNonce; + + public void setRawReceiptType(String rawReceiptType) { + this.receiptType = rawReceiptType; + } + + public AppTransaction storeType(StoreType storeType) { + this.storeType = storeType != null ? storeType.getValue() : null; return this; } - /** - The date the customer placed an order for the app before it’s available in the App Store. + * The store the customer obtained the app from. + * + * @return storeType + * @see storeType + **/ + public StoreType getStoreType() { + return StoreType.fromValue(storeType); + } - @see preorderDate - */ - public Long getPreorderDate() { - return preorderDate; + /** + * @see #getStoreType() + **/ + public String getRawStoreType() { + return storeType; } - - public void setPreorderDate(Long preorderDate) { - this.preorderDate = preorderDate; + + public void setStoreType(StoreType storeType) { + this.storeType = storeType != null ? storeType.getValue() : null; } - - public AppTransaction preorderDate(Long preorderDate) { - this.preorderDate = preorderDate; + + public void setRawStoreType(String rawStoreType) { + this.storeType = rawStoreType; + } + + public AppTransaction applicationVersion(String applicationVersion) { + this.applicationVersion = applicationVersion; return this; } /** - * The unique identifier of the app download transaction. + * The app version that the app transaction applies to. * - * @return appTransactionId - * @see appTransactionId + * @return applicationVersion + * @see appVersion **/ - public String getAppTransactionId() { - return this.appTransactionId; + public String getApplicationVersion() { + return applicationVersion; } - public void setAppTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; + public void setApplicationVersion(String applicationVersion) { + this.applicationVersion = applicationVersion; } - public AppTransaction appTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; + public AppTransaction versionExternalIdentifier(Long versionExternalIdentifier) { + this.versionExternalIdentifier = versionExternalIdentifier; return this; } - public AppTransaction originalPlatform(PurchasePlatform originalPlatform) { - this.originalPlatform = originalPlatform != null ? originalPlatform.getValue() : null; + /** + * The number that the App Store uses to uniquely identify the version of the app. + * + * @return versionExternalIdentifier + * @see appVersionID + **/ + public Long getVersionExternalIdentifier() { + return versionExternalIdentifier; + } + + public void setVersionExternalIdentifier(Long versionExternalIdentifier) { + this.versionExternalIdentifier = versionExternalIdentifier; + } + + public AppTransaction deviceVerification(String deviceVerification) { + this.deviceVerification = deviceVerification; return this; } /** - * The platform on which the customer originally purchased the app. + * The device verification value to use to verify whether the app transaction belongs to the device. * - * @return originalPlatform - * @see originalPlatform + * @return deviceVerification + * @see deviceVerification **/ - public PurchasePlatform getOriginalPlatform() { - return originalPlatform != null ? PurchasePlatform.fromValue(originalPlatform) : null; + public String getDeviceVerification() { + return deviceVerification; + } + + public void setDeviceVerification(String deviceVerification) { + this.deviceVerification = deviceVerification; + } + + public AppTransaction deviceVerificationNonce(UUID deviceVerificationNonce) { + this.deviceVerificationNonce = deviceVerificationNonce; + return this; } /** - * @see #getOriginalPlatform() - */ - public String getRawOriginalPlatform() { - return originalPlatform; + * The UUID used to compute the device verification value. + * + * @return deviceVerificationNonce + * @see deviceVerificationNonce + **/ + public UUID getDeviceVerificationNonce() { + return deviceVerificationNonce; } - public void setOriginalPlatform(PurchasePlatform originalPlatform) { - this.originalPlatform = originalPlatform != null ? originalPlatform.getValue() : null; + public void setDeviceVerificationNonce(UUID deviceVerificationNonce) { + this.deviceVerificationNonce = deviceVerificationNonce; } - public void setRawOriginalPlatform(String rawOriginalPlatform) { - this.originalPlatform = rawOriginalPlatform; + public AppTransaction unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -334,46 +386,59 @@ public void setUnknownFields(Map unknownFields) { this.unknownFields = unknownFields; } - public AppTransaction unknownFields(Map unknownFields) { - this.unknownFields = unknownFields; - return this; - } - public Long getSignedDate() { return getReceiptCreationDate(); } @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AppTransaction that = (AppTransaction) o; - return Objects.equals(receiptType, that.receiptType) && Objects.equals(appAppleId, that.appAppleId) && Objects.equals(bundleId, that.bundleId) && Objects.equals(applicationVersion, that.applicationVersion) && Objects.equals(versionExternalIdentifier, that.versionExternalIdentifier) && Objects.equals(receiptCreationDate, that.receiptCreationDate) && Objects.equals(originalPurchaseDate, that.originalPurchaseDate) && Objects.equals(originalApplicationVersion, that.originalApplicationVersion) && Objects.equals(deviceVerification, that.deviceVerification) && Objects.equals(deviceVerificationNonce, that.deviceVerificationNonce) && Objects.equals(preorderDate, that.preorderDate) && Objects.equals(appTransactionId, that.appTransactionId) && Objects.equals(originalPlatform, that.originalPlatform) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AppTransaction appTransaction = (AppTransaction) o; + return Objects.equals(this.appAppleId, appTransaction.appAppleId) && + Objects.equals(this.appTransactionId, appTransaction.appTransactionId) && + Objects.equals(this.bundleId, appTransaction.bundleId) && + Objects.equals(this.originalApplicationVersion, appTransaction.originalApplicationVersion) && + Objects.equals(this.originalPlatform, appTransaction.originalPlatform) && + Objects.equals(this.originalPurchaseDate, appTransaction.originalPurchaseDate) && + Objects.equals(this.preorderDate, appTransaction.preorderDate) && + Objects.equals(this.receiptCreationDate, appTransaction.receiptCreationDate) && + Objects.equals(this.receiptType, appTransaction.receiptType) && + Objects.equals(this.storeType, appTransaction.storeType) && + Objects.equals(this.applicationVersion, appTransaction.applicationVersion) && + Objects.equals(this.versionExternalIdentifier, appTransaction.versionExternalIdentifier) && + Objects.equals(this.deviceVerification, appTransaction.deviceVerification) && + Objects.equals(this.deviceVerificationNonce, appTransaction.deviceVerificationNonce) && + Objects.equals(this.unknownFields, appTransaction.unknownFields); } @Override public int hashCode() { - return Objects.hash(receiptType, appAppleId, bundleId, applicationVersion, versionExternalIdentifier, receiptCreationDate, originalPurchaseDate, originalApplicationVersion, deviceVerification, deviceVerificationNonce, preorderDate, appTransactionId, originalPlatform, unknownFields); + return Objects.hash(appAppleId, appTransactionId, bundleId, originalApplicationVersion, originalPlatform, originalPurchaseDate, preorderDate, receiptCreationDate, receiptType, storeType, applicationVersion, versionExternalIdentifier, deviceVerification, deviceVerificationNonce, unknownFields); } @Override public String toString() { return "AppTransaction{" + - "receiptType='" + receiptType + '\'' + - ", appAppleId=" + appAppleId + + "appAppleId=" + appAppleId + + ", appTransactionId='" + appTransactionId + '\'' + ", bundleId='" + bundleId + '\'' + + ", originalApplicationVersion='" + originalApplicationVersion + '\'' + + ", originalPlatform='" + originalPlatform + '\'' + + ", originalPurchaseDate=" + originalPurchaseDate + + ", preorderDate=" + preorderDate + + ", receiptCreationDate=" + receiptCreationDate + + ", receiptType='" + receiptType + '\'' + + ", storeType='" + storeType + '\'' + ", applicationVersion='" + applicationVersion + '\'' + ", versionExternalIdentifier=" + versionExternalIdentifier + - ", receiptCreationDate=" + receiptCreationDate + - ", originalPurchaseDate=" + originalPurchaseDate + - ", originalApplicationVersion='" + originalApplicationVersion + '\'' + ", deviceVerification='" + deviceVerification + '\'' + ", deviceVerificationNonce=" + deviceVerificationNonce + - ", preorderDate=" + preorderDate + - ", appTransactionId='" + appTransactionId + '\'' + - ", originalPlatform='" + originalPlatform + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/AppTransactionInfoResponse.java b/src/main/java/com/apple/itunes/storekit/model/AppTransactionInfoResponse.java index 3af17c76..df22bd08 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AppTransactionInfoResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/AppTransactionInfoResponse.java @@ -12,7 +12,7 @@ * A response that contains signed app transaction information for a customer. * * @see AppTransactionInfoResponse - */ + **/ public class AppTransactionInfoResponse { private static final String SERIALIZED_NAME_SIGNED_APP_TRANSACTION_INFO = "signedAppTransactionInfo"; @@ -31,7 +31,7 @@ public AppTransactionInfoResponse signedAppTransactionInfo(String signedAppTrans /** * A customer’s app transaction information, signed by Apple, in JSON Web Signature (JWS) format. - * + * * @return signedAppTransactionInfo * @see JWSAppTransaction **/ @@ -49,10 +49,10 @@ public AppTransactionInfoResponse unknownFields(Map unknownField } /** - * Fields that are not recognized for this object. - * - * @return A map of JSON keys to objects. - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -69,9 +69,9 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - AppTransactionInfoResponse that = (AppTransactionInfoResponse) o; - return Objects.equals(this.signedAppTransactionInfo, that.signedAppTransactionInfo) && - Objects.equals(this.unknownFields, that.unknownFields); + AppTransactionInfoResponse appTransactionInfoResponse = (AppTransactionInfoResponse) o; + return Objects.equals(this.signedAppTransactionInfo, appTransactionInfoResponse.signedAppTransactionInfo) && + Objects.equals(this.unknownFields, appTransactionInfoResponse.unknownFields); } @Override @@ -86,4 +86,4 @@ public String toString() { ", unknownFields=" + unknownFields + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/AutoRenewStatus.java b/src/main/java/com/apple/itunes/storekit/model/AutoRenewStatus.java index 180e8785..ee8946b2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/AutoRenewStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/AutoRenewStatus.java @@ -8,10 +8,16 @@ * The renewal status for an auto-renewable subscription. * * @see autoRenewStatus - */ + **/ public enum AutoRenewStatus { + /** + * Automatic renewal is off. + **/ OFF(0), + /** + * Automatic renewal is on. + **/ ON(1); private final Integer value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/BillingPlanType.java b/src/main/java/com/apple/itunes/storekit/model/BillingPlanType.java index 1c558dad..854ac39f 100644 --- a/src/main/java/com/apple/itunes/storekit/model/BillingPlanType.java +++ b/src/main/java/com/apple/itunes/storekit/model/BillingPlanType.java @@ -6,7 +6,7 @@ /** * @see billingPlanType - */ + **/ public enum BillingPlanType { BILLED_UPFRONT("BILLED_UPFRONT"), diff --git a/src/main/java/com/apple/itunes/storekit/model/BulletPoint.java b/src/main/java/com/apple/itunes/storekit/model/BulletPoint.java index a86d4087..d51fc453 100644 --- a/src/main/java/com/apple/itunes/storekit/model/BulletPoint.java +++ b/src/main/java/com/apple/itunes/storekit/model/BulletPoint.java @@ -12,50 +12,57 @@ * The text and its bullet-point image to include in a retention message’s bulleted list. * * @see BulletPoint - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class BulletPoint { - private static final String SERIALIZED_NAME_TEXT = "text"; - private static final String SERIALIZED_NAME_IMAGE_IDENTIFIER = "imageIdentifier"; private static final String SERIALIZED_NAME_ALT_TEXT = "altText"; - @JsonProperty(value = SERIALIZED_NAME_TEXT, required = true) - private String text; - @JsonProperty(value = SERIALIZED_NAME_IMAGE_IDENTIFIER, required = true) - private UUID imageIdentifier; + private static final String SERIALIZED_NAME_IMAGE_IDENTIFIER = "imageIdentifier"; + private static final String SERIALIZED_NAME_TEXT = "text"; + @JsonProperty(value = SERIALIZED_NAME_ALT_TEXT, required = true) private String altText; + @JsonProperty(value = SERIALIZED_NAME_IMAGE_IDENTIFIER, required = true) + private UUID imageIdentifier; + @JsonProperty(value = SERIALIZED_NAME_TEXT, required = true) + private String text; - private static final int MAXIMUM_TEXT_LENGTH = 66; private static final int MAXIMUM_ALT_TEXT_LENGTH = 150; + private static final int MAXIMUM_TEXT_LENGTH = 66; protected BulletPoint() { } - public BulletPoint(String text, - UUID imageIdentifier, - String altText) { + public BulletPoint(String text, UUID imageIdentifier, String altText) { this.text = validateText(text); this.imageIdentifier = Objects.requireNonNull(imageIdentifier); this.altText = validateAltText(altText); } - public BulletPoint text(String text) { - this.text = validateText(text); + public BulletPoint altText(String altText) { + this.altText = validateAltText(altText); return this; } /** - * The text of the individual bullet point. + * The alternative text you provide for the corresponding image of the bullet point. * - * @return text - * @see bulletPointText + * @return altText + * @see altText **/ - public String getText() { - return text; + public String getAltText() { + return altText; } - public void setText(String text) { - this.text = validateText(text); + public void setAltText(String altText) { + this.altText = validateAltText(altText); + } + + private String validateAltText(String altText) { + Objects.requireNonNull(altText); + if (altText.length() > MAXIMUM_ALT_TEXT_LENGTH) { + throw new IllegalArgumentException("altText length longer than maximum allowed"); + } + return altText; } public BulletPoint imageIdentifier(UUID imageIdentifier) { @@ -74,26 +81,26 @@ public UUID getImageIdentifier() { } public void setImageIdentifier(UUID imageIdentifier) { - this.imageIdentifier = imageIdentifier; + this.imageIdentifier = Objects.requireNonNull(imageIdentifier); } - public BulletPoint altText(String altText) { - this.altText = validateAltText(altText); + public BulletPoint text(String text) { + this.text = validateText(text); return this; } /** - * The alternative text you provide for the corresponding image of the bullet point. + * The text of the individual bullet point. * - * @return altText - * @see altText + * @return text + * @see bulletPointText **/ - public String getAltText() { - return altText; + public String getText() { + return text; } - public void setAltText(String altText) { - this.altText = validateAltText(altText); + public void setText(String text) { + this.text = validateText(text); } private String validateText(String text) { @@ -104,14 +111,6 @@ private String validateText(String text) { return text; } - private String validateAltText(String altText) { - Objects.requireNonNull(altText); - if (altText.length() > MAXIMUM_ALT_TEXT_LENGTH) { - throw new IllegalArgumentException("altText length longer than maximum allowed"); - } - return altText; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -121,22 +120,22 @@ public boolean equals(Object o) { return false; } BulletPoint bulletPoint = (BulletPoint) o; - return Objects.equals(this.text, bulletPoint.text) && + return Objects.equals(this.altText, bulletPoint.altText) && Objects.equals(this.imageIdentifier, bulletPoint.imageIdentifier) && - Objects.equals(this.altText, bulletPoint.altText); + Objects.equals(this.text, bulletPoint.text); } @Override public int hashCode() { - return Objects.hash(text, imageIdentifier, altText); + return Objects.hash(altText, imageIdentifier, text); } @Override public String toString() { return "BulletPoint{" + - "text='" + text + '\'' + + "altText='" + altText + '\'' + ", imageIdentifier=" + imageIdentifier + - ", altText='" + altText + '\'' + + ", text='" + text + '\'' + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/CheckTestNotificationResponse.java b/src/main/java/com/apple/itunes/storekit/model/CheckTestNotificationResponse.java index 61b9af56..7194ec78 100644 --- a/src/main/java/com/apple/itunes/storekit/model/CheckTestNotificationResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/CheckTestNotificationResponse.java @@ -5,65 +5,75 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; /** - * A response that contains the contents of the test notification sent by the App Store server and the result from your server. + * A response that contains the contents of the App Store server’s test notification and the result from your server. * * @see CheckTestNotificationResponse - */ + **/ public class CheckTestNotificationResponse { - private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; private static final String SERIALIZED_NAME_SEND_ATTEMPTS = "sendAttempts"; - @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) - private String signedPayload; + private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; + @JsonProperty(SERIALIZED_NAME_SEND_ATTEMPTS) private List sendAttempts; + @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) + private String signedPayload; @JsonAnySetter private Map unknownFields; - public CheckTestNotificationResponse() { } - public CheckTestNotificationResponse signedPayload(String signedPayload) { - this.signedPayload = signedPayload; + public CheckTestNotificationResponse sendAttempts(List sendAttempts) { + this.sendAttempts = sendAttempts; + return this; + } + + public CheckTestNotificationResponse addSendAttempt(SendAttemptItem sendAttempt) { + Objects.requireNonNull(sendAttempt); + if (this.sendAttempts == null) { + this.sendAttempts = new ArrayList<>(); + } + this.sendAttempts.add(sendAttempt); return this; } /** - * A cryptographically signed payload, in JSON Web Signature (JWS) format, containing the response body for a version 2 notification. + * An array of information the App Store server records for its attempts to send the TEST notification to your server. * - * @return signedPayload - * @see signedPayload + * @return sendAttempts + * @see sendAttemptItem **/ - public String getSignedPayload() { - return signedPayload; + public List getSendAttempts() { + return sendAttempts; } - public void setSignedPayload(String signedPayload) { - this.signedPayload = signedPayload; + public void setSendAttempts(List sendAttempts) { + this.sendAttempts = sendAttempts; } - public CheckTestNotificationResponse sendAttempts(List sendAttempts) { - this.sendAttempts = sendAttempts; + public CheckTestNotificationResponse signedPayload(String signedPayload) { + this.signedPayload = signedPayload; return this; } /** - * An array of information the App Store server records for its attempts to send the TEST notification to your server. The array may contain a maximum of six sendAttemptItem objects. + * The signed payload, in JWS format, that contains the TEST notification that the App Store server sent to your server. * - * @return sendAttempts - * @see sendAttemptItem + * @return signedPayload + * @see signedPayload **/ - public List getSendAttempts() { - return sendAttempts; + public String getSignedPayload() { + return signedPayload; } - public void setSendAttempts(List sendAttempts) { - this.sendAttempts = sendAttempts; + public void setSignedPayload(String signedPayload) { + this.signedPayload = signedPayload; } public CheckTestNotificationResponse unknownFields(Map unknownFields) { @@ -72,10 +82,10 @@ public CheckTestNotificationResponse unknownFields(Map unknownFi } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -93,23 +103,22 @@ public boolean equals(Object o) { return false; } CheckTestNotificationResponse checkTestNotificationResponse = (CheckTestNotificationResponse) o; - return Objects.equals(this.signedPayload, checkTestNotificationResponse.signedPayload) && - Objects.equals(this.sendAttempts, checkTestNotificationResponse.sendAttempts) && + return Objects.equals(this.sendAttempts, checkTestNotificationResponse.sendAttempts) && + Objects.equals(this.signedPayload, checkTestNotificationResponse.signedPayload) && Objects.equals(this.unknownFields, checkTestNotificationResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(signedPayload, sendAttempts, unknownFields); + return Objects.hash(sendAttempts, signedPayload, unknownFields); } @Override public String toString() { return "CheckTestNotificationResponse{" + - "signedPayload='" + signedPayload + '\'' + - ", sendAttempts=" + sendAttempts + + "sendAttempts=" + sendAttempts + + ", signedPayload='" + signedPayload + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequest.java b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequest.java index cb67c447..8a06c757 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequest.java @@ -11,7 +11,7 @@ * The request body that contains consumption information for an In-App Purchase. * * @see ConsumptionRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class ConsumptionRequest { private static final String SERIALIZED_NAME_CUSTOMER_CONSENTED = "customerConsented"; @@ -21,7 +21,7 @@ public class ConsumptionRequest { private static final String SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED = "sampleContentProvided"; @JsonProperty(value = SERIALIZED_NAME_CUSTOMER_CONSENTED, required = true) - private boolean customerConsented; + private Boolean customerConsented; @JsonProperty(SERIALIZED_NAME_CONSUMPTION_PERCENTAGE) private Integer consumptionPercentage; @JsonProperty(value = SERIALIZED_NAME_DELIVERY_STATUS, required = true) @@ -29,49 +29,52 @@ public class ConsumptionRequest { @JsonProperty(SERIALIZED_NAME_REFUND_PREFERENCE) private String refundPreference; @JsonProperty(value = SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED, required = true) - private boolean sampleContentProvided; + private Boolean sampleContentProvided; + + private static final int MINIMUM_CONSUMPTION_PERCENTAGE = 0; + private static final int MAXIMUM_CONSUMPTION_PERCENTAGE = 100000; protected ConsumptionRequest() { } - public ConsumptionRequest(boolean customerConsented, DeliveryStatus deliveryStatus, boolean sampleContentProvided) { - this.customerConsented = customerConsented; + public ConsumptionRequest(Boolean customerConsented, DeliveryStatus deliveryStatus, Boolean sampleContentProvided) { + this.customerConsented = Objects.requireNonNull(customerConsented); this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); - this.sampleContentProvided = sampleContentProvided; + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); } - public ConsumptionRequest(boolean customerConsented, String rawDeliveryStatus, boolean sampleContentProvided) { - this.customerConsented = customerConsented; + public ConsumptionRequest(Boolean customerConsented, String rawDeliveryStatus, Boolean sampleContentProvided) { + this.customerConsented = Objects.requireNonNull(customerConsented); this.deliveryStatus = Objects.requireNonNull(rawDeliveryStatus); - this.sampleContentProvided = sampleContentProvided; + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); } - public ConsumptionRequest customerConsented(boolean customerConsented) { - this.customerConsented = customerConsented; + public ConsumptionRequest customerConsented(Boolean customerConsented) { + this.customerConsented = Objects.requireNonNull(customerConsented); return this; } /** - * A Boolean value that indicates whether the customer consented to provide consumption data to the App Store. + * A Boolean value of true or false that indicates whether the customer consented to provide consumption data. * * @return customerConsented * @see customerConsented **/ - public boolean getCustomerConsented() { + public Boolean getCustomerConsented() { return customerConsented; } - public void setCustomerConsented(boolean customerConsented) { - this.customerConsented = customerConsented; + public void setCustomerConsented(Boolean customerConsented) { + this.customerConsented = Objects.requireNonNull(customerConsented); } public ConsumptionRequest consumptionPercentage(Integer consumptionPercentage) { - this.consumptionPercentage = consumptionPercentage; + this.consumptionPercentage = validateConsumptionPercentage(consumptionPercentage); return this; } /** - * An integer that indicates the percentage, in milliunits, of the In-App Purchase the customer consumed. + * An integer that indicates the percentage of the In-App Purchase the customer consumed, in milliunits. * * @return consumptionPercentage * @see consumptionPercentage @@ -81,7 +84,14 @@ public Integer getConsumptionPercentage() { } public void setConsumptionPercentage(Integer consumptionPercentage) { - this.consumptionPercentage = consumptionPercentage; + this.consumptionPercentage = validateConsumptionPercentage(consumptionPercentage); + } + + private Integer validateConsumptionPercentage(Integer consumptionPercentage) { + if (consumptionPercentage != null && (consumptionPercentage < MINIMUM_CONSUMPTION_PERCENTAGE || consumptionPercentage > MAXIMUM_CONSUMPTION_PERCENTAGE)) { + throw new IllegalArgumentException("consumptionPercentage must be between " + MINIMUM_CONSUMPTION_PERCENTAGE + " and " + MAXIMUM_CONSUMPTION_PERCENTAGE); + } + return consumptionPercentage; } public ConsumptionRequest deliveryStatus(DeliveryStatus deliveryStatus) { @@ -90,7 +100,7 @@ public ConsumptionRequest deliveryStatus(DeliveryStatus deliveryStatus) { } /** - * A value that indicates whether the app successfully delivered an in-app purchase that works properly. + * A value that indicates whether the app successfully delivered an In-App Purchase that works properly. * * @return deliveryStatus * @see deliveryStatus @@ -101,13 +111,13 @@ public DeliveryStatus getDeliveryStatus() { /** * @see #getDeliveryStatus() - */ + **/ public String getRawDeliveryStatus() { return deliveryStatus; } public void setDeliveryStatus(DeliveryStatus deliveryStatus) { - this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); + this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); } public void setRawDeliveryStatus(String rawDeliveryStatus) { @@ -120,47 +130,47 @@ public ConsumptionRequest refundPreference(RefundPreference refundPreference) { } /** - * A value that indicates your preferred outcome for the refund request. + * A value that indicates your preference, based on your operational logic, as to whether the App Store should grant the refund. * * @return refundPreference * @see refundPreference **/ public RefundPreference getRefundPreference() { - return refundPreference != null ? RefundPreference.fromValue(refundPreference) : null; + return RefundPreference.fromValue(refundPreference); } /** * @see #getRefundPreference() - */ + **/ public String getRawRefundPreference() { return refundPreference; } public void setRefundPreference(RefundPreference refundPreference) { - this.refundPreference = Objects.requireNonNull(refundPreference).getValue(); + this.refundPreference = refundPreference != null ? refundPreference.getValue() : null; } public void setRawRefundPreference(String rawRefundPreference) { - this.refundPreference = Objects.requireNonNull(rawRefundPreference); + this.refundPreference = rawRefundPreference; } - public ConsumptionRequest sampleContentProvided(boolean sampleContentProvided) { - this.sampleContentProvided = sampleContentProvided; + public ConsumptionRequest sampleContentProvided(Boolean sampleContentProvided) { + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); return this; } /** - * A Boolean value that indicates whether you provided, prior to its purchase, a free sample or trial of the content, or information about its functionality. + * A Boolean value of true or false that indicates whether you provided, prior to its purchase, a free sample or trial of the content, or information about its functionality. * * @return sampleContentProvided * @see sampleContentProvided **/ - public boolean getSampleContentProvided() { + public Boolean getSampleContentProvided() { return sampleContentProvided; } - public void setSampleContentProvided(boolean sampleContentProvided) { - this.sampleContentProvided = sampleContentProvided; + public void setSampleContentProvided(Boolean sampleContentProvided) { + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); } @Override @@ -172,11 +182,11 @@ public boolean equals(Object o) { return false; } ConsumptionRequest consumptionRequest = (ConsumptionRequest) o; - return (this.customerConsented == consumptionRequest.customerConsented) && + return Objects.equals(this.customerConsented, consumptionRequest.customerConsented) && Objects.equals(this.consumptionPercentage, consumptionRequest.consumptionPercentage) && Objects.equals(this.deliveryStatus, consumptionRequest.deliveryStatus) && Objects.equals(this.refundPreference, consumptionRequest.refundPreference) && - (this.sampleContentProvided == consumptionRequest.sampleContentProvided); + Objects.equals(this.sampleContentProvided, consumptionRequest.sampleContentProvided); } @Override @@ -189,8 +199,8 @@ public String toString() { return "ConsumptionRequest{" + "customerConsented=" + customerConsented + ", consumptionPercentage=" + consumptionPercentage + - ", deliveryStatus=" + deliveryStatus + - ", refundPreference=" + refundPreference + + ", deliveryStatus='" + deliveryStatus + '\'' + + ", refundPreference='" + refundPreference + '\'' + ", sampleContentProvided=" + sampleContentProvided + '}'; } diff --git a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestReason.java b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestReason.java index 6c7e3d66..27d17c0e 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestReason.java @@ -8,13 +8,28 @@ * The customer-provided reason for a refund request. * * @see consumptionRequestReason - */ + **/ public enum ConsumptionRequestReason { + /** + * The customer didn’t intend to make the in-app purchase. + **/ UNINTENDED_PURCHASE("UNINTENDED_PURCHASE"), + /** + * The customer had issues with receiving or using the in-app purchase. + **/ FULFILLMENT_ISSUE("FULFILLMENT_ISSUE"), + /** + * The customer wasn’t satisfied with the in-app purchase. + **/ UNSATISFIED_WITH_PURCHASE("UNSATISFIED_WITH_PURCHASE"), + /** + * The customer requested a refund based on a legal reason. + **/ LEGAL("LEGAL"), + /** + * The customer requested a refund for other reasons. + **/ OTHER("OTHER"); private final String value; @@ -42,4 +57,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestV1.java b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestV1.java index 91f3174a..a5c52f4c 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestV1.java +++ b/src/main/java/com/apple/itunes/storekit/model/ConsumptionRequestV1.java @@ -14,73 +14,155 @@ * * @see ConsumptionRequestV1 * @deprecated Use {@link ConsumptionRequest} instead. - */ + **/ @Deprecated @JsonInclude(JsonInclude.Include.NON_NULL) public class ConsumptionRequestV1 { - private static final String SERIALIZED_NAME_CUSTOMER_CONSENTED = "customerConsented"; + private static final String SERIALIZED_NAME_ACCOUNT_TENURE = "accountTenure"; + private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; private static final String SERIALIZED_NAME_CONSUMPTION_STATUS = "consumptionStatus"; - private static final String SERIALIZED_NAME_PLATFORM = "platform"; - private static final String SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED = "sampleContentProvided"; + private static final String SERIALIZED_NAME_CUSTOMER_CONSENTED = "customerConsented"; private static final String SERIALIZED_NAME_DELIVERY_STATUS = "deliveryStatus"; - private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; - private static final String SERIALIZED_NAME_ACCOUNT_TENURE = "accountTenure"; - private static final String SERIALIZED_NAME_PLAY_TIME = "playTime"; - private static final String SERIALIZED_NAME_LIFETIME_DOLLARS_REFUNDED = "lifetimeDollarsRefunded"; private static final String SERIALIZED_NAME_LIFETIME_DOLLARS_PURCHASED = "lifetimeDollarsPurchased"; - private static final String SERIALIZED_NAME_USER_STATUS = "userStatus"; + private static final String SERIALIZED_NAME_LIFETIME_DOLLARS_REFUNDED = "lifetimeDollarsRefunded"; + private static final String SERIALIZED_NAME_PLATFORM = "platform"; + private static final String SERIALIZED_NAME_PLAY_TIME = "playTime"; private static final String SERIALIZED_NAME_REFUND_PREFERENCE = "refundPreference"; - @JsonProperty(SERIALIZED_NAME_CUSTOMER_CONSENTED) - private Boolean customerConsented; - @JsonProperty(SERIALIZED_NAME_CONSUMPTION_STATUS) - private Integer consumptionStatus; - @JsonProperty(SERIALIZED_NAME_PLATFORM) - private Integer platform; - @JsonProperty(SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED) - private Boolean sampleContentProvided; - @JsonProperty(SERIALIZED_NAME_DELIVERY_STATUS) - private Integer deliveryStatus; - @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) + private static final String SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED = "sampleContentProvided"; + private static final String SERIALIZED_NAME_USER_STATUS = "userStatus"; + + @JsonProperty(value = SERIALIZED_NAME_ACCOUNT_TENURE, required = true) + private Integer accountTenure; + @JsonProperty(value = SERIALIZED_NAME_APP_ACCOUNT_TOKEN, required = true) @JsonSerialize(nullsUsing = AppAccountTokenNullSerializer.class) private UUID appAccountToken; - @JsonProperty(SERIALIZED_NAME_ACCOUNT_TENURE) - private Integer accountTenure; - @JsonProperty(SERIALIZED_NAME_PLAY_TIME) - private Integer playTime; - @JsonProperty(SERIALIZED_NAME_LIFETIME_DOLLARS_REFUNDED) - private Integer lifetimeDollarsRefunded; - @JsonProperty(SERIALIZED_NAME_LIFETIME_DOLLARS_PURCHASED) + @JsonProperty(value = SERIALIZED_NAME_CONSUMPTION_STATUS, required = true) + private Integer consumptionStatus; + @JsonProperty(value = SERIALIZED_NAME_CUSTOMER_CONSENTED, required = true) + private Boolean customerConsented; + @JsonProperty(value = SERIALIZED_NAME_DELIVERY_STATUS, required = true) + private Integer deliveryStatus; + @JsonProperty(value = SERIALIZED_NAME_LIFETIME_DOLLARS_PURCHASED, required = true) private Integer lifetimeDollarsPurchased; - @JsonProperty(SERIALIZED_NAME_USER_STATUS) - private Integer userStatus; + @JsonProperty(value = SERIALIZED_NAME_LIFETIME_DOLLARS_REFUNDED, required = true) + private Integer lifetimeDollarsRefunded; + @JsonProperty(value = SERIALIZED_NAME_PLATFORM, required = true) + private Integer platform; + @JsonProperty(value = SERIALIZED_NAME_PLAY_TIME, required = true) + private Integer playTime; @JsonProperty(SERIALIZED_NAME_REFUND_PREFERENCE) private Integer refundPreference; + @JsonProperty(value = SERIALIZED_NAME_SAMPLE_CONTENT_PROVIDED, required = true) + private Boolean sampleContentProvided; + @JsonProperty(value = SERIALIZED_NAME_USER_STATUS, required = true) + private Integer userStatus; + protected ConsumptionRequestV1() { + } + + public ConsumptionRequestV1( + AccountTenure accountTenure, + UUID appAccountToken, + ConsumptionStatus consumptionStatus, + Boolean customerConsented, + DeliveryStatusV1 deliveryStatus, + LifetimeDollarsPurchased lifetimeDollarsPurchased, + LifetimeDollarsRefunded lifetimeDollarsRefunded, + Platform platform, + PlayTime playTime, + Boolean sampleContentProvided, + UserStatus userStatus + ) { + this.accountTenure = Objects.requireNonNull(accountTenure).getValue(); + this.appAccountToken = appAccountToken; + this.consumptionStatus = Objects.requireNonNull(consumptionStatus).getValue(); + this.customerConsented = Objects.requireNonNull(customerConsented); + this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); + this.lifetimeDollarsPurchased = Objects.requireNonNull(lifetimeDollarsPurchased).getValue(); + this.lifetimeDollarsRefunded = Objects.requireNonNull(lifetimeDollarsRefunded).getValue(); + this.platform = Objects.requireNonNull(platform).getValue(); + this.playTime = Objects.requireNonNull(playTime).getValue(); + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); + this.userStatus = Objects.requireNonNull(userStatus).getValue(); + } + + public ConsumptionRequestV1( + Integer rawAccountTenure, + UUID appAccountToken, + Integer rawConsumptionStatus, + Boolean customerConsented, + Integer rawDeliveryStatus, + Integer rawLifetimeDollarsPurchased, + Integer rawLifetimeDollarsRefunded, + Integer rawPlatform, + Integer rawPlayTime, + Boolean sampleContentProvided, + Integer rawUserStatus + ) { + this.accountTenure = Objects.requireNonNull(rawAccountTenure); + this.appAccountToken = appAccountToken; + this.consumptionStatus = Objects.requireNonNull(rawConsumptionStatus); + this.customerConsented = Objects.requireNonNull(customerConsented); + this.deliveryStatus = Objects.requireNonNull(rawDeliveryStatus); + this.lifetimeDollarsPurchased = Objects.requireNonNull(rawLifetimeDollarsPurchased); + this.lifetimeDollarsRefunded = Objects.requireNonNull(rawLifetimeDollarsRefunded); + this.platform = Objects.requireNonNull(rawPlatform); + this.playTime = Objects.requireNonNull(rawPlayTime); + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); + this.userStatus = Objects.requireNonNull(rawUserStatus); + } - public ConsumptionRequestV1() { + public ConsumptionRequestV1 accountTenure(AccountTenure accountTenure) { + this.accountTenure = Objects.requireNonNull(accountTenure).getValue(); + return this; } - public ConsumptionRequestV1 customerConsented(Boolean customerConsented) { - this.customerConsented = customerConsented; + /** + * The age of the customer’s account. + * + * @return accountTenure + * @see accountTenure + **/ + public AccountTenure getAccountTenure() { + return AccountTenure.fromValue(accountTenure); + } + + /** + * @see #getAccountTenure() + **/ + public Integer getRawAccountTenure() { + return accountTenure; + } + + public void setAccountTenure(AccountTenure accountTenure) { + this.accountTenure = Objects.requireNonNull(accountTenure).getValue(); + } + + public void setRawAccountTenure(Integer rawAccountTenure) { + this.accountTenure = Objects.requireNonNull(rawAccountTenure); + } + + public ConsumptionRequestV1 appAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; return this; } /** - * A Boolean value that indicates whether the customer consented to provide consumption data to the App Store. + * The UUID of the in-app user account that completed the in-app purchase transaction. * - * @return customerConsented - * @see customerConsented + * @return appAccountToken + * @see appAccountToken **/ - public Boolean getCustomerConsented() { - return customerConsented; + public UUID getAppAccountToken() { + return appAccountToken; } - public void setCustomerConsented(Boolean customerConsented) { - this.customerConsented = customerConsented; + public void setAppAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; } public ConsumptionRequestV1 consumptionStatus(ConsumptionStatus consumptionStatus) { - this.consumptionStatus = consumptionStatus != null ? consumptionStatus.getValue() : null; + this.consumptionStatus = Objects.requireNonNull(consumptionStatus).getValue(); return this; } @@ -91,75 +173,45 @@ public ConsumptionRequestV1 consumptionStatus(ConsumptionStatus consumptionStatu * @see consumptionStatus **/ public ConsumptionStatus getConsumptionStatus() { - return consumptionStatus != null ? ConsumptionStatus.fromValue(consumptionStatus) : null; + return ConsumptionStatus.fromValue(consumptionStatus); } /** * @see #getConsumptionStatus() - */ + **/ public Integer getRawConsumptionStatus() { return consumptionStatus; } public void setConsumptionStatus(ConsumptionStatus consumptionStatus) { - this.consumptionStatus = consumptionStatus != null ? consumptionStatus.getValue() : null; + this.consumptionStatus = Objects.requireNonNull(consumptionStatus).getValue(); } public void setRawConsumptionStatus(Integer rawConsumptionStatus) { - this.consumptionStatus = rawConsumptionStatus; - } - - public ConsumptionRequestV1 platform(Platform platform) { - this.platform = platform != null ? platform.getValue() : null; - return this; - } - - /** - * A value that indicates the platform on which the customer consumed the in-app purchase. - * - * @return platform - * @see platform - **/ - public Platform getPlatform() { - return platform != null ? Platform.fromValue(platform) : null; + this.consumptionStatus = Objects.requireNonNull(rawConsumptionStatus); } - /** - * @see #getPlatform() - */ - public Integer getRawPlatform() { - return platform; - } - - public void setPlatform(Platform platform) { - this.platform = platform != null ? platform.getValue() : null; - } - - public void setRawPlatform(Integer rawPlatform) { - this.platform = rawPlatform; - } - - public ConsumptionRequestV1 sampleContentProvided(Boolean sampleContentProvided) { - this.sampleContentProvided = sampleContentProvided; + public ConsumptionRequestV1 customerConsented(Boolean customerConsented) { + this.customerConsented = Objects.requireNonNull(customerConsented); return this; } /** - * A Boolean value that indicates whether you provided, prior to its purchase, a free sample or trial of the content, or information about its functionality. + * A Boolean value of true or false that indicates whether the customer consented to provide consumption data. * - * @return sampleContentProvided - * @see sampleContentProvided + * @return customerConsented + * @see customerConsented **/ - public Boolean getSampleContentProvided() { - return sampleContentProvided; + public Boolean getCustomerConsented() { + return customerConsented; } - public void setSampleContentProvided(Boolean sampleContentProvided) { - this.sampleContentProvided = sampleContentProvided; + public void setCustomerConsented(Boolean customerConsented) { + this.customerConsented = Objects.requireNonNull(customerConsented); } public ConsumptionRequestV1 deliveryStatus(DeliveryStatusV1 deliveryStatus) { - this.deliveryStatus = deliveryStatus != null ? deliveryStatus.getValue() : null; + this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); return this; } @@ -170,75 +222,116 @@ public ConsumptionRequestV1 deliveryStatus(DeliveryStatusV1 deliveryStatus) { * @see deliveryStatusV1 **/ public DeliveryStatusV1 getDeliveryStatus() { - return deliveryStatus != null ? DeliveryStatusV1.fromValue(deliveryStatus) : null; + return DeliveryStatusV1.fromValue(deliveryStatus); } /** * @see #getDeliveryStatus() - */ + **/ public Integer getRawDeliveryStatus() { return deliveryStatus; } public void setDeliveryStatus(DeliveryStatusV1 deliveryStatus) { - this.deliveryStatus = deliveryStatus != null ? deliveryStatus.getValue() : null; + this.deliveryStatus = Objects.requireNonNull(deliveryStatus).getValue(); } public void setRawDeliveryStatus(Integer rawDeliveryStatus) { - this.deliveryStatus = rawDeliveryStatus; + this.deliveryStatus = Objects.requireNonNull(rawDeliveryStatus); } - public ConsumptionRequestV1 appAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + public ConsumptionRequestV1 lifetimeDollarsPurchased(LifetimeDollarsPurchased lifetimeDollarsPurchased) { + this.lifetimeDollarsPurchased = Objects.requireNonNull(lifetimeDollarsPurchased).getValue(); return this; } /** - * The UUID that an app optionally generates to map a customer’s in-app purchase with its resulting App Store transaction. + * A value that indicates the total amount, in USD, of in-app purchases the customer has made in your app, across all platforms. * - * @return appAccountToken - * @see appAccountToken + * @return lifetimeDollarsPurchased + * @see lifetimeDollarsPurchased **/ - public UUID getAppAccountToken() { - return appAccountToken; + public LifetimeDollarsPurchased getLifetimeDollarsPurchased() { + return LifetimeDollarsPurchased.fromValue(lifetimeDollarsPurchased); } - public void setAppAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + /** + * @see #getLifetimeDollarsPurchased() + **/ + public Integer getRawLifetimeDollarsPurchased() { + return lifetimeDollarsPurchased; } - public ConsumptionRequestV1 accountTenure(AccountTenure accountTenure) { - this.accountTenure = accountTenure != null ? accountTenure.getValue() : null; + public void setLifetimeDollarsPurchased(LifetimeDollarsPurchased lifetimeDollarsPurchased) { + this.lifetimeDollarsPurchased = Objects.requireNonNull(lifetimeDollarsPurchased).getValue(); + } + + public void setRawLifetimeDollarsPurchased(Integer rawLifetimeDollarsPurchased) { + this.lifetimeDollarsPurchased = Objects.requireNonNull(rawLifetimeDollarsPurchased); + } + + public ConsumptionRequestV1 lifetimeDollarsRefunded(LifetimeDollarsRefunded lifetimeDollarsRefunded) { + this.lifetimeDollarsRefunded = Objects.requireNonNull(lifetimeDollarsRefunded).getValue(); return this; } /** - * The age of the customer’s account. + * A value that indicates the total amount, in USD, of refunds the customer has received, in your app, across all platforms. * - * @return accountTenure - * @see accountTenure + * @return lifetimeDollarsRefunded + * @see lifetimeDollarsRefunded **/ - public AccountTenure getAccountTenure() { - return accountTenure != null ? AccountTenure.fromValue(accountTenure) : null; + public LifetimeDollarsRefunded getLifetimeDollarsRefunded() { + return LifetimeDollarsRefunded.fromValue(lifetimeDollarsRefunded); } /** - * @see #getAccountTenure() - */ - public Integer getRawAccountTenure() { - return accountTenure; + * @see #getLifetimeDollarsRefunded() + **/ + public Integer getRawLifetimeDollarsRefunded() { + return lifetimeDollarsRefunded; } - public void setAccountTenure(AccountTenure accountTenure) { - this.accountTenure = accountTenure != null ? accountTenure.getValue() : null; + public void setLifetimeDollarsRefunded(LifetimeDollarsRefunded lifetimeDollarsRefunded) { + this.lifetimeDollarsRefunded = Objects.requireNonNull(lifetimeDollarsRefunded).getValue(); } - public void setRawAccountTenure(Integer rawAccountTenure) { - this.accountTenure = rawAccountTenure; + public void setRawLifetimeDollarsRefunded(Integer rawLifetimeDollarsRefunded) { + this.lifetimeDollarsRefunded = Objects.requireNonNull(rawLifetimeDollarsRefunded); + } + + public ConsumptionRequestV1 platform(Platform platform) { + this.platform = Objects.requireNonNull(platform).getValue(); + return this; + } + + /** + * A value that indicates the platform on which the customer consumed the in-app purchase. + * + * @return platform + * @see platform + **/ + public Platform getPlatform() { + return Platform.fromValue(platform); + } + + /** + * @see #getPlatform() + **/ + public Integer getRawPlatform() { + return platform; + } + + public void setPlatform(Platform platform) { + this.platform = Objects.requireNonNull(platform).getValue(); + } + + public void setRawPlatform(Integer rawPlatform) { + this.platform = Objects.requireNonNull(rawPlatform); } public ConsumptionRequestV1 playTime(PlayTime playTime) { - this.playTime = playTime != null ? playTime.getValue() : null; + this.playTime = Objects.requireNonNull(playTime).getValue(); return this; } @@ -249,86 +342,75 @@ public ConsumptionRequestV1 playTime(PlayTime playTime) { * @see playTime **/ public PlayTime getPlayTime() { - return playTime != null ? PlayTime.fromValue(playTime) : null; + return PlayTime.fromValue(playTime); } /** * @see #getPlayTime() - */ + **/ public Integer getRawPlayTime() { return playTime; } public void setPlayTime(PlayTime playTime) { - this.playTime = playTime != null ? playTime.getValue() : null; + this.playTime = Objects.requireNonNull(playTime).getValue(); } public void setRawPlayTime(Integer rawPlayTime) { - this.playTime = rawPlayTime; + this.playTime = Objects.requireNonNull(rawPlayTime); } - public ConsumptionRequestV1 lifetimeDollarsRefunded(LifetimeDollarsRefunded lifetimeDollarsRefunded) { - this.lifetimeDollarsRefunded = lifetimeDollarsRefunded != null ? lifetimeDollarsRefunded.getValue() : null; + public ConsumptionRequestV1 refundPreference(RefundPreferenceV1 refundPreference) { + this.refundPreference = refundPreference != null ? refundPreference.getValue() : null; return this; } /** - * A value that indicates the total amount, in USD, of refunds the customer has received, in your app, across all platforms. + * A value that indicates your preference, based on your operational logic, as to whether Apple should grant the refund. * - * @return lifetimeDollarsRefunded - * @see lifetimeDollarsRefunded + * @return refundPreference + * @see refundPreferenceV1 **/ - public LifetimeDollarsRefunded getLifetimeDollarsRefunded() { - return lifetimeDollarsRefunded != null ? LifetimeDollarsRefunded.fromValue(lifetimeDollarsRefunded) : null; + public RefundPreferenceV1 getRefundPreference() { + return RefundPreferenceV1.fromValue(refundPreference); } /** - * @see #getLifetimeDollarsRefunded() - */ - public Integer getRawLifetimeDollarsRefunded() { - return lifetimeDollarsRefunded; + * @see #getRefundPreference() + **/ + public Integer getRawRefundPreference() { + return refundPreference; } - public void setLifetimeDollarsRefunded(LifetimeDollarsRefunded lifetimeDollarsRefunded) { - this.lifetimeDollarsRefunded = lifetimeDollarsRefunded != null ? lifetimeDollarsRefunded.getValue() : null; + public void setRefundPreference(RefundPreferenceV1 refundPreference) { + this.refundPreference = refundPreference != null ? refundPreference.getValue() : null; } - public void setRawLifetimeDollarsRefunded(Integer rawLifetimeDollarsRefunded) { - this.lifetimeDollarsRefunded = rawLifetimeDollarsRefunded; + public void setRawRefundPreference(Integer rawRefundPreference) { + this.refundPreference = rawRefundPreference; } - public ConsumptionRequestV1 lifetimeDollarsPurchased(LifetimeDollarsPurchased lifetimeDollarsPurchased) { - this.lifetimeDollarsPurchased = lifetimeDollarsPurchased != null ? lifetimeDollarsPurchased.getValue() : null; + public ConsumptionRequestV1 sampleContentProvided(Boolean sampleContentProvided) { + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); return this; } /** - * A value that indicates the total amount, in USD, of in-app purchases the customer has made in your app, across all platforms. + * A Boolean value of true or false that indicates whether you provided, prior to its purchase, a free sample or trial of the content, or information about its functionality. * - * @return lifetimeDollarsPurchased - * @see lifetimeDollarsPurchased + * @return sampleContentProvided + * @see sampleContentProvided **/ - public LifetimeDollarsPurchased getLifetimeDollarsPurchased() { - return lifetimeDollarsPurchased != null ? LifetimeDollarsPurchased.fromValue(lifetimeDollarsPurchased) : null; - } - - /** - * @see #getLifetimeDollarsPurchased() - */ - public Integer getRawLifetimeDollarsPurchased() { - return lifetimeDollarsPurchased; - } - - public void setLifetimeDollarsPurchased(LifetimeDollarsPurchased lifetimeDollarsPurchased) { - this.lifetimeDollarsPurchased = lifetimeDollarsPurchased != null ? lifetimeDollarsPurchased.getValue() : null; + public Boolean getSampleContentProvided() { + return sampleContentProvided; } - public void setRawLifetimeDollarsPurchased(Integer rawLifetimeDollarsPurchased) { - this.lifetimeDollarsPurchased = rawLifetimeDollarsPurchased; + public void setSampleContentProvided(Boolean sampleContentProvided) { + this.sampleContentProvided = Objects.requireNonNull(sampleContentProvided); } public ConsumptionRequestV1 userStatus(UserStatus userStatus) { - this.userStatus = userStatus != null ? userStatus.getValue() : null; + this.userStatus = Objects.requireNonNull(userStatus).getValue(); return this; } @@ -339,52 +421,22 @@ public ConsumptionRequestV1 userStatus(UserStatus userStatus) { * @see userStatus **/ public UserStatus getUserStatus() { - return userStatus != null ? UserStatus.fromValue(userStatus) : null; + return UserStatus.fromValue(userStatus); } /** * @see #getUserStatus() - */ + **/ public Integer getRawUserStatus() { return userStatus; } public void setUserStatus(UserStatus userStatus) { - this.userStatus = userStatus != null ? userStatus.getValue() : null; + this.userStatus = Objects.requireNonNull(userStatus).getValue(); } public void setRawUserStatus(Integer rawUserStatus) { - this.userStatus = rawUserStatus; - } - - public ConsumptionRequestV1 refundPreference(RefundPreferenceV1 refundPreference) { - this.refundPreference = refundPreference != null ? refundPreference.getValue() : null; - return this; - } - - /** - * A value that indicates your preference, based on your operational logic, as to whether Apple should grant the refund. - * - * @return refundPreference - * @see refundPreferenceV1 - **/ - public RefundPreferenceV1 getRefundPreference() { - return refundPreference != null ? RefundPreferenceV1.fromValue(refundPreference) : null; - } - - /** - * @see #getRefundPreference() - */ - public Integer getRawRefundPreference() { - return refundPreference; - } - - public void setRefundPreference(RefundPreferenceV1 refundPreference) { - this.refundPreference = refundPreference != null ? refundPreference.getValue() : null; - } - - public void setRawRefundPreference(Integer rawRefundPreference) { - this.refundPreference = rawRefundPreference; + this.userStatus = Objects.requireNonNull(rawUserStatus); } @Override @@ -395,41 +447,41 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - ConsumptionRequestV1 consumptionRequest = (ConsumptionRequestV1) o; - return Objects.equals(this.customerConsented, consumptionRequest.customerConsented) && - Objects.equals(this.consumptionStatus, consumptionRequest.consumptionStatus) && - Objects.equals(this.platform, consumptionRequest.platform) && - Objects.equals(this.sampleContentProvided, consumptionRequest.sampleContentProvided) && - Objects.equals(this.deliveryStatus, consumptionRequest.deliveryStatus) && - Objects.equals(this.appAccountToken, consumptionRequest.appAccountToken) && - Objects.equals(this.accountTenure, consumptionRequest.accountTenure) && - Objects.equals(this.playTime, consumptionRequest.playTime) && - Objects.equals(this.lifetimeDollarsRefunded, consumptionRequest.lifetimeDollarsRefunded) && - Objects.equals(this.lifetimeDollarsPurchased, consumptionRequest.lifetimeDollarsPurchased) && - Objects.equals(this.userStatus, consumptionRequest.userStatus) && - Objects.equals(this.refundPreference, consumptionRequest.refundPreference); + ConsumptionRequestV1 consumptionRequestV1 = (ConsumptionRequestV1) o; + return Objects.equals(this.accountTenure, consumptionRequestV1.accountTenure) && + Objects.equals(this.appAccountToken, consumptionRequestV1.appAccountToken) && + Objects.equals(this.consumptionStatus, consumptionRequestV1.consumptionStatus) && + Objects.equals(this.customerConsented, consumptionRequestV1.customerConsented) && + Objects.equals(this.deliveryStatus, consumptionRequestV1.deliveryStatus) && + Objects.equals(this.lifetimeDollarsPurchased, consumptionRequestV1.lifetimeDollarsPurchased) && + Objects.equals(this.lifetimeDollarsRefunded, consumptionRequestV1.lifetimeDollarsRefunded) && + Objects.equals(this.platform, consumptionRequestV1.platform) && + Objects.equals(this.playTime, consumptionRequestV1.playTime) && + Objects.equals(this.refundPreference, consumptionRequestV1.refundPreference) && + Objects.equals(this.sampleContentProvided, consumptionRequestV1.sampleContentProvided) && + Objects.equals(this.userStatus, consumptionRequestV1.userStatus); } @Override public int hashCode() { - return Objects.hash(customerConsented, consumptionStatus, platform, sampleContentProvided, deliveryStatus, appAccountToken, accountTenure, playTime, lifetimeDollarsRefunded, lifetimeDollarsPurchased, userStatus, refundPreference); + return Objects.hash(accountTenure, appAccountToken, consumptionStatus, customerConsented, deliveryStatus, lifetimeDollarsPurchased, lifetimeDollarsRefunded, platform, playTime, refundPreference, sampleContentProvided, userStatus); } @Override public String toString() { return "ConsumptionRequestV1{" + - "customerConsented=" + customerConsented + + "accountTenure=" + accountTenure + + ", appAccountToken=" + appAccountToken + ", consumptionStatus=" + consumptionStatus + - ", platform=" + platform + - ", sampleContentProvided=" + sampleContentProvided + + ", customerConsented=" + customerConsented + ", deliveryStatus=" + deliveryStatus + - ", appAccountToken=" + appAccountToken + - ", accountTenure=" + accountTenure + - ", playTime=" + playTime + - ", lifetimeDollarsRefunded=" + lifetimeDollarsRefunded + ", lifetimeDollarsPurchased=" + lifetimeDollarsPurchased + - ", userStatus=" + userStatus + + ", lifetimeDollarsRefunded=" + lifetimeDollarsRefunded + + ", platform=" + platform + + ", playTime=" + playTime + ", refundPreference=" + refundPreference + + ", sampleContentProvided=" + sampleContentProvided + + ", userStatus=" + userStatus + '}'; } } diff --git a/src/main/java/com/apple/itunes/storekit/model/ConsumptionStatus.java b/src/main/java/com/apple/itunes/storekit/model/ConsumptionStatus.java index de272ba8..5b3243de 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ConsumptionStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/ConsumptionStatus.java @@ -5,15 +5,27 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * A value that indicates the extent to which the customer consumed the in-app purchase. + * A value that indicates the extent to which the customer consumed the In-App Purchase. * * @see consumptionStatus - */ + **/ public enum ConsumptionStatus { + /** + * The consumption status is undeclared. + **/ UNDECLARED(0), + /** + * The In-App Purchase is not consumed. + **/ NOT_CONSUMED(1), + /** + * The In-App Purchase is partially consumed. + **/ PARTIALLY_CONSUMED(2), + /** + * The In-App Purchase is fully consumed. + **/ FULLY_CONSUMED(3); private final Integer value; @@ -41,4 +53,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Data.java b/src/main/java/com/apple/itunes/storekit/model/Data.java index 4d3cd498..6b1a2746 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Data.java +++ b/src/main/java/com/apple/itunes/storekit/model/Data.java @@ -9,79 +9,49 @@ import java.util.Objects; /** - * The app metadata and the signed renewal and transaction information. + * The payload data that contains app metadata and the signed renewal and transaction information. * * @see data - */ + **/ public class Data { - private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_BUNDLE_VERSION = "bundleVersion"; - private static final String SERIALIZED_NAME_SIGNED_TRANSACTION_INFO = "signedTransactionInfo"; + private static final String SERIALIZED_NAME_CONSUMPTION_REQUEST_REASON = "consumptionRequestReason"; + private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; private static final String SERIALIZED_NAME_SIGNED_RENEWAL_INFO = "signedRenewalInfo"; + private static final String SERIALIZED_NAME_SIGNED_TRANSACTION_INFO = "signedTransactionInfo"; private static final String SERIALIZED_NAME_STATUS = "status"; - private static final String SERIALIZED_NAME_CONSUMPTION_REQUEST_REASON = "consumptionRequestReason"; - @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) - private String environment; + @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) private Long appAppleId; @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) private String bundleId; @JsonProperty(SERIALIZED_NAME_BUNDLE_VERSION) private String bundleVersion; - @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) - private String signedTransactionInfo; + @JsonProperty(SERIALIZED_NAME_CONSUMPTION_REQUEST_REASON) + private String consumptionRequestReason; + @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) + private String environment; @JsonProperty(SERIALIZED_NAME_SIGNED_RENEWAL_INFO) private String signedRenewalInfo; + @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) + private String signedTransactionInfo; @JsonProperty(SERIALIZED_NAME_STATUS) private Integer status; - @JsonProperty(SERIALIZED_NAME_CONSUMPTION_REQUEST_REASON) - private String consumptionRequestReason; @JsonAnySetter private Map unknownFields; - public Data() { } - public Data environment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; - return this; - } - - /** - * The server environment that the notification applies to, either sandbox or production. - * - * @return environment - * @see environment - **/ - public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; - } - - /** - * @see #getEnvironment() - */ - public String getRawEnvironment() { - return environment; - } - - public void setEnvironment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; - } - - public void setRawEnvironment(String rawEnvironment) { - this.environment = rawEnvironment; - } - public Data appAppleId(Long appAppleId) { this.appAppleId = appAppleId; return this; } /** - * The unique identifier of an app in the App Store. + * The unique identifier of the app that the notification applies to. * * @return appAppleId * @see appAppleId @@ -100,10 +70,10 @@ public Data bundleId(String bundleId) { } /** - * The bundle identifier of an app. + * The bundle identifier of the app. * * @return bundleId - * @see bundleId + * @see bundleId **/ public String getBundleId() { return bundleId; @@ -132,23 +102,64 @@ public void setBundleVersion(String bundleVersion) { this.bundleVersion = bundleVersion; } - public Data signedTransactionInfo(String signedTransactionInfo) { - this.signedTransactionInfo = signedTransactionInfo; + public Data consumptionRequestReason(ConsumptionRequestReason consumptionRequestReason) { + this.consumptionRequestReason = consumptionRequestReason != null ? consumptionRequestReason.getValue() : null; return this; } /** - * Transaction information signed by the App Store, in JSON Web Signature (JWS) format. + * The reason the customer requested the refund. * - * @return signedTransactionInfo - * @see JWSTransaction + * @return consumptionRequestReason + * @see consumptionRequestReason **/ - public String getSignedTransactionInfo() { - return signedTransactionInfo; + public ConsumptionRequestReason getConsumptionRequestReason() { + return ConsumptionRequestReason.fromValue(consumptionRequestReason); } - public void setSignedTransactionInfo(String signedTransactionInfo) { - this.signedTransactionInfo = signedTransactionInfo; + /** + * @see #getConsumptionRequestReason() + **/ + public String getRawConsumptionRequestReason() { + return consumptionRequestReason; + } + + public void setConsumptionRequestReason(ConsumptionRequestReason consumptionRequestReason) { + this.consumptionRequestReason = consumptionRequestReason != null ? consumptionRequestReason.getValue() : null; + } + + public void setRawConsumptionRequestReason(String rawConsumptionRequestReason) { + this.consumptionRequestReason = rawConsumptionRequestReason; + } + + public Data environment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; + return this; + } + + /** + * The server environment that the notification applies to, either sandbox or production. + * + * @return environment + * @see environment + **/ + public Environment getEnvironment() { + return Environment.fromValue(environment); + } + + /** + * @see #getEnvironment() + **/ + public String getRawEnvironment() { + return environment; + } + + public void setEnvironment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; + } + + public void setRawEnvironment(String rawEnvironment) { + this.environment = rawEnvironment; } public Data signedRenewalInfo(String signedRenewalInfo) { @@ -157,10 +168,10 @@ public Data signedRenewalInfo(String signedRenewalInfo) { } /** - * Subscription renewal information, signed by the App Store, in JSON Web Signature (JWS) format. + * Subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. * * @return signedRenewalInfo - * @see JWSRenewalInfo + * @see JWSRenewalInfo **/ public String getSignedRenewalInfo() { return signedRenewalInfo; @@ -170,6 +181,25 @@ public void setSignedRenewalInfo(String signedRenewalInfo) { this.signedRenewalInfo = signedRenewalInfo; } + public Data signedTransactionInfo(String signedTransactionInfo) { + this.signedTransactionInfo = signedTransactionInfo; + return this; + } + + /** + * Transaction information signed by the App Store, in JSON Web Signature (JWS) format. + * + * @return signedTransactionInfo + * @see JWSTransaction + **/ + public String getSignedTransactionInfo() { + return signedTransactionInfo; + } + + public void setSignedTransactionInfo(String signedTransactionInfo) { + this.signedTransactionInfo = signedTransactionInfo; + } + public Data status(Status status) { this.status = status != null ? status.getValue() : null; return this; @@ -182,12 +212,12 @@ public Data status(Status status) { * @see status **/ public Status getStatus() { - return status != null ? Status.fromValue(status) : null; + return Status.fromValue(status); } /** * @see #getStatus() - */ + **/ public Integer getRawStatus() { return status; } @@ -200,46 +230,16 @@ public void setRawStatus(Integer rawStatus) { this.status = rawStatus; } - public Data consumptionRequestReason(ConsumptionRequestReason consumptionRequestReason) { - this.consumptionRequestReason = consumptionRequestReason != null ? consumptionRequestReason.getValue() : null; - return this; - } - - /** - * The reason the customer requested the refund. - * - * @return consumptionRequestReason - * @see consumptionRequestReason - **/ - public ConsumptionRequestReason getConsumptionRequestReason() { - return consumptionRequestReason != null ? ConsumptionRequestReason.fromValue(consumptionRequestReason) : null; - } - - /** - * @see #getConsumptionRequestReason() - */ - public String getRawConsumptionRequestReason() { - return consumptionRequestReason; - } - - public void setConsumptionRequestReason(ConsumptionRequestReason consumptionRequestReason) { - this.consumptionRequestReason = consumptionRequestReason != null ? consumptionRequestReason.getValue() : null; - } - - public void setRawConsumptionRequestReason(String rawConsumptionRequestReason) { - this.consumptionRequestReason = rawConsumptionRequestReason; - } - public Data unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -257,35 +257,34 @@ public boolean equals(Object o) { return false; } Data data = (Data) o; - return Objects.equals(this.environment, data.environment) && - Objects.equals(this.appAppleId, data.appAppleId) && + return Objects.equals(this.appAppleId, data.appAppleId) && Objects.equals(this.bundleId, data.bundleId) && Objects.equals(this.bundleVersion, data.bundleVersion) && - Objects.equals(this.signedTransactionInfo, data.signedTransactionInfo) && + Objects.equals(this.consumptionRequestReason, data.consumptionRequestReason) && + Objects.equals(this.environment, data.environment) && Objects.equals(this.signedRenewalInfo, data.signedRenewalInfo) && + Objects.equals(this.signedTransactionInfo, data.signedTransactionInfo) && Objects.equals(this.status, data.status) && - Objects.equals(this.consumptionRequestReason, data.consumptionRequestReason) && Objects.equals(this.unknownFields, data.unknownFields); } @Override public int hashCode() { - return Objects.hash(environment, appAppleId, bundleId, bundleVersion, signedTransactionInfo, signedRenewalInfo, status, consumptionRequestReason, unknownFields); + return Objects.hash(appAppleId, bundleId, bundleVersion, consumptionRequestReason, environment, signedRenewalInfo, signedTransactionInfo, status, unknownFields); } @Override public String toString() { return "Data{" + - "environment='" + environment + '\'' + - ", appAppleId=" + appAppleId + + "appAppleId=" + appAppleId + ", bundleId='" + bundleId + '\'' + ", bundleVersion='" + bundleVersion + '\'' + - ", signedTransactionInfo='" + signedTransactionInfo + '\'' + + ", consumptionRequestReason='" + consumptionRequestReason + '\'' + + ", environment='" + environment + '\'' + ", signedRenewalInfo='" + signedRenewalInfo + '\'' + + ", signedTransactionInfo='" + signedTransactionInfo + '\'' + ", status=" + status + - ", consumptionRequestReason='" + consumptionRequestReason + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/DecodedRealtimeRequestBody.java b/src/main/java/com/apple/itunes/storekit/model/DecodedRealtimeRequestBody.java index f37ad3fc..4284ad18 100644 --- a/src/main/java/com/apple/itunes/storekit/model/DecodedRealtimeRequestBody.java +++ b/src/main/java/com/apple/itunes/storekit/model/DecodedRealtimeRequestBody.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -13,15 +14,16 @@ * The decoded request body the App Store sends to your server to request a real-time retention message. * * @see DecodedRealtimeRequestBody - */ + **/ public class DecodedRealtimeRequestBody implements DecodedSignedData { private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; private static final String SERIALIZED_NAME_USER_LOCALE = "userLocale"; private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; - private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; + private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; + @JsonProperty(value = SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID, required = true) private String originalTransactionId; @JsonProperty(value = SERIALIZED_NAME_APP_APPLE_ID, required = true) @@ -32,41 +34,51 @@ public class DecodedRealtimeRequestBody implements DecodedSignedData { private String userLocale; @JsonProperty(value = SERIALIZED_NAME_REQUEST_IDENTIFIER, required = true) private UUID requestIdentifier; - @JsonProperty(value = SERIALIZED_NAME_SIGNED_DATE, required = true) - private Long signedDate; @JsonProperty(value = SERIALIZED_NAME_ENVIRONMENT, required = true) private String environment; + @JsonProperty(value = SERIALIZED_NAME_SIGNED_DATE, required = true) + private Long signedDate; @JsonAnySetter private Map unknownFields; - protected DecodedRealtimeRequestBody() { } - public DecodedRealtimeRequestBody(String originalTransactionId, - Long appAppleId, - String productId, - String userLocale, - UUID requestIdentifier, - Long signedDate, - Environment environment) { - this(originalTransactionId, appAppleId, productId, userLocale, requestIdentifier, signedDate, Objects.requireNonNull(environment).getValue()); + public DecodedRealtimeRequestBody( + String originalTransactionId, + Long appAppleId, + String productId, + String userLocale, + UUID requestIdentifier, + Environment environment, + Long signedDate + ) { + this.originalTransactionId = Objects.requireNonNull(originalTransactionId); + this.appAppleId = Objects.requireNonNull(appAppleId); + this.productId = Objects.requireNonNull(productId); + this.userLocale = Objects.requireNonNull(userLocale); + this.requestIdentifier = Objects.requireNonNull(requestIdentifier); + this.environment = Objects.requireNonNull(environment).getValue(); + this.signedDate = Objects.requireNonNull(signedDate); } - public DecodedRealtimeRequestBody(String originalTransactionId, - Long appAppleId, - String productId, - String userLocale, - UUID requestIdentifier, - Long signedDate, - String rawEnvironment) { + @JsonCreator + public DecodedRealtimeRequestBody( + @JsonProperty(value = SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID, required = true) String originalTransactionId, + @JsonProperty(value = SERIALIZED_NAME_APP_APPLE_ID, required = true) Long appAppleId, + @JsonProperty(value = SERIALIZED_NAME_PRODUCT_ID, required = true) String productId, + @JsonProperty(value = SERIALIZED_NAME_USER_LOCALE, required = true) String userLocale, + @JsonProperty(value = SERIALIZED_NAME_REQUEST_IDENTIFIER, required = true) UUID requestIdentifier, + @JsonProperty(value = SERIALIZED_NAME_ENVIRONMENT, required = true) String rawEnvironment, + @JsonProperty(value = SERIALIZED_NAME_SIGNED_DATE, required = true) Long signedDate + ) { this.originalTransactionId = Objects.requireNonNull(originalTransactionId); this.appAppleId = Objects.requireNonNull(appAppleId); this.productId = Objects.requireNonNull(productId); this.userLocale = Objects.requireNonNull(userLocale); this.requestIdentifier = Objects.requireNonNull(requestIdentifier); - this.signedDate = Objects.requireNonNull(signedDate); this.environment = Objects.requireNonNull(rawEnvironment); + this.signedDate = Objects.requireNonNull(signedDate); } public DecodedRealtimeRequestBody originalTransactionId(String originalTransactionId) { @@ -164,25 +176,6 @@ public void setRequestIdentifier(UUID requestIdentifier) { this.requestIdentifier = Objects.requireNonNull(requestIdentifier); } - public DecodedRealtimeRequestBody signedDate(Long signedDate) { - this.signedDate = Objects.requireNonNull(signedDate); - return this; - } - - /** - * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature (JWS) data. - * - * @return signedDate - * @see signedDate - **/ - public Long getSignedDate() { - return signedDate; - } - - public void setSignedDate(Long signedDate) { - this.signedDate = Objects.requireNonNull(signedDate); - } - public DecodedRealtimeRequestBody environment(Environment environment) { this.environment = Objects.requireNonNull(environment).getValue(); return this; @@ -195,12 +188,12 @@ public DecodedRealtimeRequestBody environment(Environment environment) { * @see environment **/ public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + return Environment.fromValue(environment); } /** * @see #getEnvironment() - */ + **/ public String getRawEnvironment() { return environment; } @@ -213,16 +206,35 @@ public void setRawEnvironment(String rawEnvironment) { this.environment = Objects.requireNonNull(rawEnvironment); } + public DecodedRealtimeRequestBody signedDate(Long signedDate) { + this.signedDate = Objects.requireNonNull(signedDate); + return this; + } + + /** + * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature (JWS) data. + * + * @return signedDate + * @see signedDate + **/ + public Long getSignedDate() { + return signedDate; + } + + public void setSignedDate(Long signedDate) { + this.signedDate = Objects.requireNonNull(signedDate); + } + public DecodedRealtimeRequestBody unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -233,22 +245,26 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - DecodedRealtimeRequestBody that = (DecodedRealtimeRequestBody) o; - return Objects.equals(originalTransactionId, that.originalTransactionId) && - Objects.equals(appAppleId, that.appAppleId) && - Objects.equals(productId, that.productId) && - Objects.equals(userLocale, that.userLocale) && - Objects.equals(requestIdentifier, that.requestIdentifier) && - Objects.equals(signedDate, that.signedDate) && - Objects.equals(environment, that.environment) && - Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DecodedRealtimeRequestBody decodedRealtimeRequestBody = (DecodedRealtimeRequestBody) o; + return Objects.equals(this.originalTransactionId, decodedRealtimeRequestBody.originalTransactionId) && + Objects.equals(this.appAppleId, decodedRealtimeRequestBody.appAppleId) && + Objects.equals(this.productId, decodedRealtimeRequestBody.productId) && + Objects.equals(this.userLocale, decodedRealtimeRequestBody.userLocale) && + Objects.equals(this.requestIdentifier, decodedRealtimeRequestBody.requestIdentifier) && + Objects.equals(this.environment, decodedRealtimeRequestBody.environment) && + Objects.equals(this.signedDate, decodedRealtimeRequestBody.signedDate) && + Objects.equals(this.unknownFields, decodedRealtimeRequestBody.unknownFields); } @Override public int hashCode() { - return Objects.hash(originalTransactionId, appAppleId, productId, userLocale, requestIdentifier, signedDate, environment, unknownFields); + return Objects.hash(originalTransactionId, appAppleId, productId, userLocale, requestIdentifier, environment, signedDate, unknownFields); } @Override @@ -259,9 +275,9 @@ public String toString() { ", productId='" + productId + '\'' + ", userLocale='" + userLocale + '\'' + ", requestIdentifier=" + requestIdentifier + - ", signedDate=" + signedDate + ", environment='" + environment + '\'' + + ", signedDate=" + signedDate + ", unknownFields=" + unknownFields + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationRequest.java b/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationRequest.java index bb0f49dd..45f03cd8 100644 --- a/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationRequest.java @@ -12,18 +12,15 @@ * The request body that contains the default configuration information. * * @see DefaultConfigurationRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class DefaultConfigurationRequest { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; - @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIER) + + @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER, required = true) private UUID messageIdentifier; - /** - * @deprecated Use {@link #DefaultConfigurationRequest(UUID)} instead. - */ - @Deprecated - public DefaultConfigurationRequest() { + protected DefaultConfigurationRequest() { } public DefaultConfigurationRequest(UUID messageIdentifier) { @@ -31,7 +28,7 @@ public DefaultConfigurationRequest(UUID messageIdentifier) { } public DefaultConfigurationRequest messageIdentifier(UUID messageIdentifier) { - this.messageIdentifier = messageIdentifier; + this.messageIdentifier = Objects.requireNonNull(messageIdentifier); return this; } @@ -46,7 +43,7 @@ public UUID getMessageIdentifier() { } public void setMessageIdentifier(UUID messageIdentifier) { - this.messageIdentifier = messageIdentifier; + this.messageIdentifier = Objects.requireNonNull(messageIdentifier); } @Override @@ -73,4 +70,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationResponse.java b/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationResponse.java index 65fec933..f0c7a8a2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/DefaultConfigurationResponse.java @@ -2,9 +2,11 @@ package com.apple.itunes.storekit.model; -import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -12,17 +14,22 @@ * The response body that contains the default configuration information. * * @see DefaultConfigurationResponse - */ -@JsonInclude(JsonInclude.Include.NON_NULL) + **/ public class DefaultConfigurationResponse { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; + @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER, required = true) private UUID messageIdentifier; + @JsonAnySetter + private Map unknownFields; protected DefaultConfigurationResponse() { } - public DefaultConfigurationResponse(UUID messageIdentifier) { + @JsonCreator + public DefaultConfigurationResponse( + @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER, required = true) UUID messageIdentifier + ) { this.messageIdentifier = Objects.requireNonNull(messageIdentifier); } @@ -45,6 +52,24 @@ public void setMessageIdentifier(UUID messageIdentifier) { this.messageIdentifier = Objects.requireNonNull(messageIdentifier); } + public DefaultConfigurationResponse unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -54,19 +79,20 @@ public boolean equals(Object o) { return false; } DefaultConfigurationResponse defaultConfigurationResponse = (DefaultConfigurationResponse) o; - return Objects.equals(this.messageIdentifier, defaultConfigurationResponse.messageIdentifier); + return Objects.equals(this.messageIdentifier, defaultConfigurationResponse.messageIdentifier) && + Objects.equals(this.unknownFields, defaultConfigurationResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(messageIdentifier); + return Objects.hash(messageIdentifier, unknownFields); } @Override public String toString() { return "DefaultConfigurationResponse{" + "messageIdentifier=" + messageIdentifier + + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/DeliveryStatus.java b/src/main/java/com/apple/itunes/storekit/model/DeliveryStatus.java index daa71f99..f7816778 100644 --- a/src/main/java/com/apple/itunes/storekit/model/DeliveryStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/DeliveryStatus.java @@ -8,13 +8,28 @@ * A value that indicates whether the app successfully delivered an In-App Purchase that works properly. * * @see deliveryStatus - */ + **/ public enum DeliveryStatus { + /** + * The app delivered the In-App Purchase and it’s working properly. + **/ DELIVERED("DELIVERED"), + /** + * The app didn’t deliver the In-App Purchase due to a quality issue. + **/ UNDELIVERED_QUALITY_ISSUE("UNDELIVERED_QUALITY_ISSUE"), + /** + * The app delivered the wrong item. + **/ UNDELIVERED_WRONG_ITEM("UNDELIVERED_WRONG_ITEM"), + /** + * The app didn’t deliver the In-App Purchase due to a server outage. + **/ UNDELIVERED_SERVER_OUTAGE("UNDELIVERED_SERVER_OUTAGE"), + /** + * The app didn’t deliver the In-App Purchase for other reasons. + **/ UNDELIVERED_OTHER("UNDELIVERED_OTHER"); private final String value; diff --git a/src/main/java/com/apple/itunes/storekit/model/DeliveryStatusV1.java b/src/main/java/com/apple/itunes/storekit/model/DeliveryStatusV1.java index 3a103969..3754ba15 100644 --- a/src/main/java/com/apple/itunes/storekit/model/DeliveryStatusV1.java +++ b/src/main/java/com/apple/itunes/storekit/model/DeliveryStatusV1.java @@ -5,19 +5,37 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * A value that indicates whether the app successfully delivered an in-app purchase that works properly. + * A value that indicates whether the app successfully delivered an In-App Purchase that works properly. * - * @see deliveryStatus + * @see deliveryStatusV1 * @deprecated Use {@link DeliveryStatus} instead. - */ + **/ @Deprecated public enum DeliveryStatusV1 { + /** + * The app delivered the consumable In-App Purchase and it’s working properly. + **/ DELIVERED_AND_WORKING_PROPERLY(0), + /** + * The app didn’t deliver the consumable In-App Purchase due to a quality issue. + **/ DID_NOT_DELIVER_DUE_TO_QUALITY_ISSUE(1), + /** + * The app delivered the wrong item. + **/ DELIVERED_WRONG_ITEM(2), + /** + * The app didn’t deliver the consumable In-App Purchase due to a server outage. + **/ DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE(3), + /** + * The app didn’t deliver the consumable In-App Purchase due to an in-game currency change. + **/ DID_NOT_DELIVER_DUE_TO_IN_GAME_CURRENCY_CHANGE(4), + /** + * The app didn’t deliver the consumable In-App Purchase for other reasons. + **/ DID_NOT_DELIVER_FOR_OTHER_REASON(5); private final Integer value; @@ -44,4 +62,4 @@ public Integer getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/Environment.java b/src/main/java/com/apple/itunes/storekit/model/Environment.java index 20eb058d..edbede6f 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Environment.java +++ b/src/main/java/com/apple/itunes/storekit/model/Environment.java @@ -8,13 +8,18 @@ * The server environment, either sandbox or production. * * @see environment - */ + **/ public enum Environment { + /** + * Indicates that the data applies to testing in the sandbox environment. + **/ SANDBOX("Sandbox"), + /** + * Indicates that the data applies to the production environment. + **/ PRODUCTION("Production"), XCODE("Xcode"), - // Used for unit testing LOCAL_TESTING("LocalTesting"); private final String value; @@ -42,4 +47,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ErrorPayload.java b/src/main/java/com/apple/itunes/storekit/model/ErrorPayload.java index 329c54dc..d1d91990 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ErrorPayload.java +++ b/src/main/java/com/apple/itunes/storekit/model/ErrorPayload.java @@ -2,18 +2,23 @@ package com.apple.itunes.storekit.model; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; + public class ErrorPayload { @JsonProperty - private long errorCode; + private Long errorCode; @JsonProperty private String errorMessage; + @JsonAnySetter + private Map unknownFields; public ErrorPayload() { } - public ErrorPayload(long errorCode, String errorMessage) { + public ErrorPayload(Long errorCode, String errorMessage) { this.errorCode = errorCode; this.errorMessage = errorMessage; } @@ -26,11 +31,24 @@ public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } - public long getErrorCode() { + public Long getErrorCode() { return errorCode; } - public void setErrorCode(long errorCode) { + public void setErrorCode(Long errorCode) { this.errorCode = errorCode; } + + /** + Fields that are not recognized for this object + + @return A map of JSON keys to objects + */ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } } diff --git a/src/main/java/com/apple/itunes/storekit/model/ExpirationIntent.java b/src/main/java/com/apple/itunes/storekit/model/ExpirationIntent.java index b064a581..d80d83ac 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ExpirationIntent.java +++ b/src/main/java/com/apple/itunes/storekit/model/ExpirationIntent.java @@ -8,13 +8,28 @@ * The reason an auto-renewable subscription expired. * * @see expirationIntent - */ + **/ public enum ExpirationIntent { + /** + * The customer canceled their subscription. + **/ CUSTOMER_CANCELLED(1), + /** + * Billing error; for example, the customer’s payment information is no longer valid. + **/ BILLING_ERROR(2), + /** + * The customer didn’t consent to an auto-renewable subscription price increase that requires their consent, or to a subscription offer conversion that requires their consent, so the subscription expired. + **/ CUSTOMER_DID_NOT_CONSENT_TO_PRICE_INCREASE(3), + /** + * The product wasn’t available for purchase at the time of renewal. + **/ PRODUCT_NOT_AVAILABLE(4), + /** + * The subscription expired for some other reason. + **/ OTHER(5); private final Integer value; @@ -42,4 +57,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ExtendReasonCode.java b/src/main/java/com/apple/itunes/storekit/model/ExtendReasonCode.java index 37260730..bc84a61a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ExtendReasonCode.java +++ b/src/main/java/com/apple/itunes/storekit/model/ExtendReasonCode.java @@ -8,12 +8,24 @@ * The code that represents the reason for the subscription-renewal-date extension. * * @see extendReasonCode - */ + **/ public enum ExtendReasonCode { + /** + * Undeclared; no information provided. + **/ UNDECLARED(0), + /** + * The renewal-date extension is for customer satisfaction. + **/ CUSTOMER_SATISFACTION(1), + /** + * The renewal-date extension is for other reasons. + **/ OTHER(2), + /** + * The renewal-date extension is due to a service issue or outage. + **/ SERVICE_ISSUE_OR_OUTAGE(3); private final Integer value; @@ -41,4 +53,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateRequest.java b/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateRequest.java index 3b3058fd..6c0840d9 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateRequest.java @@ -11,25 +11,41 @@ * The request body that contains subscription-renewal-extension data for an individual subscription. * * @see ExtendRenewalDateRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class ExtendRenewalDateRequest { private static final String SERIALIZED_NAME_EXTEND_BY_DAYS = "extendByDays"; private static final String SERIALIZED_NAME_EXTEND_REASON_CODE = "extendReasonCode"; private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; - @JsonProperty(SERIALIZED_NAME_EXTEND_BY_DAYS) + + @JsonProperty(value = SERIALIZED_NAME_EXTEND_BY_DAYS, required = true) private Integer extendByDays; - @JsonProperty(SERIALIZED_NAME_EXTEND_REASON_CODE) - private ExtendReasonCode extendReasonCode; - @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) + @JsonProperty(value = SERIALIZED_NAME_EXTEND_REASON_CODE, required = true) + private Integer extendReasonCode; + @JsonProperty(value = SERIALIZED_NAME_REQUEST_IDENTIFIER, required = true) private String requestIdentifier; + private static final int MINIMUM_EXTEND_BY_DAYS = 1; + private static final int MAXIMUM_EXTEND_BY_DAYS = 90; + private static final int MAXIMUM_REQUEST_IDENTIFIER_LENGTH = 128; + + protected ExtendRenewalDateRequest() { + } + + public ExtendRenewalDateRequest(Integer extendByDays, ExtendReasonCode extendReasonCode, String requestIdentifier) { + this.extendByDays = validateExtendByDays(extendByDays); + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + } - public ExtendRenewalDateRequest() { + public ExtendRenewalDateRequest(Integer extendByDays, Integer rawExtendReasonCode, String requestIdentifier) { + this.extendByDays = validateExtendByDays(extendByDays); + this.extendReasonCode = Objects.requireNonNull(rawExtendReasonCode); + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); } public ExtendRenewalDateRequest extendByDays(Integer extendByDays) { - this.extendByDays = extendByDays; + this.extendByDays = validateExtendByDays(extendByDays); return this; } @@ -38,42 +54,60 @@ public ExtendRenewalDateRequest extendByDays(Integer extendByDays) { * * @return extendByDays * @see extendByDays - * maximum: 90 **/ public Integer getExtendByDays() { return extendByDays; } public void setExtendByDays(Integer extendByDays) { - this.extendByDays = extendByDays; + this.extendByDays = validateExtendByDays(extendByDays); + } + + private Integer validateExtendByDays(Integer extendByDays) { + Objects.requireNonNull(extendByDays); + if (extendByDays < MINIMUM_EXTEND_BY_DAYS || extendByDays > MAXIMUM_EXTEND_BY_DAYS) { + throw new IllegalArgumentException("extendByDays must be between " + MINIMUM_EXTEND_BY_DAYS + " and " + MAXIMUM_EXTEND_BY_DAYS); + } + return extendByDays; } public ExtendRenewalDateRequest extendReasonCode(ExtendReasonCode extendReasonCode) { - this.extendReasonCode = extendReasonCode; + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); return this; } /** - * The reason code for the subscription date extension + * The reason code for the subscription date extension. * * @return extendReasonCode * @see extendReasonCode **/ public ExtendReasonCode getExtendReasonCode() { + return ExtendReasonCode.fromValue(extendReasonCode); + } + + /** + * @see #getExtendReasonCode() + **/ + public Integer getRawExtendReasonCode() { return extendReasonCode; } public void setExtendReasonCode(ExtendReasonCode extendReasonCode) { - this.extendReasonCode = extendReasonCode; + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); + } + + public void setRawExtendReasonCode(Integer rawExtendReasonCode) { + this.extendReasonCode = Objects.requireNonNull(rawExtendReasonCode); } public ExtendRenewalDateRequest requestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); return this; } /** - * A string that contains a unique identifier you provide to track each subscription-renewal-date extension request. + * A string that contains a value you provide to uniquely identify this renewal-date extension request. * * @return requestIdentifier * @see requestIdentifier @@ -83,7 +117,15 @@ public String getRequestIdentifier() { } public void setRequestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + } + + private String validateRequestIdentifier(String requestIdentifier) { + Objects.requireNonNull(requestIdentifier); + if (requestIdentifier.length() > MAXIMUM_REQUEST_IDENTIFIER_LENGTH) { + throw new IllegalArgumentException("requestIdentifier length longer than maximum allowed"); + } + return requestIdentifier; } @Override @@ -114,4 +156,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateResponse.java b/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateResponse.java index 73e61026..0e3bf176 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/ExtendRenewalDateResponse.java @@ -12,63 +12,63 @@ * A response that indicates whether an individual renewal-date extension succeeded, and related details. * * @see ExtendRenewalDateResponse - */ + **/ public class ExtendRenewalDateResponse { + private static final String SERIALIZED_NAME_EFFECTIVE_DATE = "effectiveDate"; private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; - private static final String SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID = "webOrderLineItemId"; private static final String SERIALIZED_NAME_SUCCESS = "success"; - private static final String SERIALIZED_NAME_EFFECTIVE_DATE = "effectiveDate"; + private static final String SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID = "webOrderLineItemId"; + + @JsonProperty(SERIALIZED_NAME_EFFECTIVE_DATE) + private Long effectiveDate; @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) private String originalTransactionId; - @JsonProperty(SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID) - private String webOrderLineItemId; @JsonProperty(SERIALIZED_NAME_SUCCESS) private Boolean success; - @JsonProperty(SERIALIZED_NAME_EFFECTIVE_DATE) - private Long effectiveDate; + @JsonProperty(SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID) + private String webOrderLineItemId; @JsonAnySetter private Map unknownFields; - public ExtendRenewalDateResponse() { } - public ExtendRenewalDateResponse originalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public ExtendRenewalDateResponse effectiveDate(Long effectiveDate) { + this.effectiveDate = effectiveDate; return this; } /** - * The original transaction identifier of a purchase. + * The new subscription expiration date of a successful subscription-renewal-date extension. * - * @return originalTransactionId - * @see originalTransactionId + * @return effectiveDate + * @see effectiveDate **/ - public String getOriginalTransactionId() { - return originalTransactionId; + public Long getEffectiveDate() { + return effectiveDate; } - public void setOriginalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public void setEffectiveDate(Long effectiveDate) { + this.effectiveDate = effectiveDate; } - public ExtendRenewalDateResponse webOrderLineItemId(String webOrderLineItemId) { - this.webOrderLineItemId = webOrderLineItemId; + public ExtendRenewalDateResponse originalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; return this; } /** - * The unique identifier of subscription-purchase events across devices, including renewals. + * The original transaction identifier of the subscription that experienced a service interruption. * - * @return webOrderLineItemId - * @see webOrderLineItemId + * @return originalTransactionId + * @see originalTransactionId **/ - public String getWebOrderLineItemId() { - return webOrderLineItemId; + public String getOriginalTransactionId() { + return originalTransactionId; } - public void setWebOrderLineItemId(String webOrderLineItemId) { - this.webOrderLineItemId = webOrderLineItemId; + public void setOriginalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; } public ExtendRenewalDateResponse success(Boolean success) { @@ -90,23 +90,23 @@ public void setSuccess(Boolean success) { this.success = success; } - public ExtendRenewalDateResponse effectiveDate(Long effectiveDate) { - this.effectiveDate = effectiveDate; + public ExtendRenewalDateResponse webOrderLineItemId(String webOrderLineItemId) { + this.webOrderLineItemId = webOrderLineItemId; return this; } /** - * The new subscription expiration date for a subscription-renewal extension. + * A unique ID that identifies subscription-purchase events, including subscription renewals, across devices. * - * @return effectiveDate - * @see effectiveDate + * @return webOrderLineItemId + * @see webOrderLineItemId **/ - public Long getEffectiveDate() { - return effectiveDate; + public String getWebOrderLineItemId() { + return webOrderLineItemId; } - public void setEffectiveDate(Long effectiveDate) { - this.effectiveDate = effectiveDate; + public void setWebOrderLineItemId(String webOrderLineItemId) { + this.webOrderLineItemId = webOrderLineItemId; } public ExtendRenewalDateResponse unknownFields(Map unknownFields) { @@ -115,10 +115,10 @@ public ExtendRenewalDateResponse unknownFields(Map unknownFields } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -136,27 +136,26 @@ public boolean equals(Object o) { return false; } ExtendRenewalDateResponse extendRenewalDateResponse = (ExtendRenewalDateResponse) o; - return Objects.equals(this.originalTransactionId, extendRenewalDateResponse.originalTransactionId) && - Objects.equals(this.webOrderLineItemId, extendRenewalDateResponse.webOrderLineItemId) && + return Objects.equals(this.effectiveDate, extendRenewalDateResponse.effectiveDate) && + Objects.equals(this.originalTransactionId, extendRenewalDateResponse.originalTransactionId) && Objects.equals(this.success, extendRenewalDateResponse.success) && - Objects.equals(this.effectiveDate, extendRenewalDateResponse.effectiveDate) && + Objects.equals(this.webOrderLineItemId, extendRenewalDateResponse.webOrderLineItemId) && Objects.equals(this.unknownFields, extendRenewalDateResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(originalTransactionId, webOrderLineItemId, success, effectiveDate, unknownFields); + return Objects.hash(effectiveDate, originalTransactionId, success, webOrderLineItemId, unknownFields); } @Override public String toString() { return "ExtendRenewalDateResponse{" + - "originalTransactionId='" + originalTransactionId + '\'' + - ", webOrderLineItemId='" + webOrderLineItemId + '\'' + + "effectiveDate=" + effectiveDate + + ", originalTransactionId='" + originalTransactionId + '\'' + ", success=" + success + - ", effectiveDate=" + effectiveDate + + ", webOrderLineItemId='" + webOrderLineItemId + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ExternalPurchaseToken.java b/src/main/java/com/apple/itunes/storekit/model/ExternalPurchaseToken.java index 7b02142d..4c8f53a2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ExternalPurchaseToken.java +++ b/src/main/java/com/apple/itunes/storekit/model/ExternalPurchaseToken.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -12,39 +13,53 @@ * The payload data that contains an external purchase token. * * @see externalPurchaseToken - */ + **/ public class ExternalPurchaseToken { private static final String SERIALIZED_NAME_EXTERNAL_PURCHASE_ID = "externalPurchaseId"; private static final String SERIALIZED_NAME_TOKEN_CREATION_DATE = "tokenCreationDate"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; - private static final String SERIALIZED_NAME_TOKEN_TYPE = "tokenType"; private static final String SERIALIZED_NAME_TOKEN_EXPIRATION_DATE = "tokenExpirationDate"; - @JsonProperty(SERIALIZED_NAME_EXTERNAL_PURCHASE_ID) + private static final String SERIALIZED_NAME_TOKEN_TYPE = "tokenType"; + + @JsonProperty(value = SERIALIZED_NAME_EXTERNAL_PURCHASE_ID, required = true) private String externalPurchaseId; - @JsonProperty(SERIALIZED_NAME_TOKEN_CREATION_DATE) + @JsonProperty(value = SERIALIZED_NAME_TOKEN_CREATION_DATE, required = true) private Long tokenCreationDate; - @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) + @JsonProperty(value = SERIALIZED_NAME_APP_APPLE_ID, required = true) private Long appAppleId; - @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) + @JsonProperty(value = SERIALIZED_NAME_BUNDLE_ID, required = true) private String bundleId; - @JsonProperty(SERIALIZED_NAME_TOKEN_TYPE) - private String tokenType; @JsonProperty(SERIALIZED_NAME_TOKEN_EXPIRATION_DATE) private Long tokenExpirationDate; + @JsonProperty(SERIALIZED_NAME_TOKEN_TYPE) + private String tokenType; @JsonAnySetter private Map unknownFields; - public ExternalPurchaseToken() { + protected ExternalPurchaseToken() { + } + + @JsonCreator + public ExternalPurchaseToken( + @JsonProperty(value = SERIALIZED_NAME_EXTERNAL_PURCHASE_ID, required = true) String externalPurchaseId, + @JsonProperty(value = SERIALIZED_NAME_TOKEN_CREATION_DATE, required = true) Long tokenCreationDate, + @JsonProperty(value = SERIALIZED_NAME_APP_APPLE_ID, required = true) Long appAppleId, + @JsonProperty(value = SERIALIZED_NAME_BUNDLE_ID, required = true) String bundleId + ) { + this.externalPurchaseId = Objects.requireNonNull(externalPurchaseId); + this.tokenCreationDate = Objects.requireNonNull(tokenCreationDate); + this.appAppleId = Objects.requireNonNull(appAppleId); + this.bundleId = Objects.requireNonNull(bundleId); } public ExternalPurchaseToken externalPurchaseId(String externalPurchaseId) { - this.externalPurchaseId = externalPurchaseId; + this.externalPurchaseId = Objects.requireNonNull(externalPurchaseId); return this; } /** - * The field of an external purchase token that uniquely identifies the token. + * The unique identifier of the token. * * @return externalPurchaseId * @see externalPurchaseId @@ -54,16 +69,16 @@ public String getExternalPurchaseId() { } public void setExternalPurchaseId(String externalPurchaseId) { - this.externalPurchaseId = externalPurchaseId; + this.externalPurchaseId = Objects.requireNonNull(externalPurchaseId); } public ExternalPurchaseToken tokenCreationDate(Long tokenCreationDate) { - this.tokenCreationDate = tokenCreationDate; + this.tokenCreationDate = Objects.requireNonNull(tokenCreationDate); return this; } /** - * The field of an external purchase token that contains the UNIX date, in milliseconds, when the system created the token. + * The UNIX time, in milliseconds, when the system created the token. * * @return tokenCreationDate * @see tokenCreationDate @@ -73,16 +88,16 @@ public Long getTokenCreationDate() { } public void setTokenCreationDate(Long tokenCreationDate) { - this.tokenCreationDate = tokenCreationDate; + this.tokenCreationDate = Objects.requireNonNull(tokenCreationDate); } public ExternalPurchaseToken appAppleId(Long appAppleId) { - this.appAppleId = appAppleId; + this.appAppleId = Objects.requireNonNull(appAppleId); return this; } /** - * The unique identifier of an app in the App Store. + * The app Apple ID for which the system generated the token. * * @return appAppleId * @see appAppleId @@ -92,16 +107,16 @@ public Long getAppAppleId() { } public void setAppAppleId(Long appAppleId) { - this.appAppleId = appAppleId; + this.appAppleId = Objects.requireNonNull(appAppleId); } public ExternalPurchaseToken bundleId(String bundleId) { - this.bundleId = bundleId; + this.bundleId = Objects.requireNonNull(bundleId); return this; } /** - * The bundle identifier of an app. + * The bundle ID of the app for which the system generated the token. * * @return bundleId * @see bundleId @@ -111,7 +126,26 @@ public String getBundleId() { } public void setBundleId(String bundleId) { - this.bundleId = bundleId; + this.bundleId = Objects.requireNonNull(bundleId); + } + + public ExternalPurchaseToken tokenExpirationDate(Long tokenExpirationDate) { + this.tokenExpirationDate = tokenExpirationDate; + return this; + } + + /** + * The UNIX time, in milliseconds, when a token expires. + * + * @return tokenExpirationDate + * @see tokenExpirationDate + **/ + public Long getTokenExpirationDate() { + return tokenExpirationDate; + } + + public void setTokenExpirationDate(Long tokenExpirationDate) { + this.tokenExpirationDate = tokenExpirationDate; } public ExternalPurchaseToken tokenType(TokenType tokenType) { @@ -120,18 +154,18 @@ public ExternalPurchaseToken tokenType(TokenType tokenType) { } /** - * The type of an external purchase custom link token. + * The custom link token type, either SERVICES or ACQUISITION. * * @return tokenType * @see tokenType **/ public TokenType getTokenType() { - return tokenType != null ? TokenType.fromValue(tokenType) : null; + return TokenType.fromValue(tokenType); } /** * @see #getTokenType() - */ + **/ public String getRawTokenType() { return tokenType; } @@ -144,35 +178,16 @@ public void setRawTokenType(String rawTokenType) { this.tokenType = rawTokenType; } - public ExternalPurchaseToken tokenExpirationDate(Long tokenExpirationDate) { - this.tokenExpirationDate = tokenExpirationDate; - return this; - } - - /** - * The field of a custom link token that contains the UNIX date, in milliseconds, when the token expires. - * - * @return tokenExpirationDate - * @see tokenExpirationDate - **/ - public Long getTokenExpirationDate() { - return tokenExpirationDate; - } - - public void setTokenExpirationDate(Long tokenExpirationDate) { - this.tokenExpirationDate = tokenExpirationDate; - } - public ExternalPurchaseToken unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -194,14 +209,14 @@ public boolean equals(Object o) { Objects.equals(this.tokenCreationDate, externalPurchaseToken.tokenCreationDate) && Objects.equals(this.appAppleId, externalPurchaseToken.appAppleId) && Objects.equals(this.bundleId, externalPurchaseToken.bundleId) && - Objects.equals(this.tokenType, externalPurchaseToken.tokenType) && Objects.equals(this.tokenExpirationDate, externalPurchaseToken.tokenExpirationDate) && + Objects.equals(this.tokenType, externalPurchaseToken.tokenType) && Objects.equals(this.unknownFields, externalPurchaseToken.unknownFields); } @Override public int hashCode() { - return Objects.hash(externalPurchaseId, tokenCreationDate, appAppleId, bundleId, tokenType, tokenExpirationDate, unknownFields); + return Objects.hash(externalPurchaseId, tokenCreationDate, appAppleId, bundleId, tokenExpirationDate, tokenType, unknownFields); } @Override @@ -211,10 +226,9 @@ public String toString() { ", tokenCreationDate=" + tokenCreationDate + ", appAppleId=" + appAppleId + ", bundleId='" + bundleId + '\'' + - ", tokenType='" + tokenType + '\'' + ", tokenExpirationDate=" + tokenExpirationDate + + ", tokenType='" + tokenType + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/GetCustomerGroupsResponse.java b/src/main/java/com/apple/itunes/storekit/model/GetCustomerGroupsResponse.java new file mode 100644 index 00000000..e6b06139 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/GetCustomerGroupsResponse.java @@ -0,0 +1,100 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A response that contains the groups a customer belongs to, and their role in each group. + * + * @see GetCustomerGroupsResponse + **/ +public class GetCustomerGroupsResponse { + private static final String SERIALIZED_NAME_GROUPS = "groups"; + + @JsonProperty(SERIALIZED_NAME_GROUPS) + private List groups; + @JsonAnySetter + private Map unknownFields; + + public GetCustomerGroupsResponse() { + } + + public GetCustomerGroupsResponse groups(List groups) { + this.groups = groups; + return this; + } + + public GetCustomerGroupsResponse addGroup(GroupEntry group) { + Objects.requireNonNull(group); + if (this.groups == null) { + this.groups = new ArrayList<>(); + } + this.groups.add(group); + return this; + } + + /** + * An array of groups that the customer belongs to. + * + * @return groups + * @see GroupEntry + **/ + public List getGroups() { + return groups; + } + + public void setGroups(List groups) { + this.groups = groups; + } + + public GetCustomerGroupsResponse unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GetCustomerGroupsResponse getCustomerGroupsResponse = (GetCustomerGroupsResponse) o; + return Objects.equals(this.groups, getCustomerGroupsResponse.groups) && + Objects.equals(this.unknownFields, getCustomerGroupsResponse.unknownFields); + } + + @Override + public int hashCode() { + return Objects.hash(groups, unknownFields); + } + + @Override + public String toString() { + return "GetCustomerGroupsResponse{" + + "groups=" + groups + + ", unknownFields=" + unknownFields + + '}'; + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/GetGroupMembersResponse.java b/src/main/java/com/apple/itunes/storekit/model/GetGroupMembersResponse.java new file mode 100644 index 00000000..75b10db2 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/GetGroupMembersResponse.java @@ -0,0 +1,148 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A response that contains a page of the customers that belong to a group. + * + * @see GetGroupMembersResponse + **/ +public class GetGroupMembersResponse { + private static final String SERIALIZED_NAME_MEMBERS = "members"; + private static final String SERIALIZED_NAME_PAGINATION_TOKEN = "paginationToken"; + private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; + + @JsonProperty(SERIALIZED_NAME_MEMBERS) + private List members; + @JsonProperty(SERIALIZED_NAME_PAGINATION_TOKEN) + private String paginationToken; + @JsonProperty(SERIALIZED_NAME_HAS_MORE) + private Boolean hasMore; + @JsonAnySetter + private Map unknownFields; + + public GetGroupMembersResponse() { + } + + public GetGroupMembersResponse members(List members) { + this.members = members; + return this; + } + + public GetGroupMembersResponse addMember(GroupMemberEntry member) { + Objects.requireNonNull(member); + if (this.members == null) { + this.members = new ArrayList<>(); + } + this.members.add(member); + return this; + } + + /** + * An array of the customers that belong to the group. + * + * @return members + * @see GroupMemberEntry + **/ + public List getMembers() { + return members; + } + + public void setMembers(List members) { + this.members = members; + } + + public GetGroupMembersResponse paginationToken(String paginationToken) { + this.paginationToken = paginationToken; + return this; + } + + /** + * A token you send in a subsequent request to get the next set of members. + * + * @return paginationToken + * @see paginationToken + **/ + public String getPaginationToken() { + return paginationToken; + } + + public void setPaginationToken(String paginationToken) { + this.paginationToken = paginationToken; + } + + public GetGroupMembersResponse hasMore(Boolean hasMore) { + this.hasMore = hasMore; + return this; + } + + /** + * A Boolean value that indicates whether the group has more members than the response contains. + * + * @return hasMore + * @see hasMore + **/ + public Boolean getHasMore() { + return hasMore; + } + + public void setHasMore(Boolean hasMore) { + this.hasMore = hasMore; + } + + public GetGroupMembersResponse unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GetGroupMembersResponse getGroupMembersResponse = (GetGroupMembersResponse) o; + return Objects.equals(this.members, getGroupMembersResponse.members) && + Objects.equals(this.paginationToken, getGroupMembersResponse.paginationToken) && + Objects.equals(this.hasMore, getGroupMembersResponse.hasMore) && + Objects.equals(this.unknownFields, getGroupMembersResponse.unknownFields); + } + + @Override + public int hashCode() { + return Objects.hash(members, paginationToken, hasMore, unknownFields); + } + + @Override + public String toString() { + return "GetGroupMembersResponse{" + + "members=" + members + + ", paginationToken='" + paginationToken + '\'' + + ", hasMore=" + hasMore + + ", unknownFields=" + unknownFields + + '}'; + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/GetImageListResponse.java b/src/main/java/com/apple/itunes/storekit/model/GetImageListResponse.java index 8c0df7ed..1d91865a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/GetImageListResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/GetImageListResponse.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -13,15 +14,15 @@ * A response that contains status information for all images. * * @see GetImageListResponse - */ + **/ public class GetImageListResponse { private static final String SERIALIZED_NAME_IMAGE_IDENTIFIERS = "imageIdentifiers"; + @JsonProperty(SERIALIZED_NAME_IMAGE_IDENTIFIERS) private List imageIdentifiers; @JsonAnySetter private Map unknownFields; - public GetImageListResponse() { } @@ -30,6 +31,15 @@ public GetImageListResponse imageIdentifiers(List imag return this; } + public GetImageListResponse addImageIdentifier(GetImageListResponseItem imageIdentifier) { + Objects.requireNonNull(imageIdentifier); + if (this.imageIdentifiers == null) { + this.imageIdentifiers = new ArrayList<>(); + } + this.imageIdentifiers.add(imageIdentifier); + return this; + } + /** * An array of all image identifiers and their image state. * @@ -50,10 +60,10 @@ public GetImageListResponse unknownFields(Map unknownFields) { } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +98,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/GetImageListResponseItem.java b/src/main/java/com/apple/itunes/storekit/model/GetImageListResponseItem.java index d906ebd6..af916d9a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/GetImageListResponseItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/GetImageListResponseItem.java @@ -13,17 +13,18 @@ * An image identifier and state information for an image. * * @see GetImageListResponseItem - */ + **/ public class GetImageListResponseItem { private static final String SERIALIZED_NAME_IMAGE_IDENTIFIER = "imageIdentifier"; - private static final String SERIALIZED_NAME_IMAGE_STATE = "imageState"; private static final String SERIALIZED_NAME_IMAGE_SIZE = "imageSize"; + private static final String SERIALIZED_NAME_IMAGE_STATE = "imageState"; + @JsonProperty(SERIALIZED_NAME_IMAGE_IDENTIFIER) private UUID imageIdentifier; - @JsonProperty(SERIALIZED_NAME_IMAGE_STATE) - private String imageState; @JsonProperty(SERIALIZED_NAME_IMAGE_SIZE) private String imageSize; + @JsonProperty(SERIALIZED_NAME_IMAGE_STATE) + private String imageState; @JsonAnySetter private Map unknownFields; @@ -49,77 +50,76 @@ public void setImageIdentifier(UUID imageIdentifier) { this.imageIdentifier = imageIdentifier; } - public GetImageListResponseItem imageState(ImageState imageState) { - this.imageState = imageState != null ? imageState.getValue() : null; + public GetImageListResponseItem imageSize(ImageSize imageSize) { + this.imageSize = imageSize != null ? imageSize.getValue() : null; return this; } /** - * The current state of the image. + * The size of the image. * - * @return imageState - * @see imageState + * @return imageSize + * @see imageSize **/ - public ImageState getImageState() { - return imageState != null ? ImageState.fromValue(imageState) : null; + public ImageSize getImageSize() { + return ImageSize.fromValue(imageSize); } /** - * @see #getImageState() - */ - public String getRawImageState() { - return imageState; + * @see #getImageSize() + **/ + public String getRawImageSize() { + return imageSize; } - public void setImageState(ImageState imageState) { - this.imageState = imageState != null ? imageState.getValue() : null; + public void setImageSize(ImageSize imageSize) { + this.imageSize = imageSize != null ? imageSize.getValue() : null; } - public void setRawImageState(String rawImageState) { - this.imageState = rawImageState; + public void setRawImageSize(String rawImageSize) { + this.imageSize = rawImageSize; } - public GetImageListResponseItem imageSize(ImageSize imageSize) { - this.imageSize = imageSize != null ? imageSize.getValue() : null; + public GetImageListResponseItem imageState(ImageState imageState) { + this.imageState = imageState != null ? imageState.getValue() : null; return this; } /** - * The size of the image. + * The current state of the image. * - * @return imageSize - * @see imageSize + * @return imageState + * @see imageState **/ - public ImageSize getImageSize() { - return imageSize != null ? ImageSize.fromValue(imageSize) : null; + public ImageState getImageState() { + return ImageState.fromValue(imageState); } /** - * @see #getImageSize() - */ - public String getRawImageSize() { - return imageSize; + * @see #getImageState() + **/ + public String getRawImageState() { + return imageState; } - public void setImageSize(ImageSize imageSize) { - this.imageSize = imageSize != null ? imageSize.getValue() : null; + public void setImageState(ImageState imageState) { + this.imageState = imageState != null ? imageState.getValue() : null; } - public void setRawImageSize(String rawImageSize) { - this.imageSize = rawImageSize; + public void setRawImageState(String rawImageState) { + this.imageState = rawImageState; } - public GetImageListResponseItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -138,24 +138,23 @@ public boolean equals(Object o) { } GetImageListResponseItem getImageListResponseItem = (GetImageListResponseItem) o; return Objects.equals(this.imageIdentifier, getImageListResponseItem.imageIdentifier) && - Objects.equals(this.imageState, getImageListResponseItem.imageState) && Objects.equals(this.imageSize, getImageListResponseItem.imageSize) && + Objects.equals(this.imageState, getImageListResponseItem.imageState) && Objects.equals(this.unknownFields, getImageListResponseItem.unknownFields); } @Override public int hashCode() { - return Objects.hash(imageIdentifier, imageState, imageSize, unknownFields); + return Objects.hash(imageIdentifier, imageSize, imageState, unknownFields); } @Override public String toString() { return "GetImageListResponseItem{" + "imageIdentifier=" + imageIdentifier + - ", imageState='" + imageState + '\'' + ", imageSize='" + imageSize + '\'' + + ", imageState='" + imageState + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponse.java b/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponse.java index 6632f40c..9ac04496 100644 --- a/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponse.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -13,15 +14,15 @@ * A response that contains status information for all messages. * * @see GetMessageListResponse - */ + **/ public class GetMessageListResponse { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIERS = "messageIdentifiers"; + @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIERS) private List messageIdentifiers; @JsonAnySetter private Map unknownFields; - public GetMessageListResponse() { } @@ -30,11 +31,20 @@ public GetMessageListResponse messageIdentifiers(List(); + } + this.messageIdentifiers.add(messageIdentifier); + return this; + } + /** - * An array of all message identifiers and their message state. + * An array of all message identifiers and their message states. * * @return messageIdentifiers - * @see messageIdentifiers + * @see GetMessageListResponseItem **/ public List getMessageIdentifiers() { return messageIdentifiers; @@ -50,10 +60,10 @@ public GetMessageListResponse unknownFields(Map unknownFields) { } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +98,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponseItem.java b/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponseItem.java index a6af3dad..2501f516 100644 --- a/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponseItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/GetMessageListResponseItem.java @@ -13,10 +13,11 @@ * A message identifier and status information for a message. * * @see GetMessageListResponseItem - */ + **/ public class GetMessageListResponseItem { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; private static final String SERIALIZED_NAME_MESSAGE_STATE = "messageState"; + @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIER) private UUID messageIdentifier; @JsonProperty(SERIALIZED_NAME_MESSAGE_STATE) @@ -55,15 +56,15 @@ public GetMessageListResponseItem messageState(MessageState messageState) { * The current state of the message. * * @return messageState - * @see messageState + * @see messageState **/ public MessageState getMessageState() { - return messageState != null ? MessageState.fromValue(messageState) : null; + return MessageState.fromValue(messageState); } /** * @see #getMessageState() - */ + **/ public String getRawMessageState() { return messageState; } @@ -76,17 +77,16 @@ public void setRawMessageState(String rawMessageState) { this.messageState = rawMessageState; } - public GetMessageListResponseItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -103,10 +103,10 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - GetMessageListResponseItem sendAttemptItem = (GetMessageListResponseItem) o; - return Objects.equals(this.messageIdentifier, sendAttemptItem.messageIdentifier) && - Objects.equals(this.messageState, sendAttemptItem.messageState) && - Objects.equals(this.unknownFields, sendAttemptItem.unknownFields); + GetMessageListResponseItem getMessageListResponseItem = (GetMessageListResponseItem) o; + return Objects.equals(this.messageIdentifier, getMessageListResponseItem.messageIdentifier) && + Objects.equals(this.messageState, getMessageListResponseItem.messageState) && + Objects.equals(this.unknownFields, getMessageListResponseItem.unknownFields); } @Override @@ -123,4 +123,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/GroupEntry.java b/src/main/java/com/apple/itunes/storekit/model/GroupEntry.java new file mode 100644 index 00000000..b13004e4 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/GroupEntry.java @@ -0,0 +1,159 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * The identifier, type, and per-product roles for a group that a customer belongs to. + * + * @see GroupEntry + **/ +public class GroupEntry { + private static final String SERIALIZED_NAME_GROUP_ID = "groupId"; + private static final String SERIALIZED_NAME_GROUP_TYPE = "groupType"; + private static final String SERIALIZED_NAME_ROLES = "roles"; + + @JsonProperty(SERIALIZED_NAME_GROUP_ID) + private String groupId; + @JsonProperty(SERIALIZED_NAME_GROUP_TYPE) + private String groupType; + @JsonProperty(SERIALIZED_NAME_ROLES) + private List roles; + @JsonAnySetter + private Map unknownFields; + + public GroupEntry() { + } + + public GroupEntry groupId(String groupId) { + this.groupId = groupId; + return this; + } + + /** + * The identifier of the group. + * + * @return groupId + * @see groupId + **/ + public String getGroupId() { + return groupId; + } + + public void setGroupId(String groupId) { + this.groupId = groupId; + } + + public GroupEntry groupType(GroupType groupType) { + this.groupType = groupType != null ? groupType.getValue() : null; + return this; + } + + /** + * The type of the group. + * + * @return groupType + * @see groupType + **/ + public GroupType getGroupType() { + return GroupType.fromValue(groupType); + } + + /** + * @see #getGroupType() + **/ + public String getRawGroupType() { + return groupType; + } + + public void setGroupType(GroupType groupType) { + this.groupType = groupType != null ? groupType.getValue() : null; + } + + public void setRawGroupType(String rawGroupType) { + this.groupType = rawGroupType; + } + + public GroupEntry roles(List roles) { + this.roles = roles; + return this; + } + + public GroupEntry addRole(RoleEntry role) { + Objects.requireNonNull(role); + if (this.roles == null) { + this.roles = new ArrayList<>(); + } + this.roles.add(role); + return this; + } + + /** + * An optional array of the customer’s roles in this group, one for each of your products that the group provides access to. + * + * @return roles + * @see RoleEntry + **/ + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public GroupEntry unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GroupEntry groupEntry = (GroupEntry) o; + return Objects.equals(this.groupId, groupEntry.groupId) && + Objects.equals(this.groupType, groupEntry.groupType) && + Objects.equals(this.roles, groupEntry.roles) && + Objects.equals(this.unknownFields, groupEntry.unknownFields); + } + + @Override + public int hashCode() { + return Objects.hash(groupId, groupType, roles, unknownFields); + } + + @Override + public String toString() { + return "GroupEntry{" + + "groupId='" + groupId + '\'' + + ", groupType='" + groupType + '\'' + + ", roles=" + roles + + ", unknownFields=" + unknownFields + + '}'; + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/GroupMemberEntry.java b/src/main/java/com/apple/itunes/storekit/model/GroupMemberEntry.java new file mode 100644 index 00000000..cd8611b0 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/GroupMemberEntry.java @@ -0,0 +1,89 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; +import java.util.Objects; + +/** + * A customer that belongs to a group. + * + * @see GroupMemberEntry + **/ +public class GroupMemberEntry { + private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; + + @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) + private String appTransactionId; + @JsonAnySetter + private Map unknownFields; + + public GroupMemberEntry() { + } + + public GroupMemberEntry appTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; + return this; + } + + /** + * The unique identifier of the member’s app download transaction. + * + * @return appTransactionId + * @see appTransactionId + **/ + public String getAppTransactionId() { + return appTransactionId; + } + + public void setAppTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; + } + + public GroupMemberEntry unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GroupMemberEntry groupMemberEntry = (GroupMemberEntry) o; + return Objects.equals(this.appTransactionId, groupMemberEntry.appTransactionId) && + Objects.equals(this.unknownFields, groupMemberEntry.unknownFields); + } + + @Override + public int hashCode() { + return Objects.hash(appTransactionId, unknownFields); + } + + @Override + public String toString() { + return "GroupMemberEntry{" + + "appTransactionId='" + appTransactionId + '\'' + + ", unknownFields=" + unknownFields + + '}'; + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/GroupType.java b/src/main/java/com/apple/itunes/storekit/model/GroupType.java new file mode 100644 index 00000000..92c495d9 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/GroupType.java @@ -0,0 +1,47 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * A string that describes the kind of multiseat purchase a customer’s access comes from. + * + * @see groupType + **/ +public enum GroupType { + + /** + * An organization bought seats through Volume Purchasing and assigned one to the customer. + **/ + ORGANIZATION("ORGANIZATION"), + /** + * A subscriber bought seats through Group Purchases and invited the customer to join. + **/ + CONSUMER("CONSUMER"); + + private final String value; + + GroupType(String value) { + this.value = value; + } + + public static GroupType fromValue(String value) { + for (GroupType b : GroupType.values()) { + if (b.value.equals(value)) { + return b; + } + } + return null; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/HeaderPosition.java b/src/main/java/com/apple/itunes/storekit/model/HeaderPosition.java index dc45526b..82b8e5d3 100644 --- a/src/main/java/com/apple/itunes/storekit/model/HeaderPosition.java +++ b/src/main/java/com/apple/itunes/storekit/model/HeaderPosition.java @@ -8,10 +8,16 @@ * The position where the header text appears in a message. * * @see headerPosition - */ + **/ public enum HeaderPosition { + /** + * Position the header text above the message body. + **/ ABOVE_BODY("ABOVE_BODY"), + /** + * Position the header text above the image. + **/ ABOVE_IMAGE("ABOVE_IMAGE"); private final String value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/HelperValidationUtils.java b/src/main/java/com/apple/itunes/storekit/model/HelperValidationUtils.java index 6266629d..eae413f5 100644 --- a/src/main/java/com/apple/itunes/storekit/model/HelperValidationUtils.java +++ b/src/main/java/com/apple/itunes/storekit/model/HelperValidationUtils.java @@ -43,7 +43,7 @@ public static String validateDisplayName(String displayName) { * @throws IllegalArgumentException if SKU exceeds maximum length */ public static String validateSku(String sku) { - if (sku != null && sku.length() > MAXIMUM_SKU_LENGTH) { + if (sku != null && sku.codePointCount(0, sku.length()) > MAXIMUM_SKU_LENGTH) { throw new IllegalArgumentException("SKU length cannot exceed " + MAXIMUM_SKU_LENGTH + " characters"); } return sku; @@ -53,7 +53,8 @@ public static String validateSku(String sku) { * Validates periodCount is not null and between `MIN_PERIOD` and `MAX_PERIOD` inclusive. * * @param periodCount - * @throws IllegalArgumentException if periodCount is null or out of range + * @throws NullPointerException if periodCount is null + * @throws IllegalArgumentException if periodCount is out of range */ public static Integer validatePeriodCount(Integer periodCount) { Objects.requireNonNull(periodCount, "periodCount cannot be null"); @@ -67,11 +68,11 @@ public static Integer validatePeriodCount(Integer periodCount) { * Validates a list of items is not null, not empty, and contains no null elements. * * @param list the list of items to validate - * @param the type of items in the list, must extend AbstractAdvancedCommerceItem + * @param the type of items in the list * @return the validated list of items * @throws IllegalArgumentException if the list is null, empty, or contains null elements */ - public static List validateItems(List list) { + public static List validateItems(List list) { if (list == null) { throw new IllegalArgumentException("Items list cannot be null"); } @@ -91,7 +92,7 @@ public static List validateItems(Lis private static String validateStringWithMaxLength(String value, int maxLength, String fieldName) { Objects.requireNonNull(value, fieldName + " cannot be null"); - if (value.length() > maxLength) { + if (value.codePointCount(0, value.length()) > maxLength) { throw new IllegalArgumentException(fieldName + " length cannot exceed " + maxLength + " characters"); } return value; diff --git a/src/main/java/com/apple/itunes/storekit/model/HistoryResponse.java b/src/main/java/com/apple/itunes/storekit/model/HistoryResponse.java index d16d4a8a..14e424bb 100644 --- a/src/main/java/com/apple/itunes/storekit/model/HistoryResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/HistoryResponse.java @@ -14,69 +14,50 @@ * A response that contains the customer’s transaction history for an app. * * @see HistoryResponse - */ + **/ public class HistoryResponse { - private static final String SERIALIZED_NAME_REVISION = "revision"; - private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; - private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; + private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; + private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; + private static final String SERIALIZED_NAME_REVISION = "revision"; private static final String SERIALIZED_NAME_SIGNED_TRANSACTIONS = "signedTransactions"; - @JsonProperty(SERIALIZED_NAME_REVISION) - private String revision; - @JsonProperty(SERIALIZED_NAME_HAS_MORE) - private Boolean hasMore; - @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) - private String bundleId; + @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) private Long appAppleId; + @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) + private String bundleId; @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) private String environment; + @JsonProperty(SERIALIZED_NAME_HAS_MORE) + private Boolean hasMore; + @JsonProperty(SERIALIZED_NAME_REVISION) + private String revision; @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTIONS) - private List signedTransactions = null; + private List signedTransactions; @JsonAnySetter private Map unknownFields; - public HistoryResponse() { } - public HistoryResponse revision(String revision) { - this.revision = revision; - return this; - } - - /** - * A token you use in a query to request the next set of transactions for the customer. - * - * @return revision - * @see revision - **/ - public String getRevision() { - return revision; - } - - public void setRevision(String revision) { - this.revision = revision; - } - - public HistoryResponse hasMore(Boolean hasMore) { - this.hasMore = hasMore; + public HistoryResponse appAppleId(Long appAppleId) { + this.appAppleId = appAppleId; return this; } /** - * A Boolean value indicating whether the App Store has more transaction data. + * The app’s identifier in the App Store. * - * @return hasMore - * @see hasMore + * @return appAppleId + * @see appAppleId **/ - public Boolean getHasMore() { - return hasMore; + public Long getAppAppleId() { + return appAppleId; } - public void setHasMore(Boolean hasMore) { - this.hasMore = hasMore; + public void setAppAppleId(Long appAppleId) { + this.appAppleId = appAppleId; } public HistoryResponse bundleId(String bundleId) { @@ -85,7 +66,7 @@ public HistoryResponse bundleId(String bundleId) { } /** - * The bundle identifier of an app. + * The bundle identifier of the app. * * @return bundleId * @see bundleId @@ -98,25 +79,6 @@ public void setBundleId(String bundleId) { this.bundleId = bundleId; } - public HistoryResponse appAppleId(Long appAppleId) { - this.appAppleId = appAppleId; - return this; - } - - /** - * The unique identifier of an app in the App Store. - * - * @return appAppleId - * @see appAppleId - **/ - public Long getAppAppleId() { - return appAppleId; - } - - public void setAppAppleId(Long appAppleId) { - this.appAppleId = appAppleId; - } - public HistoryResponse environment(Environment environment) { this.environment = environment != null ? environment.getValue() : null; return this; @@ -129,12 +91,12 @@ public HistoryResponse environment(Environment environment) { * @see environment **/ public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + return Environment.fromValue(environment); } /** * @see #getEnvironment() - */ + **/ public String getRawEnvironment() { return environment; } @@ -147,21 +109,60 @@ public void setRawEnvironment(String rawEnvironment) { this.environment = rawEnvironment; } + public HistoryResponse hasMore(Boolean hasMore) { + this.hasMore = hasMore; + return this; + } + + /** + * A Boolean value that indicates whether the App Store has more transactions than it returns in this response. + * + * @return hasMore + * @see hasMore + **/ + public Boolean getHasMore() { + return hasMore; + } + + public void setHasMore(Boolean hasMore) { + this.hasMore = hasMore; + } + + public HistoryResponse revision(String revision) { + this.revision = revision; + return this; + } + + /** + * A token you use in a query to request the next set of transactions from the endpoint. + * + * @return revision + * @see revision + **/ + public String getRevision() { + return revision; + } + + public void setRevision(String revision) { + this.revision = revision; + } + public HistoryResponse signedTransactions(List signedTransactions) { this.signedTransactions = signedTransactions; return this; } - public HistoryResponse addSignedTransactionsItem(String signedTransactionsItem) { + public HistoryResponse addSignedTransaction(String signedTransaction) { + Objects.requireNonNull(signedTransaction); if (this.signedTransactions == null) { this.signedTransactions = new ArrayList<>(); } - this.signedTransactions.add(signedTransactionsItem); + this.signedTransactions.add(signedTransaction); return this; } /** - * An array of in-app purchase transactions for the customer, signed by Apple, in JSON Web Signature format. + * An array of in-app purchase transactions for the customer, signed by Apple, in JSON Web Signature (JWS) format. * * @return signedTransactions * @see JWSTransaction @@ -180,10 +181,10 @@ public HistoryResponse unknownFields(Map unknownFields) { } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -201,31 +202,30 @@ public boolean equals(Object o) { return false; } HistoryResponse historyResponse = (HistoryResponse) o; - return Objects.equals(this.revision, historyResponse.revision) && - Objects.equals(this.hasMore, historyResponse.hasMore) && + return Objects.equals(this.appAppleId, historyResponse.appAppleId) && Objects.equals(this.bundleId, historyResponse.bundleId) && - Objects.equals(this.appAppleId, historyResponse.appAppleId) && Objects.equals(this.environment, historyResponse.environment) && + Objects.equals(this.hasMore, historyResponse.hasMore) && + Objects.equals(this.revision, historyResponse.revision) && Objects.equals(this.signedTransactions, historyResponse.signedTransactions) && Objects.equals(this.unknownFields, historyResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(revision, hasMore, bundleId, appAppleId, environment, signedTransactions, unknownFields); + return Objects.hash(appAppleId, bundleId, environment, hasMore, revision, signedTransactions, unknownFields); } @Override public String toString() { return "HistoryResponse{" + - "revision='" + revision + '\'' + - ", hasMore=" + hasMore + + "appAppleId=" + appAppleId + ", bundleId='" + bundleId + '\'' + - ", appAppleId=" + appAppleId + ", environment='" + environment + '\'' + + ", hasMore=" + hasMore + + ", revision='" + revision + '\'' + ", signedTransactions=" + signedTransactions + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ImageSize.java b/src/main/java/com/apple/itunes/storekit/model/ImageSize.java index c9bb360b..16d23aea 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ImageSize.java +++ b/src/main/java/com/apple/itunes/storekit/model/ImageSize.java @@ -8,10 +8,16 @@ * The size of an image. * * @see imageSize - */ + **/ public enum ImageSize { + /** + * 3840 pixels in width, and from 160 to 2160 pixels in height, inclusive. + **/ FULL_SIZE("FULL_SIZE"), + /** + * 1024 by 1024 pixels, to use for bullet points only. + **/ BULLET_POINT("BULLET_POINT"); private final String value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ImageState.java b/src/main/java/com/apple/itunes/storekit/model/ImageState.java index f1c7fd85..aaf738c6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ImageState.java +++ b/src/main/java/com/apple/itunes/storekit/model/ImageState.java @@ -8,11 +8,20 @@ * The approval state of an image. * * @see imageState - */ + **/ public enum ImageState { + /** + * The image is awaiting approval. + **/ PENDING("PENDING"), + /** + * The image is approved. + **/ APPROVED("APPROVED"), + /** + * The image is rejected. + **/ REJECTED("REJECTED"); private final String value; @@ -40,4 +49,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/InAppOwnershipType.java b/src/main/java/com/apple/itunes/storekit/model/InAppOwnershipType.java index 350c3062..b5b132a2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/InAppOwnershipType.java +++ b/src/main/java/com/apple/itunes/storekit/model/InAppOwnershipType.java @@ -5,14 +5,24 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * The relationship of the user with the family-shared purchase to which they have access. + * A string that describes whether the transaction was purchased by the customer, or is available to them through Family Sharing, an organization, or a group. * * @see inAppOwnershipType - */ + **/ public enum InAppOwnershipType { + /** + * The transaction belongs to a family member who benefits from service. + **/ FAMILY_SHARED("FAMILY_SHARED"), - PURCHASED("PURCHASED"); + /** + * The transaction belongs to the purchaser. + **/ + PURCHASED("PURCHASED"), + /** + * The transaction belongs to a customer who has access through an organization or group. + **/ + ASSIGNED("ASSIGNED"); private final String value; @@ -39,4 +49,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayload.java b/src/main/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayload.java index a33c0e64..941b3989 100644 --- a/src/main/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayload.java +++ b/src/main/java/com/apple/itunes/storekit/model/JWSRenewalInfoDecodedPayload.java @@ -16,78 +16,79 @@ * A decoded payload containing subscription renewal information for an auto-renewable subscription. * * @see JWSRenewalInfoDecodedPayload - */ + **/ public class JWSRenewalInfoDecodedPayload implements DecodedSignedData { - private static final String SERIALIZED_NAME_EXPIRATION_INTENT = "expirationIntent"; - private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; + private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; + private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; private static final String SERIALIZED_NAME_AUTO_RENEW_PRODUCT_ID = "autoRenewProductId"; - private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; private static final String SERIALIZED_NAME_AUTO_RENEW_STATUS = "autoRenewStatus"; - private static final String SERIALIZED_NAME_IS_IN_BILLING_RETRY_PERIOD = "isInBillingRetryPeriod"; - private static final String SERIALIZED_NAME_PRICE_INCREASE_STATUS = "priceIncreaseStatus"; + private static final String SERIALIZED_NAME_CURRENCY = "currency"; + private static final String SERIALIZED_NAME_ELIGIBLE_WIN_BACK_OFFER_IDS = "eligibleWinBackOfferIds"; + private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; + private static final String SERIALIZED_NAME_EXPIRATION_INTENT = "expirationIntent"; private static final String SERIALIZED_NAME_GRACE_PERIOD_EXPIRES_DATE = "gracePeriodExpiresDate"; - private static final String SERIALIZED_NAME_OFFER_TYPE = "offerType"; + private static final String SERIALIZED_NAME_IS_IN_BILLING_RETRY_PERIOD = "isInBillingRetryPeriod"; + private static final String SERIALIZED_NAME_OFFER_DISCOUNT_TYPE = "offerDiscountType"; private static final String SERIALIZED_NAME_OFFER_IDENTIFIER = "offerIdentifier"; - private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; - private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; + private static final String SERIALIZED_NAME_OFFER_PERIOD = "offerPeriod"; + private static final String SERIALIZED_NAME_OFFER_TYPE = "offerType"; + private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; + private static final String SERIALIZED_NAME_PRICE_INCREASE_STATUS = "priceIncreaseStatus"; + private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; private static final String SERIALIZED_NAME_RECENT_SUBSCRIPTION_START_DATE = "recentSubscriptionStartDate"; private static final String SERIALIZED_NAME_RENEWAL_DATE = "renewalDate"; private static final String SERIALIZED_NAME_RENEWAL_PRICE = "renewalPrice"; - private static final String SERIALIZED_NAME_CURRENCY = "currency"; - private static final String SERIALIZED_NAME_OFFER_DISCOUNT_TYPE = "offerDiscountType"; - private static final String SERIALIZED_NAME_ELIGIBLE_WIN_BACK_OFFER_IDS = "eligibleWinBackOfferIds"; - private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; - private static final String SERIALIZED_NAME_OFFER_PERIOD = "offerPeriod"; - private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; + private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; private static final String SERIALIZED_NAME_ADVANCED_COMMERCE_INFO = "advancedCommerceInfo"; private static final String SERIALIZED_NAME_COMMITMENT_INFO = "commitmentInfo"; private static final String SERIALIZED_NAME_RENEWAL_BILLING_PLAN_TYPE = "renewalBillingPlanType"; - @JsonProperty(SERIALIZED_NAME_EXPIRATION_INTENT) - private Integer expirationIntent; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) - private String originalTransactionId; + + @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) + private UUID appAccountToken; + @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) + private String appTransactionId; @JsonProperty(SERIALIZED_NAME_AUTO_RENEW_PRODUCT_ID) private String autoRenewProductId; - @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) - private String productId; @JsonProperty(SERIALIZED_NAME_AUTO_RENEW_STATUS) private Integer autoRenewStatus; - @JsonProperty(SERIALIZED_NAME_IS_IN_BILLING_RETRY_PERIOD) - private Boolean isInBillingRetryPeriod; - @JsonProperty(SERIALIZED_NAME_PRICE_INCREASE_STATUS) - private Integer priceIncreaseStatus; + @JsonProperty(SERIALIZED_NAME_CURRENCY) + private String currency; + @JsonProperty(SERIALIZED_NAME_ELIGIBLE_WIN_BACK_OFFER_IDS) + private List eligibleWinBackOfferIds; + @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) + private String environment; + @JsonProperty(SERIALIZED_NAME_EXPIRATION_INTENT) + private Integer expirationIntent; @JsonProperty(SERIALIZED_NAME_GRACE_PERIOD_EXPIRES_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) private Long gracePeriodExpiresDate; - @JsonProperty(SERIALIZED_NAME_OFFER_TYPE) - private Integer offerType; + @JsonProperty(SERIALIZED_NAME_IS_IN_BILLING_RETRY_PERIOD) + private Boolean isInBillingRetryPeriod; + @JsonProperty(SERIALIZED_NAME_OFFER_DISCOUNT_TYPE) + private String offerDiscountType; @JsonProperty(SERIALIZED_NAME_OFFER_IDENTIFIER) private String offerIdentifier; - @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) - private Long signedDate; - @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) - private String environment; + @JsonProperty(SERIALIZED_NAME_OFFER_PERIOD) + private String offerPeriod; + @JsonProperty(SERIALIZED_NAME_OFFER_TYPE) + private Integer offerType; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) + private String originalTransactionId; + @JsonProperty(SERIALIZED_NAME_PRICE_INCREASE_STATUS) + private Integer priceIncreaseStatus; + @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) + private String productId; @JsonProperty(SERIALIZED_NAME_RECENT_SUBSCRIPTION_START_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) private Long recentSubscriptionStartDate; @JsonProperty(SERIALIZED_NAME_RENEWAL_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) private Long renewalDate; @JsonProperty(SERIALIZED_NAME_RENEWAL_PRICE) private Long renewalPrice; - @JsonProperty(SERIALIZED_NAME_CURRENCY) - private String currency; - @JsonProperty(SERIALIZED_NAME_OFFER_DISCOUNT_TYPE) - private String offerDiscountType; - @JsonProperty(SERIALIZED_NAME_ELIGIBLE_WIN_BACK_OFFER_IDS) - private List eligibleWinBackOfferIds = null; - @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) - private String appTransactionId; - @JsonProperty(SERIALIZED_NAME_OFFER_PERIOD) - private String offerPeriod; - @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) - private UUID appAccountToken; + @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long signedDate; @JsonProperty(SERIALIZED_NAME_ADVANCED_COMMERCE_INFO) private AdvancedCommerceRenewalInfo advancedCommerceInfo; @JsonProperty(SERIALIZED_NAME_COMMITMENT_INFO) @@ -97,57 +98,45 @@ public class JWSRenewalInfoDecodedPayload implements DecodedSignedData { @JsonAnySetter private Map unknownFields; - public JWSRenewalInfoDecodedPayload() { } - public JWSRenewalInfoDecodedPayload expirationIntent(ExpirationIntent expirationIntent) { - this.expirationIntent = expirationIntent != null ? expirationIntent.getValue() : null; + public JWSRenewalInfoDecodedPayload appAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; return this; } /** - * The reason the subscription expired. + * A UUID you create at the time of purchase that associates the transaction with a customer on your own service. * - * @return expirationIntent - * @see expirationIntent + * @return appAccountToken + * @see appAccountToken **/ - public ExpirationIntent getExpirationIntent() { - return expirationIntent != null ? ExpirationIntent.fromValue(expirationIntent) : null; - } - - /** - * @see #getExpirationIntent() - */ - public Integer getRawExpirationIntent() { - return expirationIntent; - } - - public void setExpirationIntent(ExpirationIntent expirationIntent) { - this.expirationIntent = expirationIntent != null ? expirationIntent.getValue() : null; + public UUID getAppAccountToken() { + return appAccountToken; } - public void setRawExpirationIntent(Integer rawExpirationIntent) { - this.expirationIntent = rawExpirationIntent; + public void setAppAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; } - public JWSRenewalInfoDecodedPayload originalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public JWSRenewalInfoDecodedPayload appTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; return this; } /** - * The original transaction identifier of a purchase. + * The unique identifier of the app download transaction. * - * @return originalTransactionId - * @see originalTransactionId + * @return appTransactionId + * @see appTransactionId **/ - public String getOriginalTransactionId() { - return originalTransactionId; + public String getAppTransactionId() { + return appTransactionId; } - public void setOriginalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public void setAppTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; } public JWSRenewalInfoDecodedPayload autoRenewProductId(String autoRenewProductId) { @@ -156,7 +145,7 @@ public JWSRenewalInfoDecodedPayload autoRenewProductId(String autoRenewProductId } /** - * The product identifier of the product that will renew at the next billing period. + * The identifier of the product that renews at the next billing period. * * @return autoRenewProductId * @see autoRenewProductId @@ -169,25 +158,6 @@ public void setAutoRenewProductId(String autoRenewProductId) { this.autoRenewProductId = autoRenewProductId; } - public JWSRenewalInfoDecodedPayload productId(String productId) { - this.productId = productId; - return this; - } - - /** - * The unique identifier for the product, that you create in App Store Connect. - * - * @return productId - * @see productId - **/ - public String getProductId() { - return productId; - } - - public void setProductId(String productId) { - this.productId = productId; - } - public JWSRenewalInfoDecodedPayload autoRenewStatus(AutoRenewStatus autoRenewStatus) { this.autoRenewStatus = autoRenewStatus != null ? autoRenewStatus.getValue() : null; return this; @@ -200,12 +170,12 @@ public JWSRenewalInfoDecodedPayload autoRenewStatus(AutoRenewStatus autoRenewSta * @see autoRenewStatus **/ public AutoRenewStatus getAutoRenewStatus() { - return autoRenewStatus != null ? AutoRenewStatus.fromValue(autoRenewStatus) : null; + return AutoRenewStatus.fromValue(autoRenewStatus); } /** * @see #getAutoRenewStatus() - */ + **/ public Integer getRawAutoRenewStatus() { return autoRenewStatus; } @@ -218,13 +188,139 @@ public void setRawAutoRenewStatus(Integer rawAutoRenewStatus) { this.autoRenewStatus = rawAutoRenewStatus; } + public JWSRenewalInfoDecodedPayload currency(String currency) { + this.currency = currency; + return this; + } + + /** + * The currency code for the renewalPrice of the subscription. + * + * @return currency + * @see currency + **/ + public String getCurrency() { + return currency; + } + + public void setCurrency(String currency) { + this.currency = currency; + } + + public JWSRenewalInfoDecodedPayload eligibleWinBackOfferIds(List eligibleWinBackOfferIds) { + this.eligibleWinBackOfferIds = eligibleWinBackOfferIds; + return this; + } + + public JWSRenewalInfoDecodedPayload addEligibleWinBackOfferId(String eligibleWinBackOfferId) { + Objects.requireNonNull(eligibleWinBackOfferId); + if (this.eligibleWinBackOfferIds == null) { + this.eligibleWinBackOfferIds = new ArrayList<>(); + } + this.eligibleWinBackOfferIds.add(eligibleWinBackOfferId); + return this; + } + + /** + * The list of win-back offer IDs that the customer is eligible for. + * + * @return eligibleWinBackOfferIds + * @see eligibleWinBackOfferIds + **/ + public List getEligibleWinBackOfferIds() { + return eligibleWinBackOfferIds; + } + + public void setEligibleWinBackOfferIds(List eligibleWinBackOfferIds) { + this.eligibleWinBackOfferIds = eligibleWinBackOfferIds; + } + + public JWSRenewalInfoDecodedPayload environment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; + return this; + } + + /** + * The server environment, either sandbox or production. + * + * @return environment + * @see environment + **/ + public Environment getEnvironment() { + return Environment.fromValue(environment); + } + + /** + * @see #getEnvironment() + **/ + public String getRawEnvironment() { + return environment; + } + + public void setEnvironment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; + } + + public void setRawEnvironment(String rawEnvironment) { + this.environment = rawEnvironment; + } + + public JWSRenewalInfoDecodedPayload expirationIntent(ExpirationIntent expirationIntent) { + this.expirationIntent = expirationIntent != null ? expirationIntent.getValue() : null; + return this; + } + + /** + * The reason the subscription expired. + * + * @return expirationIntent + * @see expirationIntent + **/ + public ExpirationIntent getExpirationIntent() { + return ExpirationIntent.fromValue(expirationIntent); + } + + /** + * @see #getExpirationIntent() + **/ + public Integer getRawExpirationIntent() { + return expirationIntent; + } + + public void setExpirationIntent(ExpirationIntent expirationIntent) { + this.expirationIntent = expirationIntent != null ? expirationIntent.getValue() : null; + } + + public void setRawExpirationIntent(Integer rawExpirationIntent) { + this.expirationIntent = rawExpirationIntent; + } + + public JWSRenewalInfoDecodedPayload gracePeriodExpiresDate(Long gracePeriodExpiresDate) { + this.gracePeriodExpiresDate = gracePeriodExpiresDate; + return this; + } + + /** + * The time when the Billing Grace Period for subscription renewals expires. + * + * @return gracePeriodExpiresDate + * @see gracePeriodExpiresDate + **/ + public Long getGracePeriodExpiresDate() { + return gracePeriodExpiresDate; + } + + public void setGracePeriodExpiresDate(Long gracePeriodExpiresDate) { + this.gracePeriodExpiresDate = gracePeriodExpiresDate; + } + public JWSRenewalInfoDecodedPayload isInBillingRetryPeriod(Boolean isInBillingRetryPeriod) { this.isInBillingRetryPeriod = isInBillingRetryPeriod; return this; } /** - * A Boolean value that indicates whether the App Store is attempting to automatically renew an expired subscription. + * A Boolean value that indicates whether the App Store is attempting to automatically renew the expired subscription. * * @return isInBillingRetryPeriod * @see isInBillingRetryPeriod @@ -237,53 +333,72 @@ public void setIsInBillingRetryPeriod(Boolean isInBillingRetryPeriod) { this.isInBillingRetryPeriod = isInBillingRetryPeriod; } - public JWSRenewalInfoDecodedPayload priceIncreaseStatus(PriceIncreaseStatus priceIncreaseStatus) { - this.priceIncreaseStatus = priceIncreaseStatus != null ? priceIncreaseStatus.getValue() : null; + public JWSRenewalInfoDecodedPayload offerDiscountType(OfferDiscountType offerDiscountType) { + this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; return this; } /** - * The status that indicates whether the auto-renewable subscription is subject to a price increase. + * The payment mode you configure for the offer. * - * @return priceIncreaseStatus - * @see priceIncreaseStatus + * @return offerDiscountType + * @see offerDiscountType **/ - public PriceIncreaseStatus getPriceIncreaseStatus() { - return priceIncreaseStatus != null ? PriceIncreaseStatus.fromValue(priceIncreaseStatus) : null; + public OfferDiscountType getOfferDiscountType() { + return OfferDiscountType.fromValue(offerDiscountType); + } + + /** + * @see #getOfferDiscountType() + **/ + public String getRawOfferDiscountType() { + return offerDiscountType; + } + + public void setOfferDiscountType(OfferDiscountType offerDiscountType) { + this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; + } + + public void setRawOfferDiscountType(String rawOfferDiscountType) { + this.offerDiscountType = rawOfferDiscountType; + } + + public JWSRenewalInfoDecodedPayload offerIdentifier(String offerIdentifier) { + this.offerIdentifier = offerIdentifier; + return this; } /** - * @see #getPriceIncreaseStatus() - */ - public Integer getRawPriceIncreaseStatus() { - return priceIncreaseStatus; - } - - public void setPriceIncreaseStatus(PriceIncreaseStatus priceIncreaseStatus) { - this.priceIncreaseStatus = priceIncreaseStatus != null ? priceIncreaseStatus.getValue() : null; + * The offer code or the promotional offer identifier. + * + * @return offerIdentifier + * @see offerIdentifier + **/ + public String getOfferIdentifier() { + return offerIdentifier; } - public void setRawPriceIncreaseStatus(Integer rawPriceIncreaseStatus) { - this.priceIncreaseStatus = rawPriceIncreaseStatus; + public void setOfferIdentifier(String offerIdentifier) { + this.offerIdentifier = offerIdentifier; } - public JWSRenewalInfoDecodedPayload gracePeriodExpiresDate(Long gracePeriodExpiresDate) { - this.gracePeriodExpiresDate = gracePeriodExpiresDate; + public JWSRenewalInfoDecodedPayload offerPeriod(String offerPeriod) { + this.offerPeriod = offerPeriod; return this; } /** - * The time when the billing grace period for subscription renewals expires. + * The duration of the offer. * - * @return gracePeriodExpiresDate - * @see gracePeriodExpiresDate + * @return offerPeriod + * @see offerPeriod **/ - public Long getGracePeriodExpiresDate() { - return gracePeriodExpiresDate; + public String getOfferPeriod() { + return offerPeriod; } - public void setGracePeriodExpiresDate(Long gracePeriodExpiresDate) { - this.gracePeriodExpiresDate = gracePeriodExpiresDate; + public void setOfferPeriod(String offerPeriod) { + this.offerPeriod = offerPeriod; } public JWSRenewalInfoDecodedPayload offerType(OfferType offerType) { @@ -298,12 +413,12 @@ public JWSRenewalInfoDecodedPayload offerType(OfferType offerType) { * @see offerType **/ public OfferType getOfferType() { - return offerType != null ? OfferType.fromValue(offerType) : null; + return OfferType.fromValue(offerType); } /** * @see #getOfferType() - */ + **/ public Integer getRawOfferType() { return offerType; } @@ -316,72 +431,72 @@ public void setRawOfferType(Integer rawOfferType) { this.offerType = rawOfferType; } - public JWSRenewalInfoDecodedPayload offerIdentifier(String offerIdentifier) { - this.offerIdentifier = offerIdentifier; + public JWSRenewalInfoDecodedPayload originalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; return this; } /** - * The offer code or the promotional offer identifier. + * The transaction identifier of the original purchase associated with this transaction. * - * @return offerIdentifier - * @see offerIdentifier + * @return originalTransactionId + * @see originalTransactionId **/ - public String getOfferIdentifier() { - return offerIdentifier; + public String getOriginalTransactionId() { + return originalTransactionId; } - public void setOfferIdentifier(String offerIdentifier) { - this.offerIdentifier = offerIdentifier; + public void setOriginalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; } - public JWSRenewalInfoDecodedPayload signedDate(Long signedDate) { - this.signedDate = signedDate; + public JWSRenewalInfoDecodedPayload priceIncreaseStatus(PriceIncreaseStatus priceIncreaseStatus) { + this.priceIncreaseStatus = priceIncreaseStatus != null ? priceIncreaseStatus.getValue() : null; return this; } /** - * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature data. + * The status that indicates whether the auto-renewable subscription is subject to a price increase. * - * @return signedDate - * @see signedDate + * @return priceIncreaseStatus + * @see priceIncreaseStatus **/ - public Long getSignedDate() { - return signedDate; + public PriceIncreaseStatus getPriceIncreaseStatus() { + return PriceIncreaseStatus.fromValue(priceIncreaseStatus); } - public void setSignedDate(Long signedDate) { - this.signedDate = signedDate; + /** + * @see #getPriceIncreaseStatus() + **/ + public Integer getRawPriceIncreaseStatus() { + return priceIncreaseStatus; } - public JWSRenewalInfoDecodedPayload environment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; - return this; + public void setPriceIncreaseStatus(PriceIncreaseStatus priceIncreaseStatus) { + this.priceIncreaseStatus = priceIncreaseStatus != null ? priceIncreaseStatus.getValue() : null; } - /** - * The server environment, either sandbox or production. - * - * @return environment - * @see environment - **/ - public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + public void setRawPriceIncreaseStatus(Integer rawPriceIncreaseStatus) { + this.priceIncreaseStatus = rawPriceIncreaseStatus; } - /** - * @see #getEnvironment() - */ - public String getRawEnvironment() { - return environment; + public JWSRenewalInfoDecodedPayload productId(String productId) { + this.productId = productId; + return this; } - public void setEnvironment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; + /** + * The product identifier of the In-App Purchase. + * + * @return productId + * @see productId + **/ + public String getProductId() { + return productId; } - public void setRawEnvironment(String rawEnvironment) { - this.environment = rawEnvironment; + public void setProductId(String productId) { + this.productId = productId; } public JWSRenewalInfoDecodedPayload recentSubscriptionStartDate(Long recentSubscriptionStartDate) { @@ -390,7 +505,7 @@ public JWSRenewalInfoDecodedPayload recentSubscriptionStartDate(Long recentSubsc } /** - * The earliest start date of a subscription in a series of auto-renewable subscription purchases that ignores all lapses of paid service shorter than 60 days. + * The earliest start date of the auto-renewable subscription in a series of subscription purchases that ignores all lapses of paid service that are 60 days or fewer. * * @return recentSubscriptionStartDate * @see recentSubscriptionStartDate @@ -441,137 +556,23 @@ public void setRenewalPrice(Long renewalPrice) { this.renewalPrice = renewalPrice; } - public JWSRenewalInfoDecodedPayload currency(String currency) { - this.currency = currency; - return this; - } - - /** - * The currency code for the renewalPrice of the subscription. - * - * @return currency - * @see currency - **/ - public String getCurrency() { - return this.currency; - } - - public void setCurrency(String currency) { - this.currency = currency; - } - - public JWSRenewalInfoDecodedPayload offerDiscountType(OfferDiscountType offerDiscountType) { - this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; - return this; - } - - /** - * The payment mode you configure for the offer. - * - * @return offerDiscountType - * @see offerDiscountType - **/ - public OfferDiscountType getOfferDiscountType() { - return offerDiscountType != null ? OfferDiscountType.fromValue(offerDiscountType) : null; - } - - /** - * @see #getOfferDiscountType() - */ - public String getRawOfferDiscountType() { - return offerDiscountType; - } - - public void setOfferDiscountType(OfferDiscountType offerDiscountType) { - this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; - } - - public void setRawOfferDiscountType(String rawOfferDiscountType) { - this.offerDiscountType = rawOfferDiscountType; - } - - public JWSRenewalInfoDecodedPayload eligibleWinBackOfferIds(List eligibleWinBackOfferIds) { - this.eligibleWinBackOfferIds = eligibleWinBackOfferIds; - return this; - } - - public JWSRenewalInfoDecodedPayload addEligibleWinBackOfferId(String eligibleWinBackOfferId) { - if (this.eligibleWinBackOfferIds == null) { - this.eligibleWinBackOfferIds = new ArrayList<>(); - } - this.eligibleWinBackOfferIds.add(eligibleWinBackOfferId); - return this; - } - - /** - * An array of win-back offer identifiers that a customer is eligible to redeem, which sorts the identifiers to present the better offers first. - * - * @return eligibleWinBackOfferIds - * @see eligibleWinBackOfferIds - **/ - public List getEligibleWinBackOfferIds() { - return eligibleWinBackOfferIds; - } - - public void setEligibleWinBackOfferIds(List eligibleWinBackOfferIds) { - this.eligibleWinBackOfferIds = eligibleWinBackOfferIds; - } - - public JWSRenewalInfoDecodedPayload appTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; - return this; - } - - /** - * The unique identifier of the app download transaction. - * - * @return appTransactionId - * @see appTransactionId - **/ - public String getAppTransactionId() { - return this.appTransactionId; - } - - public void setAppTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; - } - - public JWSRenewalInfoDecodedPayload offerPeriod(String offerPeriod) { - this.offerPeriod = offerPeriod; - return this; - } - - /** - * The duration of the offer. - * - * @return offerPeriod - * @see offerPeriod - **/ - public String getOfferPeriod() { - return this.offerPeriod; - } - - public void setOfferPeriod(String offerPeriod) { - this.offerPeriod = offerPeriod; - } - - public JWSRenewalInfoDecodedPayload appAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + public JWSRenewalInfoDecodedPayload signedDate(Long signedDate) { + this.signedDate = signedDate; return this; } /** - * The UUID that an app optionally generates to map a customer’s In-App Purchase with its resulting App Store transaction. + * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature (JWS) data. * - * @return appAccountToken - * @see appAccountToken + * @return signedDate + * @see signedDate **/ - public UUID getAppAccountToken() { - return this.appAccountToken; + public Long getSignedDate() { + return signedDate; } - public void setAppAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + public void setSignedDate(Long signedDate) { + this.signedDate = signedDate; } public JWSRenewalInfoDecodedPayload advancedCommerceInfo(AdvancedCommerceRenewalInfo advancedCommerceInfo) { @@ -620,12 +621,12 @@ public JWSRenewalInfoDecodedPayload renewalBillingPlanType(RenewalBillingPlanTyp * @see renewalBillingPlanType **/ public RenewalBillingPlanType getRenewalBillingPlanType() { - return renewalBillingPlanType != null ? RenewalBillingPlanType.fromValue(renewalBillingPlanType) : null; + return RenewalBillingPlanType.fromValue(renewalBillingPlanType); } /** * @see #getRenewalBillingPlanType() - */ + **/ public String getRawRenewalBillingPlanType() { return renewalBillingPlanType; } @@ -644,10 +645,10 @@ public JWSRenewalInfoDecodedPayload unknownFields(Map unknownFie } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -658,41 +659,69 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - JWSRenewalInfoDecodedPayload that = (JWSRenewalInfoDecodedPayload) o; - return Objects.equals(expirationIntent, that.expirationIntent) && Objects.equals(originalTransactionId, that.originalTransactionId) && Objects.equals(autoRenewProductId, that.autoRenewProductId) && Objects.equals(productId, that.productId) && Objects.equals(autoRenewStatus, that.autoRenewStatus) && Objects.equals(isInBillingRetryPeriod, that.isInBillingRetryPeriod) && Objects.equals(priceIncreaseStatus, that.priceIncreaseStatus) && Objects.equals(gracePeriodExpiresDate, that.gracePeriodExpiresDate) && Objects.equals(offerType, that.offerType) && Objects.equals(offerIdentifier, that.offerIdentifier) && Objects.equals(signedDate, that.signedDate) && Objects.equals(environment, that.environment) && Objects.equals(recentSubscriptionStartDate, that.recentSubscriptionStartDate) && Objects.equals(renewalDate, that.renewalDate) && Objects.equals(renewalPrice, that.renewalPrice) && Objects.equals(currency, that.currency) && Objects.equals(offerDiscountType, that.offerDiscountType) && Objects.equals(eligibleWinBackOfferIds, that.eligibleWinBackOfferIds) && Objects.equals(appTransactionId, that.appTransactionId) && Objects.equals(offerPeriod, that.offerPeriod) && Objects.equals(appAccountToken, that.appAccountToken) && Objects.equals(advancedCommerceInfo, that.advancedCommerceInfo) && Objects.equals(commitmentInfo, that.commitmentInfo) && Objects.equals(renewalBillingPlanType, that.renewalBillingPlanType) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + JWSRenewalInfoDecodedPayload jWSRenewalInfoDecodedPayload = (JWSRenewalInfoDecodedPayload) o; + return Objects.equals(this.appAccountToken, jWSRenewalInfoDecodedPayload.appAccountToken) && + Objects.equals(this.appTransactionId, jWSRenewalInfoDecodedPayload.appTransactionId) && + Objects.equals(this.autoRenewProductId, jWSRenewalInfoDecodedPayload.autoRenewProductId) && + Objects.equals(this.autoRenewStatus, jWSRenewalInfoDecodedPayload.autoRenewStatus) && + Objects.equals(this.currency, jWSRenewalInfoDecodedPayload.currency) && + Objects.equals(this.eligibleWinBackOfferIds, jWSRenewalInfoDecodedPayload.eligibleWinBackOfferIds) && + Objects.equals(this.environment, jWSRenewalInfoDecodedPayload.environment) && + Objects.equals(this.expirationIntent, jWSRenewalInfoDecodedPayload.expirationIntent) && + Objects.equals(this.gracePeriodExpiresDate, jWSRenewalInfoDecodedPayload.gracePeriodExpiresDate) && + Objects.equals(this.isInBillingRetryPeriod, jWSRenewalInfoDecodedPayload.isInBillingRetryPeriod) && + Objects.equals(this.offerDiscountType, jWSRenewalInfoDecodedPayload.offerDiscountType) && + Objects.equals(this.offerIdentifier, jWSRenewalInfoDecodedPayload.offerIdentifier) && + Objects.equals(this.offerPeriod, jWSRenewalInfoDecodedPayload.offerPeriod) && + Objects.equals(this.offerType, jWSRenewalInfoDecodedPayload.offerType) && + Objects.equals(this.originalTransactionId, jWSRenewalInfoDecodedPayload.originalTransactionId) && + Objects.equals(this.priceIncreaseStatus, jWSRenewalInfoDecodedPayload.priceIncreaseStatus) && + Objects.equals(this.productId, jWSRenewalInfoDecodedPayload.productId) && + Objects.equals(this.recentSubscriptionStartDate, jWSRenewalInfoDecodedPayload.recentSubscriptionStartDate) && + Objects.equals(this.renewalDate, jWSRenewalInfoDecodedPayload.renewalDate) && + Objects.equals(this.renewalPrice, jWSRenewalInfoDecodedPayload.renewalPrice) && + Objects.equals(this.signedDate, jWSRenewalInfoDecodedPayload.signedDate) && + Objects.equals(this.advancedCommerceInfo, jWSRenewalInfoDecodedPayload.advancedCommerceInfo) && + Objects.equals(this.commitmentInfo, jWSRenewalInfoDecodedPayload.commitmentInfo) && + Objects.equals(this.renewalBillingPlanType, jWSRenewalInfoDecodedPayload.renewalBillingPlanType) && + Objects.equals(this.unknownFields, jWSRenewalInfoDecodedPayload.unknownFields); } @Override public int hashCode() { - return Objects.hash(expirationIntent, originalTransactionId, autoRenewProductId, productId, autoRenewStatus, isInBillingRetryPeriod, priceIncreaseStatus, gracePeriodExpiresDate, offerType, offerIdentifier, signedDate, environment, recentSubscriptionStartDate, renewalDate, renewalPrice, currency, offerDiscountType, eligibleWinBackOfferIds, appTransactionId, offerPeriod, appAccountToken, advancedCommerceInfo, commitmentInfo, renewalBillingPlanType, unknownFields); + return Objects.hash(appAccountToken, appTransactionId, autoRenewProductId, autoRenewStatus, currency, eligibleWinBackOfferIds, environment, expirationIntent, gracePeriodExpiresDate, isInBillingRetryPeriod, offerDiscountType, offerIdentifier, offerPeriod, offerType, originalTransactionId, priceIncreaseStatus, productId, recentSubscriptionStartDate, renewalDate, renewalPrice, signedDate, advancedCommerceInfo, commitmentInfo, renewalBillingPlanType, unknownFields); } @Override public String toString() { return "JWSRenewalInfoDecodedPayload{" + - "expirationIntent=" + expirationIntent + - ", originalTransactionId='" + originalTransactionId + '\'' + + "appAccountToken=" + appAccountToken + + ", appTransactionId='" + appTransactionId + '\'' + ", autoRenewProductId='" + autoRenewProductId + '\'' + - ", productId='" + productId + '\'' + ", autoRenewStatus=" + autoRenewStatus + - ", isInBillingRetryPeriod=" + isInBillingRetryPeriod + - ", priceIncreaseStatus=" + priceIncreaseStatus + + ", currency='" + currency + '\'' + + ", eligibleWinBackOfferIds=" + eligibleWinBackOfferIds + + ", environment='" + environment + '\'' + + ", expirationIntent=" + expirationIntent + ", gracePeriodExpiresDate=" + gracePeriodExpiresDate + - ", offerType=" + offerType + + ", isInBillingRetryPeriod=" + isInBillingRetryPeriod + + ", offerDiscountType='" + offerDiscountType + '\'' + ", offerIdentifier='" + offerIdentifier + '\'' + - ", signedDate=" + signedDate + - ", environment='" + environment + '\'' + + ", offerPeriod='" + offerPeriod + '\'' + + ", offerType=" + offerType + + ", originalTransactionId='" + originalTransactionId + '\'' + + ", priceIncreaseStatus=" + priceIncreaseStatus + + ", productId='" + productId + '\'' + ", recentSubscriptionStartDate=" + recentSubscriptionStartDate + ", renewalDate=" + renewalDate + ", renewalPrice=" + renewalPrice + - ", currency='" + currency + '\'' + - ", offerDiscountType='" + offerDiscountType + '\'' + - ", eligibleWinBackOfferIds=" + eligibleWinBackOfferIds + - ", appTransactionId='" + appTransactionId + '\'' + - ", offerPeriod='" + offerPeriod + '\'' + - ", appAccountToken='" + appAccountToken + '\'' + + ", signedDate=" + signedDate + ", advancedCommerceInfo=" + advancedCommerceInfo + ", commitmentInfo=" + commitmentInfo + ", renewalBillingPlanType='" + renewalBillingPlanType + '\'' + @@ -700,4 +729,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayload.java b/src/main/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayload.java index aae0b4b1..8948b354 100644 --- a/src/main/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayload.java +++ b/src/main/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayload.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Map; @@ -11,438 +12,512 @@ import java.util.UUID; /** - * A decoded payload containing transaction information. + * A decoded payload that contains transaction information. * * @see JWSTransactionDecodedPayload - */ + **/ public class JWSTransactionDecodedPayload implements DecodedSignedData { - private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; - private static final String SERIALIZED_NAME_TRANSACTION_ID = "transactionId"; - private static final String SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID = "webOrderLineItemId"; + private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; + private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; - private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; - private static final String SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER = "subscriptionGroupIdentifier"; - private static final String SERIALIZED_NAME_PURCHASE_DATE = "purchaseDate"; - private static final String SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE = "originalPurchaseDate"; + private static final String SERIALIZED_NAME_CURRENCY = "currency"; + private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; private static final String SERIALIZED_NAME_EXPIRES_DATE = "expiresDate"; - private static final String SERIALIZED_NAME_QUANTITY = "quantity"; - private static final String SERIALIZED_NAME_TYPE = "type"; - private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; private static final String SERIALIZED_NAME_IN_APP_OWNERSHIP_TYPE = "inAppOwnershipType"; - private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; - private static final String SERIALIZED_NAME_REVOCATION_REASON = "revocationReason"; - private static final String SERIALIZED_NAME_REVOCATION_DATE = "revocationDate"; private static final String SERIALIZED_NAME_IS_UPGRADED = "isUpgraded"; - private static final String SERIALIZED_NAME_OFFER_TYPE = "offerType"; + private static final String SERIALIZED_NAME_OFFER_DISCOUNT_TYPE = "offerDiscountType"; private static final String SERIALIZED_NAME_OFFER_IDENTIFIER = "offerIdentifier"; - private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; + private static final String SERIALIZED_NAME_OFFER_PERIOD = "offerPeriod"; + private static final String SERIALIZED_NAME_OFFER_TYPE = "offerType"; + private static final String SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE = "originalPurchaseDate"; + private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; + private static final String SERIALIZED_NAME_PRICE = "price"; + private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; + private static final String SERIALIZED_NAME_PURCHASE_DATE = "purchaseDate"; + private static final String SERIALIZED_NAME_QUANTITY = "quantity"; + private static final String SERIALIZED_NAME_REVOCATION_DATE = "revocationDate"; + private static final String SERIALIZED_NAME_REVOCATION_PERCENTAGE = "revocationPercentage"; + private static final String SERIALIZED_NAME_REVOCATION_REASON = "revocationReason"; + private static final String SERIALIZED_NAME_REVOCATION_TYPE = "revocationType"; + private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; private static final String SERIALIZED_NAME_STOREFRONT = "storefront"; private static final String SERIALIZED_NAME_STOREFRONT_ID = "storefrontId"; + private static final String SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER = "subscriptionGroupIdentifier"; + private static final String SERIALIZED_NAME_TRANSACTION_ID = "transactionId"; private static final String SERIALIZED_NAME_TRANSACTION_REASON = "transactionReason"; - private static final String SERIALIZED_NAME_PRICE = "price"; - private static final String SERIALIZED_NAME_CURRENCY = "currency"; - private static final String SERIALIZED_NAME_OFFER_DISCOUNT_TYPE = "offerDiscountType"; - private static final String SERIALIZED_NAME_APP_TRANSACTION_ID = "appTransactionId"; - private static final String SERIALIZED_NAME_OFFER_PERIOD = "offerPeriod"; - private static final String SERIALIZED_NAME_REVOCATION_TYPE = "revocationType"; - private static final String SERIALIZED_NAME_REVOCATION_PERCENTAGE = "revocationPercentage"; + private static final String SERIALIZED_NAME_TYPE = "type"; + private static final String SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID = "webOrderLineItemId"; private static final String SERIALIZED_NAME_ADVANCED_COMMERCE_INFO = "advancedCommerceInfo"; private static final String SERIALIZED_NAME_BILLING_PLAN_TYPE = "billingPlanType"; private static final String SERIALIZED_NAME_COMMITMENT_INFO = "commitmentInfo"; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) - private String originalTransactionId; - @JsonProperty(SERIALIZED_NAME_TRANSACTION_ID) - private String transactionId; - @JsonProperty(SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID) - private String webOrderLineItemId; + private static final String SERIALIZED_NAME_PREVIOUS_ORIGINAL_TRANSACTION_ID = "previousOriginalTransactionId"; + + @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) + private UUID appAccountToken; + @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) + private String appTransactionId; @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) private String bundleId; - @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) - private String productId; - @JsonProperty(SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER) - private String subscriptionGroupIdentifier; - @JsonProperty(SERIALIZED_NAME_PURCHASE_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) - private Long purchaseDate; - @JsonProperty(SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) - private Long originalPurchaseDate; + @JsonProperty(SERIALIZED_NAME_CURRENCY) + private String currency; + @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) + private String environment; @JsonProperty(SERIALIZED_NAME_EXPIRES_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) private Long expiresDate; - @JsonProperty(SERIALIZED_NAME_QUANTITY) - private Integer quantity; - @JsonProperty(SERIALIZED_NAME_TYPE) - private String type; - @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) - private UUID appAccountToken; @JsonProperty(SERIALIZED_NAME_IN_APP_OWNERSHIP_TYPE) private String inAppOwnershipType; - @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) - private Long signedDate; - @JsonProperty(SERIALIZED_NAME_REVOCATION_REASON) - private Integer revocationReason; - @JsonProperty(SERIALIZED_NAME_REVOCATION_DATE) - @JsonDeserialize(using=XcodeCompatibleTimestampDeserializer.class) - private Long revocationDate; @JsonProperty(SERIALIZED_NAME_IS_UPGRADED) private Boolean isUpgraded; - @JsonProperty(SERIALIZED_NAME_OFFER_TYPE) - private Integer offerType; + @JsonProperty(SERIALIZED_NAME_OFFER_DISCOUNT_TYPE) + private String offerDiscountType; @JsonProperty(SERIALIZED_NAME_OFFER_IDENTIFIER) private String offerIdentifier; - @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) - private String environment; + @JsonProperty(SERIALIZED_NAME_OFFER_PERIOD) + private String offerPeriod; + @JsonProperty(SERIALIZED_NAME_OFFER_TYPE) + private Integer offerType; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_PURCHASE_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long originalPurchaseDate; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) + private String originalTransactionId; + @JsonProperty(SERIALIZED_NAME_PRICE) + private Long price; + @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) + private String productId; + @JsonProperty(SERIALIZED_NAME_PURCHASE_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long purchaseDate; + @JsonProperty(SERIALIZED_NAME_QUANTITY) + private Integer quantity; + @JsonProperty(SERIALIZED_NAME_REVOCATION_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long revocationDate; + @JsonProperty(SERIALIZED_NAME_REVOCATION_PERCENTAGE) + private Integer revocationPercentage; + @JsonProperty(SERIALIZED_NAME_REVOCATION_REASON) + private Integer revocationReason; + @JsonProperty(SERIALIZED_NAME_REVOCATION_TYPE) + private String revocationType; + @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) + @JsonDeserialize(using = XcodeCompatibleTimestampDeserializer.class) + private Long signedDate; @JsonProperty(SERIALIZED_NAME_STOREFRONT) private String storefront; @JsonProperty(SERIALIZED_NAME_STOREFRONT_ID) private String storefrontId; + @JsonProperty(SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER) + private String subscriptionGroupIdentifier; + @JsonProperty(SERIALIZED_NAME_TRANSACTION_ID) + private String transactionId; @JsonProperty(SERIALIZED_NAME_TRANSACTION_REASON) private String transactionReason; - @JsonProperty(SERIALIZED_NAME_PRICE) - private Long price; - @JsonProperty(SERIALIZED_NAME_CURRENCY) - private String currency; - @JsonProperty(SERIALIZED_NAME_OFFER_DISCOUNT_TYPE) - private String offerDiscountType; - @JsonProperty(SERIALIZED_NAME_APP_TRANSACTION_ID) - private String appTransactionId; - @JsonProperty(SERIALIZED_NAME_OFFER_PERIOD) - private String offerPeriod; - @JsonProperty(SERIALIZED_NAME_REVOCATION_TYPE) - private String revocationType; - @JsonProperty(SERIALIZED_NAME_REVOCATION_PERCENTAGE) - private Integer revocationPercentage; + @JsonProperty(SERIALIZED_NAME_TYPE) + private String type; + @JsonProperty(SERIALIZED_NAME_WEB_ORDER_LINE_ITEM_ID) + private String webOrderLineItemId; @JsonProperty(SERIALIZED_NAME_ADVANCED_COMMERCE_INFO) private AdvancedCommerceTransactionInfo advancedCommerceInfo; @JsonProperty(SERIALIZED_NAME_BILLING_PLAN_TYPE) private String billingPlanType; @JsonProperty(SERIALIZED_NAME_COMMITMENT_INFO) private TransactionCommitmentInfo commitmentInfo; + @JsonProperty(SERIALIZED_NAME_PREVIOUS_ORIGINAL_TRANSACTION_ID) + private String previousOriginalTransactionId; @JsonAnySetter private Map unknownFields; + private static final int MINIMUM_REVOCATION_PERCENTAGE = 0; + private static final int MAXIMUM_REVOCATION_PERCENTAGE = 100000; public JWSTransactionDecodedPayload() { } - public JWSTransactionDecodedPayload originalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public JWSTransactionDecodedPayload appAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; return this; } /** - * The original transaction identifier of a purchase. + * A UUID you create at the time of purchase that associates the transaction with a customer on your own service. * - * @return originalTransactionId - * @see originalTransactionId + * @return appAccountToken + * @see appAccountToken **/ - public String getOriginalTransactionId() { - return originalTransactionId; + public UUID getAppAccountToken() { + return appAccountToken; } - public void setOriginalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public void setAppAccountToken(UUID appAccountToken) { + this.appAccountToken = appAccountToken; } - public JWSTransactionDecodedPayload transactionId(String transactionId) { - this.transactionId = transactionId; + public JWSTransactionDecodedPayload appTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; return this; } /** - * The unique identifier for a transaction such as an in-app purchase, restored in-app purchase, or subscription renewal. + * The unique identifier of the app download transaction. * - * @return transactionId - * @see transactionId + * @return appTransactionId + * @see appTransactionId **/ - public String getTransactionId() { - return transactionId; + public String getAppTransactionId() { + return appTransactionId; } - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; + public void setAppTransactionId(String appTransactionId) { + this.appTransactionId = appTransactionId; } - public JWSTransactionDecodedPayload webOrderLineItemId(String webOrderLineItemId) { - this.webOrderLineItemId = webOrderLineItemId; + public JWSTransactionDecodedPayload bundleId(String bundleId) { + this.bundleId = bundleId; return this; } /** - * The unique identifier of subscription-purchase events across devices, including renewals. + * The bundle identifier of the app. * - * @return webOrderLineItemId - * @see webOrderLineItemId + * @return bundleId + * @see bundleId **/ - public String getWebOrderLineItemId() { - return webOrderLineItemId; + public String getBundleId() { + return bundleId; } - public void setWebOrderLineItemId(String webOrderLineItemId) { - this.webOrderLineItemId = webOrderLineItemId; + public void setBundleId(String bundleId) { + this.bundleId = bundleId; } - public JWSTransactionDecodedPayload bundleId(String bundleId) { - this.bundleId = bundleId; + public JWSTransactionDecodedPayload currency(String currency) { + this.currency = currency; return this; } /** - * The bundle identifier of an app. + * The three-letter ISO 4217 currency code associated with the price parameter. * - * @return bundleId - * @see bundleId + * @return currency + * @see currency **/ - public String getBundleId() { - return bundleId; + public String getCurrency() { + return currency; } - public void setBundleId(String bundleId) { - this.bundleId = bundleId; + public void setCurrency(String currency) { + this.currency = currency; } - public JWSTransactionDecodedPayload productId(String productId) { - this.productId = productId; + public JWSTransactionDecodedPayload environment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; return this; } /** - * The unique identifier for the product, that you create in App Store Connect. + * The server environment, either sandbox or production. * - * @return productId - * @see productId + * @return environment + * @see environment **/ - public String getProductId() { - return productId; + public Environment getEnvironment() { + return Environment.fromValue(environment); } - public void setProductId(String productId) { - this.productId = productId; + /** + * @see #getEnvironment() + **/ + public String getRawEnvironment() { + return environment; } - public JWSTransactionDecodedPayload subscriptionGroupIdentifier(String subscriptionGroupIdentifier) { - this.subscriptionGroupIdentifier = subscriptionGroupIdentifier; + public void setEnvironment(Environment environment) { + this.environment = environment != null ? environment.getValue() : null; + } + + public void setRawEnvironment(String rawEnvironment) { + this.environment = rawEnvironment; + } + + public JWSTransactionDecodedPayload expiresDate(Long expiresDate) { + this.expiresDate = expiresDate; return this; } /** - * The identifier of the subscription group that the subscription belongs to. + * The UNIX time, in milliseconds, that the subscription expires or renews. * - * @return subscriptionGroupIdentifier - * @see subscriptionGroupIdentifier + * @return expiresDate + * @see expiresDate **/ - public String getSubscriptionGroupIdentifier() { - return subscriptionGroupIdentifier; + public Long getExpiresDate() { + return expiresDate; + } + + public void setExpiresDate(Long expiresDate) { + this.expiresDate = expiresDate; + } + + public JWSTransactionDecodedPayload inAppOwnershipType(InAppOwnershipType inAppOwnershipType) { + this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; + return this; + } + + /** + * A string that describes whether the transaction was purchased by the customer, or is available to them through Family Sharing, an organization, or a group. + * + * @return inAppOwnershipType + * @see inAppOwnershipType + **/ + public InAppOwnershipType getInAppOwnershipType() { + return InAppOwnershipType.fromValue(inAppOwnershipType); + } + + /** + * @see #getInAppOwnershipType() + **/ + public String getRawInAppOwnershipType() { + return inAppOwnershipType; + } + + public void setInAppOwnershipType(InAppOwnershipType inAppOwnershipType) { + this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; } - public void setSubscriptionGroupIdentifier(String subscriptionGroupIdentifier) { - this.subscriptionGroupIdentifier = subscriptionGroupIdentifier; + public void setRawInAppOwnershipType(String rawInAppOwnershipType) { + this.inAppOwnershipType = rawInAppOwnershipType; } - public JWSTransactionDecodedPayload purchaseDate(Long purchaseDate) { - this.purchaseDate = purchaseDate; + public JWSTransactionDecodedPayload isUpgraded(Boolean isUpgraded) { + this.isUpgraded = isUpgraded; return this; } /** - * The time that the App Store charged the user’s account for an in-app purchase, a restored in-app purchase, a subscription, or a subscription renewal after a lapse. + * A Boolean value that indicates whether the customer upgraded to another subscription. * - * @return purchaseDate - * @see purchaseDate + * @return isUpgraded + * @see isUpgraded **/ - public Long getPurchaseDate() { - return purchaseDate; + public Boolean getIsUpgraded() { + return isUpgraded; } - public void setPurchaseDate(Long purchaseDate) { - this.purchaseDate = purchaseDate; + public void setIsUpgraded(Boolean isUpgraded) { + this.isUpgraded = isUpgraded; } - public JWSTransactionDecodedPayload originalPurchaseDate(Long originalPurchaseDate) { - this.originalPurchaseDate = originalPurchaseDate; + public JWSTransactionDecodedPayload offerDiscountType(OfferDiscountType offerDiscountType) { + this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; return this; } /** - * The purchase date of the transaction associated with the original transaction identifier. + * The payment mode you configure for the offer. * - * @return originalPurchaseDate - * @see originalPurchaseDate + * @return offerDiscountType + * @see offerDiscountType **/ - public Long getOriginalPurchaseDate() { - return originalPurchaseDate; + public OfferDiscountType getOfferDiscountType() { + return OfferDiscountType.fromValue(offerDiscountType); } - public void setOriginalPurchaseDate(Long originalPurchaseDate) { - this.originalPurchaseDate = originalPurchaseDate; + /** + * @see #getOfferDiscountType() + **/ + public String getRawOfferDiscountType() { + return offerDiscountType; } - public JWSTransactionDecodedPayload expiresDate(Long expiresDate) { - this.expiresDate = expiresDate; + public void setOfferDiscountType(OfferDiscountType offerDiscountType) { + this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; + } + + public void setRawOfferDiscountType(String rawOfferDiscountType) { + this.offerDiscountType = rawOfferDiscountType; + } + + public JWSTransactionDecodedPayload offerIdentifier(String offerIdentifier) { + this.offerIdentifier = offerIdentifier; return this; } /** - * The UNIX time, in milliseconds, an auto-renewable subscription expires or renews. + * The identifier that contains the offer code or the promotional offer identifier. * - * @return expiresDate - * @see expiresDate + * @return offerIdentifier + * @see offerIdentifier **/ - public Long getExpiresDate() { - return expiresDate; + public String getOfferIdentifier() { + return offerIdentifier; } - public void setExpiresDate(Long expiresDate) { - this.expiresDate = expiresDate; + public void setOfferIdentifier(String offerIdentifier) { + this.offerIdentifier = offerIdentifier; } - public JWSTransactionDecodedPayload quantity(Integer quantity) { - this.quantity = quantity; + public JWSTransactionDecodedPayload offerPeriod(String offerPeriod) { + this.offerPeriod = offerPeriod; return this; } /** - * The number of consumable products purchased. + * The duration of the offer applied to the transaction. * - * @return quantity - * @see quantity + * @return offerPeriod + * @see offerPeriod **/ - public Integer getQuantity() { - return quantity; + public String getOfferPeriod() { + return offerPeriod; } - public void setQuantity(Integer quantity) { - this.quantity = quantity; + public void setOfferPeriod(String offerPeriod) { + this.offerPeriod = offerPeriod; } - public JWSTransactionDecodedPayload type(Type type) { - this.type = type != null ? type.getValue() : null; + public JWSTransactionDecodedPayload offerType(OfferType offerType) { + this.offerType = offerType != null ? offerType.getValue() : null; return this; } /** - * The type of the in-app purchase. + * A value that represents the promotional offer type. * - * @return type - * @see type + * @return offerType + * @see offerType **/ - public Type getType() { - return type != null ? Type.fromValue(type) : null; + public OfferType getOfferType() { + return OfferType.fromValue(offerType); } /** - * @see #getType() - */ - public String getRawType() { - return type; + * @see #getOfferType() + **/ + public Integer getRawOfferType() { + return offerType; } - public void setType(Type type) { - this.type = type != null ? type.getValue() : null; + public void setOfferType(OfferType offerType) { + this.offerType = offerType != null ? offerType.getValue() : null; } - public void setRawType(String rawType) { - this.type = rawType; + public void setRawOfferType(Integer rawOfferType) { + this.offerType = rawOfferType; } - public JWSTransactionDecodedPayload appAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + public JWSTransactionDecodedPayload originalPurchaseDate(Long originalPurchaseDate) { + this.originalPurchaseDate = originalPurchaseDate; return this; } /** - * The UUID that an app optionally generates to map a customer’s in-app purchase with its resulting App Store transaction. + * The UNIX time, in milliseconds, that represents the purchase date of the original transaction identifier. * - * @return appAccountToken - * @see appAccountToken + * @return originalPurchaseDate + * @see originalPurchaseDate **/ - public UUID getAppAccountToken() { - return appAccountToken; + public Long getOriginalPurchaseDate() { + return originalPurchaseDate; } - public void setAppAccountToken(UUID appAccountToken) { - this.appAccountToken = appAccountToken; + public void setOriginalPurchaseDate(Long originalPurchaseDate) { + this.originalPurchaseDate = originalPurchaseDate; } - public JWSTransactionDecodedPayload inAppOwnershipType(InAppOwnershipType inAppOwnershipType) { - this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; + public JWSTransactionDecodedPayload originalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; return this; } /** - * A string that describes whether the transaction was purchased by the user, or is available to them through Family Sharing. + * The transaction identifier of the original purchase. * - * @return inAppOwnershipType - * @see inAppOwnershipType + * @return originalTransactionId + * @see originalTransactionId **/ - public InAppOwnershipType getInAppOwnershipType() { - return inAppOwnershipType != null ? InAppOwnershipType.fromValue(inAppOwnershipType) : null; + public String getOriginalTransactionId() { + return originalTransactionId; } - /** - * @see #getRawInAppOwnershipType() - */ - public String getRawInAppOwnershipType() { - return inAppOwnershipType; + public void setOriginalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; } - public void setInAppOwnershipType(InAppOwnershipType inAppOwnershipType) { - this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; + public JWSTransactionDecodedPayload price(Long price) { + this.price = price; + return this; } - public void setRawInAppOwnershipType(String rawInAppOwnershipType) { - this.inAppOwnershipType = rawInAppOwnershipType; + /** + * An integer value that represents the price multiplied by 1000 of the in-app purchase or subscription offer you configured in App Store Connect and that the system records at the time of the purchase. + * + * @return price + * @see price + **/ + public Long getPrice() { + return price; } - public JWSTransactionDecodedPayload signedDate(Long signedDate) { - this.signedDate = signedDate; + public void setPrice(Long price) { + this.price = price; + } + + public JWSTransactionDecodedPayload productId(String productId) { + this.productId = productId; return this; } /** - * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature data. + * The unique identifier of the product. * - * @return signedDate - * @see signedDate + * @return productId + * @see productId **/ - public Long getSignedDate() { - return signedDate; + public String getProductId() { + return productId; } - public void setSignedDate(Long signedDate) { - this.signedDate = signedDate; + public void setProductId(String productId) { + this.productId = productId; } - public JWSTransactionDecodedPayload revocationReason(RevocationReason revocationReason) { - this.revocationReason = revocationReason != null ? revocationReason.getValue() : null; + public JWSTransactionDecodedPayload purchaseDate(Long purchaseDate) { + this.purchaseDate = purchaseDate; return this; } /** - * The reason that the App Store refunded the transaction or revoked it from Family Sharing. + * The UNIX time, in milliseconds, that the App Store charged the customer’s account for a purchase, restored product, subscription, or subscription renewal after a lapse. * - * @return revocationReason - * @see revocationReason + * @return purchaseDate + * @see purchaseDate **/ - public RevocationReason getRevocationReason() { - return revocationReason != null ? RevocationReason.fromValue(revocationReason) : null; + public Long getPurchaseDate() { + return purchaseDate; } - /** - * @see #getRevocationReason() - */ - public Integer getRawRevocationReason() { - return revocationReason; + public void setPurchaseDate(Long purchaseDate) { + this.purchaseDate = purchaseDate; } - public void setRevocationReason(RevocationReason revocationReason) { - this.revocationReason = revocationReason != null ? revocationReason.getValue(): null; + public JWSTransactionDecodedPayload quantity(Integer quantity) { + this.quantity = quantity; + return this; } - public void setRawRevocationReason(Integer rawRevocationReason) { - this.revocationReason = rawRevocationReason; + /** + * The number of products or seats the customer purchased. + * + * @return quantity + * @see quantity + **/ + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; } public JWSTransactionDecodedPayload revocationDate(Long revocationDate) { @@ -451,7 +526,7 @@ public JWSTransactionDecodedPayload revocationDate(Long revocationDate) { } /** - * The UNIX time, in milliseconds, that Apple Support refunded a transaction. + * The UNIX time, in milliseconds, that the App Store refunded the transaction or revoked it from Family Sharing. * * @return revocationDate * @see revocationDate @@ -464,102 +539,110 @@ public void setRevocationDate(Long revocationDate) { this.revocationDate = revocationDate; } - public JWSTransactionDecodedPayload isUpgraded(Boolean isUpgraded) { - this.isUpgraded = isUpgraded; + public JWSTransactionDecodedPayload revocationPercentage(Integer revocationPercentage) { + this.revocationPercentage = validateRevocationPercentage(revocationPercentage); return this; } /** - * The Boolean value that indicates whether the user upgraded to another subscription. + * The percentage, in milliunits, of the transaction that the App Store has refunded or revoked. * - * @return isUpgraded - * @see isUpgraded + * @return revocationPercentage + * @see revocationPercentage **/ - public Boolean getIsUpgraded() { - return isUpgraded; + public Integer getRevocationPercentage() { + return revocationPercentage; } - public void setIsUpgraded(Boolean isUpgraded) { - this.isUpgraded = isUpgraded; + @JsonSetter(SERIALIZED_NAME_REVOCATION_PERCENTAGE) + public void setRevocationPercentage(Integer revocationPercentage) { + this.revocationPercentage = validateRevocationPercentage(revocationPercentage); } - public JWSTransactionDecodedPayload offerType(OfferType offerType) { - this.offerType = offerType != null ? offerType.getValue() : null; + private Integer validateRevocationPercentage(Integer revocationPercentage) { + if (revocationPercentage != null && (revocationPercentage < MINIMUM_REVOCATION_PERCENTAGE || revocationPercentage > MAXIMUM_REVOCATION_PERCENTAGE)) { + throw new IllegalArgumentException("revocationPercentage must be between " + MINIMUM_REVOCATION_PERCENTAGE + " and " + MAXIMUM_REVOCATION_PERCENTAGE); + } + return revocationPercentage; + } + + public JWSTransactionDecodedPayload revocationReason(RevocationReason revocationReason) { + this.revocationReason = revocationReason != null ? revocationReason.getValue() : null; return this; } /** - * A value that represents the promotional offer type. + * The reason that the App Store refunded the transaction or revoked it from Family Sharing. * - * @return offerType - * @see offerType + * @return revocationReason + * @see revocationReason **/ - public OfferType getOfferType() { - return offerType != null ? OfferType.fromValue(offerType) : null; + public RevocationReason getRevocationReason() { + return RevocationReason.fromValue(revocationReason); } /** - * @see #getOfferType() - */ - public Integer getRawOfferType() { - return offerType; + * @see #getRevocationReason() + **/ + public Integer getRawRevocationReason() { + return revocationReason; } - public void setOfferType(OfferType offerType) { - this.offerType = offerType != null ? offerType.getValue() : null; + public void setRevocationReason(RevocationReason revocationReason) { + this.revocationReason = revocationReason != null ? revocationReason.getValue() : null; } - public void setRawOfferType(Integer rawOfferType) { - this.offerType = rawOfferType; + public void setRawRevocationReason(Integer rawRevocationReason) { + this.revocationReason = rawRevocationReason; } - public JWSTransactionDecodedPayload offerIdentifier(String offerIdentifier) { - this.offerIdentifier = offerIdentifier; + public JWSTransactionDecodedPayload revocationType(RevocationType revocationType) { + this.revocationType = revocationType != null ? revocationType.getValue() : null; return this; } /** - * The identifier that contains the offer code or the promotional offer identifier. + * The type of the refund or revocation that applies to the transaction. * - * @return offerIdentifier - * @see offerIdentifier + * @return revocationType + * @see revocationType **/ - public String getOfferIdentifier() { - return offerIdentifier; + public RevocationType getRevocationType() { + return RevocationType.fromValue(revocationType); } - public void setOfferIdentifier(String offerIdentifier) { - this.offerIdentifier = offerIdentifier; + /** + * @see #getRevocationType() + **/ + public String getRawRevocationType() { + return revocationType; } - public JWSTransactionDecodedPayload environment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; - return this; + public void setRevocationType(RevocationType revocationType) { + this.revocationType = revocationType != null ? revocationType.getValue() : null; } - /** - * The server environment, either sandbox or production. - * - * @return environment - * @see environment - **/ - public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + public void setRawRevocationType(String rawRevocationType) { + this.revocationType = rawRevocationType; } - /** - * @see #getRawEnvironment() - */ - public String getRawEnvironment() { - return environment; + public JWSTransactionDecodedPayload signedDate(Long signedDate) { + this.signedDate = signedDate; + return this; } - public void setEnvironment(Environment environment) { - this.environment = environment != null ? environment.getValue() : null; + /** + * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature (JWS) data. + * + * @return signedDate + * @see signedDate + **/ + public Long getSignedDate() { + return signedDate; } - public void setRawEnvironment(String rawEnvironment) { - this.environment = rawEnvironment; + public void setSignedDate(Long signedDate) { + this.signedDate = signedDate; } public JWSTransactionDecodedPayload storefront(String storefront) { @@ -568,7 +651,7 @@ public JWSTransactionDecodedPayload storefront(String storefront) { } /** - * The three-letter code that represents the country or region associated with the App Store storefront of the purchase. + * The three-letter code that represents the country or region associated with the App Store storefront for the purchase. * * @return storefront * @see storefront @@ -587,7 +670,7 @@ public JWSTransactionDecodedPayload storefrontId(String storefrontId) { } /** - * An Apple-defined value that uniquely identifies an App Store storefront. + * An Apple-defined value that uniquely identifies the App Store storefront associated with the purchase. * * @return storefrontId * @see storefrontId @@ -600,189 +683,121 @@ public void setStorefrontId(String storefrontId) { this.storefrontId = storefrontId; } - public JWSTransactionDecodedPayload transactionReason(TransactionReason transactionReason) { - this.transactionReason = transactionReason != null ? transactionReason.getValue() : null; + public JWSTransactionDecodedPayload subscriptionGroupIdentifier(String subscriptionGroupIdentifier) { + this.subscriptionGroupIdentifier = subscriptionGroupIdentifier; return this; } /** - * The cause of a purchase transaction, which indicates whether it’s a customer’s purchase or a renewal for an auto-renewable subscription that the system initiates. + * The identifier of the subscription group to which the subscription belongs. * - * @return transactionReason - * @see transactionReason + * @return subscriptionGroupIdentifier + * @see subscriptionGroupIdentifier **/ - public TransactionReason getTransactionReason() { - return transactionReason != null ? TransactionReason.fromValue(transactionReason) : null; - } - - /** - * @see #getTransactionReason() - */ - public String getRawTransactionReason() { - return transactionReason; - } - - public void setTransactionReason(TransactionReason transactionReason) { - this.transactionReason = transactionReason != null ? transactionReason.getValue() : null; + public String getSubscriptionGroupIdentifier() { + return subscriptionGroupIdentifier; } - public void setRawTransactionReason(String rawTransactionReason) { - this.transactionReason = rawTransactionReason; + public void setSubscriptionGroupIdentifier(String subscriptionGroupIdentifier) { + this.subscriptionGroupIdentifier = subscriptionGroupIdentifier; } - public JWSTransactionDecodedPayload price(Long price) { - this.price = price; + public JWSTransactionDecodedPayload transactionId(String transactionId) { + this.transactionId = transactionId; return this; } /** - * The price, in milliunits, of the in-app purchase or subscription offer that you configured in App Store Connect. + * The unique identifier of the transaction. * - * @return price - * @see price + * @return transactionId + * @see transactionId **/ - public Long getPrice() { - return price; + public String getTransactionId() { + return transactionId; } - public void setPrice(Long price) { - this.price = price; + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; } - public JWSTransactionDecodedPayload currency(String currency) { - this.currency = currency; + public JWSTransactionDecodedPayload transactionReason(TransactionReason transactionReason) { + this.transactionReason = transactionReason != null ? transactionReason.getValue() : null; return this; } /** - * The three-letter ISO 4217 currency code for the price of the product. + * The reason for the purchase transaction, which indicates whether it’s a customer’s purchase or a renewal for an auto-renewable subscription that the system initiates. * - * @return currency - * @see currency + * @return transactionReason + * @see transactionReason **/ - public String getCurrency() { - return this.currency; - } - - public void setCurrency(String currency) { - this.currency = currency; - } - - public JWSTransactionDecodedPayload offerDiscountType(OfferDiscountType offerDiscountType) { - this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; - return this; + public TransactionReason getTransactionReason() { + return TransactionReason.fromValue(transactionReason); } /** - * The payment mode you configure for the offer. - * - * @return offerDiscountType - * @see offerDiscountType + * @see #getTransactionReason() **/ - public OfferDiscountType getOfferDiscountType() { - return offerDiscountType != null ? OfferDiscountType.fromValue(offerDiscountType) : null; - } - - /** - * @see #getOfferDiscountType() - */ - public String getRawOfferDiscountType() { - return offerDiscountType; - } - - public void setOfferDiscountType(OfferDiscountType offerDiscountType) { - this.offerDiscountType = offerDiscountType != null ? offerDiscountType.getValue() : null; - } - - public void setRawOfferDiscountType(String rawOfferDiscountType) { - this.offerDiscountType = rawOfferDiscountType; - } - - public JWSTransactionDecodedPayload appTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; - return this; + public String getRawTransactionReason() { + return transactionReason; } - /** - * The unique identifier of the app download transaction. - * - * @return appTransactionId - * @see appTransactionId - **/ - public String getAppTransactionId() { - return this.appTransactionId; + public void setTransactionReason(TransactionReason transactionReason) { + this.transactionReason = transactionReason != null ? transactionReason.getValue() : null; } - public void setAppTransactionId(String appTransactionId) { - this.appTransactionId = appTransactionId; + public void setRawTransactionReason(String rawTransactionReason) { + this.transactionReason = rawTransactionReason; } - public JWSTransactionDecodedPayload offerPeriod(String offerPeriod) { - this.offerPeriod = offerPeriod; + public JWSTransactionDecodedPayload type(Type type) { + this.type = type != null ? type.getValue() : null; return this; } /** - * The duration of the offer. + * The type of the in-app purchase. * - * @return offerPeriod - * @see offerPeriod + * @return type + * @see type **/ - public String getOfferPeriod() { - return this.offerPeriod; - } - - public void setOfferPeriod(String offerPeriod) { - this.offerPeriod = offerPeriod; - } - - public JWSTransactionDecodedPayload revocationType(RevocationType revocationType) { - this.revocationType = revocationType != null ? revocationType.getValue() : null; - return this; + public Type getType() { + return Type.fromValue(type); } /** - * The type of the refund or revocation that applies to the transaction. - * - * @return revocationType - * @see revocationType + * @see #getType() **/ - public RevocationType getRevocationType() { - return revocationType != null ? RevocationType.fromValue(revocationType) : null; - } - - /** - * @see #getRevocationType() - */ - public String getRawRevocationType() { - return revocationType; + public String getRawType() { + return type; } - public void setRevocationType(RevocationType revocationType) { - this.revocationType = revocationType != null ? revocationType.getValue() : null; + public void setType(Type type) { + this.type = type != null ? type.getValue() : null; } - public void setRawRevocationType(String rawRevocationType) { - this.revocationType = rawRevocationType; + public void setRawType(String rawType) { + this.type = rawType; } - public JWSTransactionDecodedPayload revocationPercentage(Integer revocationPercentage) { - this.revocationPercentage = revocationPercentage; + public JWSTransactionDecodedPayload webOrderLineItemId(String webOrderLineItemId) { + this.webOrderLineItemId = webOrderLineItemId; return this; } /** - * The percentage, in milliunits, of the transaction that the App Store has refunded or revoked. + * The unique identifier of subscription purchase events across devices, including subscription renewals. * - * @return revocationPercentage - * @see revocationPercentage + * @return webOrderLineItemId + * @see webOrderLineItemId **/ - public Integer getRevocationPercentage() { - return revocationPercentage; + public String getWebOrderLineItemId() { + return webOrderLineItemId; } - public void setRevocationPercentage(Integer revocationPercentage) { - this.revocationPercentage = revocationPercentage; + public void setWebOrderLineItemId(String webOrderLineItemId) { + this.webOrderLineItemId = webOrderLineItemId; } public JWSTransactionDecodedPayload advancedCommerceInfo(AdvancedCommerceTransactionInfo advancedCommerceInfo) { @@ -814,12 +829,12 @@ public JWSTransactionDecodedPayload billingPlanType(BillingPlanType billingPlanT * @see billingPlanType **/ public BillingPlanType getBillingPlanType() { - return billingPlanType != null ? BillingPlanType.fromValue(billingPlanType) : null; + return BillingPlanType.fromValue(billingPlanType); } /** * @see #getBillingPlanType() - */ + **/ public String getRawBillingPlanType() { return billingPlanType; } @@ -849,16 +864,35 @@ public void setCommitmentInfo(TransactionCommitmentInfo commitmentInfo) { this.commitmentInfo = commitmentInfo; } + public JWSTransactionDecodedPayload previousOriginalTransactionId(String previousOriginalTransactionId) { + this.previousOriginalTransactionId = previousOriginalTransactionId; + return this; + } + + /** + * The subscription’s original transaction identifier, before you migrated the subscription. + * + * @return previousOriginalTransactionId + * @see previousOriginalTransactionId + **/ + public String getPreviousOriginalTransactionId() { + return previousOriginalTransactionId; + } + + public void setPreviousOriginalTransactionId(String previousOriginalTransactionId) { + this.previousOriginalTransactionId = previousOriginalTransactionId; + } + public JWSTransactionDecodedPayload unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -869,55 +903,93 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - JWSTransactionDecodedPayload that = (JWSTransactionDecodedPayload) o; - return Objects.equals(originalTransactionId, that.originalTransactionId) && Objects.equals(transactionId, that.transactionId) && Objects.equals(webOrderLineItemId, that.webOrderLineItemId) && Objects.equals(bundleId, that.bundleId) && Objects.equals(productId, that.productId) && Objects.equals(subscriptionGroupIdentifier, that.subscriptionGroupIdentifier) && Objects.equals(purchaseDate, that.purchaseDate) && Objects.equals(originalPurchaseDate, that.originalPurchaseDate) && Objects.equals(expiresDate, that.expiresDate) && Objects.equals(quantity, that.quantity) && Objects.equals(type, that.type) && Objects.equals(appAccountToken, that.appAccountToken) && Objects.equals(inAppOwnershipType, that.inAppOwnershipType) && Objects.equals(signedDate, that.signedDate) && Objects.equals(revocationReason, that.revocationReason) && Objects.equals(revocationDate, that.revocationDate) && Objects.equals(isUpgraded, that.isUpgraded) && Objects.equals(offerType, that.offerType) && Objects.equals(offerIdentifier, that.offerIdentifier) && Objects.equals(environment, that.environment) && Objects.equals(storefront, that.storefront) && Objects.equals(storefrontId, that.storefrontId) && Objects.equals(transactionReason, that.transactionReason) && Objects.equals(price, that.price) && Objects.equals(currency, that.currency) && Objects.equals(offerDiscountType, that.offerDiscountType) && Objects.equals(appTransactionId, that.appTransactionId) && Objects.equals(offerPeriod, that.offerPeriod) && Objects.equals(revocationType, that.revocationType) && Objects.equals(revocationPercentage, that.revocationPercentage) && Objects.equals(advancedCommerceInfo, that.advancedCommerceInfo) && Objects.equals(billingPlanType, that.billingPlanType) && Objects.equals(commitmentInfo, that.commitmentInfo) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + JWSTransactionDecodedPayload jWSTransactionDecodedPayload = (JWSTransactionDecodedPayload) o; + return Objects.equals(this.appAccountToken, jWSTransactionDecodedPayload.appAccountToken) && + Objects.equals(this.appTransactionId, jWSTransactionDecodedPayload.appTransactionId) && + Objects.equals(this.bundleId, jWSTransactionDecodedPayload.bundleId) && + Objects.equals(this.currency, jWSTransactionDecodedPayload.currency) && + Objects.equals(this.environment, jWSTransactionDecodedPayload.environment) && + Objects.equals(this.expiresDate, jWSTransactionDecodedPayload.expiresDate) && + Objects.equals(this.inAppOwnershipType, jWSTransactionDecodedPayload.inAppOwnershipType) && + Objects.equals(this.isUpgraded, jWSTransactionDecodedPayload.isUpgraded) && + Objects.equals(this.offerDiscountType, jWSTransactionDecodedPayload.offerDiscountType) && + Objects.equals(this.offerIdentifier, jWSTransactionDecodedPayload.offerIdentifier) && + Objects.equals(this.offerPeriod, jWSTransactionDecodedPayload.offerPeriod) && + Objects.equals(this.offerType, jWSTransactionDecodedPayload.offerType) && + Objects.equals(this.originalPurchaseDate, jWSTransactionDecodedPayload.originalPurchaseDate) && + Objects.equals(this.originalTransactionId, jWSTransactionDecodedPayload.originalTransactionId) && + Objects.equals(this.price, jWSTransactionDecodedPayload.price) && + Objects.equals(this.productId, jWSTransactionDecodedPayload.productId) && + Objects.equals(this.purchaseDate, jWSTransactionDecodedPayload.purchaseDate) && + Objects.equals(this.quantity, jWSTransactionDecodedPayload.quantity) && + Objects.equals(this.revocationDate, jWSTransactionDecodedPayload.revocationDate) && + Objects.equals(this.revocationPercentage, jWSTransactionDecodedPayload.revocationPercentage) && + Objects.equals(this.revocationReason, jWSTransactionDecodedPayload.revocationReason) && + Objects.equals(this.revocationType, jWSTransactionDecodedPayload.revocationType) && + Objects.equals(this.signedDate, jWSTransactionDecodedPayload.signedDate) && + Objects.equals(this.storefront, jWSTransactionDecodedPayload.storefront) && + Objects.equals(this.storefrontId, jWSTransactionDecodedPayload.storefrontId) && + Objects.equals(this.subscriptionGroupIdentifier, jWSTransactionDecodedPayload.subscriptionGroupIdentifier) && + Objects.equals(this.transactionId, jWSTransactionDecodedPayload.transactionId) && + Objects.equals(this.transactionReason, jWSTransactionDecodedPayload.transactionReason) && + Objects.equals(this.type, jWSTransactionDecodedPayload.type) && + Objects.equals(this.webOrderLineItemId, jWSTransactionDecodedPayload.webOrderLineItemId) && + Objects.equals(this.advancedCommerceInfo, jWSTransactionDecodedPayload.advancedCommerceInfo) && + Objects.equals(this.billingPlanType, jWSTransactionDecodedPayload.billingPlanType) && + Objects.equals(this.commitmentInfo, jWSTransactionDecodedPayload.commitmentInfo) && + Objects.equals(this.previousOriginalTransactionId, jWSTransactionDecodedPayload.previousOriginalTransactionId) && + Objects.equals(this.unknownFields, jWSTransactionDecodedPayload.unknownFields); } @Override public int hashCode() { - return Objects.hash(originalTransactionId, transactionId, webOrderLineItemId, bundleId, productId, subscriptionGroupIdentifier, purchaseDate, originalPurchaseDate, expiresDate, quantity, type, appAccountToken, inAppOwnershipType, signedDate, revocationReason, revocationDate, isUpgraded, offerType, offerIdentifier, environment, storefront, storefrontId, transactionReason, price, currency, offerDiscountType, appTransactionId, offerPeriod, revocationType, revocationPercentage, advancedCommerceInfo, billingPlanType, commitmentInfo, unknownFields); + return Objects.hash(appAccountToken, appTransactionId, bundleId, currency, environment, expiresDate, inAppOwnershipType, isUpgraded, offerDiscountType, offerIdentifier, offerPeriod, offerType, originalPurchaseDate, originalTransactionId, price, productId, purchaseDate, quantity, revocationDate, revocationPercentage, revocationReason, revocationType, signedDate, storefront, storefrontId, subscriptionGroupIdentifier, transactionId, transactionReason, type, webOrderLineItemId, advancedCommerceInfo, billingPlanType, commitmentInfo, previousOriginalTransactionId, unknownFields); } @Override public String toString() { return "JWSTransactionDecodedPayload{" + - "originalTransactionId='" + originalTransactionId + '\'' + - ", transactionId='" + transactionId + '\'' + - ", webOrderLineItemId='" + webOrderLineItemId + '\'' + + "appAccountToken=" + appAccountToken + + ", appTransactionId='" + appTransactionId + '\'' + ", bundleId='" + bundleId + '\'' + - ", productId='" + productId + '\'' + - ", subscriptionGroupIdentifier='" + subscriptionGroupIdentifier + '\'' + - ", purchaseDate=" + purchaseDate + - ", originalPurchaseDate=" + originalPurchaseDate + + ", currency='" + currency + '\'' + + ", environment='" + environment + '\'' + ", expiresDate=" + expiresDate + - ", quantity=" + quantity + - ", type='" + type + '\'' + - ", appAccountToken=" + appAccountToken + ", inAppOwnershipType='" + inAppOwnershipType + '\'' + - ", signedDate=" + signedDate + - ", revocationReason=" + revocationReason + - ", revocationDate=" + revocationDate + ", isUpgraded=" + isUpgraded + - ", offerType=" + offerType + + ", offerDiscountType='" + offerDiscountType + '\'' + ", offerIdentifier='" + offerIdentifier + '\'' + - ", environment='" + environment + '\'' + + ", offerPeriod='" + offerPeriod + '\'' + + ", offerType=" + offerType + + ", originalPurchaseDate=" + originalPurchaseDate + + ", originalTransactionId='" + originalTransactionId + '\'' + + ", price=" + price + + ", productId='" + productId + '\'' + + ", purchaseDate=" + purchaseDate + + ", quantity=" + quantity + + ", revocationDate=" + revocationDate + + ", revocationPercentage=" + revocationPercentage + + ", revocationReason=" + revocationReason + + ", revocationType='" + revocationType + '\'' + + ", signedDate=" + signedDate + ", storefront='" + storefront + '\'' + ", storefrontId='" + storefrontId + '\'' + + ", subscriptionGroupIdentifier='" + subscriptionGroupIdentifier + '\'' + + ", transactionId='" + transactionId + '\'' + ", transactionReason='" + transactionReason + '\'' + - ", price=" + price + - ", currency='" + currency + '\'' + - ", offerDiscountType='" + offerDiscountType + '\'' + - ", appTransactionId='" + appTransactionId + '\'' + - ", offerPeriod='" + offerPeriod + '\'' + - ", revocationType='" + revocationType + '\'' + - ", revocationPercentage=" + revocationPercentage + + ", type='" + type + '\'' + + ", webOrderLineItemId='" + webOrderLineItemId + '\'' + ", advancedCommerceInfo=" + advancedCommerceInfo + ", billingPlanType='" + billingPlanType + '\'' + ", commitmentInfo=" + commitmentInfo + + ", previousOriginalTransactionId='" + previousOriginalTransactionId + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/LastTransactionsItem.java b/src/main/java/com/apple/itunes/storekit/model/LastTransactionsItem.java index cc2f6a16..bd6bb111 100644 --- a/src/main/java/com/apple/itunes/storekit/model/LastTransactionsItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/LastTransactionsItem.java @@ -12,27 +12,46 @@ * The most recent App Store-signed transaction information and App Store-signed renewal information for an auto-renewable subscription. * * @see lastTransactionsItem - */ + **/ public class LastTransactionsItem { - private static final String SERIALIZED_NAME_STATUS = "status"; private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; - private static final String SERIALIZED_NAME_SIGNED_TRANSACTION_INFO = "signedTransactionInfo"; + private static final String SERIALIZED_NAME_STATUS = "status"; private static final String SERIALIZED_NAME_SIGNED_RENEWAL_INFO = "signedRenewalInfo"; - @JsonProperty(SERIALIZED_NAME_STATUS) - private Integer status; + private static final String SERIALIZED_NAME_SIGNED_TRANSACTION_INFO = "signedTransactionInfo"; + @JsonProperty(SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID) private String originalTransactionId; - @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) - private String signedTransactionInfo; + @JsonProperty(SERIALIZED_NAME_STATUS) + private Integer status; @JsonProperty(SERIALIZED_NAME_SIGNED_RENEWAL_INFO) private String signedRenewalInfo; + @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) + private String signedTransactionInfo; @JsonAnySetter private Map unknownFields; - public LastTransactionsItem() { } + public LastTransactionsItem originalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; + return this; + } + + /** + * The original transaction identifier of the auto-renewable subscription. + * + * @return originalTransactionId + * @see originalTransactionId + **/ + public String getOriginalTransactionId() { + return originalTransactionId; + } + + public void setOriginalTransactionId(String originalTransactionId) { + this.originalTransactionId = originalTransactionId; + } + public LastTransactionsItem status(Status status) { this.status = status != null ? status.getValue() : null; return this; @@ -45,12 +64,12 @@ public LastTransactionsItem status(Status status) { * @see status **/ public Status getStatus() { - return status != null ? Status.fromValue(status) : null; + return Status.fromValue(status); } /** * @see #getStatus() - */ + **/ public Integer getRawStatus() { return status; } @@ -63,23 +82,23 @@ public void setRawStatus(Integer rawStatus) { this.status = rawStatus; } - public LastTransactionsItem originalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public LastTransactionsItem signedRenewalInfo(String signedRenewalInfo) { + this.signedRenewalInfo = signedRenewalInfo; return this; } /** - * The original transaction identifier of a purchase. + * The subscription renewal information signed by the App Store, in JSON Web Signature (JWS) format. * - * @return originalTransactionId - * @see originalTransactionId + * @return signedRenewalInfo + * @see JWSRenewalInfo **/ - public String getOriginalTransactionId() { - return originalTransactionId; + public String getSignedRenewalInfo() { + return signedRenewalInfo; } - public void setOriginalTransactionId(String originalTransactionId) { - this.originalTransactionId = originalTransactionId; + public void setSignedRenewalInfo(String signedRenewalInfo) { + this.signedRenewalInfo = signedRenewalInfo; } public LastTransactionsItem signedTransactionInfo(String signedTransactionInfo) { @@ -88,7 +107,7 @@ public LastTransactionsItem signedTransactionInfo(String signedTransactionInfo) } /** - * Transaction information signed by the App Store, in JSON Web Signature (JWS) format. + * The transaction information signed by the App Store, in JWS format. * * @return signedTransactionInfo * @see JWSTransaction @@ -101,35 +120,16 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { this.signedTransactionInfo = signedTransactionInfo; } - public LastTransactionsItem signedRenewalInfo(String signedRenewalInfo) { - this.signedRenewalInfo = signedRenewalInfo; - return this; - } - - /** - * Subscription renewal information, signed by the App Store, in JSON Web Signature (JWS) format. - * - * @return signedRenewalInfo - * @see JWSRenewalInfo - **/ - public String getSignedRenewalInfo() { - return signedRenewalInfo; - } - - public void setSignedRenewalInfo(String signedRenewalInfo) { - this.signedRenewalInfo = signedRenewalInfo; - } - public LastTransactionsItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -147,27 +147,26 @@ public boolean equals(Object o) { return false; } LastTransactionsItem lastTransactionsItem = (LastTransactionsItem) o; - return Objects.equals(this.status, lastTransactionsItem.status) && - Objects.equals(this.originalTransactionId, lastTransactionsItem.originalTransactionId) && - Objects.equals(this.signedTransactionInfo, lastTransactionsItem.signedTransactionInfo) && + return Objects.equals(this.originalTransactionId, lastTransactionsItem.originalTransactionId) && + Objects.equals(this.status, lastTransactionsItem.status) && Objects.equals(this.signedRenewalInfo, lastTransactionsItem.signedRenewalInfo) && + Objects.equals(this.signedTransactionInfo, lastTransactionsItem.signedTransactionInfo) && Objects.equals(this.unknownFields, lastTransactionsItem.unknownFields); } @Override public int hashCode() { - return Objects.hash(status, originalTransactionId, signedTransactionInfo, signedRenewalInfo, unknownFields); + return Objects.hash(originalTransactionId, status, signedRenewalInfo, signedTransactionInfo, unknownFields); } @Override public String toString() { return "LastTransactionsItem{" + - "status=" + status + - ", originalTransactionId='" + originalTransactionId + '\'' + - ", signedTransactionInfo='" + signedTransactionInfo + '\'' + + "originalTransactionId='" + originalTransactionId + '\'' + + ", status=" + status + ", signedRenewalInfo='" + signedRenewalInfo + '\'' + + ", signedTransactionInfo='" + signedTransactionInfo + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsPurchased.java b/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsPurchased.java index 2ede5b3f..d4248dbc 100644 --- a/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsPurchased.java +++ b/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsPurchased.java @@ -5,19 +5,43 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * A value that indicates the total amount, in USD, of in-app purchases the customer has made in your app, across all platforms. + * A value that indicates the dollar amount of in-app purchases the customer has made in your app, since purchasing the app, across all platforms. * * @see lifetimeDollarsPurchased - */ + **/ public enum LifetimeDollarsPurchased { + /** + * Lifetime purchase amount is undeclared. + **/ UNDECLARED(0), + /** + * Lifetime purchase amount is 0 USD. + **/ ZERO_DOLLARS(1), + /** + * Lifetime purchase amount is between 0.01–49.99 USD. + **/ ONE_CENT_TO_FORTY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(2), + /** + * Lifetime purchase amount is between 50–99.99 USD. + **/ FIFTY_DOLLARS_TO_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(3), + /** + * Lifetime purchase amount is between 100–499.99 USD. + **/ ONE_HUNDRED_DOLLARS_TO_FOUR_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(4), + /** + * Lifetime purchase amount is between 500–999.99 USD. + **/ FIVE_HUNDRED_DOLLARS_TO_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(5), + /** + * Lifetime purchase amount is between 1000–1999.99 USD. + **/ ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(6), + /** + * Lifetime purchase amount is over 2000 USD. + **/ TWO_THOUSAND_DOLLARS_OR_GREATER(7); private final Integer value; @@ -45,4 +69,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsRefunded.java b/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsRefunded.java index ad62da60..d10d70e7 100644 --- a/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsRefunded.java +++ b/src/main/java/com/apple/itunes/storekit/model/LifetimeDollarsRefunded.java @@ -8,16 +8,40 @@ * A value that indicates the dollar amount of refunds the customer has received in your app, since purchasing the app, across all platforms. * * @see lifetimeDollarsRefunded - */ + **/ public enum LifetimeDollarsRefunded { + /** + * Lifetime refund amount is undeclared. + **/ UNDECLARED(0), + /** + * Lifetime refund amount is 0 USD. + **/ ZERO_DOLLARS(1), + /** + * Lifetime refund amount is between 0.01–49.99 USD. + **/ ONE_CENT_TO_FORTY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(2), + /** + * Lifetime refund amount is between 50–99.99 USD. + **/ FIFTY_DOLLARS_TO_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(3), + /** + * Lifetime refund amount is between 100–499.99 USD. + **/ ONE_HUNDRED_DOLLARS_TO_FOUR_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(4), + /** + * Lifetime refund amount is between 500–999.99 USD. + **/ FIVE_HUNDRED_DOLLARS_TO_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(5), + /** + * Lifetime refund amount is between 1000–1999.99 USD. + **/ ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS(6), + /** + * Lifetime refund amount is over 2000 USD. + **/ TWO_THOUSAND_DOLLARS_OR_GREATER(7); private final Integer value; @@ -45,4 +69,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateRequest.java b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateRequest.java index f1da7f08..5b7cad91 100644 --- a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateRequest.java @@ -13,31 +13,87 @@ * The request body that contains subscription-renewal-extension data to apply for all eligible active subscribers. * * @see MassExtendRenewalDateRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class MassExtendRenewalDateRequest { + private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; private static final String SERIALIZED_NAME_EXTEND_BY_DAYS = "extendByDays"; private static final String SERIALIZED_NAME_EXTEND_REASON_CODE = "extendReasonCode"; - private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; - private static final String SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES = "storefrontCountryCodes"; private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; - @JsonProperty(SERIALIZED_NAME_EXTEND_BY_DAYS) - private Integer extendByDays; - @JsonProperty(SERIALIZED_NAME_EXTEND_REASON_CODE) - private ExtendReasonCode extendReasonCode; - @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) + private static final String SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES = "storefrontCountryCodes"; + + @JsonProperty(value = SERIALIZED_NAME_REQUEST_IDENTIFIER, required = true) private String requestIdentifier; - @JsonProperty(SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES) - private List storefrontCountryCodes = null; - @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) + @JsonProperty(value = SERIALIZED_NAME_EXTEND_BY_DAYS, required = true) + private Integer extendByDays; + @JsonProperty(value = SERIALIZED_NAME_EXTEND_REASON_CODE, required = true) + private Integer extendReasonCode; + @JsonProperty(value = SERIALIZED_NAME_PRODUCT_ID, required = true) private String productId; + @JsonProperty(SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES) + private List storefrontCountryCodes; + + private static final int MAXIMUM_REQUEST_IDENTIFIER_LENGTH = 128; + private static final int MINIMUM_EXTEND_BY_DAYS = 1; + private static final int MAXIMUM_EXTEND_BY_DAYS = 90; + private static final int MAXIMUM_STOREFRONT_COUNTRY_CODE_LENGTH = 3; + + protected MassExtendRenewalDateRequest() { + } + + public MassExtendRenewalDateRequest( + String requestIdentifier, + Integer extendByDays, + ExtendReasonCode extendReasonCode, + String productId + ) { + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + this.extendByDays = validateExtendByDays(extendByDays); + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); + this.productId = Objects.requireNonNull(productId); + } + + public MassExtendRenewalDateRequest( + String requestIdentifier, + Integer extendByDays, + Integer rawExtendReasonCode, + String productId + ) { + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + this.extendByDays = validateExtendByDays(extendByDays); + this.extendReasonCode = Objects.requireNonNull(rawExtendReasonCode); + this.productId = Objects.requireNonNull(productId); + } + + public MassExtendRenewalDateRequest requestIdentifier(String requestIdentifier) { + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + return this; + } + + /** + * A string that contains a one-time UUID value you provide to identify this subscription-renewal-date extension request. + * + * @return requestIdentifier + * @see requestIdentifier + **/ + public String getRequestIdentifier() { + return requestIdentifier; + } + public void setRequestIdentifier(String requestIdentifier) { + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + } - public MassExtendRenewalDateRequest() { + private String validateRequestIdentifier(String requestIdentifier) { + Objects.requireNonNull(requestIdentifier); + if (requestIdentifier.length() > MAXIMUM_REQUEST_IDENTIFIER_LENGTH) { + throw new IllegalArgumentException("requestIdentifier length longer than maximum allowed"); + } + return requestIdentifier; } public MassExtendRenewalDateRequest extendByDays(Integer extendByDays) { - this.extendByDays = extendByDays; + this.extendByDays = validateExtendByDays(extendByDays); return this; } @@ -46,18 +102,25 @@ public MassExtendRenewalDateRequest extendByDays(Integer extendByDays) { * * @return extendByDays * @see extendByDays - * maximum: 90 **/ public Integer getExtendByDays() { return extendByDays; } public void setExtendByDays(Integer extendByDays) { - this.extendByDays = extendByDays; + this.extendByDays = validateExtendByDays(extendByDays); + } + + private Integer validateExtendByDays(Integer extendByDays) { + Objects.requireNonNull(extendByDays); + if (extendByDays < MINIMUM_EXTEND_BY_DAYS || extendByDays > MAXIMUM_EXTEND_BY_DAYS) { + throw new IllegalArgumentException("extendByDays must be between " + MINIMUM_EXTEND_BY_DAYS + " and " + MAXIMUM_EXTEND_BY_DAYS); + } + return extendByDays; } public MassExtendRenewalDateRequest extendReasonCode(ExtendReasonCode extendReasonCode) { - this.extendReasonCode = extendReasonCode; + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); return this; } @@ -68,47 +131,61 @@ public MassExtendRenewalDateRequest extendReasonCode(ExtendReasonCode extendReas * @see extendReasonCode **/ public ExtendReasonCode getExtendReasonCode() { + return ExtendReasonCode.fromValue(extendReasonCode); + } + + /** + * @see #getExtendReasonCode() + **/ + public Integer getRawExtendReasonCode() { return extendReasonCode; } public void setExtendReasonCode(ExtendReasonCode extendReasonCode) { - this.extendReasonCode = extendReasonCode; + this.extendReasonCode = Objects.requireNonNull(extendReasonCode).getValue(); } - public MassExtendRenewalDateRequest requestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + public void setRawExtendReasonCode(Integer rawExtendReasonCode) { + this.extendReasonCode = Objects.requireNonNull(rawExtendReasonCode); + } + + public MassExtendRenewalDateRequest productId(String productId) { + this.productId = Objects.requireNonNull(productId); return this; } /** - * A string that contains a unique identifier you provide to track each subscription-renewal-date extension request. + * The product identifier of the auto-renewable subscription that you’re requesting the renewal-date extension for. * - * @return requestIdentifier - * @see requestIdentifier + * @return productId + * @see productId **/ - public String getRequestIdentifier() { - return requestIdentifier; + public String getProductId() { + return productId; } - public void setRequestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + public void setProductId(String productId) { + this.productId = Objects.requireNonNull(productId); } public MassExtendRenewalDateRequest storefrontCountryCodes(List storefrontCountryCodes) { + validateStorefrontCountryCodes(storefrontCountryCodes); this.storefrontCountryCodes = storefrontCountryCodes; return this; } - public MassExtendRenewalDateRequest addStorefrontCountryCodesItem(String storefrontCountryCodesItem) { + public MassExtendRenewalDateRequest addStorefrontCountryCode(String storefrontCountryCode) { + Objects.requireNonNull(storefrontCountryCode); + validateStorefrontCountryCode(storefrontCountryCode); if (this.storefrontCountryCodes == null) { this.storefrontCountryCodes = new ArrayList<>(); } - this.storefrontCountryCodes.add(storefrontCountryCodesItem); + this.storefrontCountryCodes.add(storefrontCountryCode); return this; } /** - * A list of storefront country codes you provide to limit the storefronts for a subscription-renewal-date extension. + * A list of storefront country codes you provide to limit the storefronts that are eligible to receive the subscription-renewal-date extension. * * @return storefrontCountryCodes * @see storefrontCountryCodes @@ -118,26 +195,22 @@ public List getStorefrontCountryCodes() { } public void setStorefrontCountryCodes(List storefrontCountryCodes) { + validateStorefrontCountryCodes(storefrontCountryCodes); this.storefrontCountryCodes = storefrontCountryCodes; } - public MassExtendRenewalDateRequest productId(String productId) { - this.productId = productId; - return this; - } - - /** - * The unique identifier for the product, that you create in App Store Connect. - * - * @return productId - * @see productId - **/ - public String getProductId() { - return productId; + private void validateStorefrontCountryCodes(List storefrontCountryCodes) { + if (storefrontCountryCodes != null) { + for (String storefrontCountryCode : storefrontCountryCodes) { + validateStorefrontCountryCode(storefrontCountryCode); + } + } } - public void setProductId(String productId) { - this.productId = productId; + private void validateStorefrontCountryCode(String storefrontCountryCode) { + if (storefrontCountryCode != null && storefrontCountryCode.length() > MAXIMUM_STOREFRONT_COUNTRY_CODE_LENGTH) { + throw new IllegalArgumentException("storefrontCountryCode length longer than maximum allowed"); + } } @Override @@ -149,27 +222,26 @@ public boolean equals(Object o) { return false; } MassExtendRenewalDateRequest massExtendRenewalDateRequest = (MassExtendRenewalDateRequest) o; - return Objects.equals(this.extendByDays, massExtendRenewalDateRequest.extendByDays) && + return Objects.equals(this.requestIdentifier, massExtendRenewalDateRequest.requestIdentifier) && + Objects.equals(this.extendByDays, massExtendRenewalDateRequest.extendByDays) && Objects.equals(this.extendReasonCode, massExtendRenewalDateRequest.extendReasonCode) && - Objects.equals(this.requestIdentifier, massExtendRenewalDateRequest.requestIdentifier) && - Objects.equals(this.storefrontCountryCodes, massExtendRenewalDateRequest.storefrontCountryCodes) && - Objects.equals(this.productId, massExtendRenewalDateRequest.productId); + Objects.equals(this.productId, massExtendRenewalDateRequest.productId) && + Objects.equals(this.storefrontCountryCodes, massExtendRenewalDateRequest.storefrontCountryCodes); } @Override public int hashCode() { - return Objects.hash(extendByDays, extendReasonCode, requestIdentifier, storefrontCountryCodes, productId); + return Objects.hash(requestIdentifier, extendByDays, extendReasonCode, productId, storefrontCountryCodes); } @Override public String toString() { return "MassExtendRenewalDateRequest{" + - "extendByDays=" + extendByDays + + "requestIdentifier='" + requestIdentifier + '\'' + + ", extendByDays=" + extendByDays + ", extendReasonCode=" + extendReasonCode + - ", requestIdentifier='" + requestIdentifier + '\'' + - ", storefrontCountryCodes=" + storefrontCountryCodes + ", productId='" + productId + '\'' + + ", storefrontCountryCodes=" + storefrontCountryCodes + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateResponse.java b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateResponse.java index ab73ef3f..02f869c9 100644 --- a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateResponse.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import java.util.Map; import java.util.Objects; @@ -12,25 +13,27 @@ * A response that indicates the server successfully received the subscription-renewal-date extension request. * * @see MassExtendRenewalDateResponse - */ + **/ public class MassExtendRenewalDateResponse { private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; + @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) private String requestIdentifier; @JsonAnySetter private Map unknownFields; + private static final int MAXIMUM_REQUEST_IDENTIFIER_LENGTH = 128; public MassExtendRenewalDateResponse() { } public MassExtendRenewalDateResponse requestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); return this; } /** - * A string that contains a unique identifier you provide to track each subscription-renewal-date extension request. + * A string that contains the UUID that identifies the subscription-renewal-date extension request. * * @return requestIdentifier * @see requestIdentifier @@ -39,10 +42,17 @@ public String getRequestIdentifier() { return requestIdentifier; } + @JsonSetter(SERIALIZED_NAME_REQUEST_IDENTIFIER) public void setRequestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); } + private String validateRequestIdentifier(String requestIdentifier) { + if (requestIdentifier != null && requestIdentifier.length() > MAXIMUM_REQUEST_IDENTIFIER_LENGTH) { + throw new IllegalArgumentException("requestIdentifier length longer than maximum allowed"); + } + return requestIdentifier; + } public MassExtendRenewalDateResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; @@ -50,10 +60,10 @@ public MassExtendRenewalDateResponse unknownFields(Map unknownFi } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +98,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateStatusResponse.java b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateStatusResponse.java index 67c105c3..8e22f357 100644 --- a/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateStatusResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/MassExtendRenewalDateStatusResponse.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import java.util.Map; import java.util.Objects; @@ -12,37 +13,39 @@ * A response that indicates the current status of a request to extend the subscription renewal date to all eligible subscribers. * * @see MassExtendRenewalDateStatusResponse - */ + **/ public class MassExtendRenewalDateStatusResponse { private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; private static final String SERIALIZED_NAME_COMPLETE = "complete"; private static final String SERIALIZED_NAME_COMPLETE_DATE = "completeDate"; - private static final String SERIALIZED_NAME_SUCCEEDED_COUNT = "succeededCount"; private static final String SERIALIZED_NAME_FAILED_COUNT = "failedCount"; + private static final String SERIALIZED_NAME_SUCCEEDED_COUNT = "succeededCount"; + @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) private String requestIdentifier; @JsonProperty(SERIALIZED_NAME_COMPLETE) private Boolean complete; @JsonProperty(SERIALIZED_NAME_COMPLETE_DATE) private Long completeDate; - @JsonProperty(SERIALIZED_NAME_SUCCEEDED_COUNT) - private Long succeededCount; @JsonProperty(SERIALIZED_NAME_FAILED_COUNT) private Long failedCount; + @JsonProperty(SERIALIZED_NAME_SUCCEEDED_COUNT) + private Long succeededCount; @JsonAnySetter private Map unknownFields; + private static final int MAXIMUM_REQUEST_IDENTIFIER_LENGTH = 128; public MassExtendRenewalDateStatusResponse() { } public MassExtendRenewalDateStatusResponse requestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); return this; } /** - * A string that contains a unique identifier you provide to track each subscription-renewal-date extension request. + * The UUID that represents your request for a subscription-renewal-date extension. * * @return requestIdentifier * @see requestIdentifier @@ -51,8 +54,16 @@ public String getRequestIdentifier() { return requestIdentifier; } + @JsonSetter(SERIALIZED_NAME_REQUEST_IDENTIFIER) public void setRequestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; + this.requestIdentifier = validateRequestIdentifier(requestIdentifier); + } + + private String validateRequestIdentifier(String requestIdentifier) { + if (requestIdentifier != null && requestIdentifier.length() > MAXIMUM_REQUEST_IDENTIFIER_LENGTH) { + throw new IllegalArgumentException("requestIdentifier length longer than maximum allowed"); + } + return requestIdentifier; } public MassExtendRenewalDateStatusResponse complete(Boolean complete) { @@ -61,7 +72,7 @@ public MassExtendRenewalDateStatusResponse complete(Boolean complete) { } /** - * A Boolean value that indicates whether the App Store completed the request to extend a subscription renewal date to active subscribers. + * A Boolean value that’s TRUE to indicate that the App Store completed your request to extend a subscription renewal date for all eligible subscribers. * * @return complete * @see complete @@ -80,7 +91,7 @@ public MassExtendRenewalDateStatusResponse completeDate(Long completeDate) { } /** - * The UNIX time, in milliseconds, that the App Store completes a request to extend a subscription renewal date for eligible subscribers. + * The date that the App Store completes the request. * * @return completeDate * @see completeDate @@ -93,55 +104,54 @@ public void setCompleteDate(Long completeDate) { this.completeDate = completeDate; } - public MassExtendRenewalDateStatusResponse succeededCount(Long succeededCount) { - this.succeededCount = succeededCount; + public MassExtendRenewalDateStatusResponse failedCount(Long failedCount) { + this.failedCount = failedCount; return this; } /** - * The count of subscriptions that successfully receive a subscription-renewal-date extension. + * The final count of subscribers that fail to receive a subscription-renewal-date extension. * - * @return succeededCount - * @see succeededCount + * @return failedCount + * @see failedCount **/ - public Long getSucceededCount() { - return succeededCount; + public Long getFailedCount() { + return failedCount; } - public void setSucceededCount(Long succeededCount) { - this.succeededCount = succeededCount; + public void setFailedCount(Long failedCount) { + this.failedCount = failedCount; } - public MassExtendRenewalDateStatusResponse failedCount(Long failedCount) { - this.failedCount = failedCount; + public MassExtendRenewalDateStatusResponse succeededCount(Long succeededCount) { + this.succeededCount = succeededCount; return this; } /** - * The count of subscriptions that fail to receive a subscription-renewal-date extension. + * The final count of subscribers that successfully receive a subscription-renewal-date extension. * - * @return failedCount - * @see failedCount + * @return succeededCount + * @see succeededCount **/ - public Long getFailedCount() { - return failedCount; + public Long getSucceededCount() { + return succeededCount; } - public void setFailedCount(Long failedCount) { - this.failedCount = failedCount; + public void setSucceededCount(Long succeededCount) { + this.succeededCount = succeededCount; } - public MassExtendRenewalDateStatusResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -162,14 +172,14 @@ public boolean equals(Object o) { return Objects.equals(this.requestIdentifier, massExtendRenewalDateStatusResponse.requestIdentifier) && Objects.equals(this.complete, massExtendRenewalDateStatusResponse.complete) && Objects.equals(this.completeDate, massExtendRenewalDateStatusResponse.completeDate) && - Objects.equals(this.succeededCount, massExtendRenewalDateStatusResponse.succeededCount) && Objects.equals(this.failedCount, massExtendRenewalDateStatusResponse.failedCount) && + Objects.equals(this.succeededCount, massExtendRenewalDateStatusResponse.succeededCount) && Objects.equals(this.unknownFields, massExtendRenewalDateStatusResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(requestIdentifier, complete, completeDate, succeededCount, failedCount, unknownFields); + return Objects.hash(requestIdentifier, complete, completeDate, failedCount, succeededCount, unknownFields); } @Override @@ -178,10 +188,9 @@ public String toString() { "requestIdentifier='" + requestIdentifier + '\'' + ", complete=" + complete + ", completeDate=" + completeDate + - ", succeededCount=" + succeededCount + ", failedCount=" + failedCount + + ", succeededCount=" + succeededCount + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Message.java b/src/main/java/com/apple/itunes/storekit/model/Message.java index f1277373..f5c15ad6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Message.java +++ b/src/main/java/com/apple/itunes/storekit/model/Message.java @@ -12,13 +12,13 @@ * A message identifier you provide in a real-time response to your Get Retention Message endpoint. * * @see message - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class Message { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; - @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER) - private UUID messageIdentifier; + @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIER) + private UUID messageIdentifier; public Message() { } @@ -44,10 +44,14 @@ public void setMessageIdentifier(UUID messageIdentifier) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Message that = (Message) o; - return Objects.equals(messageIdentifier, that.messageIdentifier); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Message message = (Message) o; + return Objects.equals(this.messageIdentifier, message.messageIdentifier); } @Override @@ -61,4 +65,4 @@ public String toString() { "messageIdentifier=" + messageIdentifier + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/MessageState.java b/src/main/java/com/apple/itunes/storekit/model/MessageState.java index 81531691..b97bd814 100644 --- a/src/main/java/com/apple/itunes/storekit/model/MessageState.java +++ b/src/main/java/com/apple/itunes/storekit/model/MessageState.java @@ -8,11 +8,20 @@ * The approval state of the message. * * @see messageState - */ + **/ public enum MessageState { + /** + * The message is awaiting approval. + **/ PENDING("PENDING"), + /** + * The message is approved. + **/ APPROVED("APPROVED"), + /** + * The message is rejected. + **/ REJECTED("REJECTED"); private final String value; @@ -40,4 +49,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryRequest.java b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryRequest.java index 34bd118c..73820778 100644 --- a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryRequest.java @@ -11,39 +11,44 @@ * The request body for notification history. * * @see NotificationHistoryRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class NotificationHistoryRequest { private static final String SERIALIZED_NAME_START_DATE = "startDate"; private static final String SERIALIZED_NAME_END_DATE = "endDate"; private static final String SERIALIZED_NAME_NOTIFICATION_TYPE = "notificationType"; private static final String SERIALIZED_NAME_NOTIFICATION_SUBTYPE = "notificationSubtype"; - private static final String SERIALIZED_NAME_TRANSACTION_ID = "transactionId"; private static final String SERIALIZED_NAME_ONLY_FAILURES = "onlyFailures"; - @JsonProperty(SERIALIZED_NAME_START_DATE) + private static final String SERIALIZED_NAME_TRANSACTION_ID = "transactionId"; + + @JsonProperty(value = SERIALIZED_NAME_START_DATE, required = true) private Long startDate; - @JsonProperty(SERIALIZED_NAME_END_DATE) + @JsonProperty(value = SERIALIZED_NAME_END_DATE, required = true) private Long endDate; @JsonProperty(SERIALIZED_NAME_NOTIFICATION_TYPE) - private NotificationTypeV2 notificationType; + private String notificationType; @JsonProperty(SERIALIZED_NAME_NOTIFICATION_SUBTYPE) - private Subtype notificationSubtype; - @JsonProperty(SERIALIZED_NAME_TRANSACTION_ID) - private String transactionId; + private String notificationSubtype; @JsonProperty(SERIALIZED_NAME_ONLY_FAILURES) private Boolean onlyFailures; + @JsonProperty(SERIALIZED_NAME_TRANSACTION_ID) + private String transactionId; + protected NotificationHistoryRequest() { + } - public NotificationHistoryRequest() { + public NotificationHistoryRequest(Long startDate, Long endDate) { + this.startDate = Objects.requireNonNull(startDate); + this.endDate = Objects.requireNonNull(endDate); } public NotificationHistoryRequest startDate(Long startDate) { - this.startDate = startDate; + this.startDate = Objects.requireNonNull(startDate); return this; } /** - * The start date of the timespan for the requested App Store Server Notification history records. The startDate needs to precede the endDate. Choose a startDate that’s within the past 180 days from the current date. + * The start date of the timespan for the requested App Store Server Notification history records. * * @return startDate * @see startDate @@ -53,16 +58,16 @@ public Long getStartDate() { } public void setStartDate(Long startDate) { - this.startDate = startDate; + this.startDate = Objects.requireNonNull(startDate); } public NotificationHistoryRequest endDate(Long endDate) { - this.endDate = endDate; + this.endDate = Objects.requireNonNull(endDate); return this; } /** - * The end date of the timespan for the requested App Store Server Notification history records. Choose an endDate that’s later than the startDate. If you choose an endDate in the future, the endpoint automatically uses the current date as the endDate. + * The end date of the timespan for the requested App Store Server Notification history records. * * @return endDate * @see endDate @@ -72,66 +77,67 @@ public Long getEndDate() { } public void setEndDate(Long endDate) { - this.endDate = endDate; + this.endDate = Objects.requireNonNull(endDate); } public NotificationHistoryRequest notificationType(NotificationTypeV2 notificationType) { - this.notificationType = notificationType; + this.notificationType = notificationType != null ? notificationType.getValue() : null; return this; } /** - * A notification type. Provide this field to limit the notification history records to those with this one notification type. For a list of notifications types, see notificationType. - * Include either the transactionId or the notificationType in your query, but not both. + * A notification type. * * @return notificationType * @see notificationType **/ public NotificationTypeV2 getNotificationType() { + return NotificationTypeV2.fromValue(notificationType); + } + + /** + * @see #getNotificationType() + **/ + public String getRawNotificationType() { return notificationType; } public void setNotificationType(NotificationTypeV2 notificationType) { - this.notificationType = notificationType; + this.notificationType = notificationType != null ? notificationType.getValue() : null; + } + + public void setRawNotificationType(String rawNotificationType) { + this.notificationType = rawNotificationType; } public NotificationHistoryRequest notificationSubtype(Subtype notificationSubtype) { - this.notificationSubtype = notificationSubtype; + this.notificationSubtype = notificationSubtype != null ? notificationSubtype.getValue() : null; return this; } /** - * A notification subtype. Provide this field to limit the notification history records to those with this one notification subtype. For a list of subtypes, see subtype. If you specify a notificationSubtype, you need to also specify its related notificationType. + * A notification subtype. * * @return notificationSubtype * @see notificationSubtype **/ public Subtype getNotificationSubtype() { - return notificationSubtype; - } - - public void setNotificationSubtype(Subtype notificationSubtype) { - this.notificationSubtype = notificationSubtype; - } - - public NotificationHistoryRequest transactionId(String transactionId) { - this.transactionId = transactionId; - return this; + return Subtype.fromValue(notificationSubtype); } /** - * The transaction identifier, which may be an original transaction identifier, of any transaction belonging to the customer. Provide this field to limit the notification history request to this one customer. - * Include either the transactionId or the notificationType in your query, but not both. - * - * @return transactionId - * @see transactionId + * @see #getNotificationSubtype() **/ - public String getTransactionId() { - return transactionId; + public String getRawNotificationSubtype() { + return notificationSubtype; } - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; + public void setNotificationSubtype(Subtype notificationSubtype) { + this.notificationSubtype = notificationSubtype != null ? notificationSubtype.getValue() : null; + } + + public void setRawNotificationSubtype(String rawNotificationSubtype) { + this.notificationSubtype = rawNotificationSubtype; } public NotificationHistoryRequest onlyFailures(Boolean onlyFailures) { @@ -140,7 +146,7 @@ public NotificationHistoryRequest onlyFailures(Boolean onlyFailures) { } /** - * A Boolean value you set to true to request only the notifications that haven’t reached your server successfully. The response also includes notifications that the App Store server is currently retrying to send to your server. + * A Boolean value you set to true to request only the notifications that haven’t reached your server successfully. * * @return onlyFailures * @see onlyFailures @@ -153,6 +159,25 @@ public void setOnlyFailures(Boolean onlyFailures) { this.onlyFailures = onlyFailures; } + public NotificationHistoryRequest transactionId(String transactionId) { + this.transactionId = transactionId; + return this; + } + + /** + * The transaction identifier, which may be an original transaction identifier, of any transaction belonging to the customer. + * + * @return transactionId + * @see transactionId + **/ + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -166,13 +191,13 @@ public boolean equals(Object o) { Objects.equals(this.endDate, notificationHistoryRequest.endDate) && Objects.equals(this.notificationType, notificationHistoryRequest.notificationType) && Objects.equals(this.notificationSubtype, notificationHistoryRequest.notificationSubtype) && - Objects.equals(this.transactionId, notificationHistoryRequest.transactionId) && - Objects.equals(this.onlyFailures, notificationHistoryRequest.onlyFailures); + Objects.equals(this.onlyFailures, notificationHistoryRequest.onlyFailures) && + Objects.equals(this.transactionId, notificationHistoryRequest.transactionId); } @Override public int hashCode() { - return Objects.hash(startDate, endDate, notificationType, notificationSubtype, transactionId, onlyFailures); + return Objects.hash(startDate, endDate, notificationType, notificationSubtype, onlyFailures, transactionId); } @Override @@ -180,11 +205,10 @@ public String toString() { return "NotificationHistoryRequest{" + "startDate=" + startDate + ", endDate=" + endDate + - ", notificationType=" + notificationType + - ", notificationSubtype=" + notificationSubtype + - ", transactionId='" + transactionId + '\'' + + ", notificationType='" + notificationType + '\'' + + ", notificationSubtype='" + notificationSubtype + '\'' + ", onlyFailures=" + onlyFailures + + ", transactionId='" + transactionId + '\'' + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponse.java b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponse.java index 52275a23..7906f6b3 100644 --- a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponse.java @@ -14,41 +14,50 @@ * A response that contains the App Store Server Notifications history for your app. * * @see NotificationHistoryResponse - */ + **/ public class NotificationHistoryResponse { - private static final String SERIALIZED_NAME_PAGINATION_TOKEN = "paginationToken"; - private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; private static final String SERIALIZED_NAME_NOTIFICATION_HISTORY = "notificationHistory"; - @JsonProperty(SERIALIZED_NAME_PAGINATION_TOKEN) - private String paginationToken; + private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; + private static final String SERIALIZED_NAME_PAGINATION_TOKEN = "paginationToken"; + + @JsonProperty(SERIALIZED_NAME_NOTIFICATION_HISTORY) + private List notificationHistory; @JsonProperty(SERIALIZED_NAME_HAS_MORE) private Boolean hasMore; - @JsonProperty(SERIALIZED_NAME_NOTIFICATION_HISTORY) - private List notificationHistory = null; + @JsonProperty(SERIALIZED_NAME_PAGINATION_TOKEN) + private String paginationToken; @JsonAnySetter private Map unknownFields; - public NotificationHistoryResponse() { } - public NotificationHistoryResponse paginationToken(String paginationToken) { - this.paginationToken = paginationToken; + public NotificationHistoryResponse notificationHistory(List notificationHistory) { + this.notificationHistory = notificationHistory; + return this; + } + + public NotificationHistoryResponse addNotificationHistory(NotificationHistoryResponseItem notificationHistory) { + Objects.requireNonNull(notificationHistory); + if (this.notificationHistory == null) { + this.notificationHistory = new ArrayList<>(); + } + this.notificationHistory.add(notificationHistory); return this; } /** - * A pagination token that you return to the endpoint on a subsequent call to receive the next set of results. + * An array of App Store Server Notifications history records. * - * @return paginationToken - * @see paginationToken + * @return notificationHistory + * @see notificationHistoryResponseItem **/ - public String getPaginationToken() { - return paginationToken; + public List getNotificationHistory() { + return notificationHistory; } - public void setPaginationToken(String paginationToken) { - this.paginationToken = paginationToken; + public void setNotificationHistory(List notificationHistory) { + this.notificationHistory = notificationHistory; } public NotificationHistoryResponse hasMore(Boolean hasMore) { @@ -57,7 +66,7 @@ public NotificationHistoryResponse hasMore(Boolean hasMore) { } /** - * A Boolean value indicating whether the App Store has more transaction data. + * A Boolean value that indicates whether the App Store has more notification history records to send. * * @return hasMore * @see hasMore @@ -70,44 +79,35 @@ public void setHasMore(Boolean hasMore) { this.hasMore = hasMore; } - public NotificationHistoryResponse notificationHistory(List notificationHistory) { - this.notificationHistory = notificationHistory; - return this; - } - - public NotificationHistoryResponse addNotificationHistoryItem(NotificationHistoryResponseItem notificationHistoryItem) { - if (this.notificationHistory == null) { - this.notificationHistory = new ArrayList<>(); - } - this.notificationHistory.add(notificationHistoryItem); + public NotificationHistoryResponse paginationToken(String paginationToken) { + this.paginationToken = paginationToken; return this; } /** - * An array of App Store server notification history records. + * A pagination token that you provide to Get Notification History on a subsequent request to get the next page of responses. * - * @return notificationHistory - * @see notificationHistoryResponseItem + * @return paginationToken + * @see paginationToken **/ - public List getNotificationHistory() { - return notificationHistory; + public String getPaginationToken() { + return paginationToken; } - public void setNotificationHistory(List notificationHistory) { - this.notificationHistory = notificationHistory; + public void setPaginationToken(String paginationToken) { + this.paginationToken = paginationToken; } - public NotificationHistoryResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -125,25 +125,24 @@ public boolean equals(Object o) { return false; } NotificationHistoryResponse notificationHistoryResponse = (NotificationHistoryResponse) o; - return Objects.equals(this.paginationToken, notificationHistoryResponse.paginationToken) && + return Objects.equals(this.notificationHistory, notificationHistoryResponse.notificationHistory) && Objects.equals(this.hasMore, notificationHistoryResponse.hasMore) && - Objects.equals(this.notificationHistory, notificationHistoryResponse.notificationHistory) && + Objects.equals(this.paginationToken, notificationHistoryResponse.paginationToken) && Objects.equals(this.unknownFields, notificationHistoryResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(paginationToken, hasMore, notificationHistory, unknownFields); + return Objects.hash(notificationHistory, hasMore, paginationToken, unknownFields); } @Override public String toString() { return "NotificationHistoryResponse{" + - "paginationToken='" + paginationToken + '\'' + + "notificationHistory=" + notificationHistory + ", hasMore=" + hasMore + - ", notificationHistory=" + notificationHistory + + ", paginationToken='" + paginationToken + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponseItem.java b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponseItem.java index 53f106ae..3cffddfa 100644 --- a/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponseItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/NotificationHistoryResponseItem.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; @@ -13,47 +14,37 @@ * The App Store server notification history record, including the signed notification payload and the result of the server’s first send attempt. * * @see notificationHistoryResponseItem - */ + **/ public class NotificationHistoryResponseItem { - private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; private static final String SERIALIZED_NAME_SEND_ATTEMPTS = "sendAttempts"; - @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) - private String signedPayload; + private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; + @JsonProperty(SERIALIZED_NAME_SEND_ATTEMPTS) private List sendAttempts; + @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) + private String signedPayload; @JsonAnySetter private Map unknownFields; - public NotificationHistoryResponseItem() { } - public NotificationHistoryResponseItem signedPayload(String signedPayload) { - this.signedPayload = signedPayload; + public NotificationHistoryResponseItem sendAttempts(List sendAttempts) { + this.sendAttempts = sendAttempts; return this; } - /** - * A cryptographically signed payload, in JSON Web Signature (JWS) format, containing the response body for a version 2 notification. - * - * @return signedPayload - * @see signedPayload - **/ - public String getSignedPayload() { - return signedPayload; - } - - public void setSignedPayload(String signedPayload) { - this.signedPayload = signedPayload; - } - - public NotificationHistoryResponseItem sendAttempts(List sendAttempts) { - this.sendAttempts = sendAttempts; + public NotificationHistoryResponseItem addSendAttempt(SendAttemptItem sendAttempt) { + Objects.requireNonNull(sendAttempt); + if (this.sendAttempts == null) { + this.sendAttempts = new ArrayList<>(); + } + this.sendAttempts.add(sendAttempt); return this; } /** - * An array of information the App Store server records for its attempts to send a notification to your server. The maximum number of entries in the array is six. + * An array of information the App Store server records for its attempts to send a notification to your server. * * @return sendAttempts * @see sendAttemptItem @@ -66,6 +57,24 @@ public void setSendAttempts(List sendAttempts) { this.sendAttempts = sendAttempts; } + public NotificationHistoryResponseItem signedPayload(String signedPayload) { + this.signedPayload = signedPayload; + return this; + } + + /** + * The cryptographically signed payload, in JSON Web Signature (JWS) format, containing the original response body of a version 2 notification. + * + * @return signedPayload + * @see signedPayload + **/ + public String getSignedPayload() { + return signedPayload; + } + + public void setSignedPayload(String signedPayload) { + this.signedPayload = signedPayload; + } public NotificationHistoryResponseItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; @@ -73,10 +82,10 @@ public NotificationHistoryResponseItem unknownFields(Map unknown } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -94,23 +103,22 @@ public boolean equals(Object o) { return false; } NotificationHistoryResponseItem notificationHistoryResponseItem = (NotificationHistoryResponseItem) o; - return Objects.equals(this.signedPayload, notificationHistoryResponseItem.signedPayload) && - Objects.equals(this.sendAttempts, notificationHistoryResponseItem.sendAttempts) && + return Objects.equals(this.sendAttempts, notificationHistoryResponseItem.sendAttempts) && + Objects.equals(this.signedPayload, notificationHistoryResponseItem.signedPayload) && Objects.equals(this.unknownFields, notificationHistoryResponseItem.unknownFields); } @Override public int hashCode() { - return Objects.hash(signedPayload, sendAttempts, unknownFields); + return Objects.hash(sendAttempts, signedPayload, unknownFields); } @Override public String toString() { return "NotificationHistoryResponseItem{" + - "signedPayload='" + signedPayload + '\'' + - ", sendAttempts=" + sendAttempts + + "sendAttempts=" + sendAttempts + + ", signedPayload='" + signedPayload + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/NotificationTypeV2.java b/src/main/java/com/apple/itunes/storekit/model/NotificationTypeV2.java index 81e1204f..697b59be 100644 --- a/src/main/java/com/apple/itunes/storekit/model/NotificationTypeV2.java +++ b/src/main/java/com/apple/itunes/storekit/model/NotificationTypeV2.java @@ -5,35 +5,104 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * The type that describes the in-app purchase or external purchase event for which the App Store sends the version 2 notification. + * The type that describes the In-App Purchase or external purchase event for which the App Store sends the version 2 notification. * * @see notificationType - */ + **/ public enum NotificationTypeV2 { + /** + * A notification type that, along with its subtype, indicates that the customer subscribed to an auto-renewable subscription. + **/ SUBSCRIBED("SUBSCRIBED"), + /** + * A notification type that, along with its subtype, indicates that the customer made a change to their subscription plan. + **/ DID_CHANGE_RENEWAL_PREF("DID_CHANGE_RENEWAL_PREF"), + /** + * A notification type that, along with its subtype, indicates that the customer made a change to the subscription renewal status. + **/ DID_CHANGE_RENEWAL_STATUS("DID_CHANGE_RENEWAL_STATUS"), + /** + * A notification type that, along with its subtype, indicates that a customer with an active subscription redeemed a subscription offer. + **/ OFFER_REDEEMED("OFFER_REDEEMED"), + /** + * A notification type that, along with its subtype, indicates that the subscription successfully renewed. + **/ DID_RENEW("DID_RENEW"), + /** + * A notification type that, along with its subtype, indicates that a subscription expired. + **/ EXPIRED("EXPIRED"), + /** + * A notification type that, along with its subtype, indicates that the subscription failed to renew due to a billing issue. + **/ DID_FAIL_TO_RENEW("DID_FAIL_TO_RENEW"), + /** + * A notification type that indicates that the billing grace period has ended without renewing the subscription, so you can turn off access to the service or content. + **/ GRACE_PERIOD_EXPIRED("GRACE_PERIOD_EXPIRED"), + /** + * A notification type that, along with its subtype, indicates that the system has informed the customer of an auto-renewable subscription price increase. + **/ PRICE_INCREASE("PRICE_INCREASE"), + /** + * A notification type that indicates that the App Store successfully refunded a transaction for a consumable In-App Purchase, a non-consumable In-App Purchase, an auto-renewable subscription, or a non-renewing subscription. + **/ REFUND("REFUND"), + /** + * A notification type that indicates the App Store declined a refund request. + **/ REFUND_DECLINED("REFUND_DECLINED"), + /** + * A notification type that indicates that the customer initiated a refund request for a consumable In-App Purchase or auto-renewable subscription, and the App Store is requesting that you provide consumption data. + **/ CONSUMPTION_REQUEST("CONSUMPTION_REQUEST"), + /** + * A notification type that indicates the App Store extended the subscription renewal date for a specific subscription. + **/ RENEWAL_EXTENDED("RENEWAL_EXTENDED"), + /** + * A notification type that indicates that an In-App Purchase the customer was entitled to through Family Sharing is no longer available through sharing. + **/ REVOKE("REVOKE"), + /** + * A notification type that the App Store server sends when you request it by calling the Request a Test Notification endpoint. + **/ TEST("TEST"), + /** + * A notification type that, along with its subtype, indicates that the App Store is attempting to extend the subscription renewal date that you request by calling Extend Subscription Renewal Dates for All Active Subscribers. + **/ RENEWAL_EXTENSION("RENEWAL_EXTENSION"), + /** + * A notification type that indicates the App Store reversed a previously granted refund due to a dispute that the customer raised. + **/ REFUND_REVERSED("REFUND_REVERSED"), + /** + * A notification type that applies only to apps that get tokens from the External Purchase or TransactionReporting APIs. + **/ EXTERNAL_PURCHASE_TOKEN("EXTERNAL_PURCHASE_TOKEN"), + /** + * A notification type that indicates the customer purchased a consumable, non-consumable, or non-renewing subscription. + **/ ONE_TIME_CHARGE("ONE_TIME_CHARGE"), - RESCIND_CONSENT("RESCIND_CONSENT"), + /** + * A notification type that indicates that you called the Change Subscription Price endpoint. + **/ + PRICE_CHANGE("PRICE_CHANGE"), + /** + * A notification type that indicates you used the Change Subscription Metadata endpoint to change the metadata for a subscription. + **/ METADATA_UPDATE("METADATA_UPDATE"), + /** + * A notification type that indicates you used the Migrate Subscription to Advanced Commerce API endpoint. + **/ MIGRATION("MIGRATION"), - PRICE_CHANGE("PRICE_CHANGE"); + /** + * A notification type that indicates the parent or guardian has withdrawn consent for a child’s app usage. + **/ + RESCIND_CONSENT("RESCIND_CONSENT"); private final String value; @@ -60,4 +129,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/OfferDiscountType.java b/src/main/java/com/apple/itunes/storekit/model/OfferDiscountType.java index 146f103b..f9b35679 100644 --- a/src/main/java/com/apple/itunes/storekit/model/OfferDiscountType.java +++ b/src/main/java/com/apple/itunes/storekit/model/OfferDiscountType.java @@ -8,12 +8,24 @@ * The payment mode for a discount offer on an In-App Purchase. * * @see offerDiscountType - */ + **/ public enum OfferDiscountType { + /** + * A payment mode of a discount for auto-renewable subscriptions that indicates a free trial. + **/ FREE_TRIAL("FREE_TRIAL"), + /** + * A payment mode of a discount for auto-renewable subscriptions that customers pay over a single or multiple billing periods. + **/ PAY_AS_YOU_GO("PAY_AS_YOU_GO"), + /** + * A payment mode of a discount for auto-renewable subscriptions that customers pay up front. + **/ PAY_UP_FRONT("PAY_UP_FRONT"), + /** + * A payment mode for a discount for In-App Purchase types including consumable, non-consumable, and non-renewing subscription. + **/ ONE_TIME("ONE_TIME"); private final String value; @@ -40,4 +52,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/OfferType.java b/src/main/java/com/apple/itunes/storekit/model/OfferType.java index b33b95ad..67ad3286 100644 --- a/src/main/java/com/apple/itunes/storekit/model/OfferType.java +++ b/src/main/java/com/apple/itunes/storekit/model/OfferType.java @@ -8,12 +8,24 @@ * The type of offer. * * @see offerType - */ + **/ public enum OfferType { + /** + * An introductory offer. + **/ INTRODUCTORY_OFFER(1), + /** + * A promotional offer. + **/ PROMOTIONAL_OFFER(2), + /** + * An offer with an offer code. + **/ OFFER_CODE(3), + /** + * A win-back offer. + **/ WIN_BACK_OFFER(4); private final Integer value; @@ -41,4 +53,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/OrderLookupResponse.java b/src/main/java/com/apple/itunes/storekit/model/OrderLookupResponse.java index 2df7fe7e..a37bfdc2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/OrderLookupResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/OrderLookupResponse.java @@ -14,18 +14,18 @@ * A response that includes the order lookup status and an array of signed transactions for the in-app purchases in the order. * * @see OrderLookupResponse - */ + **/ public class OrderLookupResponse { private static final String SERIALIZED_NAME_STATUS = "status"; private static final String SERIALIZED_NAME_SIGNED_TRANSACTIONS = "signedTransactions"; + @JsonProperty(SERIALIZED_NAME_STATUS) private Integer status; @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTIONS) - private List signedTransactions = null; + private List signedTransactions; @JsonAnySetter private Map unknownFields; - public OrderLookupResponse() { } @@ -41,12 +41,12 @@ public OrderLookupResponse status(OrderLookupStatus status) { * @see OrderLookupStatus **/ public OrderLookupStatus getStatus() { - return status != null ? OrderLookupStatus.fromValue(status) : null; + return OrderLookupStatus.fromValue(status); } /** * @see #getStatus() - */ + **/ public Integer getRawStatus() { return status; } @@ -64,16 +64,17 @@ public OrderLookupResponse signedTransactions(List signedTransactions) { return this; } - public OrderLookupResponse addSignedTransactionsItem(String signedTransactionsItem) { + public OrderLookupResponse addSignedTransaction(String signedTransaction) { + Objects.requireNonNull(signedTransaction); if (this.signedTransactions == null) { this.signedTransactions = new ArrayList<>(); } - this.signedTransactions.add(signedTransactionsItem); + this.signedTransactions.add(signedTransaction); return this; } /** - * An array of in-app purchase transactions that are part of order, signed by Apple, in JSON Web Signature format. + * An array of in-app purchase transactions that are part of the order, signed by Apple, in JSON Web Signature format. * * @return signedTransactions * @see JWSTransaction @@ -86,17 +87,16 @@ public void setSignedTransactions(List signedTransactions) { this.signedTransactions = signedTransactions; } - public OrderLookupResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -133,4 +133,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/OrderLookupStatus.java b/src/main/java/com/apple/itunes/storekit/model/OrderLookupStatus.java index e248f0d8..edf237a0 100644 --- a/src/main/java/com/apple/itunes/storekit/model/OrderLookupStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/OrderLookupStatus.java @@ -8,10 +8,16 @@ * A value that indicates whether the order ID in the request is valid for your app. * * @see OrderLookupStatus - */ + **/ public enum OrderLookupStatus { + /** + * The orderId that you provided in the Look Up Order ID request is valid and contains at least one in-app purchase for your app. + **/ VALID(0), + /** + * The orderId is invalid or doesn’t contain any in-app purchases for your app. + **/ INVALID(1); private final Integer value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestConfig.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestConfig.java index 4560e20a..b41ba852 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestConfig.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestConfig.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -12,32 +13,47 @@ * An object that enumerates the test configuration parameters. * * @see PerformanceTestConfig - */ + **/ public class PerformanceTestConfig { private static final String SERIALIZED_NAME_MAX_CONCURRENT_REQUESTS = "maxConcurrentRequests"; - private static final String SERIALIZED_NAME_TOTAL_REQUESTS = "totalRequests"; - private static final String SERIALIZED_NAME_TOTAL_DURATION = "totalDuration"; private static final String SERIALIZED_NAME_RESPONSE_TIME_THRESHOLD = "responseTimeThreshold"; private static final String SERIALIZED_NAME_SUCCESS_RATE_THRESHOLD = "successRateThreshold"; - @JsonProperty(SERIALIZED_NAME_MAX_CONCURRENT_REQUESTS) + private static final String SERIALIZED_NAME_TOTAL_DURATION = "totalDuration"; + private static final String SERIALIZED_NAME_TOTAL_REQUESTS = "totalRequests"; + + @JsonProperty(value = SERIALIZED_NAME_MAX_CONCURRENT_REQUESTS, required = true) private Long maxConcurrentRequests; - @JsonProperty(SERIALIZED_NAME_TOTAL_REQUESTS) - private Long totalRequests; - @JsonProperty(SERIALIZED_NAME_TOTAL_DURATION) - private Long totalDuration; - @JsonProperty(SERIALIZED_NAME_RESPONSE_TIME_THRESHOLD) + @JsonProperty(value = SERIALIZED_NAME_RESPONSE_TIME_THRESHOLD, required = true) private Long responseTimeThreshold; - @JsonProperty(SERIALIZED_NAME_SUCCESS_RATE_THRESHOLD) + @JsonProperty(value = SERIALIZED_NAME_SUCCESS_RATE_THRESHOLD, required = true) private Integer successRateThreshold; + @JsonProperty(value = SERIALIZED_NAME_TOTAL_DURATION, required = true) + private Long totalDuration; + @JsonProperty(value = SERIALIZED_NAME_TOTAL_REQUESTS, required = true) + private Long totalRequests; @JsonAnySetter private Map unknownFields; + protected PerformanceTestConfig() { + } - public PerformanceTestConfig() { + @JsonCreator + public PerformanceTestConfig( + @JsonProperty(value = SERIALIZED_NAME_MAX_CONCURRENT_REQUESTS, required = true) Long maxConcurrentRequests, + @JsonProperty(value = SERIALIZED_NAME_RESPONSE_TIME_THRESHOLD, required = true) Long responseTimeThreshold, + @JsonProperty(value = SERIALIZED_NAME_SUCCESS_RATE_THRESHOLD, required = true) Integer successRateThreshold, + @JsonProperty(value = SERIALIZED_NAME_TOTAL_DURATION, required = true) Long totalDuration, + @JsonProperty(value = SERIALIZED_NAME_TOTAL_REQUESTS, required = true) Long totalRequests + ) { + this.maxConcurrentRequests = Objects.requireNonNull(maxConcurrentRequests); + this.responseTimeThreshold = Objects.requireNonNull(responseTimeThreshold); + this.successRateThreshold = Objects.requireNonNull(successRateThreshold); + this.totalDuration = Objects.requireNonNull(totalDuration); + this.totalRequests = Objects.requireNonNull(totalRequests); } public PerformanceTestConfig maxConcurrentRequests(Long maxConcurrentRequests) { - this.maxConcurrentRequests = maxConcurrentRequests; + this.maxConcurrentRequests = Objects.requireNonNull(maxConcurrentRequests); return this; } @@ -45,103 +61,102 @@ public PerformanceTestConfig maxConcurrentRequests(Long maxConcurrentRequests) { * The maximum number of concurrent requests the API allows. * * @return maxConcurrentRequests - * @see maxConcurrentRequests + * @see PerformanceTestConfig **/ public Long getMaxConcurrentRequests() { return maxConcurrentRequests; } public void setMaxConcurrentRequests(Long maxConcurrentRequests) { - this.maxConcurrentRequests = maxConcurrentRequests; + this.maxConcurrentRequests = Objects.requireNonNull(maxConcurrentRequests); } - public PerformanceTestConfig totalRequests(Long totalRequests) { - this.totalRequests = totalRequests; + public PerformanceTestConfig responseTimeThreshold(Long responseTimeThreshold) { + this.responseTimeThreshold = Objects.requireNonNull(responseTimeThreshold); return this; } /** - * The total number of requests to make during the test. + * The maximum time your server has to respond when the system calls your Get Retention Message endpoint in the sandbox environment. * - * @return totalRequests - * @see totalRequests + * @return responseTimeThreshold + * @see PerformanceTestConfig **/ - public Long getTotalRequests() { - return totalRequests; + public Long getResponseTimeThreshold() { + return responseTimeThreshold; } - public void setTotalRequests(Long totalRequests) { - this.totalRequests = totalRequests; + public void setResponseTimeThreshold(Long responseTimeThreshold) { + this.responseTimeThreshold = Objects.requireNonNull(responseTimeThreshold); } - public PerformanceTestConfig totalDuration(Long totalDuration) { - this.totalDuration = totalDuration; + public PerformanceTestConfig successRateThreshold(Integer successRateThreshold) { + this.successRateThreshold = Objects.requireNonNull(successRateThreshold); return this; } /** - * The total duration of the test in milliseconds. + * The success rate threshold percentage. * - * @return totalDuration - * @see totalDuration + * @return successRateThreshold + * @see PerformanceTestConfig **/ - public Long getTotalDuration() { - return totalDuration; + public Integer getSuccessRateThreshold() { + return successRateThreshold; } - public void setTotalDuration(Long totalDuration) { - this.totalDuration = totalDuration; + public void setSuccessRateThreshold(Integer successRateThreshold) { + this.successRateThreshold = Objects.requireNonNull(successRateThreshold); } - public PerformanceTestConfig responseTimeThreshold(Long responseTimeThreshold) { - this.responseTimeThreshold = responseTimeThreshold; + public PerformanceTestConfig totalDuration(Long totalDuration) { + this.totalDuration = Objects.requireNonNull(totalDuration); return this; } /** - * The maximum time your server has to respond when the system calls your Get Retention Message endpoint in the sandbox environment. + * The total duration of the test in milliseconds. * - * @return responseTimeThreshold - * @see responseTimeThreshold + * @return totalDuration + * @see PerformanceTestConfig **/ - public Long getResponseTimeThreshold() { - return responseTimeThreshold; + public Long getTotalDuration() { + return totalDuration; } - public void setResponseTimeThreshold(Long responseTimeThreshold) { - this.responseTimeThreshold = responseTimeThreshold; + public void setTotalDuration(Long totalDuration) { + this.totalDuration = Objects.requireNonNull(totalDuration); } - public PerformanceTestConfig successRateThreshold(Integer successRateThreshold) { - this.successRateThreshold = successRateThreshold; + public PerformanceTestConfig totalRequests(Long totalRequests) { + this.totalRequests = Objects.requireNonNull(totalRequests); return this; } /** - * The success rate threshold percentage. + * The total number of requests to make during the test. * - * @return successRateThreshold - * @see successRateThreshold + * @return totalRequests + * @see PerformanceTestConfig **/ - public Integer getSuccessRateThreshold() { - return successRateThreshold; + public Long getTotalRequests() { + return totalRequests; } - public void setSuccessRateThreshold(Integer successRateThreshold) { - this.successRateThreshold = successRateThreshold; + public void setTotalRequests(Long totalRequests) { + this.totalRequests = Objects.requireNonNull(totalRequests); } - public PerformanceTestConfig unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -160,26 +175,26 @@ public boolean equals(Object o) { } PerformanceTestConfig performanceTestConfig = (PerformanceTestConfig) o; return Objects.equals(this.maxConcurrentRequests, performanceTestConfig.maxConcurrentRequests) && - Objects.equals(this.totalRequests, performanceTestConfig.totalRequests) && - Objects.equals(this.totalDuration, performanceTestConfig.totalDuration) && Objects.equals(this.responseTimeThreshold, performanceTestConfig.responseTimeThreshold) && Objects.equals(this.successRateThreshold, performanceTestConfig.successRateThreshold) && + Objects.equals(this.totalDuration, performanceTestConfig.totalDuration) && + Objects.equals(this.totalRequests, performanceTestConfig.totalRequests) && Objects.equals(this.unknownFields, performanceTestConfig.unknownFields); } @Override public int hashCode() { - return Objects.hash(maxConcurrentRequests, totalRequests, totalDuration, responseTimeThreshold, successRateThreshold, unknownFields); + return Objects.hash(maxConcurrentRequests, responseTimeThreshold, successRateThreshold, totalDuration, totalRequests, unknownFields); } @Override public String toString() { return "PerformanceTestConfig{" + "maxConcurrentRequests=" + maxConcurrentRequests + - ", totalRequests=" + totalRequests + - ", totalDuration=" + totalDuration + ", responseTimeThreshold=" + responseTimeThreshold + ", successRateThreshold=" + successRateThreshold + + ", totalDuration=" + totalDuration + + ", totalRequests=" + totalRequests + ", unknownFields=" + unknownFields + '}'; } diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestRequest.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestRequest.java index dcd733c2..9484fe68 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestRequest.java @@ -11,10 +11,11 @@ * The request object you provide for a performance test that contains an original transaction identifier. * * @see PerformanceTestRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class PerformanceTestRequest { private static final String SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID = "originalTransactionId"; + @JsonProperty(value = SERIALIZED_NAME_ORIGINAL_TRANSACTION_ID, required = true) private String originalTransactionId; diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponse.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponse.java index 81f143de..1f89913a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponse.java @@ -3,32 +3,43 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; import java.util.Objects; +import java.util.UUID; /** * The performance test response object. * * @see PerformanceTestResponse - */ + **/ public class PerformanceTestResponse { private static final String SERIALIZED_NAME_CONFIG = "config"; private static final String SERIALIZED_NAME_REQUEST_ID = "requestId"; - @JsonProperty(SERIALIZED_NAME_CONFIG) + + @JsonProperty(value = SERIALIZED_NAME_CONFIG, required = true) private PerformanceTestConfig config; - @JsonProperty(SERIALIZED_NAME_REQUEST_ID) - private String requestId; + @JsonProperty(value = SERIALIZED_NAME_REQUEST_ID, required = true) + private UUID requestId; @JsonAnySetter private Map unknownFields; + protected PerformanceTestResponse() { + } - public PerformanceTestResponse() { + @JsonCreator + public PerformanceTestResponse( + @JsonProperty(value = SERIALIZED_NAME_CONFIG, required = true) PerformanceTestConfig config, + @JsonProperty(value = SERIALIZED_NAME_REQUEST_ID, required = true) UUID requestId + ) { + this.config = Objects.requireNonNull(config); + this.requestId = Objects.requireNonNull(requestId); } public PerformanceTestResponse config(PerformanceTestConfig config) { - this.config = config; + this.config = Objects.requireNonNull(config); return this; } @@ -43,11 +54,11 @@ public PerformanceTestConfig getConfig() { } public void setConfig(PerformanceTestConfig config) { - this.config = config; + this.config = Objects.requireNonNull(config); } - public PerformanceTestResponse requestId(String requestId) { - this.requestId = requestId; + public PerformanceTestResponse requestId(UUID requestId) { + this.requestId = Objects.requireNonNull(requestId); return this; } @@ -57,25 +68,24 @@ public PerformanceTestResponse requestId(String requestId) { * @return requestId * @see requestId **/ - public String getRequestId() { + public UUID getRequestId() { return requestId; } - public void setRequestId(String requestId) { - this.requestId = requestId; + public void setRequestId(UUID requestId) { + this.requestId = Objects.requireNonNull(requestId); } - public PerformanceTestResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -107,7 +117,7 @@ public int hashCode() { public String toString() { return "PerformanceTestResponse{" + "config=" + config + - ", requestId='" + requestId + '\'' + + ", requestId=" + requestId + ", unknownFields=" + unknownFields + '}'; } diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponseTimes.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponseTimes.java index 8128ddd1..1060a410 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponseTimes.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResponseTimes.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -12,32 +13,47 @@ * An object that describes test response times. * * @see PerformanceTestResponseTimes - */ + **/ public class PerformanceTestResponseTimes { private static final String SERIALIZED_NAME_AVERAGE = "average"; private static final String SERIALIZED_NAME_P50 = "p50"; private static final String SERIALIZED_NAME_P90 = "p90"; private static final String SERIALIZED_NAME_P95 = "p95"; private static final String SERIALIZED_NAME_P99 = "p99"; - @JsonProperty(SERIALIZED_NAME_AVERAGE) + + @JsonProperty(value = SERIALIZED_NAME_AVERAGE, required = true) private Long average; - @JsonProperty(SERIALIZED_NAME_P50) + @JsonProperty(value = SERIALIZED_NAME_P50, required = true) private Long p50; - @JsonProperty(SERIALIZED_NAME_P90) + @JsonProperty(value = SERIALIZED_NAME_P90, required = true) private Long p90; - @JsonProperty(SERIALIZED_NAME_P95) + @JsonProperty(value = SERIALIZED_NAME_P95, required = true) private Long p95; - @JsonProperty(SERIALIZED_NAME_P99) + @JsonProperty(value = SERIALIZED_NAME_P99, required = true) private Long p99; @JsonAnySetter private Map unknownFields; + protected PerformanceTestResponseTimes() { + } - public PerformanceTestResponseTimes() { + @JsonCreator + public PerformanceTestResponseTimes( + @JsonProperty(value = SERIALIZED_NAME_AVERAGE, required = true) Long average, + @JsonProperty(value = SERIALIZED_NAME_P50, required = true) Long p50, + @JsonProperty(value = SERIALIZED_NAME_P90, required = true) Long p90, + @JsonProperty(value = SERIALIZED_NAME_P95, required = true) Long p95, + @JsonProperty(value = SERIALIZED_NAME_P99, required = true) Long p99 + ) { + this.average = Objects.requireNonNull(average); + this.p50 = Objects.requireNonNull(p50); + this.p90 = Objects.requireNonNull(p90); + this.p95 = Objects.requireNonNull(p95); + this.p99 = Objects.requireNonNull(p99); } public PerformanceTestResponseTimes average(Long average) { - this.average = average; + this.average = Objects.requireNonNull(average); return this; } @@ -45,18 +61,18 @@ public PerformanceTestResponseTimes average(Long average) { * Average response time in milliseconds. * * @return average - * @see average + * @see PerformanceTestResponseTimes **/ public Long getAverage() { return average; } public void setAverage(Long average) { - this.average = average; + this.average = Objects.requireNonNull(average); } public PerformanceTestResponseTimes p50(Long p50) { - this.p50 = p50; + this.p50 = Objects.requireNonNull(p50); return this; } @@ -64,18 +80,18 @@ public PerformanceTestResponseTimes p50(Long p50) { * The 50th percentile response time in milliseconds. * * @return p50 - * @see p50 + * @see PerformanceTestResponseTimes **/ public Long getP50() { return p50; } public void setP50(Long p50) { - this.p50 = p50; + this.p50 = Objects.requireNonNull(p50); } public PerformanceTestResponseTimes p90(Long p90) { - this.p90 = p90; + this.p90 = Objects.requireNonNull(p90); return this; } @@ -83,18 +99,18 @@ public PerformanceTestResponseTimes p90(Long p90) { * The 90th percentile response time in milliseconds. * * @return p90 - * @see p90 + * @see PerformanceTestResponseTimes **/ public Long getP90() { return p90; } public void setP90(Long p90) { - this.p90 = p90; + this.p90 = Objects.requireNonNull(p90); } public PerformanceTestResponseTimes p95(Long p95) { - this.p95 = p95; + this.p95 = Objects.requireNonNull(p95); return this; } @@ -102,18 +118,18 @@ public PerformanceTestResponseTimes p95(Long p95) { * The 95th percentile response time in milliseconds. * * @return p95 - * @see p95 + * @see PerformanceTestResponseTimes **/ public Long getP95() { return p95; } public void setP95(Long p95) { - this.p95 = p95; + this.p95 = Objects.requireNonNull(p95); } public PerformanceTestResponseTimes p99(Long p99) { - this.p99 = p99; + this.p99 = Objects.requireNonNull(p99); return this; } @@ -121,27 +137,26 @@ public PerformanceTestResponseTimes p99(Long p99) { * The 99th percentile response time in milliseconds. * * @return p99 - * @see p99 + * @see PerformanceTestResponseTimes **/ public Long getP99() { return p99; } public void setP99(Long p99) { - this.p99 = p99; + this.p99 = Objects.requireNonNull(p99); } - public PerformanceTestResponseTimes unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResultResponse.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResultResponse.java index c97b1175..e6cf4723 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResultResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestResultResponse.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.HashMap; @@ -13,38 +14,79 @@ * An object the API returns that describes the performance test results. * * @see PerformanceTestResultResponse - */ + **/ public class PerformanceTestResultResponse { private static final String SERIALIZED_NAME_CONFIG = "config"; - private static final String SERIALIZED_NAME_TARGET = "target"; - private static final String SERIALIZED_NAME_RESULT = "result"; - private static final String SERIALIZED_NAME_SUCCESS_RATE = "successRate"; + private static final String SERIALIZED_NAME_FAILURES = "failures"; private static final String SERIALIZED_NAME_NUM_PENDING = "numPending"; private static final String SERIALIZED_NAME_RESPONSE_TIMES = "responseTimes"; - private static final String SERIALIZED_NAME_FAILURES = "failures"; - @JsonProperty(SERIALIZED_NAME_CONFIG) + private static final String SERIALIZED_NAME_RESULT = "result"; + private static final String SERIALIZED_NAME_SUCCESS_RATE = "successRate"; + private static final String SERIALIZED_NAME_TARGET = "target"; + + @JsonProperty(value = SERIALIZED_NAME_CONFIG, required = true) private PerformanceTestConfig config; - @JsonProperty(SERIALIZED_NAME_TARGET) - private String target; - @JsonProperty(SERIALIZED_NAME_RESULT) - private String result; - @JsonProperty(SERIALIZED_NAME_SUCCESS_RATE) - private Integer successRate; - @JsonProperty(SERIALIZED_NAME_NUM_PENDING) + @JsonProperty(value = SERIALIZED_NAME_FAILURES, required = true) + private Map failures; + @JsonProperty(value = SERIALIZED_NAME_NUM_PENDING, required = true) private Integer numPending; - @JsonProperty(SERIALIZED_NAME_RESPONSE_TIMES) + @JsonProperty(value = SERIALIZED_NAME_RESPONSE_TIMES, required = true) private PerformanceTestResponseTimes responseTimes; - @JsonProperty(SERIALIZED_NAME_FAILURES) - private Map failures; + @JsonProperty(value = SERIALIZED_NAME_RESULT, required = true) + private String result; + @JsonProperty(value = SERIALIZED_NAME_SUCCESS_RATE, required = true) + private Integer successRate; + @JsonProperty(value = SERIALIZED_NAME_TARGET, required = true) + private String target; @JsonAnySetter private Map unknownFields; - - public PerformanceTestResultResponse() { + protected PerformanceTestResultResponse() { + } + + public PerformanceTestResultResponse( + PerformanceTestConfig config, + Map failures, + Integer numPending, + PerformanceTestResponseTimes responseTimes, + PerformanceTestStatus result, + Integer successRate, + String target + ) { + this.config = Objects.requireNonNull(config); + Objects.requireNonNull(failures); + this.failures = new HashMap<>(); + for (Map.Entry entry : failures.entrySet()) { + this.failures.put(entry.getKey().getValue(), entry.getValue()); + } + this.numPending = Objects.requireNonNull(numPending); + this.responseTimes = Objects.requireNonNull(responseTimes); + this.result = Objects.requireNonNull(result).getValue(); + this.successRate = Objects.requireNonNull(successRate); + this.target = Objects.requireNonNull(target); + } + + @JsonCreator + public PerformanceTestResultResponse( + @JsonProperty(value = SERIALIZED_NAME_CONFIG, required = true) PerformanceTestConfig config, + @JsonProperty(value = SERIALIZED_NAME_FAILURES, required = true) Map rawFailures, + @JsonProperty(value = SERIALIZED_NAME_NUM_PENDING, required = true) Integer numPending, + @JsonProperty(value = SERIALIZED_NAME_RESPONSE_TIMES, required = true) PerformanceTestResponseTimes responseTimes, + @JsonProperty(value = SERIALIZED_NAME_RESULT, required = true) String rawResult, + @JsonProperty(value = SERIALIZED_NAME_SUCCESS_RATE, required = true) Integer successRate, + @JsonProperty(value = SERIALIZED_NAME_TARGET, required = true) String target + ) { + this.config = Objects.requireNonNull(config); + this.failures = Objects.requireNonNull(rawFailures); + this.numPending = Objects.requireNonNull(numPending); + this.responseTimes = Objects.requireNonNull(responseTimes); + this.result = Objects.requireNonNull(rawResult); + this.successRate = Objects.requireNonNull(successRate); + this.target = Objects.requireNonNull(target); } public PerformanceTestResultResponse config(PerformanceTestConfig config) { - this.config = config; + this.config = Objects.requireNonNull(config); return this; } @@ -59,79 +101,56 @@ public PerformanceTestConfig getConfig() { } public void setConfig(PerformanceTestConfig config) { - this.config = config; + this.config = Objects.requireNonNull(config); } - public PerformanceTestResultResponse target(String target) { - this.target = target; + public PerformanceTestResultResponse failures(Map failures) { + Objects.requireNonNull(failures); + this.failures = new HashMap<>(); + for (Map.Entry entry : failures.entrySet()) { + this.failures.put(entry.getKey().getValue(), entry.getValue()); + } return this; } /** - * The target URL for the performance test. + * A Failures object that represents a map of server-to-server notification failure reasons and counts that represent the number of failures encountered during the performance test. * - * @return target - * @see target + * @return failures + * @see Failures **/ - public String getTarget() { - return target; - } - - public void setTarget(String target) { - this.target = target; - } - - public PerformanceTestResultResponse result(PerformanceTestStatus result) { - this.result = result != null ? result.getValue() : null; - return this; + public Map getFailures() { + Map result = new HashMap<>(); + for (Map.Entry entry : failures.entrySet()) { + SendAttemptResult key = SendAttemptResult.fromValue(entry.getKey()); + if (key != null) { + result.put(key, entry.getValue()); + } + } + return result; } /** - * A PerformanceTestStatus object that describes the overall result of the test. - * - * @return result - * @see performanceTestStatus + * @see #getFailures() **/ - public PerformanceTestStatus getResult() { - return result != null ? PerformanceTestStatus.fromValue(result) : null; - } - - /** - * @see #getResult() - */ - public String getRawResult() { - return result; - } - - public void setResult(PerformanceTestStatus result) { - this.result = result != null ? result.getValue() : null; - } - - public void setRawResult(String rawResult) { - this.result = rawResult; - } - - public PerformanceTestResultResponse successRate(Integer successRate) { - this.successRate = successRate; - return this; + public Map getRawFailures() { + return failures; } - /** - * An integer that describes he success rate percentage of the performance test. - * - * @return successRate - * @see successRate - **/ - public Integer getSuccessRate() { - return successRate; + public void setFailures(Map failures) { + Objects.requireNonNull(failures); + this.failures = new HashMap<>(); + for (Map.Entry entry : failures.entrySet()) { + this.failures.put(entry.getKey().getValue(), entry.getValue()); + } } - public void setSuccessRate(Integer successRate) { - this.successRate = successRate; + public void setRawFailures(Map rawFailures) { + this.failures = Objects.requireNonNull(rawFailures); } public PerformanceTestResultResponse numPending(Integer numPending) { - this.numPending = numPending; + this.numPending = Objects.requireNonNull(numPending); return this; } @@ -139,18 +158,18 @@ public PerformanceTestResultResponse numPending(Integer numPending) { * An integer that describes the number of pending requests in the performance test. * * @return numPending - * @see numPending + * @see PerformanceTestResultResponse **/ public Integer getNumPending() { return numPending; } public void setNumPending(Integer numPending) { - this.numPending = numPending; + this.numPending = Objects.requireNonNull(numPending); } public PerformanceTestResultResponse responseTimes(PerformanceTestResponseTimes responseTimes) { - this.responseTimes = responseTimes; + this.responseTimes = Objects.requireNonNull(responseTimes); return this; } @@ -165,63 +184,76 @@ public PerformanceTestResponseTimes getResponseTimes() { } public void setResponseTimes(PerformanceTestResponseTimes responseTimes) { - this.responseTimes = responseTimes; + this.responseTimes = Objects.requireNonNull(responseTimes); } - public PerformanceTestResultResponse failures(Map failures) { - if (failures != null) { - this.failures = new HashMap<>(); - for (Map.Entry entry : failures.entrySet()) { - this.failures.put(entry.getKey().getValue(), entry.getValue()); - } - } else { - this.failures = null; - } + public PerformanceTestResultResponse result(PerformanceTestStatus result) { + this.result = Objects.requireNonNull(result).getValue(); return this; } /** - * A Failures object that represents a map of server-to-server notification failure reasons and counts that represent the number of failures encountered during the performance test. + * A PerformanceTestStatus object that describes the overall result of the test. * - * @return failures - * @see Failures + * @return result + * @see PerformanceTestStatus **/ - public Map getFailures() { - if (failures == null) { - return null; - } - Map result = new HashMap<>(); - for (Map.Entry entry : failures.entrySet()) { - SendAttemptResult key = SendAttemptResult.fromValue(entry.getKey()); - if (key != null) { - result.put(key, entry.getValue()); - } - } + public PerformanceTestStatus getResult() { + return PerformanceTestStatus.fromValue(result); + } + + /** + * @see #getResult() + **/ + public String getRawResult() { return result; } + public void setResult(PerformanceTestStatus result) { + this.result = Objects.requireNonNull(result).getValue(); + } + + public void setRawResult(String rawResult) { + this.result = Objects.requireNonNull(rawResult); + } + + public PerformanceTestResultResponse successRate(Integer successRate) { + this.successRate = Objects.requireNonNull(successRate); + return this; + } + /** - * @see #getFailures() - */ - public Map getRawFailures() { - return failures; + * An integer that describes the success rate percentage of the performance test. + * + * @return successRate + * @see PerformanceTestResultResponse + **/ + public Integer getSuccessRate() { + return successRate; } - public void setFailures(Map failures) { - if (failures != null) { - this.failures = new HashMap<>(); - for (Map.Entry entry : failures.entrySet()) { - this.failures.put(entry.getKey().getValue(), entry.getValue()); - } - } else { - this.failures = null; - } + public void setSuccessRate(Integer successRate) { + this.successRate = Objects.requireNonNull(successRate); } - public void setRawFailures(Map rawFailures) { - this.failures = rawFailures; + public PerformanceTestResultResponse target(String target) { + this.target = Objects.requireNonNull(target); + return this; + } + + /** + * The target URL for the performance test. + * + * @return target + * @see PerformanceTestResultResponse + **/ + public String getTarget() { + return target; } + public void setTarget(String target) { + this.target = Objects.requireNonNull(target); + } public PerformanceTestResultResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; @@ -229,10 +261,10 @@ public PerformanceTestResultResponse unknownFields(Map unknownFi } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -251,30 +283,30 @@ public boolean equals(Object o) { } PerformanceTestResultResponse performanceTestResultResponse = (PerformanceTestResultResponse) o; return Objects.equals(this.config, performanceTestResultResponse.config) && - Objects.equals(this.target, performanceTestResultResponse.target) && - Objects.equals(this.result, performanceTestResultResponse.result) && - Objects.equals(this.successRate, performanceTestResultResponse.successRate) && + Objects.equals(this.failures, performanceTestResultResponse.failures) && Objects.equals(this.numPending, performanceTestResultResponse.numPending) && Objects.equals(this.responseTimes, performanceTestResultResponse.responseTimes) && - Objects.equals(this.failures, performanceTestResultResponse.failures) && + Objects.equals(this.result, performanceTestResultResponse.result) && + Objects.equals(this.successRate, performanceTestResultResponse.successRate) && + Objects.equals(this.target, performanceTestResultResponse.target) && Objects.equals(this.unknownFields, performanceTestResultResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(config, target, result, successRate, numPending, responseTimes, failures, unknownFields); + return Objects.hash(config, failures, numPending, responseTimes, result, successRate, target, unknownFields); } @Override public String toString() { return "PerformanceTestResultResponse{" + "config=" + config + - ", target='" + target + '\'' + - ", result='" + result + '\'' + - ", successRate=" + successRate + + ", failures=" + failures + ", numPending=" + numPending + ", responseTimes=" + responseTimes + - ", failures=" + failures + + ", result='" + result + '\'' + + ", successRate=" + successRate + + ", target='" + target + '\'' + ", unknownFields=" + unknownFields + '}'; } diff --git a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestStatus.java b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestStatus.java index 62b9d3ce..64c99a4b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PerformanceTestStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/PerformanceTestStatus.java @@ -7,12 +7,21 @@ /** * The status of the performance test. * - * @see performanceTestStatus - */ + * @see PerformanceTestStatus + **/ public enum PerformanceTestStatus { + /** + * The test is still pending. + **/ PENDING("PENDING"), + /** + * The test passed. + **/ PASS("PASS"), + /** + * The test failed. + **/ FAIL("FAIL"); private final String value; diff --git a/src/main/java/com/apple/itunes/storekit/model/Platform.java b/src/main/java/com/apple/itunes/storekit/model/Platform.java index f6b36a5f..f8f9835f 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Platform.java +++ b/src/main/java/com/apple/itunes/storekit/model/Platform.java @@ -8,11 +8,20 @@ * The platform on which the customer consumed the in-app purchase. * * @see platform - */ + **/ public enum Platform { + /** + * The platform is undeclared. + **/ UNDECLARED(0), + /** + * An Apple platform. + **/ APPLE(1), + /** + * Non-Apple platform. + **/ NON_APPLE(2); private final Integer value; @@ -40,4 +49,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/PlayTime.java b/src/main/java/com/apple/itunes/storekit/model/PlayTime.java index 010b030a..6976f1e9 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PlayTime.java +++ b/src/main/java/com/apple/itunes/storekit/model/PlayTime.java @@ -8,16 +8,40 @@ * A value that indicates the amount of time that the customer used the app. * * @see playTime - */ + **/ public enum PlayTime { + /** + * The engagement time is undeclared. + **/ UNDECLARED(0), + /** + * The engagement time is between 0–5 minutes. + **/ ZERO_TO_FIVE_MINUTES(1), + /** + * The engagement time is between 5–60 minutes. + **/ FIVE_TO_SIXTY_MINUTES(2), + /** + * The engagement time is between 1–6 hours. + **/ ONE_TO_SIX_HOURS(3), + /** + * The engagement time is between 6–24 hours. + **/ SIX_HOURS_TO_TWENTY_FOUR_HOURS(4), + /** + * The engagement time is between 1–4 days. + **/ ONE_DAY_TO_FOUR_DAYS(5), + /** + * The engagement time is between 4–16 days. + **/ FOUR_DAYS_TO_SIXTEEN_DAYS(6), + /** + * The engagement time is over 16 days. + **/ OVER_SIXTEEN_DAYS(7); private final Integer value; @@ -45,4 +69,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/PriceIncreaseStatus.java b/src/main/java/com/apple/itunes/storekit/model/PriceIncreaseStatus.java index 9edee6e9..a81aca4a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PriceIncreaseStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/PriceIncreaseStatus.java @@ -8,10 +8,16 @@ * The status that indicates whether an auto-renewable subscription is subject to a price increase. * * @see priceIncreaseStatus - */ + **/ public enum PriceIncreaseStatus { + /** + * The customer hasn’t yet responded to an auto-renewable subscription price increase that requires customer consent. + **/ CUSTOMER_HAS_NOT_RESPONDED(0), + /** + * The customer consented to an auto-renewable subscription price increase that requires customer consent, or the App Store has notified the customer of an auto-renewable subscription price increase that doesn’t require consent. + **/ CUSTOMER_CONSENTED_OR_WAS_NOTIFIED_WITHOUT_NEEDING_CONSENT(1); private final Integer value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/PromotionalOffer.java b/src/main/java/com/apple/itunes/storekit/model/PromotionalOffer.java index 108ed5bb..fce41e56 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PromotionalOffer.java +++ b/src/main/java/com/apple/itunes/storekit/model/PromotionalOffer.java @@ -12,20 +12,20 @@ * A promotional offer and message you provide in a real-time response to your Get Retention Message endpoint. * * @see promotionalOffer - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class PromotionalOffer { private static final String SERIALIZED_NAME_MESSAGE_IDENTIFIER = "messageIdentifier"; private static final String SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V2 = "promotionalOfferSignatureV2"; private static final String SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V1 = "promotionalOfferSignatureV1"; - @JsonProperty(value = SERIALIZED_NAME_MESSAGE_IDENTIFIER) + + @JsonProperty(SERIALIZED_NAME_MESSAGE_IDENTIFIER) private UUID messageIdentifier; - @JsonProperty(value = SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V2) + @JsonProperty(SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V2) private String promotionalOfferSignatureV2; - @JsonProperty(value = SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V1) + @JsonProperty(SERIALIZED_NAME_PROMOTIONAL_OFFER_SIGNATURE_V1) private PromotionalOfferSignatureV1 promotionalOfferSignatureV1; - public PromotionalOffer() { } @@ -88,12 +88,16 @@ public void setPromotionalOfferSignatureV1(PromotionalOfferSignatureV1 promotion @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PromotionalOffer that = (PromotionalOffer) o; - return Objects.equals(messageIdentifier, that.messageIdentifier) && - Objects.equals(promotionalOfferSignatureV2, that.promotionalOfferSignatureV2) && - Objects.equals(promotionalOfferSignatureV1, that.promotionalOfferSignatureV1); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PromotionalOffer promotionalOffer = (PromotionalOffer) o; + return Objects.equals(this.messageIdentifier, promotionalOffer.messageIdentifier) && + Objects.equals(this.promotionalOfferSignatureV2, promotionalOffer.promotionalOfferSignatureV2) && + Objects.equals(this.promotionalOfferSignatureV1, promotionalOffer.promotionalOfferSignatureV1); } @Override @@ -109,4 +113,4 @@ public String toString() { ", promotionalOfferSignatureV1=" + promotionalOfferSignatureV1 + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/PromotionalOfferSignatureV1.java b/src/main/java/com/apple/itunes/storekit/model/PromotionalOfferSignatureV1.java index b17d7064..b1e41389 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PromotionalOfferSignatureV1.java +++ b/src/main/java/com/apple/itunes/storekit/model/PromotionalOfferSignatureV1.java @@ -10,10 +10,10 @@ import java.util.UUID; /** - * The promotional offer signature you generate using an earlier signature version. + * The promotional-offer signature you generate using an earlier signature version. * * @see promotionalOfferSignatureV1 - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class PromotionalOfferSignatureV1 { private static final String SERIALIZED_NAME_ENCODED_SIGNATURE = "encodedSignature"; @@ -23,6 +23,7 @@ public class PromotionalOfferSignatureV1 { private static final String SERIALIZED_NAME_KEY_ID = "keyId"; private static final String SERIALIZED_NAME_OFFER_IDENTIFIER = "offerIdentifier"; private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; + @JsonProperty(value = SERIALIZED_NAME_ENCODED_SIGNATURE, required = true) private String encodedSignature; @JsonProperty(value = SERIALIZED_NAME_PRODUCT_ID, required = true) @@ -36,20 +37,21 @@ public class PromotionalOfferSignatureV1 { private String keyId; @JsonProperty(value = SERIALIZED_NAME_OFFER_IDENTIFIER, required = true) private String offerIdentifier; - @JsonProperty(value = SERIALIZED_NAME_APP_ACCOUNT_TOKEN) + @JsonProperty(SERIALIZED_NAME_APP_ACCOUNT_TOKEN) @JsonSerialize(using = UUIDLowercaseSerializer.class) private UUID appAccountToken; - - private PromotionalOfferSignatureV1() { + protected PromotionalOfferSignatureV1() { } - public PromotionalOfferSignatureV1(String encodedSignature, - String productId, - UUID nonce, - Long timestamp, - String keyId, - String offerIdentifier) { + public PromotionalOfferSignatureV1( + String encodedSignature, + String productId, + UUID nonce, + Long timestamp, + String keyId, + String offerIdentifier + ) { this.encodedSignature = Objects.requireNonNull(encodedSignature); this.productId = Objects.requireNonNull(productId); this.nonce = Objects.requireNonNull(nonce); @@ -67,6 +69,7 @@ public PromotionalOfferSignatureV1 encodedSignature(String encodedSignature) { * The Base64-encoded cryptographic signature you generate using the offer parameters. * * @return encodedSignature + * @see promotionalOfferSignatureV1 **/ public String getEncodedSignature() { return encodedSignature; @@ -104,6 +107,7 @@ public PromotionalOfferSignatureV1 nonce(UUID nonce) { * A one-time-use UUID antireplay value you generate. * * @return nonce + * @see promotionalOfferSignatureV1 **/ public UUID getNonce() { return nonce; @@ -122,6 +126,7 @@ public PromotionalOfferSignatureV1 timestamp(Long timestamp) { * The UNIX time, in milliseconds, when you generate the signature. * * @return timestamp + * @see promotionalOfferSignatureV1 **/ public Long getTimestamp() { return timestamp; @@ -140,6 +145,7 @@ public PromotionalOfferSignatureV1 keyId(String keyId) { * A string that identifies the private key you use to generate the signature. * * @return keyId + * @see promotionalOfferSignatureV1 **/ public String getKeyId() { return keyId; @@ -158,6 +164,7 @@ public PromotionalOfferSignatureV1 offerIdentifier(String offerIdentifier) { * The subscription offer identifier that you set up in App Store Connect. * * @return offerIdentifier + * @see promotionalOfferSignatureV1 **/ public String getOfferIdentifier() { return offerIdentifier; @@ -176,6 +183,7 @@ public PromotionalOfferSignatureV1 appAccountToken(UUID appAccountToken) { * A UUID that you provide to associate with the transaction if the customer accepts the promotional offer. * * @return appAccountToken + * @see promotionalOfferSignatureV1 **/ public UUID getAppAccountToken() { return appAccountToken; @@ -187,16 +195,20 @@ public void setAppAccountToken(UUID appAccountToken) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - PromotionalOfferSignatureV1 that = (PromotionalOfferSignatureV1) o; - return Objects.equals(encodedSignature, that.encodedSignature) && - Objects.equals(productId, that.productId) && - Objects.equals(nonce, that.nonce) && - Objects.equals(timestamp, that.timestamp) && - Objects.equals(keyId, that.keyId) && - Objects.equals(offerIdentifier, that.offerIdentifier) && - Objects.equals(appAccountToken, that.appAccountToken); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PromotionalOfferSignatureV1 promotionalOfferSignatureV1 = (PromotionalOfferSignatureV1) o; + return Objects.equals(this.encodedSignature, promotionalOfferSignatureV1.encodedSignature) && + Objects.equals(this.productId, promotionalOfferSignatureV1.productId) && + Objects.equals(this.nonce, promotionalOfferSignatureV1.nonce) && + Objects.equals(this.timestamp, promotionalOfferSignatureV1.timestamp) && + Objects.equals(this.keyId, promotionalOfferSignatureV1.keyId) && + Objects.equals(this.offerIdentifier, promotionalOfferSignatureV1.offerIdentifier) && + Objects.equals(this.appAccountToken, promotionalOfferSignatureV1.appAccountToken); } @Override @@ -216,4 +228,4 @@ public String toString() { ", appAccountToken=" + appAccountToken + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/PurchasePlatform.java b/src/main/java/com/apple/itunes/storekit/model/PurchasePlatform.java index 8ea7bacd..5f91eb86 100644 --- a/src/main/java/com/apple/itunes/storekit/model/PurchasePlatform.java +++ b/src/main/java/com/apple/itunes/storekit/model/PurchasePlatform.java @@ -5,14 +5,15 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * Values that represent Apple platforms. + * The platform on which a customer originally purchases an app. * * @see AppStore.Platform - */ + * @see originalPlatform + **/ public enum PurchasePlatform { - IOS("iOS"), MAC_OS("macOS"), + IOS("iOS"), TV_OS("tvOS"), VISION_OS("visionOS"); @@ -41,4 +42,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RealtimeRequestBody.java b/src/main/java/com/apple/itunes/storekit/model/RealtimeRequestBody.java index 0766c306..af33da83 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RealtimeRequestBody.java +++ b/src/main/java/com/apple/itunes/storekit/model/RealtimeRequestBody.java @@ -12,15 +12,15 @@ * The request body the App Store server sends to your Get Retention Message endpoint. * * @see RealtimeRequestBody - */ + **/ public class RealtimeRequestBody { private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; + @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) private String signedPayload; @JsonAnySetter private Map unknownFields; - public RealtimeRequestBody() { } @@ -43,17 +43,16 @@ public void setSignedPayload(String signedPayload) { this.signedPayload = signedPayload; } - public RealtimeRequestBody unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -70,9 +69,9 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - RealtimeRequestBody responseBodyV2 = (RealtimeRequestBody) o; - return Objects.equals(this.signedPayload, responseBodyV2.signedPayload) && - Objects.equals(this.unknownFields, responseBodyV2.unknownFields); + RealtimeRequestBody realtimeRequestBody = (RealtimeRequestBody) o; + return Objects.equals(this.signedPayload, realtimeRequestBody.signedPayload) && + Objects.equals(this.unknownFields, realtimeRequestBody.unknownFields); } @Override @@ -88,4 +87,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RealtimeResponseBody.java b/src/main/java/com/apple/itunes/storekit/model/RealtimeResponseBody.java index f70e3907..16e41569 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RealtimeResponseBody.java +++ b/src/main/java/com/apple/itunes/storekit/model/RealtimeResponseBody.java @@ -11,23 +11,23 @@ * A response you provide to choose, in real time, a retention message the system displays to the customer. * * @see RealtimeResponseBody - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class RealtimeResponseBody { private static final String SERIALIZED_NAME_MESSAGE = "message"; private static final String SERIALIZED_NAME_ALTERNATE_PRODUCT = "alternateProduct"; private static final String SERIALIZED_NAME_PROMOTIONAL_OFFER = "promotionalOffer"; private static final String SERIALIZED_NAME_ADVANCED_COMMERCE_INFO = "advancedCommerceInfo"; - @JsonProperty(value = SERIALIZED_NAME_MESSAGE) + + @JsonProperty(SERIALIZED_NAME_MESSAGE) private Message message; - @JsonProperty(value = SERIALIZED_NAME_ALTERNATE_PRODUCT) + @JsonProperty(SERIALIZED_NAME_ALTERNATE_PRODUCT) private AlternateProduct alternateProduct; - @JsonProperty(value = SERIALIZED_NAME_PROMOTIONAL_OFFER) + @JsonProperty(SERIALIZED_NAME_PROMOTIONAL_OFFER) private PromotionalOffer promotionalOffer; - @JsonProperty(value = SERIALIZED_NAME_ADVANCED_COMMERCE_INFO) + @JsonProperty(SERIALIZED_NAME_ADVANCED_COMMERCE_INFO) private AdvancedCommerceInfo advancedCommerceInfo; - public RealtimeResponseBody() { } @@ -109,13 +109,17 @@ public void setAdvancedCommerceInfo(AdvancedCommerceInfo advancedCommerceInfo) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RealtimeResponseBody that = (RealtimeResponseBody) o; - return Objects.equals(message, that.message) && - Objects.equals(alternateProduct, that.alternateProduct) && - Objects.equals(promotionalOffer, that.promotionalOffer) && - Objects.equals(advancedCommerceInfo, that.advancedCommerceInfo); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RealtimeResponseBody realtimeResponseBody = (RealtimeResponseBody) o; + return Objects.equals(this.message, realtimeResponseBody.message) && + Objects.equals(this.alternateProduct, realtimeResponseBody.alternateProduct) && + Objects.equals(this.promotionalOffer, realtimeResponseBody.promotionalOffer) && + Objects.equals(this.advancedCommerceInfo, realtimeResponseBody.advancedCommerceInfo); } @Override @@ -132,4 +136,4 @@ public String toString() { ", advancedCommerceInfo=" + advancedCommerceInfo + '}'; } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlRequest.java b/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlRequest.java index f84e25a5..4607371b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlRequest.java @@ -11,10 +11,11 @@ * The request body for configuring the URL of your Get Retention Message endpoint. * * @see RealtimeUrlRequest - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class RealtimeUrlRequest { private static final String SERIALIZED_NAME_REALTIME_URL = "realtimeURL"; + @JsonProperty(value = SERIALIZED_NAME_REALTIME_URL, required = true) private String realtimeURL; @@ -24,11 +25,11 @@ protected RealtimeUrlRequest() { } public RealtimeUrlRequest(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + this.realtimeURL = validateRealtimeURL(realtimeURL); } public RealtimeUrlRequest realtimeURL(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + this.realtimeURL = validateRealtimeURL(realtimeURL); return this; } @@ -43,10 +44,10 @@ public String getRealtimeURL() { } public void setRealtimeURL(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + this.realtimeURL = validateRealtimeURL(realtimeURL); } - private String validateRealtimeUrl(String realtimeURL) { + private String validateRealtimeURL(String realtimeURL) { Objects.requireNonNull(realtimeURL); if (realtimeURL.length() > MAXIMUM_REALTIME_URL_LENGTH) { throw new IllegalArgumentException("realtimeURL length longer than maximum allowed"); @@ -74,8 +75,7 @@ public int hashCode() { @Override public String toString() { return "RealtimeUrlRequest{" + - "realtimeURL=" + realtimeURL + + "realtimeURL='" + realtimeURL + '\'' + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlResponse.java b/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlResponse.java index 3804d516..4b821075 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/RealtimeUrlResponse.java @@ -2,33 +2,40 @@ package com.apple.itunes.storekit.model; -import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Map; import java.util.Objects; /** * The response body that contains the URL for your Get Retention Message endpoint. * * @see RealtimeUrlResponse - */ -@JsonInclude(JsonInclude.Include.NON_NULL) + **/ public class RealtimeUrlResponse { private static final String SERIALIZED_NAME_REALTIME_URL = "realtimeURL"; - @JsonProperty(SERIALIZED_NAME_REALTIME_URL) + + @JsonProperty(value = SERIALIZED_NAME_REALTIME_URL, required = true) private String realtimeURL; + @JsonAnySetter + private Map unknownFields; private static final int MAXIMUM_REALTIME_URL_LENGTH = 256; protected RealtimeUrlResponse() { } - public RealtimeUrlResponse(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + @JsonCreator + public RealtimeUrlResponse( + @JsonProperty(value = SERIALIZED_NAME_REALTIME_URL, required = true) String realtimeURL + ) { + this.realtimeURL = validateRealtimeURL(realtimeURL); } public RealtimeUrlResponse realtimeURL(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + this.realtimeURL = validateRealtimeURL(realtimeURL); return this; } @@ -43,10 +50,10 @@ public String getRealtimeURL() { } public void setRealtimeURL(String realtimeURL) { - this.realtimeURL = validateRealtimeUrl(realtimeURL); + this.realtimeURL = validateRealtimeURL(realtimeURL); } - private String validateRealtimeUrl(String realtimeURL) { + private String validateRealtimeURL(String realtimeURL) { Objects.requireNonNull(realtimeURL); if (realtimeURL.length() > MAXIMUM_REALTIME_URL_LENGTH) { throw new IllegalArgumentException("realtimeURL length longer than maximum allowed"); @@ -54,6 +61,24 @@ private String validateRealtimeUrl(String realtimeURL) { return realtimeURL; } + public RealtimeUrlResponse unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -62,20 +87,21 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) { return false; } - RealtimeUrlResponse realtimeUrlRequest = (RealtimeUrlResponse) o; - return Objects.equals(this.realtimeURL, realtimeUrlRequest.realtimeURL); + RealtimeUrlResponse realtimeUrlResponse = (RealtimeUrlResponse) o; + return Objects.equals(this.realtimeURL, realtimeUrlResponse.realtimeURL) && + Objects.equals(this.unknownFields, realtimeUrlResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(realtimeURL); + return Objects.hash(realtimeURL, unknownFields); } @Override public String toString() { return "RealtimeUrlResponse{" + - "realtimeURL=" + realtimeURL + + "realtimeURL='" + realtimeURL + '\'' + + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RefundHistoryResponse.java b/src/main/java/com/apple/itunes/storekit/model/RefundHistoryResponse.java index c8140a5d..fb742833 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RefundHistoryResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/RefundHistoryResponse.java @@ -14,48 +14,41 @@ * A response that contains an array of signed JSON Web Signature (JWS) refunded transactions, and paging information. * * @see RefundHistoryResponse - */ + **/ public class RefundHistoryResponse { - private static final String SERIALIZED_NAME_SIGNED_TRANSACTIONS = "signedTransactions"; - private static final String SERIALIZED_NAME_REVISION = "revision"; private static final String SERIALIZED_NAME_HAS_MORE = "hasMore"; - @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTIONS) - private List signedTransactions = null; - @JsonProperty(SERIALIZED_NAME_REVISION) - private String revision; + private static final String SERIALIZED_NAME_REVISION = "revision"; + private static final String SERIALIZED_NAME_SIGNED_TRANSACTIONS = "signedTransactions"; + @JsonProperty(SERIALIZED_NAME_HAS_MORE) private Boolean hasMore; + @JsonProperty(SERIALIZED_NAME_REVISION) + private String revision; + @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTIONS) + private List signedTransactions; @JsonAnySetter private Map unknownFields; public RefundHistoryResponse() { } - public RefundHistoryResponse signedTransactions(List signedTransactions) { - this.signedTransactions = signedTransactions; - return this; - } - - public RefundHistoryResponse addSignedTransactionsItem(String signedTransactionsItem) { - if (this.signedTransactions == null) { - this.signedTransactions = new ArrayList<>(); - } - this.signedTransactions.add(signedTransactionsItem); + public RefundHistoryResponse hasMore(Boolean hasMore) { + this.hasMore = hasMore; return this; } /** - * A list of up to 20 JWS transactions, or an empty array if the customer hasn't received any refunds in your app. The transactions are sorted in ascending order by revocationDate. + * A Boolean value that indicates whether the App Store has more transactions than it returns in signedTransactions. * - * @return signedTransactions - * @see JWSTransaction + * @return hasMore + * @see hasMore **/ - public List getSignedTransactions() { - return signedTransactions; + public Boolean getHasMore() { + return hasMore; } - public void setSignedTransactions(List signedTransactions) { - this.signedTransactions = signedTransactions; + public void setHasMore(Boolean hasMore) { + this.hasMore = hasMore; } public RefundHistoryResponse revision(String revision) { @@ -64,7 +57,7 @@ public RefundHistoryResponse revision(String revision) { } /** - * A token you use in a query to request the next set of transactions for the customer. + * A token you provide in a query to request the next set of transactions from the Get Refund History endpoint. * * @return revision * @see revision @@ -77,36 +70,44 @@ public void setRevision(String revision) { this.revision = revision; } - public RefundHistoryResponse hasMore(Boolean hasMore) { - this.hasMore = hasMore; + public RefundHistoryResponse signedTransactions(List signedTransactions) { + this.signedTransactions = signedTransactions; + return this; + } + + public RefundHistoryResponse addSignedTransaction(String signedTransaction) { + Objects.requireNonNull(signedTransaction); + if (this.signedTransactions == null) { + this.signedTransactions = new ArrayList<>(); + } + this.signedTransactions.add(signedTransaction); return this; } /** - * A Boolean value indicating whether the App Store has more transaction data. + * A list of up to 20 JWS transactions, or an empty array if the customer hasn’t received any refunds in your app. * - * @return hasMore - * @see hasMore + * @return signedTransactions + * @see JWSTransaction **/ - public Boolean getHasMore() { - return hasMore; + public List getSignedTransactions() { + return signedTransactions; } - public void setHasMore(Boolean hasMore) { - this.hasMore = hasMore; + public void setSignedTransactions(List signedTransactions) { + this.signedTransactions = signedTransactions; } - public RefundHistoryResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -124,25 +125,24 @@ public boolean equals(Object o) { return false; } RefundHistoryResponse refundHistoryResponse = (RefundHistoryResponse) o; - return Objects.equals(this.signedTransactions, refundHistoryResponse.signedTransactions) && + return Objects.equals(this.hasMore, refundHistoryResponse.hasMore) && Objects.equals(this.revision, refundHistoryResponse.revision) && - Objects.equals(this.hasMore, refundHistoryResponse.hasMore) && + Objects.equals(this.signedTransactions, refundHistoryResponse.signedTransactions) && Objects.equals(this.unknownFields, refundHistoryResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(signedTransactions, revision, hasMore, unknownFields); + return Objects.hash(hasMore, revision, signedTransactions, unknownFields); } @Override public String toString() { return "RefundHistoryResponse{" + - "signedTransactions=" + signedTransactions + + "hasMore=" + hasMore + ", revision='" + revision + '\'' + - ", hasMore=" + hasMore + + ", signedTransactions=" + signedTransactions + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RefundPreference.java b/src/main/java/com/apple/itunes/storekit/model/RefundPreference.java index 714e2fb5..cf5fdbe6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RefundPreference.java +++ b/src/main/java/com/apple/itunes/storekit/model/RefundPreference.java @@ -8,11 +8,20 @@ * A value that indicates your preferred outcome for the refund request. * * @see refundPreference - */ + **/ public enum RefundPreference { + /** + * You prefer that the App Store declines the refund. + **/ DECLINE("DECLINE"), + /** + * You prefer that the App Store grants the refund in full. + **/ GRANT_FULL("GRANT_FULL"), + /** + * You prefer that the App Store grants a prorated refund. + **/ GRANT_PRORATED("GRANT_PRORATED"); private final String value; @@ -39,4 +48,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/RefundPreferenceV1.java b/src/main/java/com/apple/itunes/storekit/model/RefundPreferenceV1.java index f248184f..925e6398 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RefundPreferenceV1.java +++ b/src/main/java/com/apple/itunes/storekit/model/RefundPreferenceV1.java @@ -9,13 +9,25 @@ * * @see refundPreferenceV1 * @deprecated Use {@link RefundPreference} instead. - */ + **/ @Deprecated public enum RefundPreferenceV1 { + /** + * The refund preference is undeclared. + **/ UNDECLARED(0), + /** + * You prefer that the App Store grants the refund. + **/ PREFER_GRANT(1), + /** + * You prefer that the App Store declines the refund. + **/ PREFER_DECLINE(2), + /** + * You have no preference whether the App Store grants or declines the refund. + **/ NO_PREFERENCE(3); private final Integer value; @@ -43,4 +55,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RenewalBillingPlanType.java b/src/main/java/com/apple/itunes/storekit/model/RenewalBillingPlanType.java index c6d4765d..d5eb0d08 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RenewalBillingPlanType.java +++ b/src/main/java/com/apple/itunes/storekit/model/RenewalBillingPlanType.java @@ -6,7 +6,7 @@ /** * @see renewalBillingPlanType - */ + **/ public enum RenewalBillingPlanType { BILLED_UPFRONT("BILLED_UPFRONT"), diff --git a/src/main/java/com/apple/itunes/storekit/model/RenewalCommitmentInfo.java b/src/main/java/com/apple/itunes/storekit/model/RenewalCommitmentInfo.java index f356d8ff..187ce9f2 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RenewalCommitmentInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/RenewalCommitmentInfo.java @@ -11,9 +11,8 @@ /** * @see RenewalCommitmentInfo - */ + **/ public class RenewalCommitmentInfo { - private static final String SERIALIZED_NAME_COMMITMENT_AUTO_RENEW_PRODUCT_ID = "commitmentAutoRenewProductId"; private static final String SERIALIZED_NAME_COMMITMENT_AUTO_RENEW_STATUS = "commitmentAutoRenewStatus"; private static final String SERIALIZED_NAME_COMMITMENT_RENEWAL_BILLING_PLAN_TYPE = "commitmentRenewalBillingPlanType"; @@ -64,12 +63,12 @@ public RenewalCommitmentInfo commitmentAutoRenewStatus(AutoRenewStatus commitmen * @see commitmentAutoRenewStatus **/ public AutoRenewStatus getCommitmentAutoRenewStatus() { - return commitmentAutoRenewStatus != null ? AutoRenewStatus.fromValue(commitmentAutoRenewStatus) : null; + return AutoRenewStatus.fromValue(commitmentAutoRenewStatus); } /** * @see #getCommitmentAutoRenewStatus() - */ + **/ public Integer getRawCommitmentAutoRenewStatus() { return commitmentAutoRenewStatus; } @@ -92,12 +91,12 @@ public RenewalCommitmentInfo commitmentRenewalBillingPlanType(RenewalBillingPlan * @see commitmentRenewalBillingPlanType **/ public RenewalBillingPlanType getCommitmentRenewalBillingPlanType() { - return commitmentRenewalBillingPlanType != null ? RenewalBillingPlanType.fromValue(commitmentRenewalBillingPlanType) : null; + return RenewalBillingPlanType.fromValue(commitmentRenewalBillingPlanType); } /** * @see #getCommitmentRenewalBillingPlanType() - */ + **/ public String getRawCommitmentRenewalBillingPlanType() { return commitmentRenewalBillingPlanType; } @@ -149,6 +148,11 @@ public RenewalCommitmentInfo unknownFields(Map unknownFields) { return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -159,10 +163,19 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - RenewalCommitmentInfo that = (RenewalCommitmentInfo) o; - return Objects.equals(commitmentAutoRenewProductId, that.commitmentAutoRenewProductId) && Objects.equals(commitmentAutoRenewStatus, that.commitmentAutoRenewStatus) && Objects.equals(commitmentRenewalBillingPlanType, that.commitmentRenewalBillingPlanType) && Objects.equals(commitmentRenewalDate, that.commitmentRenewalDate) && Objects.equals(commitmentRenewalPrice, that.commitmentRenewalPrice) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RenewalCommitmentInfo renewalCommitmentInfo = (RenewalCommitmentInfo) o; + return Objects.equals(this.commitmentAutoRenewProductId, renewalCommitmentInfo.commitmentAutoRenewProductId) && + Objects.equals(this.commitmentAutoRenewStatus, renewalCommitmentInfo.commitmentAutoRenewStatus) && + Objects.equals(this.commitmentRenewalBillingPlanType, renewalCommitmentInfo.commitmentRenewalBillingPlanType) && + Objects.equals(this.commitmentRenewalDate, renewalCommitmentInfo.commitmentRenewalDate) && + Objects.equals(this.commitmentRenewalPrice, renewalCommitmentInfo.commitmentRenewalPrice) && + Objects.equals(this.unknownFields, renewalCommitmentInfo.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2.java b/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2.java index 9298d30c..7a87050c 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2.java +++ b/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2.java @@ -12,15 +12,15 @@ * The response body the App Store sends in a version 2 server notification. * * @see responseBodyV2 - */ + **/ public class ResponseBodyV2 { private static final String SERIALIZED_NAME_SIGNED_PAYLOAD = "signedPayload"; + @JsonProperty(SERIALIZED_NAME_SIGNED_PAYLOAD) private String signedPayload; @JsonAnySetter private Map unknownFields; - public ResponseBodyV2() { } @@ -30,7 +30,7 @@ public ResponseBodyV2 signedPayload(String signedPayload) { } /** - * A cryptographically signed payload, in JSON Web Signature (JWS) format, containing the response body for a version 2 notification. + * The payload in JSON Web Signature (JWS) format, signed by the App Store. * * @return signedPayload * @see signedPayload @@ -43,17 +43,16 @@ public void setSignedPayload(String signedPayload) { this.signedPayload = signedPayload; } - public ResponseBodyV2 unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +87,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayload.java b/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayload.java index 00f2bc05..959abf5a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayload.java +++ b/src/main/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayload.java @@ -9,42 +9,42 @@ import java.util.Objects; /** - * A decoded payload containing the version 2 notification data. + * A decoded payload that contains the version 2 notification data. * - * @see - */ + * @see responseBodyV2DecodedPayload + **/ public class ResponseBodyV2DecodedPayload implements DecodedSignedData { private static final String SERIALIZED_NAME_NOTIFICATION_TYPE = "notificationType"; private static final String SERIALIZED_NAME_SUBTYPE = "subtype"; - private static final String SERIALIZED_NAME_NOTIFICATION_U_U_I_D = "notificationUUID"; private static final String SERIALIZED_NAME_DATA = "data"; - private static final String SERIALIZED_NAME_VERSION = "version"; - private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; private static final String SERIALIZED_NAME_SUMMARY = "summary"; private static final String SERIALIZED_NAME_EXTERNAL_PURCHASE_TOKEN = "externalPurchaseToken"; private static final String SERIALIZED_NAME_APP_DATA = "appData"; + private static final String SERIALIZED_NAME_VERSION = "version"; + private static final String SERIALIZED_NAME_SIGNED_DATE = "signedDate"; + private static final String SERIALIZED_NAME_NOTIFICATION_UUID = "notificationUUID"; + @JsonProperty(SERIALIZED_NAME_NOTIFICATION_TYPE) private String notificationType; @JsonProperty(SERIALIZED_NAME_SUBTYPE) private String subtype; - @JsonProperty(SERIALIZED_NAME_NOTIFICATION_U_U_I_D) - private String notificationUUID; @JsonProperty(SERIALIZED_NAME_DATA) private Data data; - @JsonProperty(SERIALIZED_NAME_VERSION) - private String version; - @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) - private Long signedDate; @JsonProperty(SERIALIZED_NAME_SUMMARY) private Summary summary; @JsonProperty(SERIALIZED_NAME_EXTERNAL_PURCHASE_TOKEN) private ExternalPurchaseToken externalPurchaseToken; @JsonProperty(SERIALIZED_NAME_APP_DATA) private AppData appData; + @JsonProperty(SERIALIZED_NAME_VERSION) + private String version; + @JsonProperty(SERIALIZED_NAME_SIGNED_DATE) + private Long signedDate; + @JsonProperty(SERIALIZED_NAME_NOTIFICATION_UUID) + private String notificationUUID; @JsonAnySetter private Map unknownFields; - public ResponseBodyV2DecodedPayload() { } @@ -60,12 +60,12 @@ public ResponseBodyV2DecodedPayload notificationType(NotificationTypeV2 notifica * @see notificationType **/ public NotificationTypeV2 getNotificationType() { - return notificationType != null ? NotificationTypeV2.fromValue(notificationType) : null; + return NotificationTypeV2.fromValue(notificationType); } /** * @see #getNotificationType() - */ + **/ public String getRawNotificationType() { return notificationType; } @@ -84,18 +84,18 @@ public ResponseBodyV2DecodedPayload subtype(Subtype subtype) { } /** - * Additional information that identifies the notification event. The subtype field is present only for specific version 2 notifications. + * Additional information that identifies the notification event. * * @return subtype * @see subtype **/ public Subtype getSubtype() { - return subtype != null ? Subtype.fromValue(subtype) : null; + return Subtype.fromValue(subtype); } /** * @see #getSubtype() - */ + **/ public String getRawSubtype() { return subtype; } @@ -108,25 +108,6 @@ public void setRawSubtype(String rawSubtype) { this.subtype = rawSubtype; } - public ResponseBodyV2DecodedPayload notificationUUID(String notificationUUID) { - this.notificationUUID = notificationUUID; - return this; - } - - /** - * A unique identifier for the notification. - * - * @return notificationUUID - * @see notificationUUID - **/ - public String getNotificationUUID() { - return notificationUUID; - } - - public void setNotificationUUID(String notificationUUID) { - this.notificationUUID = notificationUUID; - } - public ResponseBodyV2DecodedPayload data(Data data) { this.data = data; return this; @@ -134,7 +115,6 @@ public ResponseBodyV2DecodedPayload data(Data data) { /** * The object that contains the app metadata and signed renewal and transaction information. - * The data, summary, and externalPurchaseToken fields are mutually exclusive. The payload contains only one of these fields. * * @return data * @see data @@ -147,44 +127,6 @@ public void setData(Data data) { this.data = data; } - public ResponseBodyV2DecodedPayload version(String version) { - this.version = version; - return this; - } - - /** - * A string that indicates the notification’s App Store Server Notifications version number. - * - * @return version - * @see version - **/ - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public ResponseBodyV2DecodedPayload signedDate(Long signedDate) { - this.signedDate = signedDate; - return this; - } - - /** - * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature data. - * - * @return signedDate - * @see signedDate - **/ - public Long getSignedDate() { - return signedDate; - } - - public void setSignedDate(Long signedDate) { - this.signedDate = signedDate; - } - public ResponseBodyV2DecodedPayload summary(Summary summary) { this.summary = summary; return this; @@ -192,7 +134,6 @@ public ResponseBodyV2DecodedPayload summary(Summary summary) { /** * The summary data that appears when the App Store server completes your request to extend a subscription renewal date for eligible subscribers. - * The data, summary, and externalPurchaseToken fields are mutually exclusive. The payload contains only one of these fields. * * @return summary * @see summary @@ -212,7 +153,6 @@ public ResponseBodyV2DecodedPayload externalPurchaseToken(ExternalPurchaseToken /** * This field appears when the notificationType is EXTERNAL_PURCHASE_TOKEN. - * The data, summary, and externalPurchaseToken fields are mutually exclusive. The payload contains only one of these fields. * * @return externalPurchaseToken * @see externalPurchaseToken @@ -231,7 +171,7 @@ public ResponseBodyV2DecodedPayload appData(AppData appData) { } /** - * The object that contains the app metadata and signed app transaction information. This field appears when the notificationType is RESCIND_CONSENT. + * The object that contains the app metadata and signed app transaction information. * * @return appData * @see appData @@ -244,16 +184,73 @@ public void setAppData(AppData appData) { this.appData = appData; } + public ResponseBodyV2DecodedPayload version(String version) { + this.version = version; + return this; + } + + /** + * The App Store Server Notification version number, "2.0". + * + * @return version + * @see version + **/ + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public ResponseBodyV2DecodedPayload signedDate(Long signedDate) { + this.signedDate = signedDate; + return this; + } + + /** + * The UNIX time, in milliseconds, that the App Store signed the JSON Web Signature data. + * + * @return signedDate + * @see signedDate + **/ + public Long getSignedDate() { + return signedDate; + } + + public void setSignedDate(Long signedDate) { + this.signedDate = signedDate; + } + + public ResponseBodyV2DecodedPayload notificationUUID(String notificationUUID) { + this.notificationUUID = notificationUUID; + return this; + } + + /** + * A unique identifier for the notification. + * + * @return notificationUUID + * @see notificationUUID + **/ + public String getNotificationUUID() { + return notificationUUID; + } + + public void setNotificationUUID(String notificationUUID) { + this.notificationUUID = notificationUUID; + } + public ResponseBodyV2DecodedPayload unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -273,19 +270,19 @@ public boolean equals(Object o) { ResponseBodyV2DecodedPayload responseBodyV2DecodedPayload = (ResponseBodyV2DecodedPayload) o; return Objects.equals(this.notificationType, responseBodyV2DecodedPayload.notificationType) && Objects.equals(this.subtype, responseBodyV2DecodedPayload.subtype) && - Objects.equals(this.notificationUUID, responseBodyV2DecodedPayload.notificationUUID) && Objects.equals(this.data, responseBodyV2DecodedPayload.data) && - Objects.equals(this.version, responseBodyV2DecodedPayload.version) && - Objects.equals(this.signedDate, responseBodyV2DecodedPayload.signedDate) && Objects.equals(this.summary, responseBodyV2DecodedPayload.summary) && Objects.equals(this.externalPurchaseToken, responseBodyV2DecodedPayload.externalPurchaseToken) && Objects.equals(this.appData, responseBodyV2DecodedPayload.appData) && + Objects.equals(this.version, responseBodyV2DecodedPayload.version) && + Objects.equals(this.signedDate, responseBodyV2DecodedPayload.signedDate) && + Objects.equals(this.notificationUUID, responseBodyV2DecodedPayload.notificationUUID) && Objects.equals(this.unknownFields, responseBodyV2DecodedPayload.unknownFields); } @Override public int hashCode() { - return Objects.hash(notificationType, subtype, notificationUUID, data, version, signedDate, summary, externalPurchaseToken, appData, unknownFields); + return Objects.hash(notificationType, subtype, data, summary, externalPurchaseToken, appData, version, signedDate, notificationUUID, unknownFields); } @Override @@ -293,15 +290,14 @@ public String toString() { return "ResponseBodyV2DecodedPayload{" + "notificationType='" + notificationType + '\'' + ", subtype='" + subtype + '\'' + - ", notificationUUID='" + notificationUUID + '\'' + ", data=" + data + - ", version='" + version + '\'' + - ", signedDate=" + signedDate + ", summary=" + summary + ", externalPurchaseToken=" + externalPurchaseToken + ", appData=" + appData + + ", version='" + version + '\'' + + ", signedDate=" + signedDate + + ", notificationUUID='" + notificationUUID + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RevocationReason.java b/src/main/java/com/apple/itunes/storekit/model/RevocationReason.java index 92b3b40f..039f439c 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RevocationReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/RevocationReason.java @@ -8,10 +8,16 @@ * The reason for a refunded transaction. * * @see revocationReason - */ + **/ public enum RevocationReason { + /** + * The App Store refunded the transaction on behalf of the customer due to an actual or perceived issue within your app. + **/ REFUNDED_DUE_TO_ISSUE(1), + /** + * The App Store refunded the transaction on behalf of the customer for other reasons, for example, an accidental purchase. + **/ REFUNDED_FOR_OTHER_REASON(0); private final Integer value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/RevocationType.java b/src/main/java/com/apple/itunes/storekit/model/RevocationType.java index 978509db..624c9c77 100644 --- a/src/main/java/com/apple/itunes/storekit/model/RevocationType.java +++ b/src/main/java/com/apple/itunes/storekit/model/RevocationType.java @@ -7,13 +7,26 @@ /** * The type of the refund or revocation that applies to the transaction. * - * @see revocationType - */ + * @see revocationType + **/ public enum RevocationType { + /** + * The transaction has a full refund. + **/ REFUND_FULL("REFUND_FULL"), + /** + * The transaction has a prorated refund. + **/ REFUND_PRORATED("REFUND_PRORATED"), - FAMILY_REVOKE("FAMILY_REVOKE"); + /** + * The transaction is revoked from Family Sharing. + **/ + FAMILY_REVOKE("FAMILY_REVOKE"), + /** + * The organization or group purchaser removed the subscription from the customer. + **/ + ASSIGNMENT_REVOKE("ASSIGNMENT_REVOKE"); private final String value; @@ -39,4 +52,4 @@ public String getValue() { public String toString() { return String.valueOf(value); } -} \ No newline at end of file +} diff --git a/src/main/java/com/apple/itunes/storekit/model/Role.java b/src/main/java/com/apple/itunes/storekit/model/Role.java new file mode 100644 index 00000000..3db04153 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/Role.java @@ -0,0 +1,47 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * A string that identifies a customer’s role for a product within a group. + * + * @see role + **/ +public enum Role { + + /** + * The customer has a seat in the group but doesn’t administer it. + **/ + NONE("NONE"), + /** + * The customer administers the group for the product. + **/ + ADMIN("ADMIN"); + + private final String value; + + Role(String value) { + this.value = value; + } + + public static Role fromValue(String value) { + for (Role b : Role.values()) { + if (b.value.equals(value)) { + return b; + } + } + return null; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/RoleEntry.java b/src/main/java/com/apple/itunes/storekit/model/RoleEntry.java new file mode 100644 index 00000000..1b3ff314 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/RoleEntry.java @@ -0,0 +1,124 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; +import java.util.Objects; + +/** + * A customer’s role for a single product within a group. + * + * @see RoleEntry + **/ +public class RoleEntry { + private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; + private static final String SERIALIZED_NAME_ROLE = "role"; + + @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) + private String productId; + @JsonProperty(SERIALIZED_NAME_ROLE) + private String role; + @JsonAnySetter + private Map unknownFields; + + public RoleEntry() { + } + + public RoleEntry productId(String productId) { + this.productId = productId; + return this; + } + + /** + * The product identifier of the in-app purchase that the role applies to. + * + * @return productId + * @see productId + **/ + public String getProductId() { + return productId; + } + + public void setProductId(String productId) { + this.productId = productId; + } + + public RoleEntry role(Role role) { + this.role = role != null ? role.getValue() : null; + return this; + } + + /** + * The customer’s role for the product. + * + * @return role + * @see role + **/ + public Role getRole() { + return Role.fromValue(role); + } + + /** + * @see #getRole() + **/ + public String getRawRole() { + return role; + } + + public void setRole(Role role) { + this.role = role != null ? role.getValue() : null; + } + + public void setRawRole(String rawRole) { + this.role = rawRole; + } + + public RoleEntry unknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + return this; + } + + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ + public Map getUnknownFields() { + return unknownFields; + } + + public void setUnknownFields(Map unknownFields) { + this.unknownFields = unknownFields; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RoleEntry roleEntry = (RoleEntry) o; + return Objects.equals(this.productId, roleEntry.productId) && + Objects.equals(this.role, roleEntry.role) && + Objects.equals(this.unknownFields, roleEntry.unknownFields); + } + + @Override + public int hashCode() { + return Objects.hash(productId, role, unknownFields); + } + + @Override + public String toString() { + return "RoleEntry{" + + "productId='" + productId + '\'' + + ", role='" + role + '\'' + + ", unknownFields=" + unknownFields + + '}'; + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/SendAttemptItem.java b/src/main/java/com/apple/itunes/storekit/model/SendAttemptItem.java index ec070181..31475ee6 100644 --- a/src/main/java/com/apple/itunes/storekit/model/SendAttemptItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/SendAttemptItem.java @@ -12,10 +12,11 @@ * The success or error information and the date the App Store server records when it attempts to send a server notification to your server. * * @see sendAttemptItem - */ + **/ public class SendAttemptItem { private static final String SERIALIZED_NAME_ATTEMPT_DATE = "attemptDate"; private static final String SERIALIZED_NAME_SEND_ATTEMPT_RESULT = "sendAttemptResult"; + @JsonProperty(SERIALIZED_NAME_ATTEMPT_DATE) private Long attemptDate; @JsonProperty(SERIALIZED_NAME_SEND_ATTEMPT_RESULT) @@ -32,7 +33,7 @@ public SendAttemptItem attemptDate(Long attemptDate) { } /** - * The date the App Store server attempts to send a notification. + * The date the App Store server attempts to send the notification. * * @return attemptDate * @see attemptDate @@ -57,12 +58,12 @@ public SendAttemptItem sendAttemptResult(SendAttemptResult sendAttemptResult) { * @see sendAttemptResult **/ public SendAttemptResult getSendAttemptResult() { - return sendAttemptResult != null ? SendAttemptResult.fromValue(sendAttemptResult) : null; + return SendAttemptResult.fromValue(sendAttemptResult); } /** * @see #getSendAttemptResult() - */ + **/ public String getRawSendAttemptResult() { return sendAttemptResult; } @@ -75,17 +76,16 @@ public void setRawSendAttemptResult(String rawSendAttemptResult) { this.sendAttemptResult = rawSendAttemptResult; } - public SendAttemptItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -122,4 +122,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/SendAttemptResult.java b/src/main/java/com/apple/itunes/storekit/model/SendAttemptResult.java index a01a0d3f..a737f007 100644 --- a/src/main/java/com/apple/itunes/storekit/model/SendAttemptResult.java +++ b/src/main/java/com/apple/itunes/storekit/model/SendAttemptResult.java @@ -8,19 +8,52 @@ * The success or error information the App Store server records when it attempts to send an App Store server notification to your server. * * @see sendAttemptResult - */ + **/ public enum SendAttemptResult { + /** + * The App Store server received a success response when it sent the notification to your server. + **/ SUCCESS("SUCCESS"), + /** + * The App Store server didn’t get a response from your server and timed out. + **/ TIMED_OUT("TIMED_OUT"), + /** + * The App Store server couldn’t establish a TLS session or validate your certificate. + **/ TLS_ISSUE("TLS_ISSUE"), + /** + * The App Store server detected a continual redirect. + **/ CIRCULAR_REDIRECT("CIRCULAR_REDIRECT"), + /** + * The App Store server didn’t receive a valid HTTP response from your server. + **/ NO_RESPONSE("NO_RESPONSE"), + /** + * A network error caused the notification attempt to fail. + **/ SOCKET_ISSUE("SOCKET_ISSUE"), + /** + * The App Store server doesn’t support the supplied charset. + **/ UNSUPPORTED_CHARSET("UNSUPPORTED_CHARSET"), + /** + * The App Store server received an invalid response from your server. + **/ INVALID_RESPONSE("INVALID_RESPONSE"), + /** + * The App Store server’s connection to your server was closed while the send was in progress. + **/ PREMATURE_CLOSE("PREMATURE_CLOSE"), + /** + * The App Store server didn’t receive an HTTP 200 response from your server. + **/ UNSUCCESSFUL_HTTP_RESPONSE_CODE("UNSUCCESSFUL_HTTP_RESPONSE_CODE"), + /** + * Another error occurred that prevented your server from receiving the notification. + **/ OTHER("OTHER"); private final String value; @@ -45,7 +78,6 @@ public String getValue() { @Override public String toString() { - return value; + return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/SendTestNotificationResponse.java b/src/main/java/com/apple/itunes/storekit/model/SendTestNotificationResponse.java index a9f2d320..e041c8a5 100644 --- a/src/main/java/com/apple/itunes/storekit/model/SendTestNotificationResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/SendTestNotificationResponse.java @@ -12,15 +12,15 @@ * A response that contains the test notification token. * * @see SendTestNotificationResponse - */ + **/ public class SendTestNotificationResponse { private static final String SERIALIZED_NAME_TEST_NOTIFICATION_TOKEN = "testNotificationToken"; + @JsonProperty(SERIALIZED_NAME_TEST_NOTIFICATION_TOKEN) private String testNotificationToken; @JsonAnySetter private Map unknownFields; - public SendTestNotificationResponse() { } @@ -30,7 +30,7 @@ public SendTestNotificationResponse testNotificationToken(String testNotificatio } /** - * A unique identifier for a notification test that the App Store server sends to your server. + * The test notification token that uniquely identifies the notification test that App Store Server Notifications sends to your server. * * @return testNotificationToken * @see testNotificationToken @@ -43,17 +43,16 @@ public void setTestNotificationToken(String testNotificationToken) { this.testNotificationToken = testNotificationToken; } - public SendTestNotificationResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +87,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Status.java b/src/main/java/com/apple/itunes/storekit/model/Status.java index 9879984b..bebeeb5a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Status.java +++ b/src/main/java/com/apple/itunes/storekit/model/Status.java @@ -8,13 +8,28 @@ * The status of an auto-renewable subscription. * * @see status - */ + **/ public enum Status { + /** + * The auto-renewable subscription is active. + **/ ACTIVE(1), + /** + * The auto-renewable subscription is expired. + **/ EXPIRED(2), + /** + * The auto-renewable subscription is in a billing retry period. + **/ BILLING_RETRY(3), + /** + * The auto-renewable subscription is in a Billing Grace Period. + **/ BILLING_GRACE_PERIOD(4), + /** + * The auto-renewable subscription is revoked. + **/ REVOKED(5); private final Integer value; @@ -42,4 +57,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/StatusResponse.java b/src/main/java/com/apple/itunes/storekit/model/StatusResponse.java index c00e2d01..6c9534e9 100644 --- a/src/main/java/com/apple/itunes/storekit/model/StatusResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/StatusResponse.java @@ -14,27 +14,55 @@ * A response that contains status information for all of a customer’s auto-renewable subscriptions in your app. * * @see StatusResponse - */ + **/ public class StatusResponse { + private static final String SERIALIZED_NAME_DATA = "data"; private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; - private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; - private static final String SERIALIZED_NAME_DATA = "data"; + private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; + + @JsonProperty(SERIALIZED_NAME_DATA) + private List data; @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) private String environment; - @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) - private String bundleId; @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) private Long appAppleId; - @JsonProperty(SERIALIZED_NAME_DATA) - private List data = null; + @JsonProperty(SERIALIZED_NAME_BUNDLE_ID) + private String bundleId; @JsonAnySetter private Map unknownFields; - public StatusResponse() { } + public StatusResponse data(List data) { + this.data = data; + return this; + } + + public StatusResponse addData(SubscriptionGroupIdentifierItem data) { + Objects.requireNonNull(data); + if (this.data == null) { + this.data = new ArrayList<>(); + } + this.data.add(data); + return this; + } + + /** + * An array of information for auto-renewable subscriptions, including App Store-signed transaction information and App Store-signed renewal information. + * + * @return data + * @see SubscriptionGroupIdentifierItem + **/ + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + public StatusResponse environment(Environment environment) { this.environment = environment != null ? environment.getValue() : null; return this; @@ -47,12 +75,12 @@ public StatusResponse environment(Environment environment) { * @see environment **/ public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + return Environment.fromValue(environment); } /** * @see #getEnvironment() - */ + **/ public String getRawEnvironment() { return environment; } @@ -65,35 +93,16 @@ public void setRawEnvironment(String rawEnvironment) { this.environment = rawEnvironment; } - public StatusResponse bundleId(String bundleId) { - this.bundleId = bundleId; - return this; - } - - /** - * The bundle identifier of an app. - * - * @return bundleId - * @see bundleId - **/ - public String getBundleId() { - return bundleId; - } - - public void setBundleId(String bundleId) { - this.bundleId = bundleId; - } - public StatusResponse appAppleId(Long appAppleId) { this.appAppleId = appAppleId; return this; } /** - * The unique identifier of an app in the App Store. + * Your app’s App Store identifier. * * @return appAppleId - * @see appAppleId + * @see appAppleId **/ public Long getAppAppleId() { return appAppleId; @@ -103,43 +112,35 @@ public void setAppAppleId(Long appAppleId) { this.appAppleId = appAppleId; } - public StatusResponse data(List data) { - this.data = data; - return this; - } - - public StatusResponse addDataItem(SubscriptionGroupIdentifierItem dataItem) { - if (this.data == null) { - this.data = new ArrayList<>(); - } - this.data.add(dataItem); + public StatusResponse bundleId(String bundleId) { + this.bundleId = bundleId; return this; } /** - * An array of information for auto-renewable subscriptions, including App Store-signed transaction information and App Store-signed renewal information. + * Your app’s bundle identifier. * - * @return data + * @return bundleId + * @see bundleId **/ - public List getData() { - return data; + public String getBundleId() { + return bundleId; } - public void setData(List data) { - this.data = data; + public void setBundleId(String bundleId) { + this.bundleId = bundleId; } - public StatusResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -157,27 +158,26 @@ public boolean equals(Object o) { return false; } StatusResponse statusResponse = (StatusResponse) o; - return Objects.equals(this.environment, statusResponse.environment) && - Objects.equals(this.bundleId, statusResponse.bundleId) && + return Objects.equals(this.data, statusResponse.data) && + Objects.equals(this.environment, statusResponse.environment) && Objects.equals(this.appAppleId, statusResponse.appAppleId) && - Objects.equals(this.data, statusResponse.data) && + Objects.equals(this.bundleId, statusResponse.bundleId) && Objects.equals(this.unknownFields, statusResponse.unknownFields); } @Override public int hashCode() { - return Objects.hash(environment, bundleId, appAppleId, data, unknownFields); + return Objects.hash(data, environment, appAppleId, bundleId, unknownFields); } @Override public String toString() { return "StatusResponse{" + - "environment='" + environment + '\'' + - ", bundleId='" + bundleId + '\'' + + "data=" + data + + ", environment='" + environment + '\'' + ", appAppleId=" + appAppleId + - ", data=" + data + + ", bundleId='" + bundleId + '\'' + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/StoreType.java b/src/main/java/com/apple/itunes/storekit/model/StoreType.java new file mode 100644 index 00000000..9bda7939 --- /dev/null +++ b/src/main/java/com/apple/itunes/storekit/model/StoreType.java @@ -0,0 +1,43 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * A string that describes the store the customer obtained the app from. + * + * @see storeType + **/ +public enum StoreType { + + /** + * The customer obtained the app from the App Store. + **/ + CONSUMER("CONSUMER"); + + private final String value; + + StoreType(String value) { + this.value = value; + } + + public static StoreType fromValue(String value) { + for (StoreType b : StoreType.values()) { + if (b.value.equals(value)) { + return b; + } + } + return null; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } +} diff --git a/src/main/java/com/apple/itunes/storekit/model/SubscriptionGroupIdentifierItem.java b/src/main/java/com/apple/itunes/storekit/model/SubscriptionGroupIdentifierItem.java index 4405436b..911b3a76 100644 --- a/src/main/java/com/apple/itunes/storekit/model/SubscriptionGroupIdentifierItem.java +++ b/src/main/java/com/apple/itunes/storekit/model/SubscriptionGroupIdentifierItem.java @@ -14,18 +14,18 @@ * Information for auto-renewable subscriptions, including signed transaction information and signed renewal information, for one subscription group. * * @see SubscriptionGroupIdentifierItem - */ + **/ public class SubscriptionGroupIdentifierItem { private static final String SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER = "subscriptionGroupIdentifier"; private static final String SERIALIZED_NAME_LAST_TRANSACTIONS = "lastTransactions"; + @JsonProperty(SERIALIZED_NAME_SUBSCRIPTION_GROUP_IDENTIFIER) private String subscriptionGroupIdentifier; @JsonProperty(SERIALIZED_NAME_LAST_TRANSACTIONS) - private List lastTransactions = null; + private List lastTransactions; @JsonAnySetter private Map unknownFields; - public SubscriptionGroupIdentifierItem() { } @@ -35,7 +35,7 @@ public SubscriptionGroupIdentifierItem subscriptionGroupIdentifier(String subscr } /** - * The identifier of the subscription group that the subscription belongs to. + * The subscription group identifier of the auto-renewable subscriptions in the lastTransactions array. * * @return subscriptionGroupIdentifier * @see subscriptionGroupIdentifier @@ -53,11 +53,12 @@ public SubscriptionGroupIdentifierItem lastTransactions(List(); } - this.lastTransactions.add(lastTransactionsItem); + this.lastTransactions.add(lastTransaction); return this; } @@ -75,17 +76,16 @@ public void setLastTransactions(List lastTransactions) { this.lastTransactions = lastTransactions; } - public SubscriptionGroupIdentifierItem unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -122,4 +122,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Subtype.java b/src/main/java/com/apple/itunes/storekit/model/Subtype.java index 56173f47..da08f688 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Subtype.java +++ b/src/main/java/com/apple/itunes/storekit/model/Subtype.java @@ -8,28 +8,85 @@ * A string that provides details about select notification types in version 2. * * @see subtype - */ + **/ public enum Subtype { + /** + * Applies to the SUBSCRIBED notificationType. + **/ INITIAL_BUY("INITIAL_BUY"), + /** + * Applies to the SUBSCRIBED notificationType. + **/ RESUBSCRIBE("RESUBSCRIBE"), + /** + * Applies to the DID_CHANGE_RENEWAL_PREF and OFFER_REDEEMED notificationType. + **/ DOWNGRADE("DOWNGRADE"), + /** + * Applies to the DID_CHANGE_RENEWAL_PREF and OFFER_REDEEMED notificationType. + **/ UPGRADE("UPGRADE"), + /** + * Applies to the DID_CHANGE_RENEWAL_STATUS notificationType. + **/ AUTO_RENEW_ENABLED("AUTO_RENEW_ENABLED"), + /** + * Applies to the DID_CHANGE_RENEWAL_STATUS notificationType. + **/ AUTO_RENEW_DISABLED("AUTO_RENEW_DISABLED"), + /** + * Applies to the EXPIRED notificationType. + **/ VOLUNTARY("VOLUNTARY"), + /** + * Applies to the EXPIRED notificationType. + **/ BILLING_RETRY("BILLING_RETRY"), + /** + * Applies to the EXPIRED notificationType. + **/ PRICE_INCREASE("PRICE_INCREASE"), + /** + * Applies to the DID_FAIL_TO_RENEW notificationType. + **/ GRACE_PERIOD("GRACE_PERIOD"), + /** + * Applies to the PRICE_INCREASE notificationType. + **/ PENDING("PENDING"), + /** + * Applies to the PRICE_INCREASE notificationType. + **/ ACCEPTED("ACCEPTED"), + /** + * Applies to the DID_RENEW notificationType. + **/ BILLING_RECOVERY("BILLING_RECOVERY"), + /** + * Applies to the EXPIRED notificationType. + **/ PRODUCT_NOT_FOR_SALE("PRODUCT_NOT_FOR_SALE"), + /** + * Applies to the RENEWAL_EXTENSION notificationType. + **/ SUMMARY("SUMMARY"), + /** + * Applies to the RENEWAL_EXTENSION notificationType. + **/ FAILURE("FAILURE"), + /** + * Applies to the EXTERNAL_PURCHASE_TOKEN notificationType. + **/ UNREPORTED("UNREPORTED"), - ACTIVE_TOKEN_REMINDER("ACTIVE_TOKEN_REMINDER"), - CREATED("CREATED"); + /** + * Applies to the EXTERNAL_PURCHASE_TOKEN notificationType. + **/ + CREATED("CREATED"), + /** + * Applies to the EXTERNAL_PURCHASE_TOKEN notificationType. + **/ + ACTIVE_TOKEN_REMINDER("ACTIVE_TOKEN_REMINDER"); private final String value; @@ -56,4 +113,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Summary.java b/src/main/java/com/apple/itunes/storekit/model/Summary.java index 77b259ed..9180a016 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Summary.java +++ b/src/main/java/com/apple/itunes/storekit/model/Summary.java @@ -4,26 +4,31 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.UUID; /** * The payload data for a subscription-renewal-date extension notification. * * @see summary - */ + **/ public class Summary { + private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; private static final String SERIALIZED_NAME_ENVIRONMENT = "environment"; private static final String SERIALIZED_NAME_APP_APPLE_ID = "appAppleId"; private static final String SERIALIZED_NAME_BUNDLE_ID = "bundleId"; private static final String SERIALIZED_NAME_PRODUCT_ID = "productId"; - private static final String SERIALIZED_NAME_REQUEST_IDENTIFIER = "requestIdentifier"; private static final String SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES = "storefrontCountryCodes"; - private static final String SERIALIZED_NAME_SUCCEEDED_COUNT = "succeededCount"; private static final String SERIALIZED_NAME_FAILED_COUNT = "failedCount"; + private static final String SERIALIZED_NAME_SUCCEEDED_COUNT = "succeededCount"; + + @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) + private UUID requestIdentifier; @JsonProperty(SERIALIZED_NAME_ENVIRONMENT) private String environment; @JsonProperty(SERIALIZED_NAME_APP_APPLE_ID) @@ -32,21 +37,39 @@ public class Summary { private String bundleId; @JsonProperty(SERIALIZED_NAME_PRODUCT_ID) private String productId; - @JsonProperty(SERIALIZED_NAME_REQUEST_IDENTIFIER) - private String requestIdentifier; @JsonProperty(SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES) private List storefrontCountryCodes; - @JsonProperty(SERIALIZED_NAME_SUCCEEDED_COUNT) - private Long succeededCount; @JsonProperty(SERIALIZED_NAME_FAILED_COUNT) private Long failedCount; + @JsonProperty(SERIALIZED_NAME_SUCCEEDED_COUNT) + private Long succeededCount; @JsonAnySetter private Map unknownFields; + private static final int MAXIMUM_STOREFRONT_COUNTRY_CODE_LENGTH = 3; public Summary() { } + public Summary requestIdentifier(UUID requestIdentifier) { + this.requestIdentifier = requestIdentifier; + return this; + } + + /** + * The UUID that represents a specific request to extend a subscription renewal date. + * + * @return requestIdentifier + * @see requestIdentifier + **/ + public UUID getRequestIdentifier() { + return requestIdentifier; + } + + public void setRequestIdentifier(UUID requestIdentifier) { + this.requestIdentifier = requestIdentifier; + } + public Summary environment(Environment environment) { this.environment = environment != null ? environment.getValue() : null; return this; @@ -59,12 +82,12 @@ public Summary environment(Environment environment) { * @see environment **/ public Environment getEnvironment() { - return environment != null ? Environment.fromValue(environment) : null; + return Environment.fromValue(environment); } /** * @see #getEnvironment() - */ + **/ public String getRawEnvironment() { return environment; } @@ -83,7 +106,7 @@ public Summary appAppleId(Long appAppleId) { } /** - * The unique identifier of an app in the App Store. + * The unique identifier of the app that the notification applies to. * * @return appAppleId * @see appAppleId @@ -102,10 +125,10 @@ public Summary bundleId(String bundleId) { } /** - * The bundle identifier of an app. + * The bundle identifier of the app. * * @return bundleId - * @see bundleId + * @see bundleId **/ public String getBundleId() { return bundleId; @@ -121,10 +144,10 @@ public Summary productId(String productId) { } /** - * The unique identifier for the product, that you create in App Store Connect. + * The product identifier of the auto-renewable subscription that the subscription-renewal-date extension applies to. * * @return productId - * @see productId + * @see productId **/ public String getProductId() { return productId; @@ -134,69 +157,50 @@ public void setProductId(String productId) { this.productId = productId; } - public Summary requestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; - return this; - } - - /** - * A string that contains a unique identifier you provide to track each subscription-renewal-date extension request. - * - * @return requestIdentifier - * @see requestIdentifier - **/ - public String getRequestIdentifier() { - return requestIdentifier; - } - - public void setRequestIdentifier(String requestIdentifier) { - this.requestIdentifier = requestIdentifier; - } - public Summary storefrontCountryCodes(List storefrontCountryCodes) { + validateStorefrontCountryCodes(storefrontCountryCodes); this.storefrontCountryCodes = storefrontCountryCodes; return this; } - public Summary addStorefrontCountryCodesItem(String storefrontCountryCodesItem) { + public Summary addStorefrontCountryCode(String storefrontCountryCode) { + Objects.requireNonNull(storefrontCountryCode); + validateStorefrontCountryCode(storefrontCountryCode); if (this.storefrontCountryCodes == null) { this.storefrontCountryCodes = new ArrayList<>(); } - this.storefrontCountryCodes.add(storefrontCountryCodesItem); + this.storefrontCountryCodes.add(storefrontCountryCode); return this; } /** - * A list of storefront country codes you provide to limit the storefronts for a subscription-renewal-date extension. + * A list of country codes that limits the App Store’s attempt to apply the subscription-renewal-date extension. * * @return storefrontCountryCodes - * @see storefrontCountryCodes + * @see storefrontCountryCodes **/ public List getStorefrontCountryCodes() { return storefrontCountryCodes; } + @JsonSetter(SERIALIZED_NAME_STOREFRONT_COUNTRY_CODES) public void setStorefrontCountryCodes(List storefrontCountryCodes) { + validateStorefrontCountryCodes(storefrontCountryCodes); this.storefrontCountryCodes = storefrontCountryCodes; } - public Summary succeededCount(Long succeededCount) { - this.succeededCount = succeededCount; - return this; - } - - /** - * The count of subscriptions that successfully receive a subscription-renewal-date extension. - * - * @return succeededCount - * @see succeededCount - **/ - public Long getSucceededCount() { - return succeededCount; + private void validateStorefrontCountryCodes(List storefrontCountryCodes) { + if (storefrontCountryCodes != null) { + for (String storefrontCountryCode : storefrontCountryCodes) { + validateStorefrontCountryCode(storefrontCountryCode); + } + } } - public void setSucceededCount(Long succeededCount) { - this.succeededCount = succeededCount; + private void validateStorefrontCountryCode(String storefrontCountryCode) { + if (storefrontCountryCode != null && storefrontCountryCode.length() > MAXIMUM_STOREFRONT_COUNTRY_CODE_LENGTH) { + throw new IllegalArgumentException("storefrontCountryCode length longer than maximum allowed"); + } } public Summary failedCount(Long failedCount) { @@ -205,10 +209,10 @@ public Summary failedCount(Long failedCount) { } /** - * The count of subscriptions that fail to receive a subscription-renewal-date extension. + * The final count of subscriptions that fail to receive a subscription-renewal-date extension. * * @return failedCount - * @see failedCount + * @see failedCount **/ public Long getFailedCount() { return failedCount; @@ -218,6 +222,24 @@ public void setFailedCount(Long failedCount) { this.failedCount = failedCount; } + public Summary succeededCount(Long succeededCount) { + this.succeededCount = succeededCount; + return this; + } + + /** + * The final count of subscriptions that successfully receive a subscription-renewal-date extension. + * + * @return succeededCount + * @see succeededCount + **/ + public Long getSucceededCount() { + return succeededCount; + } + + public void setSucceededCount(Long succeededCount) { + this.succeededCount = succeededCount; + } public Summary unknownFields(Map unknownFields) { this.unknownFields = unknownFields; @@ -225,10 +247,10 @@ public Summary unknownFields(Map unknownFields) { } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -246,35 +268,34 @@ public boolean equals(Object o) { return false; } Summary summary = (Summary) o; - return Objects.equals(this.environment, summary.environment) && + return Objects.equals(this.requestIdentifier, summary.requestIdentifier) && + Objects.equals(this.environment, summary.environment) && Objects.equals(this.appAppleId, summary.appAppleId) && Objects.equals(this.bundleId, summary.bundleId) && Objects.equals(this.productId, summary.productId) && - Objects.equals(this.requestIdentifier, summary.requestIdentifier) && Objects.equals(this.storefrontCountryCodes, summary.storefrontCountryCodes) && - Objects.equals(this.succeededCount, summary.succeededCount) && Objects.equals(this.failedCount, summary.failedCount) && + Objects.equals(this.succeededCount, summary.succeededCount) && Objects.equals(this.unknownFields, summary.unknownFields); } @Override public int hashCode() { - return Objects.hash(environment, appAppleId, bundleId, productId, requestIdentifier, storefrontCountryCodes, succeededCount, failedCount, unknownFields); + return Objects.hash(requestIdentifier, environment, appAppleId, bundleId, productId, storefrontCountryCodes, failedCount, succeededCount, unknownFields); } @Override public String toString() { return "Summary{" + - "environment='" + environment + '\'' + + "requestIdentifier=" + requestIdentifier + + ", environment='" + environment + '\'' + ", appAppleId=" + appAppleId + ", bundleId='" + bundleId + '\'' + ", productId='" + productId + '\'' + - ", requestIdentifier='" + requestIdentifier + '\'' + ", storefrontCountryCodes=" + storefrontCountryCodes + - ", succeededCount=" + succeededCount + ", failedCount=" + failedCount + + ", succeededCount=" + succeededCount + ", unknownFields=" + unknownFields + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/TokenType.java b/src/main/java/com/apple/itunes/storekit/model/TokenType.java index c139cf24..4ee0d859 100644 --- a/src/main/java/com/apple/itunes/storekit/model/TokenType.java +++ b/src/main/java/com/apple/itunes/storekit/model/TokenType.java @@ -8,11 +8,21 @@ * The type of an external purchase custom link token. * * @see tokenType - */ + **/ public enum TokenType { + /** + * A token type that indicates an initial acquisition. + **/ + ACQUISITION("ACQUISITION"), + /** + * A token type that indicates usage of App Store services. + **/ SERVICES("SERVICES"), - ACQUISITION("ACQUISITION"); + /** + * A token type an app receives from the MarketplaceKit token(for:) API. + **/ + CORE_TECHNOLOGY("CORE_TECHNOLOGY"); private final String value; diff --git a/src/main/java/com/apple/itunes/storekit/model/TransactionCommitmentInfo.java b/src/main/java/com/apple/itunes/storekit/model/TransactionCommitmentInfo.java index 8ceb8f04..579a736a 100644 --- a/src/main/java/com/apple/itunes/storekit/model/TransactionCommitmentInfo.java +++ b/src/main/java/com/apple/itunes/storekit/model/TransactionCommitmentInfo.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.Map; @@ -11,9 +12,8 @@ /** * @see TransactionCommitmentInfo - */ + **/ public class TransactionCommitmentInfo { - private static final String SERIALIZED_NAME_BILLING_PERIOD_NUMBER = "billingPeriodNumber"; private static final String SERIALIZED_NAME_COMMITMENT_EXPIRES_DATE = "commitmentExpiresDate"; private static final String SERIALIZED_NAME_COMMITMENT_PRICE = "commitmentPrice"; @@ -31,11 +31,14 @@ public class TransactionCommitmentInfo { @JsonAnySetter private Map unknownFields; + private static final int MINIMUM_BILLING_PERIOD_NUMBER = 1; + private static final int MAXIMUM_BILLING_PERIOD_NUMBER = 12; + public TransactionCommitmentInfo() { } public TransactionCommitmentInfo billingPeriodNumber(Integer billingPeriodNumber) { - this.billingPeriodNumber = billingPeriodNumber != null ? HelperValidationUtils.validatePeriodCount(billingPeriodNumber) : null; + this.billingPeriodNumber = validateBillingPeriodNumber(billingPeriodNumber); return this; } @@ -47,8 +50,16 @@ public Integer getBillingPeriodNumber() { return billingPeriodNumber; } + @JsonSetter(SERIALIZED_NAME_BILLING_PERIOD_NUMBER) public void setBillingPeriodNumber(Integer billingPeriodNumber) { - this.billingPeriodNumber = billingPeriodNumber != null ? HelperValidationUtils.validatePeriodCount(billingPeriodNumber) : null; + this.billingPeriodNumber = validateBillingPeriodNumber(billingPeriodNumber); + } + + private Integer validateBillingPeriodNumber(Integer billingPeriodNumber) { + if (billingPeriodNumber != null && (billingPeriodNumber < MINIMUM_BILLING_PERIOD_NUMBER || billingPeriodNumber > MAXIMUM_BILLING_PERIOD_NUMBER)) { + throw new IllegalArgumentException("billingPeriodNumber must be between " + MINIMUM_BILLING_PERIOD_NUMBER + " and " + MAXIMUM_BILLING_PERIOD_NUMBER); + } + return billingPeriodNumber; } public TransactionCommitmentInfo commitmentExpiresDate(Long commitmentExpiresDate) { @@ -107,6 +118,11 @@ public TransactionCommitmentInfo unknownFields(Map unknownFields return this; } + /** + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -117,10 +133,18 @@ public void setUnknownFields(Map unknownFields) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - TransactionCommitmentInfo that = (TransactionCommitmentInfo) o; - return Objects.equals(billingPeriodNumber, that.billingPeriodNumber) && Objects.equals(commitmentExpiresDate, that.commitmentExpiresDate) && Objects.equals(commitmentPrice, that.commitmentPrice) && Objects.equals(totalBillingPeriods, that.totalBillingPeriods) && Objects.equals(unknownFields, that.unknownFields); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TransactionCommitmentInfo transactionCommitmentInfo = (TransactionCommitmentInfo) o; + return Objects.equals(this.billingPeriodNumber, transactionCommitmentInfo.billingPeriodNumber) && + Objects.equals(this.commitmentExpiresDate, transactionCommitmentInfo.commitmentExpiresDate) && + Objects.equals(this.commitmentPrice, transactionCommitmentInfo.commitmentPrice) && + Objects.equals(this.totalBillingPeriods, transactionCommitmentInfo.totalBillingPeriods) && + Objects.equals(this.unknownFields, transactionCommitmentInfo.unknownFields); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/TransactionHistoryRequest.java b/src/main/java/com/apple/itunes/storekit/model/TransactionHistoryRequest.java index b7bb666a..1cd27acd 100644 --- a/src/main/java/com/apple/itunes/storekit/model/TransactionHistoryRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/TransactionHistoryRequest.java @@ -3,6 +3,7 @@ package com.apple.itunes.storekit.model; import java.util.List; +import java.util.Objects; public class TransactionHistoryRequest { private Long startDate; @@ -11,7 +12,7 @@ public class TransactionHistoryRequest { private List productTypes; private Order sort; private List subscriptionGroupIdentifiers; - private InAppOwnershipType inAppOwnershipType; + private String inAppOwnershipType; private Boolean revoked; /** @@ -160,6 +161,13 @@ public TransactionHistoryRequest subscriptionGroupIdentifiers(List subsc * @see inAppOwnershipType */ public InAppOwnershipType getInAppOwnershipType() { + return InAppOwnershipType.fromValue(inAppOwnershipType); + } + + /** + * @see #getInAppOwnershipType() + */ + public String getRawInAppOwnershipType() { return inAppOwnershipType; } @@ -167,14 +175,21 @@ public InAppOwnershipType getInAppOwnershipType() { * @see #getInAppOwnershipType() */ public void setInAppOwnershipType(InAppOwnershipType inAppOwnershipType) { - this.inAppOwnershipType = inAppOwnershipType; + this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; + } + + /** + * @see #getInAppOwnershipType() + */ + public void setRawInAppOwnershipType(String rawInAppOwnershipType) { + this.inAppOwnershipType = rawInAppOwnershipType; } /** * @see #getInAppOwnershipType() */ public TransactionHistoryRequest inAppOwnershipType(InAppOwnershipType inAppOwnershipType) { - this.inAppOwnershipType = inAppOwnershipType; + this.inAppOwnershipType = inAppOwnershipType != null ? inAppOwnershipType.getValue() : null; return this; } @@ -212,6 +227,30 @@ public enum Order { DESCENDING } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + TransactionHistoryRequest transactionHistoryRequest = (TransactionHistoryRequest) o; + return Objects.equals(this.startDate, transactionHistoryRequest.startDate) && + Objects.equals(this.endDate, transactionHistoryRequest.endDate) && + Objects.equals(this.productIds, transactionHistoryRequest.productIds) && + Objects.equals(this.productTypes, transactionHistoryRequest.productTypes) && + Objects.equals(this.sort, transactionHistoryRequest.sort) && + Objects.equals(this.subscriptionGroupIdentifiers, transactionHistoryRequest.subscriptionGroupIdentifiers) && + Objects.equals(this.inAppOwnershipType, transactionHistoryRequest.inAppOwnershipType) && + Objects.equals(this.revoked, transactionHistoryRequest.revoked); + } + + @Override + public int hashCode() { + return Objects.hash(startDate, endDate, productIds, productTypes, sort, subscriptionGroupIdentifiers, inAppOwnershipType, revoked); + } + @Override public String toString() { return "TransactionHistoryRequest{" + diff --git a/src/main/java/com/apple/itunes/storekit/model/TransactionInfoResponse.java b/src/main/java/com/apple/itunes/storekit/model/TransactionInfoResponse.java index 91c76bf2..6859f57b 100644 --- a/src/main/java/com/apple/itunes/storekit/model/TransactionInfoResponse.java +++ b/src/main/java/com/apple/itunes/storekit/model/TransactionInfoResponse.java @@ -12,15 +12,15 @@ * A response that contains signed transaction information for a single transaction. * * @see TransactionInfoResponse - */ + **/ public class TransactionInfoResponse { private static final String SERIALIZED_NAME_SIGNED_TRANSACTION_INFO = "signedTransactionInfo"; + @JsonProperty(SERIALIZED_NAME_SIGNED_TRANSACTION_INFO) private String signedTransactionInfo; @JsonAnySetter private Map unknownFields; - public TransactionInfoResponse() { } @@ -43,17 +43,16 @@ public void setSignedTransactionInfo(String signedTransactionInfo) { this.signedTransactionInfo = signedTransactionInfo; } - public TransactionInfoResponse unknownFields(Map unknownFields) { this.unknownFields = unknownFields; return this; } /** - Fields that are not recognized for this object - - @return A map of JSON keys to objects - */ + * Fields that are not recognized for this object + * + * @return A map of JSON keys to objects + **/ public Map getUnknownFields() { return unknownFields; } @@ -88,4 +87,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/TransactionReason.java b/src/main/java/com/apple/itunes/storekit/model/TransactionReason.java index 1d3e57d3..ac166fa8 100644 --- a/src/main/java/com/apple/itunes/storekit/model/TransactionReason.java +++ b/src/main/java/com/apple/itunes/storekit/model/TransactionReason.java @@ -8,10 +8,16 @@ * The cause of a purchase transaction, which indicates whether it’s a customer’s purchase or a renewal for an auto-renewable subscription that the system initiates. * * @see transactionReason - */ + **/ public enum TransactionReason { + /** + * The customer initiated the purchase, which may be for any in-app purchase type: consumable, non-consumable, non-renewing subscription, or auto-renewable subscription. + **/ PURCHASE("PURCHASE"), + /** + * The App Store server initiated the purchase transaction to renew an auto-renewable subscription. + **/ RENEWAL("RENEWAL"); private final String value; @@ -39,4 +45,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/Type.java b/src/main/java/com/apple/itunes/storekit/model/Type.java index c37046ea..e7f53669 100644 --- a/src/main/java/com/apple/itunes/storekit/model/Type.java +++ b/src/main/java/com/apple/itunes/storekit/model/Type.java @@ -5,15 +5,27 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * The type of in-app purchase products you can offer in your app. + * The type of In-App Purchase products you can offer in your app. * * @see type - */ + **/ public enum Type { + /** + * An auto-renewable subscription + **/ AUTO_RENEWABLE_SUBSCRIPTION("Auto-Renewable Subscription"), + /** + * A non-consumable In-App Purchase + **/ NON_CONSUMABLE("Non-Consumable"), + /** + * A consumable In-App Purchase + **/ CONSUMABLE("Consumable"), + /** + * A non-renewing subscription + **/ NON_RENEWING_SUBSCRIPTION("Non-Renewing Subscription"); private final String value; @@ -41,4 +53,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/UpdateAppAccountTokenRequest.java b/src/main/java/com/apple/itunes/storekit/model/UpdateAppAccountTokenRequest.java index 2b816a0c..752584b0 100644 --- a/src/main/java/com/apple/itunes/storekit/model/UpdateAppAccountTokenRequest.java +++ b/src/main/java/com/apple/itunes/storekit/model/UpdateAppAccountTokenRequest.java @@ -16,6 +16,7 @@ @JsonInclude(JsonInclude.Include.NON_NULL) public class UpdateAppAccountTokenRequest { private static final String SERIALIZED_NAME_APP_ACCOUNT_TOKEN = "appAccountToken"; + @JsonProperty(value = SERIALIZED_NAME_APP_ACCOUNT_TOKEN, required = true) private UUID appAccountToken; @@ -32,7 +33,7 @@ public UpdateAppAccountTokenRequest appAccountToken(UUID appAccountToken) { } /** - * The UUID that an app optionally generates to map a customer’s in-app purchase with its resulting App Store transaction. + * A UUID value to associate with the transaction you indicate in the endpoint parameter. * * @return appAccountToken * @see appAccountToken @@ -47,14 +48,19 @@ public void setAppAccountToken(UUID appAccountToken) { @Override public boolean equals(Object o) { - if (!(o instanceof UpdateAppAccountTokenRequest)) return false; - UpdateAppAccountTokenRequest that = (UpdateAppAccountTokenRequest) o; - return Objects.equals(getAppAccountToken(), that.getAppAccountToken()); + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + UpdateAppAccountTokenRequest updateAppAccountTokenRequest = (UpdateAppAccountTokenRequest) o; + return Objects.equals(this.appAccountToken, updateAppAccountTokenRequest.appAccountToken); } @Override public int hashCode() { - return Objects.hashCode(getAppAccountToken()); + return Objects.hash(appAccountToken); } @Override diff --git a/src/main/java/com/apple/itunes/storekit/model/UploadMessageImage.java b/src/main/java/com/apple/itunes/storekit/model/UploadMessageImage.java index 352f7d13..d2ead0a4 100644 --- a/src/main/java/com/apple/itunes/storekit/model/UploadMessageImage.java +++ b/src/main/java/com/apple/itunes/storekit/model/UploadMessageImage.java @@ -12,11 +12,12 @@ * The definition of an image with its alternative text. * * @see UploadMessageImage - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class UploadMessageImage { private static final String SERIALIZED_NAME_IMAGE_IDENTIFIER = "imageIdentifier"; private static final String SERIALIZED_NAME_ALT_TEXT = "altText"; + @JsonProperty(value = SERIALIZED_NAME_IMAGE_IDENTIFIER, required = true) private UUID imageIdentifier; @JsonProperty(value = SERIALIZED_NAME_ALT_TEXT, required = true) @@ -27,8 +28,7 @@ public class UploadMessageImage { protected UploadMessageImage() { } - public UploadMessageImage(UUID imageIdentifier, - String altText) { + public UploadMessageImage(UUID imageIdentifier, String altText) { this.imageIdentifier = Objects.requireNonNull(imageIdentifier); this.altText = validateAltText(altText); } @@ -49,10 +49,9 @@ public UUID getImageIdentifier() { } public void setImageIdentifier(UUID imageIdentifier) { - this.imageIdentifier = imageIdentifier; + this.imageIdentifier = Objects.requireNonNull(imageIdentifier); } - public UploadMessageImage altText(String altText) { this.altText = validateAltText(altText); return this; @@ -106,4 +105,3 @@ public String toString() { '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/UploadMessageRequestBody.java b/src/main/java/com/apple/itunes/storekit/model/UploadMessageRequestBody.java index 901ab590..5c07b3d7 100644 --- a/src/main/java/com/apple/itunes/storekit/model/UploadMessageRequestBody.java +++ b/src/main/java/com/apple/itunes/storekit/model/UploadMessageRequestBody.java @@ -5,31 +5,33 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.ArrayList; import java.util.List; import java.util.Objects; /** - * The request body for uploading a message, which includes the message text and an optional image reference. + * The request body for uploading a message, which includes the message text and an optional image reference and bullet points. * * @see UploadMessageRequestBody - */ + **/ @JsonInclude(JsonInclude.Include.NON_NULL) public class UploadMessageRequestBody { private static final String SERIALIZED_NAME_HEADER = "header"; private static final String SERIALIZED_NAME_BODY = "body"; private static final String SERIALIZED_NAME_IMAGE = "image"; - private static final String SERIALIZED_NAME_HEADER_POSITION = "headerPosition"; private static final String SERIALIZED_NAME_BULLET_POINTS = "bulletPoints"; + private static final String SERIALIZED_NAME_HEADER_POSITION = "headerPosition"; + @JsonProperty(value = SERIALIZED_NAME_HEADER, required = true) private String header; @JsonProperty(value = SERIALIZED_NAME_BODY, required = true) private String body; - @JsonProperty(value = SERIALIZED_NAME_IMAGE) + @JsonProperty(SERIALIZED_NAME_IMAGE) private UploadMessageImage image; - @JsonProperty(value = SERIALIZED_NAME_HEADER_POSITION) - private String headerPosition; - @JsonProperty(value = SERIALIZED_NAME_BULLET_POINTS) + @JsonProperty(SERIALIZED_NAME_BULLET_POINTS) private List bulletPoints; + @JsonProperty(SERIALIZED_NAME_HEADER_POSITION) + private String headerPosition; private static final int MAXIMUM_HEADER_LENGTH = 66; private static final int MAXIMUM_BODY_LENGTH = 144; @@ -38,21 +40,9 @@ public class UploadMessageRequestBody { protected UploadMessageRequestBody() { } - /** - * @deprecated Use {@link #UploadMessageRequestBody(String, String)} instead. - */ - @Deprecated - public UploadMessageRequestBody(String header, - String body, - UploadMessageImage image) { + public UploadMessageRequestBody(String header, String body) { this.header = validateHeader(header); this.body = validateBody(body); - this.image = image; - } - - public UploadMessageRequestBody(String header, - String body) { - this(header, body, null); } public UploadMessageRequestBody header(String header) { @@ -128,6 +118,51 @@ public void setImage(UploadMessageImage image) { this.image = image; } + public UploadMessageRequestBody bulletPoints(List bulletPoints) { + this.bulletPoints = validateBulletPoints(bulletPoints); + return this; + } + + public UploadMessageRequestBody addBulletPoint(BulletPoint bulletPoint) { + Objects.requireNonNull(bulletPoint); + if (this.bulletPoints == null) { + this.bulletPoints = new ArrayList<>(); + } + if (this.bulletPoints.size() >= MAXIMUM_BULLET_POINTS_COUNT) { + throw new IllegalArgumentException("bulletPoints count exceeds the maximum allowed"); + } + this.bulletPoints.add(bulletPoint); + return this; + } + + /** + * An optional array of up to five bullet points. + * + * @return bulletPoints + * @see BulletPoint + **/ + public List getBulletPoints() { + return bulletPoints; + } + + public void setBulletPoints(List bulletPoints) { + this.bulletPoints = validateBulletPoints(bulletPoints); + } + + private List validateBulletPoints(List bulletPoints) { + if (bulletPoints != null) { + if (bulletPoints.size() > MAXIMUM_BULLET_POINTS_COUNT) { + throw new IllegalArgumentException("bulletPoints count exceeds the maximum allowed"); + } + for (BulletPoint bulletPoint : bulletPoints) { + if (bulletPoint == null) { + throw new IllegalArgumentException("Item in the list cannot be null"); + } + } + } + return bulletPoints; + } + public UploadMessageRequestBody headerPosition(HeaderPosition headerPosition) { this.headerPosition = headerPosition != null ? headerPosition.getValue() : null; return this; @@ -140,12 +175,12 @@ public UploadMessageRequestBody headerPosition(HeaderPosition headerPosition) { * @see headerPosition **/ public HeaderPosition getHeaderPosition() { - return headerPosition != null ? HeaderPosition.fromValue(headerPosition) : null; + return HeaderPosition.fromValue(headerPosition); } /** * @see #getHeaderPosition() - */ + **/ public String getRawHeaderPosition() { return headerPosition; } @@ -158,32 +193,6 @@ public void setRawHeaderPosition(String rawHeaderPosition) { this.headerPosition = rawHeaderPosition; } - public UploadMessageRequestBody bulletPoints(List bulletPoints) { - this.bulletPoints = validateBulletPoints(bulletPoints); - return this; - } - - /** - * An optional array of bullet points. - * - * @return bulletPoints - * @see BulletPoint - **/ - public List getBulletPoints() { - return bulletPoints; - } - - public void setBulletPoints(List bulletPoints) { - this.bulletPoints = validateBulletPoints(bulletPoints); - } - - private List validateBulletPoints(List bulletPoints) { - if (bulletPoints != null && bulletPoints.size() > MAXIMUM_BULLET_POINTS_COUNT) { - throw new IllegalArgumentException("bulletPoints count exceeds the maximum allowed"); - } - return bulletPoints; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -196,13 +205,13 @@ public boolean equals(Object o) { return Objects.equals(this.header, uploadMessageRequestBody.header) && Objects.equals(this.body, uploadMessageRequestBody.body) && Objects.equals(this.image, uploadMessageRequestBody.image) && - Objects.equals(this.headerPosition, uploadMessageRequestBody.headerPosition) && - Objects.equals(this.bulletPoints, uploadMessageRequestBody.bulletPoints); + Objects.equals(this.bulletPoints, uploadMessageRequestBody.bulletPoints) && + Objects.equals(this.headerPosition, uploadMessageRequestBody.headerPosition); } @Override public int hashCode() { - return Objects.hash(header, body, image, headerPosition, bulletPoints); + return Objects.hash(header, body, image, bulletPoints, headerPosition); } @Override @@ -211,9 +220,8 @@ public String toString() { "header='" + header + '\'' + ", body='" + body + '\'' + ", image=" + image + - ", headerPosition='" + headerPosition + '\'' + ", bulletPoints=" + bulletPoints + + ", headerPosition='" + headerPosition + '\'' + '}'; } } - diff --git a/src/main/java/com/apple/itunes/storekit/model/UserStatus.java b/src/main/java/com/apple/itunes/storekit/model/UserStatus.java index 3fa784dd..2b534904 100644 --- a/src/main/java/com/apple/itunes/storekit/model/UserStatus.java +++ b/src/main/java/com/apple/itunes/storekit/model/UserStatus.java @@ -8,13 +8,28 @@ * The status of a customer’s account within your app. * * @see userStatus - */ + **/ public enum UserStatus { + /** + * Account status is undeclared. + **/ UNDECLARED(0), + /** + * The customer’s account is active. + **/ ACTIVE(1), + /** + * The customer’s account is suspended. + **/ SUSPENDED(2), + /** + * The customer’s account is terminated. + **/ TERMINATED(3), + /** + * The customer’s account has limited access. + **/ LIMITED_ACCESS(4); private final Integer value; @@ -42,4 +57,3 @@ public String toString() { return String.valueOf(value); } } - diff --git a/src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreator.java b/src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreator.java index 6954866d..fbd53bf1 100644 --- a/src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreator.java +++ b/src/main/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreator.java @@ -12,6 +12,7 @@ import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; +import java.util.Locale; import java.util.UUID; public class PromotionalOfferSignatureCreator { @@ -21,6 +22,12 @@ public class PromotionalOfferSignatureCreator { private final String bundleId; public PromotionalOfferSignatureCreator(String signingKey, String keyId, String bundleId) { + if (keyId == null) { + throw new IllegalArgumentException("keyId cannot be null"); + } + if (bundleId == null) { + throw new IllegalArgumentException("bundleId cannot be null"); + } try { signingKey = signingKey.replace("-----BEGIN PRIVATE KEY-----", "") .replaceAll("\\R+", "") @@ -40,7 +47,7 @@ public PromotionalOfferSignatureCreator(String signingKey, String keyId, String /** * Create a promotional offer signature * - * @see Generating a signature for promotional offers + * @see Generating a signature for promotional offers * @param productIdentifier The subscription product identifier * @param subscriptionOfferID The subscription discount identifier * @param appAccountToken An optional string value that you define; may be an empty string @@ -49,11 +56,20 @@ public PromotionalOfferSignatureCreator(String signingKey, String keyId, String * @return The Base64 encoded signature */ public String createSignature(String productIdentifier, String subscriptionOfferID, String appAccountToken, UUID nonce, long timestamp) { + if (productIdentifier == null) { + throw new IllegalArgumentException("productIdentifier cannot be null"); + } + if (subscriptionOfferID == null) { + throw new IllegalArgumentException("subscriptionOfferID cannot be null"); + } + if (nonce == null) { + throw new IllegalArgumentException("nonce cannot be null"); + } String payload = this.bundleId + '\u2063' + this.keyId + '\u2063' + productIdentifier + '\u2063' + subscriptionOfferID + '\u2063' + - appAccountToken.toLowerCase() + '\u2063'+ + (appAccountToken != null ? appAccountToken.toLowerCase(Locale.ROOT) : "") + '\u2063'+ nonce.toString().toLowerCase() + '\u2063' + timestamp; try { diff --git a/src/main/java/com/apple/itunes/storekit/signature/JWSSignatureCreator.java b/src/main/java/com/apple/itunes/storekit/signature/JWSSignatureCreator.java index 54e3b9d6..6ec6774d 100644 --- a/src/main/java/com/apple/itunes/storekit/signature/JWSSignatureCreator.java +++ b/src/main/java/com/apple/itunes/storekit/signature/JWSSignatureCreator.java @@ -28,6 +28,15 @@ public abstract class JWSSignatureCreator { private final String bundleId; public JWSSignatureCreator(String audience, String signingKey, String keyId, String issuerId, String bundleId) { + if (keyId == null) { + throw new IllegalArgumentException("keyId cannot be null"); + } + if (issuerId == null) { + throw new IllegalArgumentException("issuerId cannot be null"); + } + if (bundleId == null) { + throw new IllegalArgumentException("bundleId cannot be null"); + } this.audience = audience; try { signingKey = signingKey.replace("-----BEGIN PRIVATE KEY-----", "") diff --git a/src/main/java/com/apple/itunes/storekit/verification/ChainVerifier.java b/src/main/java/com/apple/itunes/storekit/verification/ChainVerifier.java index 9ca08aee..0b989725 100644 --- a/src/main/java/com/apple/itunes/storekit/verification/ChainVerifier.java +++ b/src/main/java/com/apple/itunes/storekit/verification/ChainVerifier.java @@ -64,7 +64,7 @@ public ChainVerifier(Set rootCertificates) { public PublicKey verifyChain(String[] certificates, boolean performRevocationChecking, Date effectiveDate) throws VerificationException { if (performRevocationChecking && certificates.length > 0) { // If revocation checking is enabled (which also implies effectiveDate is now), check the cache - PublicKey cachedKey = getCachedPrivateKey(Arrays.asList(certificates)); + PublicKey cachedKey = getCachedPublicKey(Arrays.asList(certificates)); if (cachedKey != null) { return cachedKey; } @@ -122,9 +122,10 @@ PublicKey verifyChainWithoutCaching(String[] certificates, boolean performRevoca } } - private PublicKey getCachedPrivateKey(List certificateChain) { - if (verifiedPublicKeyCache.containsKey(certificateChain) && verifiedPublicKeyCache.get(certificateChain).cachedExpirationDate.isAfter(clock.instant())) { - return verifiedPublicKeyCache.get(certificateChain).publicKey; + private PublicKey getCachedPublicKey(List certificateChain) { + CachedEntry cachedEntry = verifiedPublicKeyCache.get(certificateChain); + if (cachedEntry != null && cachedEntry.cachedExpirationDate.isAfter(clock.instant())) { + return cachedEntry.publicKey; } return null; } diff --git a/src/main/java/com/apple/itunes/storekit/verification/SignedDataVerifier.java b/src/main/java/com/apple/itunes/storekit/verification/SignedDataVerifier.java index 480e0ccc..b9c6d469 100644 --- a/src/main/java/com/apple/itunes/storekit/verification/SignedDataVerifier.java +++ b/src/main/java/com/apple/itunes/storekit/verification/SignedDataVerifier.java @@ -173,19 +173,19 @@ public DecodedRealtimeRequestBody verifyAndDecodeRealtimeRequest(String signedPa } protected void validateAppAppleId(Long appAppleId) throws VerificationException { - if (this.environment.equals(Environment.PRODUCTION) && !this.appAppleId.equals(appAppleId)) { + if (Environment.PRODUCTION.equals(this.environment) && !this.appAppleId.equals(appAppleId)) { throw new VerificationException(VerificationStatus.INVALID_APP_IDENTIFIER); } } protected void validateBundleId(String bundleId) throws VerificationException { - if (!this.bundleId.equals(bundleId)) { + if (this.bundleId == null || !this.bundleId.equals(bundleId)) { throw new VerificationException(VerificationStatus.INVALID_APP_IDENTIFIER); } } protected void validateEnvironment(Environment environment) throws VerificationException { - if (!this.environment.equals(environment)) { + if (this.environment == null || !this.environment.equals(environment)) { throw new VerificationException(VerificationStatus.INVALID_ENVIRONMENT); } } @@ -208,7 +208,7 @@ protected T decodeSignedObject(String signedObject if ("ES256".equals(unverifiedJWT.getAlgorithm())) { JWT.require(Algorithm.ECDSA256((ECPublicKey) signingKey)).build().verify(unverifiedJWT); } else { - throw new VerificationException(VerificationStatus.VERIFICATION_FAILURE, "Unrecognized JWT algorithm + " + unverifiedJWT.getAlgorithm()); + throw new VerificationException(VerificationStatus.VERIFICATION_FAILURE, "Unrecognized JWT algorithm: " + unverifiedJWT.getAlgorithm()); } return decodedData; } catch (VerificationException e) { diff --git a/src/test/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreatorTest.java b/src/test/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreatorTest.java index 7d838bdf..acc8ebe1 100644 --- a/src/test/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreatorTest.java +++ b/src/test/java/com/apple/itunes/storekit/advancedcommerce/AdvancedCommerceInAppSignatureCreatorTest.java @@ -3,7 +3,13 @@ package com.apple.itunes.storekit.advancedcommerce; import com.apple.itunes.storekit.model.AdvancedCommerceInAppRequest; +import com.apple.itunes.storekit.model.AdvancedCommerceOneTimeChargeCreateRequest; +import com.apple.itunes.storekit.model.AdvancedCommerceOneTimeChargeItem; +import com.apple.itunes.storekit.model.AdvancedCommerceRequestInfo; +import com.apple.itunes.storekit.model.AdvancedCommerceSubscriptionModifyInAppRequest; +import com.apple.itunes.storekit.util.TestSigningUtility; import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; @@ -21,6 +27,7 @@ class AdvancedCommerceInAppSignatureCreatorTest { private static final String ISSUER_ID = "issuerId"; private static final String BUNDLE_ID = "bundleId"; private static final String TEST_VALUE = "testValue"; + private static final UUID REQUEST_REFERENCE_ID = UUID.fromString("3db5c98d-8acf-4e29-831e-8e1f82f9f6e9"); @Test void testSignatureCreator() throws Exception { @@ -30,7 +37,7 @@ void testSignatureCreator() throws Exception { TestInAppRequest request = new TestInAppRequest(TEST_VALUE); String signature = signatureCreator.createSignature(request); Assertions.assertNotNull(signature); - DecodedJWT decodedJWT = JWT.decode(signature); + DecodedJWT decodedJWT = JWT.require(Algorithm.ECDSA256(TestSigningUtility.getTestSigningPublicKey(), null)).build().verify(signature); // Header Assertions.assertEquals("JWT", decodedJWT.getType()); Assertions.assertEquals("ES256", decodedJWT.getAlgorithm()); @@ -51,6 +58,39 @@ void testSignatureCreator() throws Exception { } } + @Test + void testOneTimeChargeCreateRequestOmitsUnsetFields() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + AdvancedCommerceInAppSignatureCreator signatureCreator = new AdvancedCommerceInAppSignatureCreator(new String(key.readAllBytes()), KEY_ID, ISSUER_ID, BUNDLE_ID); + AdvancedCommerceOneTimeChargeCreateRequest request = new AdvancedCommerceOneTimeChargeCreateRequest( + new AdvancedCommerceRequestInfo(REQUEST_REFERENCE_ID), + "USD", + new AdvancedCommerceOneTimeChargeItem("description", "displayName", "sku", 15990L), + "C003-00-2" + ); + String signature = signatureCreator.createSignature(request); + String expectedJson = "{\"requestInfo\":{\"requestReferenceId\":\"3db5c98d-8acf-4e29-831e-8e1f82f9f6e9\"},\"operation\":\"CREATE_ONE_TIME_CHARGE\",\"version\":\"1\",\"currency\":\"USD\",\"item\":{\"SKU\":\"sku\",\"description\":\"description\",\"displayName\":\"displayName\",\"price\":15990},\"taxCode\":\"C003-00-2\"}"; + Assertions.assertEquals(new ObjectMapper().readTree(expectedJson), new ObjectMapper().readTree(getDecodedRequest(signature))); + } + } + + @Test + void testSubscriptionModifyInAppRequestOmitsUnsetFields() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + AdvancedCommerceInAppSignatureCreator signatureCreator = new AdvancedCommerceInAppSignatureCreator(new String(key.readAllBytes()), KEY_ID, ISSUER_ID, BUNDLE_ID); + AdvancedCommerceSubscriptionModifyInAppRequest request = new AdvancedCommerceSubscriptionModifyInAppRequest( + new AdvancedCommerceRequestInfo(REQUEST_REFERENCE_ID), + true, + "123" + ); + String signature = signatureCreator.createSignature(request); + String expectedJson = "{\"requestInfo\":{\"requestReferenceId\":\"3db5c98d-8acf-4e29-831e-8e1f82f9f6e9\"},\"operation\":\"MODIFY_SUBSCRIPTION\",\"version\":\"1\",\"retainBillingCycle\":true,\"transactionId\":\"123\"}"; + Assertions.assertEquals(new ObjectMapper().readTree(expectedJson), new ObjectMapper().readTree(getDecodedRequest(signature))); + } + } + @Test void testRequestMissing() throws Exception { try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { @@ -60,6 +100,11 @@ void testRequestMissing() throws Exception { } } + private static String getDecodedRequest(String signature) throws Exception { + DecodedJWT decodedJWT = JWT.require(Algorithm.ECDSA256(TestSigningUtility.getTestSigningPublicKey(), null)).build().verify(signature); + return new String(Base64.getDecoder().decode(decodedJWT.getClaim("request").asString()), StandardCharsets.UTF_8); + } + private static class TestInAppRequest implements AdvancedCommerceInAppRequest { @JsonProperty("testValue") diff --git a/src/test/java/com/apple/itunes/storekit/client/APIErrorTest.java b/src/test/java/com/apple/itunes/storekit/client/APIErrorTest.java new file mode 100644 index 00000000..44cc4f1c --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/client/APIErrorTest.java @@ -0,0 +1,69 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.client; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.Set; + +public class APIErrorTest { + + @Test + public void testErrorCodesAreUnique() { + Set errorCodes = new HashSet<>(); + for (APIError apiError : APIError.values()) { + Assertions.assertTrue(errorCodes.add(apiError.errorCode())); + } + } + + @Test + public void testFetchErrorResponseFromErrorCode() { + for (APIError apiError : APIError.values()) { + Assertions.assertEquals(apiError, APIError.fetchErrorResponseFromErrorCode(apiError.errorCode())); + } + Assertions.assertNull(APIError.fetchErrorResponseFromErrorCode(9990000L)); + } + + @Test + public void testAppStoreServerAPIErrorCodes() { + Assertions.assertEquals(APIError.INVALID_LIMIT, APIError.fetchErrorResponseFromErrorCode(4000004L)); + Assertions.assertEquals(APIError.INVALID_REFUND_PREFERENCE, APIError.fetchErrorResponseFromErrorCode(4000044L)); + Assertions.assertEquals(APIError.CONSUMPTION_PERCENTAGE_OUT_OF_RANGE, APIError.fetchErrorResponseFromErrorCode(4000207L)); + Assertions.assertEquals(APIError.UNDELIVERED_CONSUMPTION_PERCENTAGE_NON_ZERO, APIError.fetchErrorResponseFromErrorCode(4000208L)); + Assertions.assertEquals(APIError.CONSUMPTION_PERCENTAGE_AUTO_RENEWABLE_SUBSCRIPTION, APIError.fetchErrorResponseFromErrorCode(4000209L)); + Assertions.assertEquals(APIError.ADVANCED_COMMERCE_TRANSACTION_NOT_SUPPORTED, APIError.fetchErrorResponseFromErrorCode(4000210L)); + Assertions.assertEquals(APIError.INVALID_GROUP_ID, APIError.fetchErrorResponseFromErrorCode(4000225L)); + Assertions.assertEquals(APIError.INVALID_ASSIGNED_TRANSACTION_NOT_SUPPORTED, APIError.fetchErrorResponseFromErrorCode(4000227L)); + Assertions.assertEquals(APIError.ASSIGNED_SUBSCRIPTION_EXTENSION_INELIGIBLE, APIError.fetchErrorResponseFromErrorCode(4030028L)); + Assertions.assertEquals(APIError.GROUP_NOT_FOUND, APIError.fetchErrorResponseFromErrorCode(4040022L)); + } + + @Test + public void testOneNamePerErrorCode() { + Assertions.assertEquals(APIError.APP_TRANSACTION_ID_NOT_SUPPORTED, APIError.fetchErrorResponseFromErrorCode(4000048L)); + Assertions.assertEquals(APIError.INVALID_APP_ACCOUNT_TOKEN_UUID, APIError.fetchErrorResponseFromErrorCode(4000183L)); + Assertions.assertEquals(APIError.FAMILY_TRANSACTION_NOT_SUPPORTED, APIError.fetchErrorResponseFromErrorCode(4000185L)); + Assertions.assertEquals(APIError.TRANSACTION_ID_IS_NOT_ORIGINAL_TRANSACTION_ID, APIError.fetchErrorResponseFromErrorCode(4000187L)); + Assertions.assertEquals(APIError.APP_TRANSACTION_DOES_NOT_EXIST, APIError.fetchErrorResponseFromErrorCode(4040019L)); + for (APIError apiError : APIError.values()) { + Assertions.assertFalse(apiError.name().endsWith("_ERROR"), apiError.name()); + } + } + + @Test + public void testAdvancedCommerceAPIErrorCodes() { + Assertions.assertEquals(APIError.INVALID_CURRENCY, APIError.fetchErrorResponseFromErrorCode(4000053L)); + Assertions.assertEquals(APIError.NULL_REQUEST_INFO, APIError.fetchErrorResponseFromErrorCode(4000079L)); + Assertions.assertEquals(APIError.REPEATED_REQUEST_REFERENCE_ID, APIError.fetchErrorResponseFromErrorCode(4000097L)); + Assertions.assertEquals(APIError.REMOVAL_ALL_NOT_ALLOWED, APIError.fetchErrorResponseFromErrorCode(4000168L)); + Assertions.assertEquals(APIError.SUBSCRIPTION_ALREADY_MIGRATED, APIError.fetchErrorResponseFromErrorCode(4000176L)); + Assertions.assertEquals(APIError.REVOKE_ON_INACTIVE_SUBSCRIPTION, APIError.fetchErrorResponseFromErrorCode(4000186L)); + Assertions.assertEquals(APIError.FREE_TRIAL_OFFER_MUST_USE_PERIOD_COUNT_OF_ONE, APIError.fetchErrorResponseFromErrorCode(4000223L)); + Assertions.assertEquals(APIError.UNAUTHORIZED, APIError.fetchErrorResponseFromErrorCode(4010000L)); + Assertions.assertEquals(APIError.SUBSCRIPTION_DOES_NOT_EXIST, APIError.fetchErrorResponseFromErrorCode(4030008L)); + Assertions.assertEquals(APIError.MIGRATION_NOT_ALLOWED_WHEN_PRICE_INCREASE_COMMUNICATED, APIError.fetchErrorResponseFromErrorCode(4030027L)); + Assertions.assertEquals(APIError.PRODUCT_NOT_FOUND, APIError.fetchErrorResponseFromErrorCode(4040016L)); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/client/AppStoreServerAPIClientTest.java b/src/test/java/com/apple/itunes/storekit/client/AppStoreServerAPIClientTest.java index ceda9c57..44f32c08 100644 --- a/src/test/java/com/apple/itunes/storekit/client/AppStoreServerAPIClientTest.java +++ b/src/test/java/com/apple/itunes/storekit/client/AppStoreServerAPIClientTest.java @@ -39,8 +39,13 @@ import com.apple.itunes.storekit.model.ExtendReasonCode; import com.apple.itunes.storekit.model.ExtendRenewalDateRequest; import com.apple.itunes.storekit.model.ExtendRenewalDateResponse; +import com.apple.itunes.storekit.model.GetCustomerGroupsResponse; +import com.apple.itunes.storekit.model.GetGroupMembersResponse; import com.apple.itunes.storekit.model.GetImageListResponse; import com.apple.itunes.storekit.model.GetMessageListResponse; +import com.apple.itunes.storekit.model.GroupEntry; +import com.apple.itunes.storekit.model.GroupMemberEntry; +import com.apple.itunes.storekit.model.GroupType; import com.apple.itunes.storekit.model.HeaderPosition; import com.apple.itunes.storekit.model.HistoryResponse; import com.apple.itunes.storekit.model.ImageSize; @@ -72,6 +77,8 @@ import com.apple.itunes.storekit.model.RefundHistoryResponse; import com.apple.itunes.storekit.model.RefundPreference; import com.apple.itunes.storekit.model.RefundPreferenceV1; +import com.apple.itunes.storekit.model.Role; +import com.apple.itunes.storekit.model.RoleEntry; import com.apple.itunes.storekit.model.SendAttemptItem; import com.apple.itunes.storekit.model.SendAttemptResult; import com.apple.itunes.storekit.model.SendTestNotificationResponse; @@ -90,6 +97,8 @@ import com.auth0.jwt.interfaces.DecodedJWT; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.fasterxml.jackson.databind.node.ObjectNode; import okhttp3.MediaType; import okhttp3.Protocol; import okhttp3.Request; @@ -138,12 +147,12 @@ public void testExtendRenewalDateForAllActiveSubscribers() throws IOException, A Assertions.assertEquals("com.example.productId", root.get("productId")); }); - MassExtendRenewalDateRequest extendRenewalDateRequest = new MassExtendRenewalDateRequest() - .extendByDays(45) - .extendReasonCode(ExtendReasonCode.CUSTOMER_SATISFACTION) - .requestIdentifier("fdf964a4-233b-486c-aac1-97d8d52688ac") - .storefrontCountryCodes(List.of("USA", "MEX")) - .productId("com.example.productId"); + MassExtendRenewalDateRequest extendRenewalDateRequest = new MassExtendRenewalDateRequest( + "fdf964a4-233b-486c-aac1-97d8d52688ac", + 45, + ExtendReasonCode.CUSTOMER_SATISFACTION, + "com.example.productId") + .storefrontCountryCodes(List.of("USA", "MEX")); MassExtendRenewalDateResponse massExtendRenewalDateResponse = client.extendRenewalDateForAllActiveSubscribers(extendRenewalDateRequest); @@ -176,10 +185,10 @@ public void testExtendSubscriptionRenewalDate() throws IOException, APIException Assertions.assertEquals("fdf964a4-233b-486c-aac1-97d8d52688ac", root.get("requestIdentifier")); }); - ExtendRenewalDateRequest extendRenewalDateRequest = new ExtendRenewalDateRequest() - .extendByDays(45) - .extendReasonCode(ExtendReasonCode.CUSTOMER_SATISFACTION) - .requestIdentifier("fdf964a4-233b-486c-aac1-97d8d52688ac"); + ExtendRenewalDateRequest extendRenewalDateRequest = new ExtendRenewalDateRequest( + 45, + ExtendReasonCode.CUSTOMER_SATISFACTION, + "fdf964a4-233b-486c-aac1-97d8d52688ac"); ExtendRenewalDateResponse extendRenewalDateResponse = client.extendSubscriptionRenewalDate("4124214", extendRenewalDateRequest); @@ -254,11 +263,11 @@ public void testGetRefundHistory() throws APIException, IOException { public void testGetStatusOfSubscriptionRenewalDateExtensions() throws APIException, IOException { AppStoreServerAPIClient client = getClientWithBody("models/getStatusOfSubscriptionRenewalDateExtensionsResponse.json", request -> { Assertions.assertEquals("GET", request.method()); - Assertions.assertEquals("/inApps/v1/subscriptions/extend/mass/20fba8a0-2b80-4a7d-a17f-85c1854727f8/com.example.product", request.url().encodedPath()); + Assertions.assertEquals("/inApps/v1/subscriptions/extend/mass/com.example.product/20fba8a0-2b80-4a7d-a17f-85c1854727f8", request.url().encodedPath()); Assertions.assertNull(request.body()); }); - MassExtendRenewalDateStatusResponse massExtendRenewalDateStatusResponse = client.getStatusOfSubscriptionRenewalDateExtensions("com.example.product", "20fba8a0-2b80-4a7d-a17f-85c1854727f8"); + MassExtendRenewalDateStatusResponse massExtendRenewalDateStatusResponse = client.getStatusOfSubscriptionRenewalDateExtensions("20fba8a0-2b80-4a7d-a17f-85c1854727f8", "com.example.product"); Assertions.assertNotNull(massExtendRenewalDateStatusResponse); Assertions.assertEquals("20fba8a0-2b80-4a7d-a17f-85c1854727f8", massExtendRenewalDateStatusResponse.getRequestIdentifier()); @@ -320,9 +329,7 @@ public void testGetNotificationHistory() throws APIException, IOException { Assertions.assertTrue((Boolean) root.get("onlyFailures")); }); - NotificationHistoryRequest notificationHistoryRequest = new NotificationHistoryRequest() - .startDate(1698148900000L) - .endDate(1698148950000L) + NotificationHistoryRequest notificationHistoryRequest = new NotificationHistoryRequest(1698148900000L, 1698148950000L) .notificationType(NotificationTypeV2.SUBSCRIBED) .notificationSubtype(Subtype.INITIAL_BUY) .transactionId("999733843") @@ -518,18 +525,18 @@ public void testSendConsumptionData() throws APIException, IOException { Assertions.assertEquals(3, ((Number) root.get("refundPreference")).intValue()); }); - ConsumptionRequestV1 consumptionRequest = new ConsumptionRequestV1() - .customerConsented(true) - .consumptionStatus(ConsumptionStatus.NOT_CONSUMED) - .platform(Platform.NON_APPLE) - .sampleContentProvided(false) - .deliveryStatus(DeliveryStatusV1.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE) - .appAccountToken(UUID.fromString("7389a31a-fb6d-4569-a2a6-db7d85d84813")) - .accountTenure(AccountTenure.THIRTY_DAYS_TO_NINETY_DAYS) - .playTime(PlayTime.ONE_DAY_TO_FOUR_DAYS) - .lifetimeDollarsRefunded(LifetimeDollarsRefunded.ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS) - .lifetimeDollarsPurchased(LifetimeDollarsPurchased.TWO_THOUSAND_DOLLARS_OR_GREATER) - .userStatus(UserStatus.LIMITED_ACCESS) + ConsumptionRequestV1 consumptionRequest = new ConsumptionRequestV1( + AccountTenure.THIRTY_DAYS_TO_NINETY_DAYS, + UUID.fromString("7389a31a-fb6d-4569-a2a6-db7d85d84813"), + ConsumptionStatus.NOT_CONSUMED, + true, + DeliveryStatusV1.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE, + LifetimeDollarsPurchased.TWO_THOUSAND_DOLLARS_OR_GREATER, + LifetimeDollarsRefunded.ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS, + Platform.NON_APPLE, + PlayTime.ONE_DAY_TO_FOUR_DAYS, + false, + UserStatus.LIMITED_ACCESS) .refundPreference(RefundPreferenceV1.NO_PREFERENCE); client.sendConsumptionData("49571273", consumptionRequest); @@ -569,17 +576,18 @@ public void testSendConsumptionDataWithNullAppAccountToken() throws APIException Assertions.assertEquals(3, ((Number) root.get("refundPreference")).intValue()); }); - ConsumptionRequestV1 consumptionRequest = new ConsumptionRequestV1() - .customerConsented(true) - .consumptionStatus(ConsumptionStatus.NOT_CONSUMED) - .platform(Platform.NON_APPLE) - .sampleContentProvided(false) - .deliveryStatus(DeliveryStatusV1.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE) - .accountTenure(AccountTenure.THIRTY_DAYS_TO_NINETY_DAYS) - .playTime(PlayTime.ONE_DAY_TO_FOUR_DAYS) - .lifetimeDollarsRefunded(LifetimeDollarsRefunded.ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS) - .lifetimeDollarsPurchased(LifetimeDollarsPurchased.TWO_THOUSAND_DOLLARS_OR_GREATER) - .userStatus(UserStatus.LIMITED_ACCESS) + ConsumptionRequestV1 consumptionRequest = new ConsumptionRequestV1( + AccountTenure.THIRTY_DAYS_TO_NINETY_DAYS, + null, + ConsumptionStatus.NOT_CONSUMED, + true, + DeliveryStatusV1.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE, + LifetimeDollarsPurchased.TWO_THOUSAND_DOLLARS_OR_GREATER, + LifetimeDollarsRefunded.ONE_THOUSAND_DOLLARS_TO_ONE_THOUSAND_NINE_HUNDRED_NINETY_NINE_DOLLARS_AND_NINETY_NINE_CENTS, + Platform.NON_APPLE, + PlayTime.ONE_DAY_TO_FOUR_DAYS, + false, + UserStatus.LIMITED_ACCESS) .refundPreference(RefundPreferenceV1.NO_PREFERENCE); client.sendConsumptionData("49571273", consumptionRequest); @@ -603,7 +611,7 @@ public void testUploadImage() throws IOException, APIException { Assertions.assertArrayEquals(new byte[]{1, 2, 3}, bytes); }); - client.uploadImage(UUID.fromString("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890"), new byte[]{1, 2, 3}); + client.uploadImage(UUID.fromString("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890"), new byte[]{1, 2, 3}, null); } @Test @@ -737,8 +745,7 @@ public void testConfigureDefaultMessage() throws IOException, APIException { Assertions.assertEquals("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890", root.get("messageIdentifier")); }); - DefaultConfigurationRequest defaultConfigurationRequest = new DefaultConfigurationRequest() - .messageIdentifier(UUID.fromString("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890")); + DefaultConfigurationRequest defaultConfigurationRequest = new DefaultConfigurationRequest(UUID.fromString("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890")); client.configureDefaultMessage("com.example.product", "en-US", defaultConfigurationRequest); } @@ -894,6 +901,8 @@ public void testHeaders() throws APIException, IOException { Assertions.assertEquals("keyId", token.getKeyId()); Assertions.assertEquals("com.example", token.getClaim("bid").asString()); Assertions.assertEquals("ES256", token.getAlgorithm()); + Assertions.assertNotNull(token.getIssuedAtAsInstant()); + Assertions.assertTrue(token.getExpiresAtAsInstant().isAfter(token.getIssuedAtAsInstant())); }); client.getTransactionInfo("1234"); @@ -1095,7 +1104,7 @@ public void testFamilyTransactionNotSupportedError() throws IOException { client.setAppAccountToken("1234", updateAppAccountTokenRequest); } catch (APIException e) { Assertions.assertEquals(400, e.getHttpStatusCode()); - Assertions.assertEquals(APIError.FAMILY_TRANSACTION_NOT_SUPPORTED_ERROR, e.getApiError()); + Assertions.assertEquals(APIError.FAMILY_TRANSACTION_NOT_SUPPORTED, e.getApiError()); return; } Assertions.fail(); @@ -1110,7 +1119,7 @@ public void testTransactionIdNotOriginalTransactionId() throws IOException { client.setAppAccountToken("1234", updateAppAccountTokenRequest); } catch (APIException e) { Assertions.assertEquals(400, e.getHttpStatusCode()); - Assertions.assertEquals(APIError.TRANSACTION_ID_IS_NOT_ORIGINAL_TRANSACTION_ID_ERROR, e.getApiError()); + Assertions.assertEquals(APIError.TRANSACTION_ID_IS_NOT_ORIGINAL_TRANSACTION_ID, e.getApiError()); return; } Assertions.fail(); @@ -1154,7 +1163,7 @@ public void testGetAppTransactionInfoAppTransactionDoesNotExistError() throws IO client.getAppTransactionInfo("nonexistent_transaction_id"); } catch (APIException e) { Assertions.assertEquals(404, e.getHttpStatusCode()); - Assertions.assertEquals(APIError.APP_TRANSACTION_DOES_NOT_EXIST_ERROR, e.getApiError()); + Assertions.assertEquals(APIError.APP_TRANSACTION_DOES_NOT_EXIST, e.getApiError()); Assertions.assertEquals(4040019L, e.getRawApiError()); Assertions.assertEquals("No AppTransaction exists for the customer.", e.getApiErrorMessage()); return; @@ -1291,7 +1300,7 @@ public void testInitiatePerformanceTest() throws IOException, APIException { PerformanceTestResponse response = client.initiatePerformanceTest(performanceTestRequest); Assertions.assertNotNull(response); - Assertions.assertEquals("c4b87a1d-2e3f-4a5b-9c6d-7e8f9a0b1c2d", response.getRequestId()); + Assertions.assertEquals(UUID.fromString("c4b87a1d-2e3f-4a5b-9c6d-7e8f9a0b1c2d"), response.getRequestId()); PerformanceTestConfig config = response.getConfig(); Assertions.assertNotNull(config); Assertions.assertEquals(10L, config.getMaxConcurrentRequests()); @@ -1309,7 +1318,7 @@ public void testGetPerformanceTestResults() throws IOException, APIException { Assertions.assertNull(request.body()); }); - PerformanceTestResultResponse response = client.getPerformanceTestResults("c4b87a1d-2e3f-4a5b-9c6d-7e8f9a0b1c2d"); + PerformanceTestResultResponse response = client.getPerformanceTestResults(UUID.fromString("C4B87A1D-2E3F-4A5B-9C6D-7E8F9A0B1C2D")); Assertions.assertNotNull(response); PerformanceTestConfig config = response.getConfig(); @@ -1335,6 +1344,42 @@ public void testGetPerformanceTestResults() throws IOException, APIException { Assertions.assertEquals(Map.of("TIMED_OUT", 1, "NO_RESPONSE", 1), response.getRawFailures()); } + @Test + public void testGetPerformanceTestResultsWithMissingRequiredField() throws IOException { + ObjectNode body = (ObjectNode) new ObjectMapper().readTree(TestingUtility.readFile("models/performanceTestResultResponse.json")); + body.remove("target"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body.toString(), request -> {}); + + APIException e = Assertions.assertThrows(APIException.class, () -> client.getPerformanceTestResults(UUID.fromString("c4b87a1d-2e3f-4a5b-9c6d-7e8f9a0b1c2d"))); + + Assertions.assertEquals(200, e.getHttpStatusCode()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + Assertions.assertTrue(e.getCause().getMessage().contains("'target'"), e.getCause().getMessage()); + } + + @Test + public void testGetDefaultMessageWithMissingRequiredField() throws IOException { + AppStoreServerAPIClient client = getAppStoreServerAPIClient("{}", request -> {}); + + APIException e = Assertions.assertThrows(APIException.class, () -> client.getDefaultMessage("com.example.product", "en-US")); + + Assertions.assertEquals(200, e.getHttpStatusCode()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + } + + @Test + public void testCancelSubscriptionWithMissingRequiredField() throws IOException { + AppStoreServerAPIClient client = getAppStoreServerAPIClient("{\"signedTransactionInfo\": \"signed_transaction_info\"}", request -> {}); + AdvancedCommerceSubscriptionCancelRequest cancelRequest = new AdvancedCommerceSubscriptionCancelRequest( + new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c"))); + + APIException e = Assertions.assertThrows(APIException.class, () -> client.cancelSubscription("4124214", cancelRequest)); + + Assertions.assertEquals(200, e.getHttpStatusCode()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + Assertions.assertTrue(e.getCause().getMessage().contains("'signedRenewalInfo'"), e.getCause().getMessage()); + } + @Test public void testChangeSubscriptionPrice() throws IOException, APIException { AppStoreServerAPIClient client = getClientWithBody("models/advancedCommerceSubscriptionPriceChangeResponse.json", request -> { @@ -1442,9 +1487,9 @@ public void testRevokeSubscription() throws IOException, APIException { AdvancedCommerceSubscriptionRevokeRequest revokeRequest = new AdvancedCommerceSubscriptionRevokeRequest( new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c")), - true, AdvancedCommerceRefundReason.UNINTENDED_PURCHASE, - AdvancedCommerceRefundType.PRORATED.getValue()) + true, + AdvancedCommerceRefundType.PRORATED) .storefront("USA"); AdvancedCommerceSubscriptionRevokeResponse response = client.revokeSubscription("4124214", revokeRequest); @@ -1486,9 +1531,9 @@ public void testRequestTransactionRefund() throws IOException, APIException { }); AdvancedCommerceRequestRefundRequest requestRefundRequest = new AdvancedCommerceRequestRefundRequest( + new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c")), List.of(new AdvancedCommerceRequestRefundItem("AD_FREE_1M", AdvancedCommerceRefundReason.UNSATISFIED_WITH_PURCHASE, AdvancedCommerceRefundType.FULL, true)), - true, - new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c"))) + true) .currency("USD") .storefront("USA"); @@ -1596,6 +1641,408 @@ public void testMigrateSubscriptionToAdvancedCommerceAPI() throws IOException, A Assertions.assertEquals("signed_transaction_info_value", response.getSignedTransactionInfo()); } + @Test + public void testPathParametersArePercentEncoded() throws IOException, APIException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionInfoResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/inApps/v1/transactions/..%2F..%2Fv1%2Fnotifications%2Ftest%3Ffoo%3Dbar%23fragment", request.url().encodedPath()); + Assertions.assertNull(request.url().query()); + Assertions.assertNull(request.url().fragment()); + }); + + client.getTransactionInfo("../../v1/notifications/test?foo=bar#fragment"); + } + + @Test + public void testDotAndEmptyPathParametersAreRejected() throws IOException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionInfoResponse.json", request -> Assertions.fail()); + + for (String pathParameter : List.of("..", ".", "")) { + Assertions.assertThrows(IllegalArgumentException.class, () -> client.getTransactionInfo(pathParameter)); + Assertions.assertThrows(IllegalArgumentException.class, () -> client.getDefaultMessage("com.example", pathParameter)); + } + } + + @Test + public void testMultiplePathParametersArePercentEncoded() throws IOException, APIException { + AppStoreServerAPIClient client = getClientWithBody("models/getDefaultMessageResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/inApps/v1/messaging/default/com.example%2Fproduct/en%20US", request.url().encodedPath()); + }); + + client.getDefaultMessage("com.example/product", "en US"); + } + + @Test + public void testGetTransactionHistoryWithNullRequest() throws IOException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionHistoryResponse.json", request -> Assertions.fail()); + + NullPointerException exception = Assertions.assertThrows(NullPointerException.class, () -> client.getTransactionHistory("1234", null, null, GetTransactionHistoryVersion.V2)); + Assertions.assertEquals("transactionHistoryRequest cannot be null", exception.getMessage()); + } + + @Test + public void testAPIErrorWithUnknownFields() throws IOException { + String body = "{\"errorCode\": 4040010, \"errorMessage\": \"Transaction id not found.\", \"newField\": {\"key\": \"value\"}}"; + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 404); + try { + client.getTransactionInfo("1234"); + } catch (APIException e) { + Assertions.assertEquals(404, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.TRANSACTION_ID_NOT_FOUND, e.getApiError()); + Assertions.assertEquals(4040010L, e.getRawApiError()); + Assertions.assertEquals("Transaction id not found.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testAPIErrorWithoutErrorCode() throws IOException { + String body = "{\"errorMessage\": \"Testing error.\"}"; + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 400); + try { + client.getTransactionInfo("1234"); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertNull(e.getApiError()); + Assertions.assertNull(e.getRawApiError()); + Assertions.assertEquals("Testing error.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testAPIErrorWithEmptyBody() throws IOException { + AppStoreServerAPIClient client = getAppStoreServerAPIClient("", request -> {}, 500); + try { + client.getTransactionInfo("1234"); + } catch (APIException e) { + Assertions.assertEquals(500, e.getHttpStatusCode()); + Assertions.assertNull(e.getApiError()); + Assertions.assertNull(e.getRawApiError()); + Assertions.assertNull(e.getApiErrorMessage()); + Assertions.assertNull(e.getCause()); + return; + } + Assertions.fail(); + } + + @Test + public void testAPIErrorWithNullBody() throws IOException { + AppStoreServerAPIClient client = getAppStoreServerAPIClient("null", request -> {}, 500); + try { + client.getTransactionInfo("1234"); + } catch (APIException e) { + Assertions.assertEquals(500, e.getHttpStatusCode()); + Assertions.assertNull(e.getApiError()); + Assertions.assertNull(e.getRawApiError()); + Assertions.assertNull(e.getApiErrorMessage()); + Assertions.assertNull(e.getCause()); + return; + } + Assertions.fail(); + } + + @Test + public void testConsumptionPercentageOutOfRangeError() throws IOException { + String body = TestingUtility.readFile("models/consumptionPercentageOutOfRangeError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 400); + try { + ConsumptionRequest consumptionRequest = new ConsumptionRequest(true, DeliveryStatus.DELIVERED, false) + .consumptionPercentage(100000); + client.sendConsumptionInformation("49571273", consumptionRequest); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.CONSUMPTION_PERCENTAGE_OUT_OF_RANGE, e.getApiError()); + Assertions.assertEquals(4000207L, e.getRawApiError()); + Assertions.assertEquals("Invalid request. The consumption percentage is outside the valid range.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testAdvancedCommerceSubscriptionDoesNotExistError() throws IOException { + String body = TestingUtility.readFile("models/subscriptionDoesNotExistError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> { + Assertions.assertEquals("/advancedCommerce/v1/subscription/cancel/4124214", request.url().encodedPath()); + }, 403); + try { + AdvancedCommerceSubscriptionCancelRequest cancelRequest = new AdvancedCommerceSubscriptionCancelRequest( + new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c"))); + client.cancelSubscription("4124214", cancelRequest); + } catch (APIException e) { + Assertions.assertEquals(403, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.SUBSCRIPTION_DOES_NOT_EXIST, e.getApiError()); + Assertions.assertEquals(4030008L, e.getRawApiError()); + Assertions.assertEquals("The subscription doesn't exist.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testAdvancedCommerceRepeatedRequestReferenceIdError() throws IOException { + String body = "{\"errorCode\": 4000097, \"errorMessage\": \"The requestReferenceId was repeated.\"}"; + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> { + Assertions.assertEquals("/advancedCommerce/v1/subscription/revoke/4124214", request.url().encodedPath()); + }, 400); + try { + AdvancedCommerceSubscriptionRevokeRequest revokeRequest = new AdvancedCommerceSubscriptionRevokeRequest( + new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c")), + AdvancedCommerceRefundReason.UNINTENDED_PURCHASE, + true, + AdvancedCommerceRefundType.PRORATED); + client.revokeSubscription("4124214", revokeRequest); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.REPEATED_REQUEST_REFERENCE_ID, e.getApiError()); + Assertions.assertEquals(4000097L, e.getRawApiError()); + Assertions.assertEquals("The requestReferenceId was repeated.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testProductionAndSandboxBaseUrls() throws IOException, APIException { + Map expectedHosts = Map.of( + Environment.PRODUCTION, "api.storekit.apple.com", + Environment.SANDBOX, "api.storekit-sandbox.apple.com"); + String body = TestingUtility.readFile("models/transactionInfoResponse.json"); + for (Map.Entry expectedHost : expectedHosts.entrySet()) { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + AppStoreServerAPIClient client = new AppStoreServerAPIClient(new String(key.readAllBytes()), "keyId", "issuerId", "com.example", expectedHost.getKey()) { + @Override + protected Response getResponse(Request request) { + Assertions.assertEquals("https", request.url().scheme()); + Assertions.assertEquals(expectedHost.getValue(), request.url().host()); + Assertions.assertEquals("/inApps/v1/transactions/1234", request.url().encodedPath()); + return new Response.Builder() + .body(ResponseBody.create(body, MediaType.parse("application/json"))) + .code(200) + .request(request) + .protocol(Protocol.HTTP_1_1) + .message("") + .build(); + } + }; + Assertions.assertNotNull(client.getTransactionInfo("1234")); + } + } + } + + @Test + public void testGetCustomerGroups() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/getCustomerGroupsResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/groups/v1/currentGroups/1234", request.url().encodedPath()); + Assertions.assertEquals(0, request.url().querySize()); + Assertions.assertNull(request.body()); + }); + + GetCustomerGroupsResponse getCustomerGroupsResponse = client.getCustomerGroups("1234"); + + Assertions.assertNotNull(getCustomerGroupsResponse); + GetCustomerGroupsResponse expectedGetCustomerGroupsResponse = new GetCustomerGroupsResponse() + .groups(List.of( + new GroupEntry() + .groupId("900000000000000000") + .groupType(GroupType.ORGANIZATION) + .roles(List.of( + new RoleEntry() + .productId("example.productId.one") + .role(Role.ADMIN), + new RoleEntry() + .productId("example.productId.two") + .role(Role.NONE) + )), + new GroupEntry() + .groupId("900000000000000001") + .groupType(GroupType.CONSUMER) + )); + Assertions.assertEquals(expectedGetCustomerGroupsResponse, getCustomerGroupsResponse); + GroupEntry organizationGroup = getCustomerGroupsResponse.getGroups().get(0); + Assertions.assertEquals("900000000000000000", organizationGroup.getGroupId()); + Assertions.assertEquals(GroupType.ORGANIZATION, organizationGroup.getGroupType()); + Assertions.assertEquals("ORGANIZATION", organizationGroup.getRawGroupType()); + Assertions.assertEquals("example.productId.one", organizationGroup.getRoles().get(0).getProductId()); + Assertions.assertEquals(Role.ADMIN, organizationGroup.getRoles().get(0).getRole()); + Assertions.assertEquals("ADMIN", organizationGroup.getRoles().get(0).getRawRole()); + Assertions.assertEquals("example.productId.two", organizationGroup.getRoles().get(1).getProductId()); + Assertions.assertEquals(Role.NONE, organizationGroup.getRoles().get(1).getRole()); + Assertions.assertEquals("NONE", organizationGroup.getRoles().get(1).getRawRole()); + GroupEntry consumerGroup = getCustomerGroupsResponse.getGroups().get(1); + Assertions.assertEquals("900000000000000001", consumerGroup.getGroupId()); + Assertions.assertEquals(GroupType.CONSUMER, consumerGroup.getGroupType()); + Assertions.assertEquals("CONSUMER", consumerGroup.getRawGroupType()); + Assertions.assertNull(consumerGroup.getRoles()); + } + + @Test + public void testGetCustomerGroupsWithUnknownValues() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/getCustomerGroupsResponseWithUnknownValues.json", request -> {}); + + GetCustomerGroupsResponse getCustomerGroupsResponse = client.getCustomerGroups("1234"); + + Assertions.assertNotNull(getCustomerGroupsResponse); + Assertions.assertEquals(Map.of("unknownField", "unknown_value"), getCustomerGroupsResponse.getUnknownFields()); + GroupEntry groupEntry = getCustomerGroupsResponse.getGroups().get(0); + Assertions.assertEquals("900000000000000002", groupEntry.getGroupId()); + Assertions.assertNull(groupEntry.getGroupType()); + Assertions.assertEquals("UNKNOWN_GROUP_TYPE", groupEntry.getRawGroupType()); + Assertions.assertEquals(Map.of("unknownGroupField", "unknown_group_value"), groupEntry.getUnknownFields()); + RoleEntry roleEntry = groupEntry.getRoles().get(0); + Assertions.assertEquals("example.productId.three", roleEntry.getProductId()); + Assertions.assertNull(roleEntry.getRole()); + Assertions.assertEquals("UNKNOWN_ROLE", roleEntry.getRawRole()); + Assertions.assertEquals(Map.of("unknownRoleField", "unknown_role_value"), roleEntry.getUnknownFields()); + } + + @Test + public void testGetCustomerGroupsInvalidTransactionIdError() throws IOException { + String body = TestingUtility.readFile("models/invalidTransactionIdError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 400); + try { + client.getCustomerGroups("invalid_transaction_id"); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.INVALID_TRANSACTION_ID, e.getApiError()); + Assertions.assertEquals(4000006L, e.getRawApiError()); + Assertions.assertEquals("Invalid transaction id.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testGetCustomerGroupsTransactionIdNotFoundError() throws IOException { + String body = TestingUtility.readFile("models/transactionIdNotFoundError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 404); + try { + client.getCustomerGroups("not_found_transaction_id"); + } catch (APIException e) { + Assertions.assertEquals(404, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.TRANSACTION_ID_NOT_FOUND, e.getApiError()); + Assertions.assertEquals(4040010L, e.getRawApiError()); + Assertions.assertEquals("Transaction id not found.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testGetGroupMembers() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/getGroupMembersResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/groups/v1/group/900000000000000000", request.url().encodedPath()); + Assertions.assertEquals(2, request.url().querySize()); + Assertions.assertEquals("pagination_token_input", request.url().queryParameter("paginationToken")); + Assertions.assertEquals("50", request.url().queryParameter("limit")); + Assertions.assertNull(request.body()); + }); + + GetGroupMembersResponse getGroupMembersResponse = client.getGroupMembers("900000000000000000", "pagination_token_input", 50); + + Assertions.assertNotNull(getGroupMembersResponse); + GetGroupMembersResponse expectedGetGroupMembersResponse = new GetGroupMembersResponse() + .members(List.of( + new GroupMemberEntry() + .appTransactionId("700000000000000000"), + new GroupMemberEntry() + .appTransactionId("700000000000000001") + )) + .paginationToken("pagination_token_output") + .hasMore(true); + Assertions.assertEquals(expectedGetGroupMembersResponse, getGroupMembersResponse); + Assertions.assertEquals("700000000000000000", getGroupMembersResponse.getMembers().get(0).getAppTransactionId()); + Assertions.assertEquals("700000000000000001", getGroupMembersResponse.getMembers().get(1).getAppTransactionId()); + Assertions.assertEquals("pagination_token_output", getGroupMembersResponse.getPaginationToken()); + Assertions.assertTrue(getGroupMembersResponse.getHasMore()); + } + + @Test + public void testGetGroupMembersWithoutOptionalParameters() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/getGroupMembersResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/groups/v1/group/900000000000000000", request.url().encodedPath()); + Assertions.assertEquals(0, request.url().querySize()); + Assertions.assertNull(request.body()); + }); + + GetGroupMembersResponse getGroupMembersResponse = client.getGroupMembers("900000000000000000", null, null); + + Assertions.assertNotNull(getGroupMembersResponse); + Assertions.assertEquals(2, getGroupMembersResponse.getMembers().size()); + } + + @Test + public void testGetGroupMembersInvalidGroupIdError() throws IOException { + String body = TestingUtility.readFile("models/invalidGroupIdError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 400); + try { + client.getGroupMembers("invalid_group_id", null, null); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.INVALID_GROUP_ID, e.getApiError()); + Assertions.assertEquals(4000225L, e.getRawApiError()); + Assertions.assertEquals("Invalid request. The group ID is invalid.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testGetGroupMembersInvalidLimitError() throws IOException { + String body = TestingUtility.readFile("models/invalidLimitError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 400); + try { + client.getGroupMembers("900000000000000000", null, 101); + } catch (APIException e) { + Assertions.assertEquals(400, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.INVALID_LIMIT, e.getApiError()); + Assertions.assertEquals(4000004L, e.getRawApiError()); + Assertions.assertEquals("Invalid request limit.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testGetGroupMembersGroupNotFoundError() throws IOException { + String body = TestingUtility.readFile("models/groupNotFoundError.json"); + AppStoreServerAPIClient client = getAppStoreServerAPIClient(body, request -> {}, 404); + try { + client.getGroupMembers("900000000000000009", null, null); + } catch (APIException e) { + Assertions.assertEquals(404, e.getHttpStatusCode()); + Assertions.assertEquals(APIError.GROUP_NOT_FOUND, e.getApiError()); + Assertions.assertEquals(4040022L, e.getRawApiError()); + Assertions.assertEquals("Group not found.", e.getApiErrorMessage()); + return; + } + Assertions.fail(); + } + + @Test + public void testGroupPathParametersArePercentEncoded() throws IOException, APIException { + AppStoreServerAPIClient customerGroupsClient = getClientWithBody("models/getCustomerGroupsResponse.json", request -> { + Assertions.assertEquals("/groups/v1/currentGroups/..%2F1234%3Ffoo%3Dbar", request.url().encodedPath()); + Assertions.assertNull(request.url().query()); + }); + customerGroupsClient.getCustomerGroups("../1234?foo=bar"); + + AppStoreServerAPIClient groupMembersClient = getClientWithBody("models/getGroupMembersResponse.json", request -> { + Assertions.assertEquals("/groups/v1/group/..%2F9000%23fragment", request.url().encodedPath()); + Assertions.assertNull(request.url().query()); + Assertions.assertNull(request.url().fragment()); + }); + groupMembersClient.getGroupMembers("../9000#fragment", null, null); + } + public AppStoreServerAPIClient getClientWithBody(String path, Consumer requestVerifier) throws IOException { String body = TestingUtility.readFile(path); return getAppStoreServerAPIClient(body, requestVerifier); diff --git a/src/test/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorTest.java b/src/test/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorTest.java index bb82c492..ccd59a70 100644 --- a/src/test/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorTest.java +++ b/src/test/java/com/apple/itunes/storekit/client/BearerTokenAuthenticatorTest.java @@ -2,10 +2,15 @@ package com.apple.itunes.storekit.client; +import com.auth0.jwt.JWT; +import com.auth0.jwt.interfaces.DecodedJWT; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.InputStream; +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; class BearerTokenAuthenticatorTest { @@ -18,4 +23,22 @@ void testCreatingToken() throws Exception { Assertions.assertNotNull(token); } } + + @Test + void testTokenIncludesIssuedAt() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + var tokenGenerator = new BearerTokenAuthenticator(new String(key.readAllBytes()), "keyId", "issuerId", "bundleId"); + Instant before = Instant.now().truncatedTo(ChronoUnit.SECONDS); + DecodedJWT token = JWT.decode(tokenGenerator.generateToken()); + Instant after = Instant.now(); + Instant issuedAt = token.getIssuedAtAsInstant(); + Assertions.assertNotNull(issuedAt); + Assertions.assertFalse(issuedAt.isBefore(before)); + Assertions.assertFalse(issuedAt.isAfter(after)); + Assertions.assertEquals(Duration.ofMinutes(5), Duration.between(issuedAt, token.getExpiresAtAsInstant())); + Assertions.assertEquals("issuerId", token.getIssuer()); + Assertions.assertEquals("bundleId", token.getClaim("bid").asString()); + } + } } diff --git a/src/test/java/com/apple/itunes/storekit/client/TransactionHistoryRequestQueryTest.java b/src/test/java/com/apple/itunes/storekit/client/TransactionHistoryRequestQueryTest.java new file mode 100644 index 00000000..58391f35 --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/client/TransactionHistoryRequestQueryTest.java @@ -0,0 +1,86 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.client; + +import com.apple.itunes.storekit.model.Environment; +import com.apple.itunes.storekit.model.HistoryResponse; +import com.apple.itunes.storekit.model.InAppOwnershipType; +import com.apple.itunes.storekit.model.TransactionHistoryRequest; +import com.apple.itunes.storekit.util.TestingUtility; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.function.Consumer; + +public class TransactionHistoryRequestQueryTest { + + @Test + public void testGetTransactionHistoryWithRawInAppOwnershipType() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionHistoryResponse.json", request -> { + Assertions.assertEquals("GET", request.method()); + Assertions.assertEquals("/inApps/v2/history/1234", request.url().encodedPath()); + Assertions.assertEquals("NEW_OWNERSHIP_TYPE", request.url().queryParameter("inAppOwnershipType")); + }); + + TransactionHistoryRequest request = new TransactionHistoryRequest(); + request.setRawInAppOwnershipType("NEW_OWNERSHIP_TYPE"); + + HistoryResponse historyResponse = client.getTransactionHistory("1234", null, request, GetTransactionHistoryVersion.V2); + + Assertions.assertNotNull(historyResponse); + } + + @Test + public void testGetTransactionHistoryWithInAppOwnershipType() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionHistoryResponse.json", request -> { + Assertions.assertEquals("/inApps/v2/history/1234", request.url().encodedPath()); + Assertions.assertEquals("PURCHASED", request.url().queryParameter("inAppOwnershipType")); + }); + + TransactionHistoryRequest request = new TransactionHistoryRequest() + .inAppOwnershipType(InAppOwnershipType.PURCHASED); + + HistoryResponse historyResponse = client.getTransactionHistory("1234", null, request, GetTransactionHistoryVersion.V2); + + Assertions.assertNotNull(historyResponse); + } + + @Test + public void testGetTransactionHistoryWithoutInAppOwnershipType() throws APIException, IOException { + AppStoreServerAPIClient client = getClientWithBody("models/transactionHistoryResponse.json", request -> { + Assertions.assertEquals("/inApps/v2/history/1234", request.url().encodedPath()); + Assertions.assertNull(request.url().queryParameter("inAppOwnershipType")); + }); + + HistoryResponse historyResponse = client.getTransactionHistory("1234", null, new TransactionHistoryRequest(), GetTransactionHistoryVersion.V2); + + Assertions.assertNotNull(historyResponse); + } + + private AppStoreServerAPIClient getClientWithBody(String path, Consumer requestVerifier) throws IOException { + String body = TestingUtility.readFile(path); + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + return new AppStoreServerAPIClient(new String(key.readAllBytes()), "keyId", "issuerId", "com.example", Environment.LOCAL_TESTING) { + @Override + protected Response getResponse(Request request) { + requestVerifier.accept(request); + return new Response.Builder() + .body(ResponseBody.create(body, MediaType.parse("application/json"))) + .code(200) + .request(request) + .protocol(Protocol.HTTP_1_1) + .message("") + .build(); + } + }; + } + } +} diff --git a/src/test/java/com/apple/itunes/storekit/migration/ReceiptUtilityTest.java b/src/test/java/com/apple/itunes/storekit/migration/ReceiptUtilityTest.java index a20b48a5..7c40ff85 100644 --- a/src/test/java/com/apple/itunes/storekit/migration/ReceiptUtilityTest.java +++ b/src/test/java/com/apple/itunes/storekit/migration/ReceiptUtilityTest.java @@ -7,6 +7,9 @@ import org.junit.jupiter.api.Test; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Base64; public class ReceiptUtilityTest { @@ -33,6 +36,65 @@ public void testXcodeAppReceiptExtractionWithTransactions() throws IOException { Assertions.assertEquals(APP_RECEIPT_EXPECTED_TRANSACTION_ID, extractedTransactionId); } + @Test + public void testAppReceiptExtractionWithEmptyReceipt() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt("")); + } + + @Test + public void testAppReceiptExtractionWithNonSequenceRoot() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt("AgEB")); + } + + @Test + public void testAppReceiptExtractionWithNonPKCS7Sequence() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt("MAMCAQE=")); + } + + @Test + public void testAppReceiptExtractionWithInvalidBase64() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt("not a receipt!")); + } + + @Test + public void testAppReceiptExtractionWithUnpaddedBase64() throws IOException { + String receipt = TestingUtility.readFile("xcode/xcode-app-receipt-with-transaction"); + Assertions.assertTrue(receipt.endsWith("=")); + String unpaddedReceipt = receipt.replace("=", ""); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt(unpaddedReceipt)); + } + + @Test + public void testAppReceiptExtractionWithUrlSafeBase64() throws IOException { + byte[] receipt = Base64.getDecoder().decode(TestingUtility.readFile("xcode/xcode-app-receipt-with-transaction")); + String urlSafeReceipt = Base64.getUrlEncoder().encodeToString(receipt); + Assertions.assertTrue(urlSafeReceipt.contains("-") || urlSafeReceipt.contains("_")); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt(urlSafeReceipt)); + } + + @Test + public void testAppReceiptExtractionWithTruncatedReceipt() throws IOException { + byte[] receipt = Base64.getDecoder().decode(TestingUtility.readFile("xcode/xcode-app-receipt-with-transaction")); + String truncatedReceipt = Base64.getEncoder().encodeToString(Arrays.copyOf(receipt, receipt.length / 2)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt(truncatedReceipt)); + } + + @Test + public void testAppReceiptExtractionWithMalformedSignedData() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromAppReceipt("MA4GCSqGSIb3DQEHAgIBAQ==")); + } + @Test public void testTransactionReceiptExtraction() throws IOException { String receipt = TestingUtility.readFile("mock_signed_data/legacyTransaction"); @@ -42,4 +104,98 @@ public void testTransactionReceiptExtraction() throws IOException { Assertions.assertEquals(TRANSACTION_RECEIPT_EXPECTED_TRANSACTION_ID, extractedTransactionId); } + + @Test + public void testTransactionReceiptExtractionWithMissingPurchaseInfo() { + String receipt = Base64.getEncoder().encodeToString("{\n\t\"signature\" = \"abc\";\n}".getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithInvalidBase64() { + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt("not a receipt!")); + } + + @Test + public void testTransactionReceiptExtractionWithInvalidPurchaseInfo() { + String receipt = Base64.getEncoder().encodeToString("{\n\t\"purchase-info\" = \"a\";\n}".getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithUnpaddedBase64() throws IOException { + String receipt = TestingUtility.readFile("mock_signed_data/legacyTransaction"); + Assertions.assertTrue(receipt.endsWith("=")); + String unpaddedReceipt = receipt.replace("=", ""); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(unpaddedReceipt)); + } + + @Test + public void testTransactionReceiptExtractionWithUnpaddedPurchaseInfo() { + String receipt = Base64.getEncoder().encodeToString("{\n\t\"purchase-info\" = \"YQ\";\n}".getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithUnpaddedPurchaseInfoContainingTransactionId() { + String purchaseInfo = Base64.getEncoder().withoutPadding().encodeToString("{\n\t\"transaction-id\" = \"1234\";\n}".getBytes(StandardCharsets.UTF_8)); + Assertions.assertNotEquals(0, purchaseInfo.length() % 4); + String receipt = Base64.getEncoder().encodeToString(("{\n\t\"purchase-info\" = \"" + purchaseInfo + "\";\n}").getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithPurchaseInfoNotUTF8() { + String purchaseInfo = Base64.getEncoder().encodeToString(new byte[]{(byte) 0xff, (byte) 0xfe, (byte) 0xfd}); + String receipt = Base64.getEncoder().encodeToString(("{\n\t\"purchase-info\" = \"" + purchaseInfo + "\";\n}").getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithPurchaseInfoContainingTransactionIdAndInvalidUTF8() { + byte[] transactionId = "{\n\t\"transaction-id\" = \"123\";\n}".getBytes(StandardCharsets.UTF_8); + byte[] purchaseInfoBytes = Arrays.copyOf(transactionId, transactionId.length + 1); + purchaseInfoBytes[transactionId.length] = (byte) 0xff; + String purchaseInfo = Base64.getEncoder().encodeToString(purchaseInfoBytes); + String receipt = Base64.getEncoder().encodeToString(("{\n\t\"purchase-info\" = \"" + purchaseInfo + "\";\n}").getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithInvalidUTF8() { + String purchaseInfo = Base64.getEncoder().encodeToString("{\n\t\"transaction-id\" = \"123\";\n}".getBytes(StandardCharsets.UTF_8)); + byte[] topLevel = ("{\n\t\"purchase-info\" = \"" + purchaseInfo + "\";\n}").getBytes(StandardCharsets.UTF_8); + byte[] topLevelWithInvalidByte = Arrays.copyOf(topLevel, topLevel.length + 1); + topLevelWithInvalidByte[topLevel.length] = (byte) 0xff; + String receipt = Base64.getEncoder().encodeToString(topLevelWithInvalidByte); + String validReceipt = Base64.getEncoder().encodeToString(topLevel); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertEquals("123", util.extractTransactionIdFromTransactionReceipt(validReceipt)); + Assertions.assertThrows(IllegalArgumentException.class, () -> util.extractTransactionIdFromTransactionReceipt(receipt)); + } + + @Test + public void testTransactionReceiptExtractionWithNoTransactionId() { + String purchaseInfo = Base64.getEncoder().encodeToString("{\n\t\"product-id\" = \"com.example.product\";\n}".getBytes(StandardCharsets.UTF_8)); + String receipt = Base64.getEncoder().encodeToString(("{\n\t\"purchase-info\" = \"" + purchaseInfo + "\";\n}").getBytes(StandardCharsets.UTF_8)); + + ReceiptUtility util = new ReceiptUtility(); + Assertions.assertNull(util.extractTransactionIdFromTransactionReceipt(receipt)); + } } diff --git a/src/test/java/com/apple/itunes/storekit/model/AdvancedCommerceModelsTest.java b/src/test/java/com/apple/itunes/storekit/model/AdvancedCommerceModelsTest.java index 6161df85..5d986d05 100644 --- a/src/test/java/com/apple/itunes/storekit/model/AdvancedCommerceModelsTest.java +++ b/src/test/java/com/apple/itunes/storekit/model/AdvancedCommerceModelsTest.java @@ -3,14 +3,19 @@ package com.apple.itunes.storekit.model; import com.apple.itunes.storekit.util.TestingUtility; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; public class AdvancedCommerceModelsTest { @@ -250,7 +255,18 @@ public void testAdvancedCommerceRequestRefundItem() throws Exception { Assertions.assertEquals(AdvancedCommerceRefundReason.LEGAL, item.getRefundReason()); Assertions.assertEquals(AdvancedCommerceRefundType.FULL, item.getRefundType()); Assertions.assertEquals(true, item.getRevoke()); - Assertions.assertEquals(5000, item.getRefundAmount()); + Assertions.assertEquals(5000L, item.getRefundAmount()); + } + + @Test + public void testAdvancedCommerceRequestRefundItemRefundAmountIs64Bit() throws Exception { + long refundAmount = Integer.MAX_VALUE + 1000L; + AdvancedCommerceRequestRefundItem item = new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.CUSTOM, false) + .refundAmount(refundAmount); + + String json = createRequestObjectMapper().writeValueAsString(item); + Assertions.assertEquals(refundAmount, objectMapper.readTree(json).get("refundAmount").longValue()); + Assertions.assertEquals(refundAmount, objectMapper.readValue(json, AdvancedCommerceRequestRefundItem.class).getRefundAmount()); } @Test @@ -332,7 +348,8 @@ public void testAdvancedCommerceSubscriptionRevokeRequest() throws Exception { Assertions.assertNotNull(request.getRequestInfo()); Assertions.assertTrue(request.getRefundRiskingPreference()); Assertions.assertEquals(AdvancedCommerceRefundReason.LEGAL, request.getRefundReason()); - Assertions.assertEquals("FULL", request.getRefundType()); + Assertions.assertEquals(AdvancedCommerceRefundType.FULL, request.getRefundType()); + Assertions.assertEquals("FULL", request.getRawRefundType()); Assertions.assertEquals("USA", request.getStorefront()); } @@ -545,7 +562,7 @@ public void testAdvancedCommerceSubscriptionModifyChangeItem() throws Exception Assertions.assertEquals("description", item.getDescription()); Assertions.assertEquals("displayName", item.getDisplayName()); Assertions.assertEquals("sku", item.getSku()); - Assertions.assertEquals("currentSKU", item.getCurrentSKU()); + Assertions.assertEquals("currentSKU", item.getCurrentSku()); Assertions.assertEquals(13000L, item.getPrice()); Assertions.assertEquals(AdvancedCommerceEffective.IMMEDIATELY, item.getEffective()); Assertions.assertEquals(AdvancedCommerceReason.UPGRADE, item.getReason()); @@ -639,7 +656,7 @@ public void testAdvancedCommerceRequestInfo() throws Exception { Assertions.assertEquals(UUID.fromString("550e8400-e29b-41d4-a716-446655440010"), requestInfo.getRequestReferenceId()); Assertions.assertEquals(UUID.fromString("660e8400-e29b-41d4-a716-446655440011"), requestInfo.getAppAccountToken()); - Assertions.assertEquals("consistency_token_value", requestInfo.consistencyToken()); + Assertions.assertEquals("consistency_token_value", requestInfo.getConsistencyToken()); } @@ -770,4 +787,469 @@ public void testSubscriptionReactivateInAppRequestDeserializationSetsOperationAn Assertions.assertEquals("REACTIVATE_SUBSCRIPTION", node.get("operation").asText()); Assertions.assertEquals("1", node.get("version").asText()); } + + private static final UUID REQUEST_REFERENCE_ID = UUID.fromString("7c80bb86-f892-4b21-a919-1357811d6c4f"); + + private static ObjectMapper createRequestObjectMapper() { + ObjectMapper requestObjectMapper = new ObjectMapper(); + requestObjectMapper.setVisibility(requestObjectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + return requestObjectMapper; + } + + private static AdvancedCommerceRequestInfo createRequestInfo() { + return new AdvancedCommerceRequestInfo(REQUEST_REFERENCE_ID); + } + + @Test + public void testAdvancedCommerceDescriptorsPublicConstructor() throws Exception { + Assertions.assertTrue(Modifier.isPublic(AdvancedCommerceDescriptors.class.getConstructor(String.class, String.class).getModifiers())); + + AdvancedCommerceDescriptors descriptors = new AdvancedCommerceDescriptors("description", "display name"); + Assertions.assertEquals("description", descriptors.getDescription()); + Assertions.assertEquals("display name", descriptors.getDisplayName()); + Assertions.assertEquals(AdvancedCommerceDescriptors.class, descriptors.getClass()); + + AdvancedCommerceSubscriptionCreateRequest request = new AdvancedCommerceSubscriptionCreateRequest( + createRequestInfo(), + "USD", + descriptors, + List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L)), + AdvancedCommercePeriod.P1M, + "taxCode"); + Assertions.assertEquals(descriptors, request.getDescriptors()); + } + + @Test + public void testAdvancedCommerceRequestSerializationOmitsUnsetOptionalFields() throws Exception { + ObjectMapper requestObjectMapper = createRequestObjectMapper(); + + AdvancedCommerceSubscriptionCancelRequest cancelRequest = new AdvancedCommerceSubscriptionCancelRequest(createRequestInfo()); + Assertions.assertEquals(objectMapper.readTree("{\"requestInfo\":{\"requestReferenceId\":\"7c80bb86-f892-4b21-a919-1357811d6c4f\"}}"), + objectMapper.readTree(requestObjectMapper.writeValueAsString(cancelRequest))); + + AdvancedCommerceSubscriptionModifyInAppRequest modifyRequest = new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), true, "123") + .addRemoveItem(new AdvancedCommerceSubscriptionModifyRemoveItem("sku")) + .descriptors(new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.IMMEDIATELY)); + Assertions.assertEquals(objectMapper.readTree("{\"requestInfo\":{\"requestReferenceId\":\"7c80bb86-f892-4b21-a919-1357811d6c4f\"},\"operation\":\"MODIFY_SUBSCRIPTION\",\"version\":\"1\",\"descriptors\":{\"effective\":\"IMMEDIATELY\"},\"removeItems\":[{\"SKU\":\"sku\"}],\"retainBillingCycle\":true,\"transactionId\":\"123\"}"), + objectMapper.readTree(requestObjectMapper.writeValueAsString(modifyRequest))); + + AdvancedCommerceRequestRefundRequest refundRequest = new AdvancedCommerceRequestRefundRequest( + createRequestInfo(), + List.of(new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, false)), + true); + Assertions.assertEquals(objectMapper.readTree("{\"requestInfo\":{\"requestReferenceId\":\"7c80bb86-f892-4b21-a919-1357811d6c4f\"},\"items\":[{\"SKU\":\"sku\",\"refundReason\":\"LEGAL\",\"refundType\":\"FULL\",\"revoke\":false}],\"refundRiskingPreference\":true}"), + objectMapper.readTree(requestObjectMapper.writeValueAsString(refundRequest))); + + List requests = List.of( + new AdvancedCommerceOneTimeChargeCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceOneTimeChargeItem("description", "display name", "sku", 1000L), "taxCode"), + new AdvancedCommerceSubscriptionCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceDescriptors("description", "display name"), List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L)), + AdvancedCommercePeriod.P1M, "taxCode"), + new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), false, "123") + .addAddItem(new AdvancedCommerceSubscriptionModifyAddItem("sku", "description", "display name", 1000L)) + .addChangeItem(new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE)) + .periodChange(new AdvancedCommerceSubscriptionModifyPeriodChange(AdvancedCommerceEffective.NEXT_BILL_CYCLE, AdvancedCommercePeriod.P1Y)), + new AdvancedCommerceSubscriptionReactivateInAppRequest(createRequestInfo(), "123") + .addItem(new AdvancedCommerceSubscriptionReactivateItem("sku")), + new AdvancedCommerceSubscriptionMigrateRequest(createRequestInfo(), new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name"), List.of(new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "display name")), + "targetProductId", "taxCode"), + new AdvancedCommerceSubscriptionRevokeRequest(createRequestInfo(), AdvancedCommerceRefundReason.LEGAL, true, AdvancedCommerceRefundType.PRORATED), + new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L))), + new AdvancedCommerceSubscriptionChangeMetadataRequest(createRequestInfo()) + .descriptors(new AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective.IMMEDIATELY)) + .addItem(new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", AdvancedCommerceEffective.IMMEDIATELY)), + new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L) + .offer(new AdvancedCommerceOffer(AdvancedCommerceOfferPeriod.P1M, 1, 500L, AdvancedCommerceOfferReason.ACQUISITION)) + ); + for (Object request : requests) { + String json = requestObjectMapper.writeValueAsString(request); + Assertions.assertFalse(json.contains("null"), json); + } + } + + @Test + public void testAdvancedCommerceItemEqualsAndHashCode() { + Assertions.assertEquals(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L), new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L)); + Assertions.assertEquals(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L).hashCode(), new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L).hashCode()); + Assertions.assertNotEquals(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L), new AdvancedCommerceSubscriptionPriceChangeItem("sku2", 1000L)); + Assertions.assertNotEquals(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L), new AdvancedCommerceSubscriptionPriceChangeItem("sku", 2000L)); + + Assertions.assertEquals(new AdvancedCommerceSubscriptionModifyRemoveItem("sku"), new AdvancedCommerceSubscriptionModifyRemoveItem("sku")); + Assertions.assertEquals(new AdvancedCommerceSubscriptionModifyRemoveItem("sku").hashCode(), new AdvancedCommerceSubscriptionModifyRemoveItem("sku").hashCode()); + Assertions.assertNotEquals(new AdvancedCommerceSubscriptionModifyRemoveItem("sku"), new AdvancedCommerceSubscriptionModifyRemoveItem("sku2")); + + Assertions.assertEquals(new AdvancedCommerceSubscriptionReactivateItem("sku"), new AdvancedCommerceSubscriptionReactivateItem("sku")); + Assertions.assertEquals(new AdvancedCommerceSubscriptionReactivateItem("sku").hashCode(), new AdvancedCommerceSubscriptionReactivateItem("sku").hashCode()); + Assertions.assertNotEquals(new AdvancedCommerceSubscriptionReactivateItem("sku"), new AdvancedCommerceSubscriptionReactivateItem("sku2")); + Assertions.assertNotEquals(new AdvancedCommerceSubscriptionReactivateItem("sku"), new AdvancedCommerceSubscriptionModifyRemoveItem("sku")); + + Assertions.assertEquals( + new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L))), + new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L)))); + Assertions.assertEquals( + new AdvancedCommerceSubscriptionReactivateInAppRequest(createRequestInfo(), "123").addItem(new AdvancedCommerceSubscriptionReactivateItem("sku")), + new AdvancedCommerceSubscriptionReactivateInAppRequest(createRequestInfo(), "123").addItem(new AdvancedCommerceSubscriptionReactivateItem("sku"))); + } + + @Test + public void testAdvancedCommerceDescriptorsEqualsAndHashCode() { + AdvancedCommerceSubscriptionChangeMetadataDescriptors changeMetadataDescriptors = + new AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective.IMMEDIATELY).description("description"); + AdvancedCommerceSubscriptionChangeMetadataDescriptors otherChangeMetadataDescriptors = + new AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective.IMMEDIATELY).description("description"); + Assertions.assertEquals(changeMetadataDescriptors, otherChangeMetadataDescriptors); + Assertions.assertEquals(changeMetadataDescriptors.hashCode(), otherChangeMetadataDescriptors.hashCode()); + Set changeMetadataDescriptorsSet = new HashSet<>(); + changeMetadataDescriptorsSet.add(changeMetadataDescriptors); + Assertions.assertTrue(changeMetadataDescriptorsSet.contains(otherChangeMetadataDescriptors)); + + AdvancedCommerceSubscriptionModifyDescriptors modifyDescriptors = + new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.NEXT_BILL_CYCLE).displayName("display name"); + AdvancedCommerceSubscriptionModifyDescriptors otherModifyDescriptors = + new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.NEXT_BILL_CYCLE).displayName("display name"); + Assertions.assertEquals(modifyDescriptors, otherModifyDescriptors); + Assertions.assertEquals(modifyDescriptors.hashCode(), otherModifyDescriptors.hashCode()); + + AdvancedCommerceSubscriptionModifyInAppRequest modifyRequest = new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), true, "123").descriptors(modifyDescriptors); + AdvancedCommerceSubscriptionModifyInAppRequest otherModifyRequest = new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), true, "123").descriptors(otherModifyDescriptors); + Assertions.assertEquals(modifyRequest, otherModifyRequest); + Assertions.assertEquals(modifyRequest.hashCode(), otherModifyRequest.hashCode()); + } + + @Test + public void testAdvancedCommerceItemSkuRequired() { + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyRemoveItem(null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionReactivateItem(null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionPriceChangeItem(null, 1000L)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceOneTimeChargeItem("description", "display name", null, 1000L)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionCreateItem(null, "description", "display name", 1000L)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceRequestRefundItem(null, AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyRemoveItem("sku").sku(null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyRemoveItem("sku").setSku(null)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new AdvancedCommerceSubscriptionModifyRemoveItem("A".repeat(129))); + + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", null, AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyChangeItem(null, "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE).currentSku(null)); + + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionChangeMetadataItem(null, AdvancedCommerceEffective.IMMEDIATELY)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", AdvancedCommerceEffective.IMMEDIATELY).setCurrentSku(null)); + AdvancedCommerceSubscriptionChangeMetadataItem changeMetadataItem = new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", AdvancedCommerceEffective.IMMEDIATELY).sku("sku"); + changeMetadataItem.setSku(null); + Assertions.assertNull(changeMetadataItem.getSku()); + changeMetadataItem.setSku("a".repeat(128)); + Assertions.assertEquals("a".repeat(128), changeMetadataItem.getSku()); + Assertions.assertThrows(IllegalArgumentException.class, () -> changeMetadataItem.setSku("a".repeat(129))); + Assertions.assertEquals("a".repeat(128), changeMetadataItem.getSku()); + } + + @Test + public void testAdvancedCommerceItemFluentSettersReturnConcreteType() { + AdvancedCommerceSubscriptionModifyAddItem addItem = new AdvancedCommerceSubscriptionModifyAddItem("sku", "description", "display name", 1000L) + .sku("sku2") + .description("description2") + .displayName("display name2") + .proratedPrice(500L); + Assertions.assertEquals("sku2", addItem.getSku()); + Assertions.assertEquals("description2", addItem.getDescription()); + Assertions.assertEquals("display name2", addItem.getDisplayName()); + Assertions.assertEquals(500L, addItem.getProratedPrice()); + + AdvancedCommerceSubscriptionCreateItem createItem = new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L) + .sku("sku2") + .offer(null); + Assertions.assertEquals("sku2", createItem.getSku()); + AdvancedCommerceOneTimeChargeItem oneTimeChargeItem = new AdvancedCommerceOneTimeChargeItem("description", "display name", "sku", 1000L).description("description2").price(2000L); + Assertions.assertEquals("description2", oneTimeChargeItem.getDescription()); + AdvancedCommerceSubscriptionModifyChangeItem changeItem = new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE) + .displayName("display name2") + .reason(AdvancedCommerceReason.DOWNGRADE); + Assertions.assertEquals(AdvancedCommerceReason.DOWNGRADE, changeItem.getReason()); + AdvancedCommerceSubscriptionMigrateItem migrateItem = new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "display name").sku("sku2"); + Assertions.assertEquals("sku2", migrateItem.getSku()); + AdvancedCommerceSubscriptionMigrateRenewalItem migrateRenewalItem = new AdvancedCommerceSubscriptionMigrateRenewalItem("sku", "description", "display name").displayName("display name2"); + Assertions.assertEquals("display name2", migrateRenewalItem.getDisplayName()); + AdvancedCommerceSubscriptionModifyRemoveItem removeItem = new AdvancedCommerceSubscriptionModifyRemoveItem("sku").sku("sku2"); + Assertions.assertEquals("sku2", removeItem.getSku()); + AdvancedCommerceSubscriptionReactivateItem reactivateItem = new AdvancedCommerceSubscriptionReactivateItem("sku").sku("sku2"); + Assertions.assertEquals("sku2", reactivateItem.getSku()); + AdvancedCommerceSubscriptionPriceChangeItem priceChangeItem = new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L).sku("sku2").price(2000L); + Assertions.assertEquals(2000L, priceChangeItem.getPrice()); + AdvancedCommerceRequestRefundItem refundItem = new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.CUSTOM, true).sku("sku2").refundAmount(100L); + Assertions.assertEquals("sku2", refundItem.getSku()); + AdvancedCommerceSubscriptionMigrateDescriptors migrateDescriptors = new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name") + .description("description2") + .displayName("display name2") + .unknownFields(Map.of("key", "value")); + Assertions.assertEquals("description2", migrateDescriptors.getDescription()); + Assertions.assertEquals("display name2", migrateDescriptors.getDisplayName()); + Assertions.assertEquals(Map.of("key", "value"), migrateDescriptors.getUnknownFields()); + AdvancedCommerceSubscriptionCancelResponse cancelResponse = new AdvancedCommerceSubscriptionCancelResponse("renewal", "transaction") + .unknownFields(Map.of("key", "value")); + Assertions.assertEquals(Map.of("key", "value"), cancelResponse.getUnknownFields()); + AdvancedCommerceRequestRefundResponse refundResponse = new AdvancedCommerceRequestRefundResponse("transaction").unknownFields(null); + Assertions.assertNull(refundResponse.getUnknownFields()); + AdvancedCommerceSubscriptionChangeMetadataResponse changeMetadataResponse = new AdvancedCommerceSubscriptionChangeMetadataResponse("renewal", "transaction").unknownFields(null); + Assertions.assertNull(changeMetadataResponse.getUnknownFields()); + AdvancedCommerceSubscriptionMigrateResponse migrateResponse = new AdvancedCommerceSubscriptionMigrateResponse("renewal", "transaction").unknownFields(null); + Assertions.assertNull(migrateResponse.getUnknownFields()); + AdvancedCommerceSubscriptionPriceChangeResponse priceChangeResponse = new AdvancedCommerceSubscriptionPriceChangeResponse("renewal", "transaction").unknownFields(null); + Assertions.assertNull(priceChangeResponse.getUnknownFields()); + AdvancedCommerceSubscriptionRevokeResponse revokeResponse = new AdvancedCommerceSubscriptionRevokeResponse("renewal", "transaction").unknownFields(null); + Assertions.assertNull(revokeResponse.getUnknownFields()); + } + + @Test + public void testAdvancedCommerceRequestInfoConsistencyToken() { + AdvancedCommerceRequestInfo requestInfo = createRequestInfo().consistencyToken("token"); + Assertions.assertEquals("token", requestInfo.getConsistencyToken()); + Assertions.assertTrue(requestInfo.toString().startsWith("AdvancedCommerceRequestInfo{"), requestInfo.toString()); + } + + @Test + public void testAdvancedCommerceSubscriptionModifyChangeItemCurrentSku() { + AdvancedCommerceSubscriptionModifyChangeItem item = new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE); + Assertions.assertEquals("currentSku", item.getCurrentSku()); + Assertions.assertEquals("sku", item.getSku()); + Assertions.assertEquals("currentSku2", item.currentSku("currentSku2").getCurrentSku()); + item.setCurrentSku("currentSku3"); + Assertions.assertEquals("currentSku3", item.getCurrentSku()); + Assertions.assertThrows(NullPointerException.class, () -> item.setCurrentSku(null)); + Assertions.assertThrows(IllegalArgumentException.class, () -> item.setCurrentSku("A".repeat(129))); + } + + @Test + public void testAdvancedCommerceRequestRefundItemRawRefundReason() { + AdvancedCommerceRequestRefundItem item = new AdvancedCommerceRequestRefundItem("sku", "NEW_REASON", "NEW_TYPE", true); + Assertions.assertNull(item.getRefundReason()); + Assertions.assertEquals("NEW_REASON", item.getRawRefundReason()); + Assertions.assertNull(item.getRefundType()); + Assertions.assertEquals("NEW_TYPE", item.getRawRefundType()); + + item.setRefundReason(AdvancedCommerceRefundReason.OTHER); + Assertions.assertEquals(AdvancedCommerceRefundReason.OTHER, item.getRefundReason()); + Assertions.assertEquals("OTHER", item.getRawRefundReason()); + } + + @Test + public void testAdvancedCommerceSubscriptionModifyPeriodChangeRawValues() throws Exception { + AdvancedCommerceSubscriptionModifyPeriodChange periodChange = new AdvancedCommerceSubscriptionModifyPeriodChange("FUTURE_EFFECTIVE", "P5Y"); + Assertions.assertNull(periodChange.getEffective()); + Assertions.assertEquals("FUTURE_EFFECTIVE", periodChange.getRawEffective()); + Assertions.assertNull(periodChange.getPeriod()); + Assertions.assertEquals("P5Y", periodChange.getRawPeriod()); + Assertions.assertEquals(objectMapper.readTree("{\"effective\":\"FUTURE_EFFECTIVE\",\"period\":\"P5Y\"}"), + objectMapper.readTree(createRequestObjectMapper().writeValueAsString(periodChange))); + + AdvancedCommerceSubscriptionModifyPeriodChange knownPeriodChange = new AdvancedCommerceSubscriptionModifyPeriodChange("IMMEDIATELY", "P1M"); + Assertions.assertEquals(AdvancedCommerceEffective.IMMEDIATELY, knownPeriodChange.getEffective()); + Assertions.assertEquals(AdvancedCommercePeriod.P1M, knownPeriodChange.getPeriod()); + Assertions.assertEquals(new AdvancedCommerceSubscriptionModifyPeriodChange(AdvancedCommerceEffective.IMMEDIATELY, AdvancedCommercePeriod.P1M), knownPeriodChange); + + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyPeriodChange((String) null, "P1M")); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyPeriodChange("IMMEDIATELY", (String) null)); + + knownPeriodChange.setRawPeriod("P2M"); + Assertions.assertEquals(AdvancedCommercePeriod.P2M, knownPeriodChange.getPeriod()); + knownPeriodChange.setRawEffective("NEXT_BILL_CYCLE"); + Assertions.assertEquals(AdvancedCommerceEffective.NEXT_BILL_CYCLE, knownPeriodChange.getEffective()); + } + + @Test + public void testAdvancedCommerceRawEnumAccessors() { + AdvancedCommerceSubscriptionModifyDescriptors modifyDescriptors = new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.IMMEDIATELY); + Assertions.assertEquals("IMMEDIATELY", modifyDescriptors.getRawEffective()); + modifyDescriptors.setRawEffective("LATER"); + Assertions.assertNull(modifyDescriptors.getEffective()); + Assertions.assertEquals("LATER", modifyDescriptors.getRawEffective()); + + AdvancedCommerceSubscriptionChangeMetadataDescriptors changeMetadataDescriptors = new AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective.NEXT_BILL_CYCLE); + Assertions.assertEquals("NEXT_BILL_CYCLE", changeMetadataDescriptors.getRawEffective()); + changeMetadataDescriptors.setRawEffective("LATER"); + Assertions.assertNull(changeMetadataDescriptors.getEffective()); + + AdvancedCommerceSubscriptionChangeMetadataItem changeMetadataItem = new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", AdvancedCommerceEffective.IMMEDIATELY); + Assertions.assertEquals("IMMEDIATELY", changeMetadataItem.getRawEffective()); + changeMetadataItem.setRawEffective("LATER"); + Assertions.assertNull(changeMetadataItem.getEffective()); + + AdvancedCommerceSubscriptionModifyChangeItem changeItem = new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.APPLY_OFFER); + Assertions.assertEquals("IMMEDIATELY", changeItem.getRawEffective()); + Assertions.assertEquals("APPLY_OFFER", changeItem.getRawReason()); + changeItem.setRawReason("NEW_REASON"); + Assertions.assertNull(changeItem.getReason()); + Assertions.assertEquals("NEW_REASON", changeItem.getRawReason()); + + AdvancedCommerceSubscriptionCreateRequest createRequest = new AdvancedCommerceSubscriptionCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceDescriptors("description", "display name"), List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L)), + AdvancedCommercePeriod.P1M, "taxCode"); + Assertions.assertEquals("P1M", createRequest.getRawPeriod()); + createRequest.setRawPeriod("P5Y"); + Assertions.assertNull(createRequest.getPeriod()); + Assertions.assertEquals("P5Y", createRequest.getRawPeriod()); + + AdvancedCommerceSubscriptionRevokeRequest revokeRequest = new AdvancedCommerceSubscriptionRevokeRequest(createRequestInfo(), AdvancedCommerceRefundReason.LEGAL, true, AdvancedCommerceRefundType.FULL); + Assertions.assertEquals(AdvancedCommerceRefundReason.LEGAL, revokeRequest.getRefundReason()); + Assertions.assertEquals("LEGAL", revokeRequest.getRawRefundReason()); + Assertions.assertEquals(AdvancedCommerceRefundType.FULL, revokeRequest.getRefundType()); + Assertions.assertEquals("FULL", revokeRequest.getRawRefundType()); + revokeRequest.setRawRefundReason("NEW_REASON"); + Assertions.assertNull(revokeRequest.getRefundReason()); + Assertions.assertEquals("NEW_REASON", revokeRequest.getRawRefundReason()); + Assertions.assertEquals(AdvancedCommerceRefundType.PRORATED, revokeRequest.refundType(AdvancedCommerceRefundType.PRORATED).getRefundType()); + Assertions.assertEquals("PRORATED", revokeRequest.getRawRefundType()); + revokeRequest.setRefundType(AdvancedCommerceRefundType.FULL); + Assertions.assertEquals(AdvancedCommerceRefundType.FULL, revokeRequest.getRefundType()); + revokeRequest.setRawRefundType("NEW_TYPE"); + Assertions.assertNull(revokeRequest.getRefundType()); + Assertions.assertEquals("NEW_TYPE", revokeRequest.getRawRefundType()); + Assertions.assertThrows(NullPointerException.class, () -> revokeRequest.setRefundType(null)); + Assertions.assertThrows(NullPointerException.class, () -> revokeRequest.setRawRefundType(null)); + Assertions.assertThrows(NullPointerException.class, () -> revokeRequest.setRawRefundReason(null)); + } + + @Test + public void testAdvancedCommerceRequestItemListValidation() { + Assertions.assertThrows(IllegalArgumentException.class, + () -> new AdvancedCommerceRequestRefundRequest(createRequestInfo(), new ArrayList<>(), true)); + Assertions.assertThrows(IllegalArgumentException.class, + () -> new AdvancedCommerceRequestRefundRequest(createRequestInfo(), Arrays.asList((AdvancedCommerceRequestRefundItem) null), true)); + Assertions.assertThrows(IllegalArgumentException.class, + () -> new AdvancedCommerceRequestRefundRequest(createRequestInfo(), List.of(new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)), true).items(new ArrayList<>())); + + Assertions.assertThrows(IllegalArgumentException.class, + () -> new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), new ArrayList<>())); + Assertions.assertThrows(IllegalArgumentException.class, + () -> new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L))).setItems(new ArrayList<>())); + + AdvancedCommerceSubscriptionModifyInAppRequest modifyRequest = new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), true, "123"); + Assertions.assertThrows(IllegalArgumentException.class, () -> modifyRequest.removeItems(new ArrayList<>())); + Assertions.assertThrows(IllegalArgumentException.class, () -> modifyRequest.setRemoveItems(Arrays.asList((AdvancedCommerceSubscriptionModifyRemoveItem) null))); + modifyRequest.setRemoveItems(null); + Assertions.assertNull(modifyRequest.getRemoveItems()); + + AdvancedCommerceSubscriptionChangeMetadataRequest changeMetadataRequest = new AdvancedCommerceSubscriptionChangeMetadataRequest(createRequestInfo()); + Assertions.assertThrows(IllegalArgumentException.class, () -> changeMetadataRequest.items(new ArrayList<>())); + Assertions.assertThrows(IllegalArgumentException.class, () -> changeMetadataRequest.setItems(Arrays.asList((AdvancedCommerceSubscriptionChangeMetadataItem) null))); + changeMetadataRequest.setItems(null); + Assertions.assertNull(changeMetadataRequest.getItems()); + + List priceChangeItems = List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L)); + Assertions.assertEquals(priceChangeItems, HelperValidationUtils.validateItems(priceChangeItems)); + } + + @Test + public void testAdvancedCommerceSubscriptionReactivateInAppRequestItemsValidation() { + AdvancedCommerceSubscriptionReactivateInAppRequest request = new AdvancedCommerceSubscriptionReactivateInAppRequest(createRequestInfo(), "transactionId"); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.items(new ArrayList<>())); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setItems(new ArrayList<>())); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.items(Arrays.asList((AdvancedCommerceSubscriptionReactivateItem) null))); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setItems(Arrays.asList((AdvancedCommerceSubscriptionReactivateItem) null))); + + Assertions.assertNull(request.getItems()); + Assertions.assertFalse(createRequestObjectMapper().valueToTree(request).has("items")); + request.setItems(null); + Assertions.assertNull(request.getItems()); + + List items = List.of(new AdvancedCommerceSubscriptionReactivateItem("sku")); + Assertions.assertEquals(items, request.items(items).getItems()); + request.setItems(items); + Assertions.assertEquals(items, request.getItems()); + Assertions.assertEquals("sku", createRequestObjectMapper().valueToTree(request).get("items").get(0).get("SKU").asText()); + } + + @Test + public void testAdvancedCommerceRequestAddItemAppendsToList() { + AdvancedCommerceSubscriptionPriceChangeRequest priceChangeRequest = new AdvancedCommerceSubscriptionPriceChangeRequest(createRequestInfo(), new ArrayList<>(List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L)))) + .addItem(new AdvancedCommerceSubscriptionPriceChangeItem("sku2", 2000L)); + Assertions.assertEquals(List.of(new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L), new AdvancedCommerceSubscriptionPriceChangeItem("sku2", 2000L)), priceChangeRequest.getItems()); + + AdvancedCommerceSubscriptionCreateRequest createRequest = new AdvancedCommerceSubscriptionCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceDescriptors("description", "display name"), new ArrayList<>(List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L))), + AdvancedCommercePeriod.P1M, "taxCode") + .addItem(new AdvancedCommerceSubscriptionCreateItem("sku2", "description", "display name", 1000L)); + Assertions.assertEquals(2, createRequest.getItems().size()); + + AdvancedCommerceSubscriptionMigrateRequest migrateRequest = new AdvancedCommerceSubscriptionMigrateRequest(createRequestInfo(), new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name"), new ArrayList<>(List.of(new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "display name"))), + "targetProductId", "taxCode") + .addItem(new AdvancedCommerceSubscriptionMigrateItem("sku2", "description", "display name")); + Assertions.assertEquals(2, migrateRequest.getItems().size()); + + List refundItems = new ArrayList<>(); + refundItems.add(new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)); + AdvancedCommerceRequestRefundRequest refundRequestWithItems = new AdvancedCommerceRequestRefundRequest(createRequestInfo(), refundItems, true) + .addItem(new AdvancedCommerceRequestRefundItem("sku2", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)); + Assertions.assertEquals(2, refundRequestWithItems.getItems().size()); + } + + @Test + public void testAdvancedCommerceRequestRefundRequestCurrencyOptional() { + AdvancedCommerceRequestRefundRequest request = new AdvancedCommerceRequestRefundRequest( + createRequestInfo(), + List.of(new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)), + true) + .currency("USD"); + Assertions.assertEquals("USD", request.getCurrency()); + Assertions.assertNull(request.currency(null).getCurrency()); + request.setCurrency("EUR"); + request.setCurrency(null); + Assertions.assertNull(request.getCurrency()); + } + + @Test + public void testValidationUtilsCountsCodePoints() { + String emoji = "\uD83D\uDC4D"; + Assertions.assertEquals(emoji.repeat(45), HelperValidationUtils.validateDescription(emoji.repeat(45))); + Assertions.assertThrows(IllegalArgumentException.class, + () -> HelperValidationUtils.validateDescription(emoji.repeat(46))); + Assertions.assertEquals(emoji.repeat(30), HelperValidationUtils.validateDisplayName(emoji.repeat(30))); + Assertions.assertThrows(IllegalArgumentException.class, + () -> HelperValidationUtils.validateDisplayName(emoji.repeat(31))); + Assertions.assertEquals(emoji.repeat(128), HelperValidationUtils.validateSku(emoji.repeat(128))); + Assertions.assertThrows(IllegalArgumentException.class, + () -> HelperValidationUtils.validateSku(emoji.repeat(129))); + String combiningCharacter = "e\u0301"; + Assertions.assertThrows(IllegalArgumentException.class, + () -> HelperValidationUtils.validateDisplayName(combiningCharacter.repeat(16))); + } + + @Test + public void testAdvancedCommerceInAppRequestOperationAndVersion() { + AdvancedCommerceOneTimeChargeCreateRequest oneTimeChargeCreateRequest = new AdvancedCommerceOneTimeChargeCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceOneTimeChargeItem("description", "display name", "sku", 1000L), "taxCode"); + Assertions.assertEquals("CREATE_ONE_TIME_CHARGE", oneTimeChargeCreateRequest.getOperation()); + Assertions.assertEquals("1", oneTimeChargeCreateRequest.getVersion()); + Assertions.assertTrue(oneTimeChargeCreateRequest.toString().contains("operation='CREATE_ONE_TIME_CHARGE', version='1'"), oneTimeChargeCreateRequest.toString()); + + AdvancedCommerceSubscriptionReactivateInAppRequest reactivateRequest = new AdvancedCommerceSubscriptionReactivateInAppRequest(createRequestInfo(), "123"); + Assertions.assertEquals("REACTIVATE_SUBSCRIPTION", reactivateRequest.getOperation()); + Assertions.assertEquals("1", reactivateRequest.getVersion()); + Assertions.assertTrue(reactivateRequest.toString().contains("operation='REACTIVATE_SUBSCRIPTION', version='1'"), reactivateRequest.toString()); + + AdvancedCommerceSubscriptionModifyInAppRequest modifyRequest = new AdvancedCommerceSubscriptionModifyInAppRequest(createRequestInfo(), true, "123"); + Assertions.assertEquals("MODIFY_SUBSCRIPTION", modifyRequest.getOperation()); + Assertions.assertTrue(modifyRequest.toString().contains("operation='MODIFY_SUBSCRIPTION', version='1'"), modifyRequest.toString()); + + AdvancedCommerceSubscriptionCreateRequest createRequest = new AdvancedCommerceSubscriptionCreateRequest(createRequestInfo(), "USD", new AdvancedCommerceDescriptors("description", "display name"), List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L)), + AdvancedCommercePeriod.P1M, "taxCode"); + Assertions.assertEquals("CREATE_SUBSCRIPTION", createRequest.getOperation()); + Assertions.assertTrue(createRequest.toString().contains("operation='CREATE_SUBSCRIPTION', version='1'"), createRequest.toString()); + } + + @Test + public void testAdvancedCommerceToString() { + Assertions.assertEquals("AdvancedCommerceSubscriptionPriceChangeResponse{signedRenewalInfo='r', signedTransactionInfo='t', unknownFields={key=value}}", + new AdvancedCommerceSubscriptionPriceChangeResponse("r", "t").unknownFields(Map.of("key", "value")).toString()); + Assertions.assertEquals("AdvancedCommerceSubscriptionCancelResponse{signedRenewalInfo='r', signedTransactionInfo='t', unknownFields=null}", + new AdvancedCommerceSubscriptionCancelResponse("r", "t").toString()); + Assertions.assertEquals("AdvancedCommerceSubscriptionModifyAddItem{sku='sku', description='description', displayName='display name', offer=null, price=1000, proratedPrice=null}", + new AdvancedCommerceSubscriptionModifyAddItem("sku", "description", "display name", 1000L).toString()); + Assertions.assertEquals("AdvancedCommerceSubscriptionModifyDescriptors{description='null', displayName='null', effective='IMMEDIATELY'}", + new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.IMMEDIATELY).toString()); + Assertions.assertEquals("AdvancedCommerceSubscriptionMigrateDescriptors{description='description', displayName='display name', unknownFields=null}", + new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name").toString()); + Assertions.assertEquals("AdvancedCommerceSubscriptionChangeMetadataRequest{requestInfo=AdvancedCommerceRequestInfo{appAccountToken=null, consistencyToken='null', requestReferenceId=7c80bb86-f892-4b21-a919-1357811d6c4f}, descriptors=null, items=null, storefront='null', taxCode='null'}", + new AdvancedCommerceSubscriptionChangeMetadataRequest(createRequestInfo()).toString()); + } } diff --git a/src/test/java/com/apple/itunes/storekit/model/AppStoreServerAPIModelsTest.java b/src/test/java/com/apple/itunes/storekit/model/AppStoreServerAPIModelsTest.java new file mode 100644 index 00000000..ee46b9da --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/model/AppStoreServerAPIModelsTest.java @@ -0,0 +1,283 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Map; + +public class AppStoreServerAPIModelsTest { + + private final ObjectMapper objectMapper = createObjectMapper(); + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + return objectMapper; + } + + @SuppressWarnings("unchecked") + private Map serialize(Object value) throws JsonProcessingException { + return objectMapper.readValue(objectMapper.writeValueAsString(value), Map.class); + } + + @Test + public void testConsumptionRequestRefundPreferenceIsOptional() throws JsonProcessingException { + ConsumptionRequest request = new ConsumptionRequest(true, DeliveryStatus.DELIVERED, false) + .refundPreference(RefundPreference.GRANT_FULL); + + request.setRefundPreference(null); + Assertions.assertNull(request.getRefundPreference()); + Assertions.assertNull(request.getRawRefundPreference()); + Assertions.assertFalse(serialize(request).containsKey("refundPreference")); + + request.setRawRefundPreference("GRANT_FULL"); + Assertions.assertEquals(RefundPreference.GRANT_FULL, request.getRefundPreference()); + + request.setRawRefundPreference(null); + Assertions.assertNull(request.getRefundPreference()); + Assertions.assertNull(request.getRawRefundPreference()); + + request.setRefundPreference(RefundPreference.DECLINE); + Assertions.assertEquals("DECLINE", request.getRawRefundPreference()); + Assertions.assertEquals("DECLINE", serialize(request).get("refundPreference")); + } + + @Test + public void testExtendRenewalDateRequestExtendReasonCode() throws JsonProcessingException { + ExtendRenewalDateRequest request = new ExtendRenewalDateRequest(45, ExtendReasonCode.CUSTOMER_SATISFACTION, "fdf964a4-233b-486c-aac1-97d8d52688ac"); + + Assertions.assertEquals(ExtendReasonCode.CUSTOMER_SATISFACTION, request.getExtendReasonCode()); + Assertions.assertEquals(1, request.getRawExtendReasonCode()); + Map root = serialize(request); + Assertions.assertEquals(1, ((Number) root.get("extendReasonCode")).intValue()); + + request.setRawExtendReasonCode(99); + Assertions.assertNull(request.getExtendReasonCode()); + Assertions.assertEquals(99, request.getRawExtendReasonCode()); + root = serialize(request); + Assertions.assertEquals(99, ((Number) root.get("extendReasonCode")).intValue()); + + Assertions.assertThrows(NullPointerException.class, () -> request.setExtendReasonCode(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setRawExtendReasonCode(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.extendReasonCode(null)); + Assertions.assertEquals(99, request.getRawExtendReasonCode()); + + request.setExtendReasonCode(ExtendReasonCode.SERVICE_ISSUE_OR_OUTAGE); + ExtendRenewalDateRequest rawRequest = new ExtendRenewalDateRequest(45, 3, "fdf964a4-233b-486c-aac1-97d8d52688ac"); + Assertions.assertEquals(request, rawRequest); + Assertions.assertEquals(request.hashCode(), rawRequest.hashCode()); + } + + @Test + public void testMassExtendRenewalDateRequestExtendReasonCode() throws JsonProcessingException { + MassExtendRenewalDateRequest request = new MassExtendRenewalDateRequest("fdf964a4-233b-486c-aac1-97d8d52688ac", 45, ExtendReasonCode.OTHER, "com.example.productId"); + + Assertions.assertEquals(ExtendReasonCode.OTHER, request.getExtendReasonCode()); + Assertions.assertEquals(2, request.getRawExtendReasonCode()); + Map root = serialize(request); + Assertions.assertEquals(2, ((Number) root.get("extendReasonCode")).intValue()); + + request.setRawExtendReasonCode(99); + Assertions.assertNull(request.getExtendReasonCode()); + Assertions.assertEquals(99, request.getRawExtendReasonCode()); + root = serialize(request); + Assertions.assertEquals(99, ((Number) root.get("extendReasonCode")).intValue()); + + Assertions.assertThrows(NullPointerException.class, () -> request.setExtendReasonCode(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setRawExtendReasonCode(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.extendReasonCode(null)); + Assertions.assertEquals(99, request.getRawExtendReasonCode()); + + MassExtendRenewalDateRequest rawRequest = new MassExtendRenewalDateRequest("fdf964a4-233b-486c-aac1-97d8d52688ac", 45, 99, "com.example.productId"); + Assertions.assertEquals(request, rawRequest); + Assertions.assertEquals(request.hashCode(), rawRequest.hashCode()); + } + + @Test + public void testNotificationHistoryRequestRawNotificationTypes() throws JsonProcessingException { + NotificationHistoryRequest request = new NotificationHistoryRequest(1698148900000L, 1698148950000L) + .notificationType(NotificationTypeV2.SUBSCRIBED) + .notificationSubtype(Subtype.INITIAL_BUY); + + Assertions.assertEquals(NotificationTypeV2.SUBSCRIBED, request.getNotificationType()); + Assertions.assertEquals("SUBSCRIBED", request.getRawNotificationType()); + Assertions.assertEquals(Subtype.INITIAL_BUY, request.getNotificationSubtype()); + Assertions.assertEquals("INITIAL_BUY", request.getRawNotificationSubtype()); + Map root = serialize(request); + Assertions.assertEquals("SUBSCRIBED", root.get("notificationType")); + Assertions.assertEquals("INITIAL_BUY", root.get("notificationSubtype")); + + request.setRawNotificationType("NEW_NOTIFICATION_TYPE"); + request.setRawNotificationSubtype("NEW_SUBTYPE"); + Assertions.assertNull(request.getNotificationType()); + Assertions.assertEquals("NEW_NOTIFICATION_TYPE", request.getRawNotificationType()); + Assertions.assertNull(request.getNotificationSubtype()); + Assertions.assertEquals("NEW_SUBTYPE", request.getRawNotificationSubtype()); + root = serialize(request); + Assertions.assertEquals("NEW_NOTIFICATION_TYPE", root.get("notificationType")); + Assertions.assertEquals("NEW_SUBTYPE", root.get("notificationSubtype")); + + request.setNotificationType(null); + request.setNotificationSubtype(null); + Assertions.assertNull(request.getRawNotificationType()); + Assertions.assertNull(request.getRawNotificationSubtype()); + root = serialize(request); + Assertions.assertFalse(root.containsKey("notificationType")); + Assertions.assertFalse(root.containsKey("notificationSubtype")); + } + + @Test + public void testTransactionHistoryRequestRawInAppOwnershipType() { + TransactionHistoryRequest request = new TransactionHistoryRequest() + .inAppOwnershipType(InAppOwnershipType.FAMILY_SHARED); + + Assertions.assertEquals(InAppOwnershipType.FAMILY_SHARED, request.getInAppOwnershipType()); + Assertions.assertEquals("FAMILY_SHARED", request.getRawInAppOwnershipType()); + + request.setRawInAppOwnershipType("NEW_OWNERSHIP_TYPE"); + Assertions.assertNull(request.getInAppOwnershipType()); + Assertions.assertEquals("NEW_OWNERSHIP_TYPE", request.getRawInAppOwnershipType()); + + request.setInAppOwnershipType(InAppOwnershipType.PURCHASED); + Assertions.assertEquals(InAppOwnershipType.PURCHASED, request.getInAppOwnershipType()); + Assertions.assertEquals("PURCHASED", request.getRawInAppOwnershipType()); + + request.setInAppOwnershipType(null); + Assertions.assertNull(request.getInAppOwnershipType()); + Assertions.assertNull(request.getRawInAppOwnershipType()); + } + + @Test + public void testTransactionHistoryRequestEquality() { + TransactionHistoryRequest request = new TransactionHistoryRequest() + .startDate(123455L) + .endDate(123456L) + .productIds(List.of("com.example.1", "com.example.2")) + .productTypes(List.of(TransactionHistoryRequest.ProductType.CONSUMABLE, TransactionHistoryRequest.ProductType.AUTO_RENEWABLE)) + .sort(TransactionHistoryRequest.Order.ASCENDING) + .subscriptionGroupIdentifiers(List.of("sub_group_id")) + .inAppOwnershipType(InAppOwnershipType.FAMILY_SHARED) + .revoked(false); + TransactionHistoryRequest otherRequest = new TransactionHistoryRequest() + .startDate(123455L) + .endDate(123456L) + .productIds(List.of("com.example.1", "com.example.2")) + .productTypes(List.of(TransactionHistoryRequest.ProductType.CONSUMABLE, TransactionHistoryRequest.ProductType.AUTO_RENEWABLE)) + .sort(TransactionHistoryRequest.Order.ASCENDING) + .subscriptionGroupIdentifiers(List.of("sub_group_id")) + .revoked(false); + otherRequest.setRawInAppOwnershipType("FAMILY_SHARED"); + + Assertions.assertEquals(request, otherRequest); + Assertions.assertEquals(request.hashCode(), otherRequest.hashCode()); + + otherRequest.setRevoked(true); + Assertions.assertNotEquals(request, otherRequest); + + otherRequest.setRevoked(false); + otherRequest.setInAppOwnershipType(InAppOwnershipType.PURCHASED); + Assertions.assertNotEquals(request, otherRequest); + + Assertions.assertEquals(new TransactionHistoryRequest(), new TransactionHistoryRequest()); + Assertions.assertEquals(new TransactionHistoryRequest().hashCode(), new TransactionHistoryRequest().hashCode()); + Assertions.assertNotEquals(new TransactionHistoryRequest(), null); + } + + @Test + public void testAccountTenureToString() { + Assertions.assertEquals("0", AccountTenure.UNDECLARED.toString()); + Assertions.assertEquals("7", AccountTenure.GREATER_THAN_THREE_HUNDRED_SIXTY_FIVE_DAYS.toString()); + for (AccountTenure accountTenure : AccountTenure.values()) { + Assertions.assertEquals(String.valueOf(accountTenure.getValue()), accountTenure.toString()); + } + } + + @Test + public void testExtendRenewalDateRequestLimits() { + String identifier128 = "a".repeat(128); + String identifier129 = "a".repeat(129); + for (int days : new int[]{1, 90}) { + ExtendRenewalDateRequest request = new ExtendRenewalDateRequest(days, ExtendReasonCode.CUSTOMER_SATISFACTION, identifier128); + Assertions.assertEquals(days, request.getExtendByDays()); + Assertions.assertEquals(days, new ExtendRenewalDateRequest(days, 99, identifier128).getExtendByDays()); + Assertions.assertEquals(days, new ExtendRenewalDateRequest(45, 99, "id").extendByDays(days).getExtendByDays()); + request.setExtendByDays(days); + Assertions.assertEquals(days, request.getExtendByDays()); + MassExtendRenewalDateRequest massRequest = new MassExtendRenewalDateRequest(identifier128, days, ExtendReasonCode.CUSTOMER_SATISFACTION, "com.example.productId"); + Assertions.assertEquals(days, massRequest.getExtendByDays()); + Assertions.assertEquals(days, new MassExtendRenewalDateRequest(identifier128, days, 99, "com.example.productId").getExtendByDays()); + Assertions.assertEquals(days, new MassExtendRenewalDateRequest("id", 45, 99, "com.example.productId").extendByDays(days).getExtendByDays()); + massRequest.setExtendByDays(days); + Assertions.assertEquals(days, massRequest.getExtendByDays()); + } + ExtendRenewalDateRequest request = new ExtendRenewalDateRequest(45, ExtendReasonCode.CUSTOMER_SATISFACTION, "id"); + MassExtendRenewalDateRequest massRequest = new MassExtendRenewalDateRequest("id", 45, ExtendReasonCode.CUSTOMER_SATISFACTION, "com.example.productId"); + for (int days : new int[]{0, 91}) { + Assertions.assertThrows(IllegalArgumentException.class, () -> new ExtendRenewalDateRequest(days, ExtendReasonCode.CUSTOMER_SATISFACTION, "id")); + Assertions.assertThrows(IllegalArgumentException.class, () -> new ExtendRenewalDateRequest(days, 99, "id")); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.extendByDays(days)); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setExtendByDays(days)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new MassExtendRenewalDateRequest("id", days, ExtendReasonCode.CUSTOMER_SATISFACTION, "com.example.productId")); + Assertions.assertThrows(IllegalArgumentException.class, () -> new MassExtendRenewalDateRequest("id", days, 99, "com.example.productId")); + Assertions.assertThrows(IllegalArgumentException.class, () -> massRequest.extendByDays(days)); + Assertions.assertThrows(IllegalArgumentException.class, () -> massRequest.setExtendByDays(days)); + } + Assertions.assertEquals(45, request.getExtendByDays()); + Assertions.assertEquals(45, massRequest.getExtendByDays()); + + Assertions.assertEquals(identifier128, request.requestIdentifier(identifier128).getRequestIdentifier()); + Assertions.assertEquals(identifier128, massRequest.requestIdentifier(identifier128).getRequestIdentifier()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new ExtendRenewalDateRequest(45, ExtendReasonCode.CUSTOMER_SATISFACTION, identifier129)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new ExtendRenewalDateRequest(45, 99, identifier129)); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.requestIdentifier(identifier129)); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setRequestIdentifier(identifier129)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new MassExtendRenewalDateRequest(identifier129, 45, ExtendReasonCode.CUSTOMER_SATISFACTION, "com.example.productId")); + Assertions.assertThrows(IllegalArgumentException.class, () -> new MassExtendRenewalDateRequest(identifier129, 45, 99, "com.example.productId")); + Assertions.assertThrows(IllegalArgumentException.class, () -> massRequest.requestIdentifier(identifier129)); + Assertions.assertThrows(IllegalArgumentException.class, () -> massRequest.setRequestIdentifier(identifier129)); + Assertions.assertEquals(identifier128, request.getRequestIdentifier()); + Assertions.assertEquals(identifier128, massRequest.getRequestIdentifier()); + } + + @Test + public void testMassExtendRenewalDateRequestStorefrontCountryCodeLimits() { + MassExtendRenewalDateRequest request = new MassExtendRenewalDateRequest("id", 45, ExtendReasonCode.CUSTOMER_SATISFACTION, "com.example.productId"); + Assertions.assertEquals(List.of("USA", "CA"), request.storefrontCountryCodes(List.of("USA", "CA")).getStorefrontCountryCodes()); + request.setStorefrontCountryCodes(null); + Assertions.assertNull(request.getStorefrontCountryCodes()); + request.addStorefrontCountryCode("USA"); + Assertions.assertEquals(List.of("USA"), request.getStorefrontCountryCodes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.addStorefrontCountryCode("ABCD")); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.storefrontCountryCodes(List.of("USA", "ABCD"))); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setStorefrontCountryCodes(List.of("ABCD"))); + Assertions.assertEquals(List.of("USA"), request.getStorefrontCountryCodes()); + } + + @Test + public void testConsumptionRequestConsumptionPercentageLimits() { + ConsumptionRequest request = new ConsumptionRequest(true, DeliveryStatus.DELIVERED, false); + for (int percentage : new int[]{0, 100000}) { + Assertions.assertEquals(percentage, request.consumptionPercentage(percentage).getConsumptionPercentage()); + request.setConsumptionPercentage(null); + request.setConsumptionPercentage(percentage); + Assertions.assertEquals(percentage, request.getConsumptionPercentage()); + } + for (int percentage : new int[]{-1, 100001}) { + Assertions.assertThrows(IllegalArgumentException.class, () -> request.consumptionPercentage(percentage)); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setConsumptionPercentage(percentage)); + } + Assertions.assertEquals(100000, request.getConsumptionPercentage()); + Assertions.assertNull(request.consumptionPercentage(null).getConsumptionPercentage()); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/model/AppTransactionTest.java b/src/test/java/com/apple/itunes/storekit/model/AppTransactionTest.java index 6fbcdc90..2d88533a 100644 --- a/src/test/java/com/apple/itunes/storekit/model/AppTransactionTest.java +++ b/src/test/java/com/apple/itunes/storekit/model/AppTransactionTest.java @@ -36,5 +36,8 @@ public void testAppTransactionDecoding() throws IOException, NoSuchAlgorithmExce Assertions.assertEquals("71134", appTransaction.getAppTransactionId()); Assertions.assertEquals(PurchasePlatform.IOS, appTransaction.getOriginalPlatform()); Assertions.assertEquals("iOS", appTransaction.getRawOriginalPlatform()); + Assertions.assertEquals(StoreType.CONSUMER, appTransaction.getStoreType()); + Assertions.assertEquals("CONSUMER", appTransaction.getRawStoreType()); + Assertions.assertNull(appTransaction.getUnknownFields()); } } diff --git a/src/test/java/com/apple/itunes/storekit/model/ConsistencyRulesTest.java b/src/test/java/com/apple/itunes/storekit/model/ConsistencyRulesTest.java new file mode 100644 index 00000000..fcaef8b2 --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/model/ConsistencyRulesTest.java @@ -0,0 +1,645 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + +public class ConsistencyRulesTest { + + private static final AdvancedCommerceRequestInfo REQUEST_INFO = + new AdvancedCommerceRequestInfo(UUID.fromString("932c6903-0ab8-4469-9f21-015f6fab013c")); + + private static final ObjectMapper objectMapper = createObjectMapper(); + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + return objectMapper; + } + + @SuppressWarnings("unchecked") + private static Map serialize(Object value) throws Exception { + return objectMapper.readValue(objectMapper.writeValueAsString(value), Map.class); + } + + private static T newInstance(Class type) throws Exception { + Constructor constructor = type.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } + + private static void assertEqualObjects(Object a, Object b) { + Assertions.assertEquals(a, b); + Assertions.assertEquals(b, a); + Assertions.assertEquals(a.hashCode(), b.hashCode()); + } + + private static void assertNotEqualObjects(Object a, Object b) { + Assertions.assertNotEquals(a, b); + Assertions.assertNotEquals(b, a); + } + + @Test + public void testRevokeRequestRefundTypeIsTypedWithRawStorage() throws Exception { + AdvancedCommerceSubscriptionRevokeRequest typed = new AdvancedCommerceSubscriptionRevokeRequest( + REQUEST_INFO, AdvancedCommerceRefundReason.LEGAL, true, AdvancedCommerceRefundType.PRORATED); + AdvancedCommerceSubscriptionRevokeRequest raw = new AdvancedCommerceSubscriptionRevokeRequest( + REQUEST_INFO, "LEGAL", true, "PRORATED"); + assertEqualObjects(typed, raw); + Assertions.assertEquals(AdvancedCommerceRefundType.PRORATED, raw.getRefundType()); + Assertions.assertEquals("PRORATED", raw.getRawRefundType()); + Assertions.assertEquals(Map.of("requestInfo", Map.of("requestReferenceId", "932c6903-0ab8-4469-9f21-015f6fab013c"), + "refundReason", "LEGAL", "refundType", "PRORATED", "refundRiskingPreference", true), serialize(typed)); + + AdvancedCommerceSubscriptionRevokeRequest unknown = new AdvancedCommerceSubscriptionRevokeRequest( + REQUEST_INFO, "LEGAL", true, "PARTIAL"); + Assertions.assertNull(unknown.getRefundType()); + Assertions.assertEquals("PARTIAL", unknown.getRawRefundType()); + Assertions.assertEquals("PARTIAL", serialize(unknown).get("refundType")); + AdvancedCommerceSubscriptionRevokeRequest decoded = objectMapper.readValue( + objectMapper.writeValueAsString(unknown), AdvancedCommerceSubscriptionRevokeRequest.class); + Assertions.assertEquals(unknown, decoded); + Assertions.assertEquals("PARTIAL", decoded.getRawRefundType()); + + Assertions.assertSame(typed, typed.refundType(AdvancedCommerceRefundType.FULL)); + Assertions.assertEquals("FULL", typed.getRawRefundType()); + Assertions.assertThrows(NullPointerException.class, () -> typed.refundType(null)); + Assertions.assertThrows(NullPointerException.class, () -> typed.setRefundType(null)); + Assertions.assertThrows(NullPointerException.class, () -> typed.setRawRefundType(null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionRevokeRequest( + REQUEST_INFO, AdvancedCommerceRefundReason.LEGAL, true, (AdvancedCommerceRefundType) null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionRevokeRequest( + REQUEST_INFO, "LEGAL", true, (String) null)); + } + + @Test + public void testRevokeRequestHasNoStringTypedRefundTypeAccessors() throws Exception { + Class type = AdvancedCommerceSubscriptionRevokeRequest.class; + Assertions.assertEquals(AdvancedCommerceRefundType.class, type.getMethod("getRefundType").getReturnType()); + Assertions.assertThrows(NoSuchMethodException.class, () -> type.getMethod("refundType", String.class)); + Assertions.assertThrows(NoSuchMethodException.class, () -> type.getMethod("setRefundType", String.class)); + Assertions.assertThrows(NoSuchMethodException.class, () -> type.getConstructor( + AdvancedCommerceRequestInfo.class, Boolean.class, AdvancedCommerceRefundReason.class, String.class)); + } + + @Test + public void testAdvancedCommerceResponsesCompareInheritedMembers() throws Exception { + List> pairs = List.of( + List.of(new AdvancedCommerceSubscriptionCancelResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionCancelResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionCancelResponse("renewal", "other")), + List.of(new AdvancedCommerceSubscriptionChangeMetadataResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionChangeMetadataResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionChangeMetadataResponse("other", "transaction")), + List.of(new AdvancedCommerceSubscriptionPriceChangeResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionPriceChangeResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionPriceChangeResponse("renewal", "other")), + List.of(new AdvancedCommerceSubscriptionRevokeResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionRevokeResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionRevokeResponse("other", "transaction"))); + for (List pair : pairs) { + Object a = pair.get(0); + Assertions.assertEquals(a.getClass(), a.getClass().getDeclaredMethod("equals", Object.class).getDeclaringClass()); + Assertions.assertEquals(a.getClass(), a.getClass().getDeclaredMethod("hashCode").getDeclaringClass()); + assertEqualObjects(a, pair.get(1)); + assertNotEqualObjects(a, pair.get(2)); + ((AbstractAdvancedCommerceResponse) pair.get(1)).unknownFields(Map.of("newKey", "value")); + assertNotEqualObjects(a, pair.get(1)); + } + assertNotEqualObjects(new AdvancedCommerceSubscriptionCancelResponse("renewal", "transaction"), + new AdvancedCommerceSubscriptionRevokeResponse("renewal", "transaction")); + } + + @Test + public void testAdvancedCommerceItemsCompareInheritedMembers() throws Exception { + AdvancedCommerceSubscriptionMigrateItem migrateItem = new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "name"); + assertEqualObjects(migrateItem, new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "name")); + assertNotEqualObjects(migrateItem, new AdvancedCommerceSubscriptionMigrateItem("sku2", "description", "name")); + assertNotEqualObjects(migrateItem, new AdvancedCommerceSubscriptionMigrateItem("sku", "description2", "name")); + assertNotEqualObjects(migrateItem, new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "name2")); + assertNotEqualObjects(migrateItem, new AdvancedCommerceSubscriptionMigrateRenewalItem("sku", "description", "name")); + + AdvancedCommerceSubscriptionModifyRemoveItem removeItem = new AdvancedCommerceSubscriptionModifyRemoveItem("sku"); + assertEqualObjects(removeItem, new AdvancedCommerceSubscriptionModifyRemoveItem("sku")); + assertNotEqualObjects(removeItem, new AdvancedCommerceSubscriptionModifyRemoveItem("sku2")); + AdvancedCommerceSubscriptionReactivateItem reactivateItem = new AdvancedCommerceSubscriptionReactivateItem("sku"); + assertEqualObjects(reactivateItem, new AdvancedCommerceSubscriptionReactivateItem("sku")); + assertNotEqualObjects(reactivateItem, new AdvancedCommerceSubscriptionReactivateItem("sku2")); + assertNotEqualObjects(removeItem, reactivateItem); + + for (Class type : List.of(AdvancedCommerceSubscriptionMigrateItem.class, AdvancedCommerceSubscriptionModifyRemoveItem.class, + AdvancedCommerceSubscriptionReactivateItem.class)) { + Assertions.assertEquals(type, type.getDeclaredMethod("equals", Object.class).getDeclaringClass()); + Assertions.assertEquals(type, type.getDeclaredMethod("hashCode").getDeclaringClass()); + } + } + + @Test + public void testRequestRefundItemEqualsComparesSkuThroughTheBaseClass() { + AdvancedCommerceRequestRefundItem item = new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, + AdvancedCommerceRefundType.CUSTOM, true).refundAmount(1500L); + AdvancedCommerceRequestRefundItem same = new AdvancedCommerceRequestRefundItem("sku", "LEGAL", "CUSTOM", true).refundAmount(1500L); + assertEqualObjects(item, same); + assertNotEqualObjects(item, new AdvancedCommerceRequestRefundItem("sku2", "LEGAL", "CUSTOM", true).refundAmount(1500L)); + assertNotEqualObjects(item, new AdvancedCommerceRequestRefundItem("sku", "LEGAL", "CUSTOM", true).refundAmount(1000L)); + Assertions.assertEquals(Objects.hash(item.getSku(), item.getRefundAmount(), item.getRawRefundReason(), item.getRawRefundType(), + item.getRevoke()), item.hashCode()); + } + + @Test + public void testUpdateAppAccountTokenRequestEqualsUsesTheExactClass() { + UUID token = UUID.fromString("7389a31a-fb6d-4569-a2a6-db7d85d84813"); + UpdateAppAccountTokenRequest request = new UpdateAppAccountTokenRequest(token); + assertEqualObjects(request, new UpdateAppAccountTokenRequest(token)); + assertNotEqualObjects(request, new UpdateAppAccountTokenRequest(UUID.fromString("00000000-0000-0000-0000-000000000000"))); + Assertions.assertNotEquals(request, null); + Assertions.assertEquals(Objects.hash(token), request.hashCode()); + UpdateAppAccountTokenRequest subclass = new UpdateAppAccountTokenRequest(token) { + }; + assertNotEqualObjects(request, subclass); + } + + @Test + public void testRawConstructorsOfAdvancedCommerceRequestTypes() { + assertEqualObjects(new AdvancedCommerceSubscriptionChangeMetadataDescriptors(AdvancedCommerceEffective.IMMEDIATELY), + new AdvancedCommerceSubscriptionChangeMetadataDescriptors("IMMEDIATELY")); + AdvancedCommerceSubscriptionChangeMetadataDescriptors changeMetadataDescriptors = + new AdvancedCommerceSubscriptionChangeMetadataDescriptors("LATER"); + Assertions.assertNull(changeMetadataDescriptors.getEffective()); + Assertions.assertEquals("LATER", changeMetadataDescriptors.getRawEffective()); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionChangeMetadataDescriptors((String) null)); + + assertEqualObjects(new AdvancedCommerceSubscriptionModifyDescriptors(AdvancedCommerceEffective.NEXT_BILL_CYCLE), + new AdvancedCommerceSubscriptionModifyDescriptors("NEXT_BILL_CYCLE")); + AdvancedCommerceSubscriptionModifyDescriptors modifyDescriptors = new AdvancedCommerceSubscriptionModifyDescriptors("LATER"); + Assertions.assertNull(modifyDescriptors.getEffective()); + Assertions.assertEquals("LATER", modifyDescriptors.getRawEffective()); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyDescriptors((String) null)); + + assertEqualObjects(new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", AdvancedCommerceEffective.IMMEDIATELY), + new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", "IMMEDIATELY")); + AdvancedCommerceSubscriptionChangeMetadataItem changeMetadataItem = new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", "LATER"); + Assertions.assertNull(changeMetadataItem.getEffective()); + Assertions.assertEquals("LATER", changeMetadataItem.getRawEffective()); + Assertions.assertEquals("currentSku", changeMetadataItem.getCurrentSku()); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionChangeMetadataItem("currentSku", (String) null)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionChangeMetadataItem(null, "LATER")); + + assertEqualObjects(new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "name", + "currentSku", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE), + new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "name", "currentSku", "IMMEDIATELY", 1000L, "UPGRADE")); + AdvancedCommerceSubscriptionModifyChangeItem modifyChangeItem = new AdvancedCommerceSubscriptionModifyChangeItem( + "sku", "description", "name", "currentSku", "LATER", 1000L, "SIDEGRADE"); + Assertions.assertNull(modifyChangeItem.getEffective()); + Assertions.assertEquals("LATER", modifyChangeItem.getRawEffective()); + Assertions.assertNull(modifyChangeItem.getReason()); + Assertions.assertEquals("SIDEGRADE", modifyChangeItem.getRawReason()); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyChangeItem( + "sku", "description", "name", "currentSku", null, 1000L, "UPGRADE")); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyChangeItem( + "sku", "description", "name", "currentSku", "IMMEDIATELY", 1000L, null)); + + List items = List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "name", 1000L)); + AdvancedCommerceDescriptors descriptors = new AdvancedCommerceDescriptors("description", "name"); + assertEqualObjects(new AdvancedCommerceSubscriptionCreateRequest(REQUEST_INFO, "USD", descriptors, items, AdvancedCommercePeriod.P1M, "taxCode"), + new AdvancedCommerceSubscriptionCreateRequest(REQUEST_INFO, "USD", descriptors, items, "P1M", "taxCode")); + AdvancedCommerceSubscriptionCreateRequest createRequest = new AdvancedCommerceSubscriptionCreateRequest( + REQUEST_INFO, "USD", descriptors, items, "P2W", "taxCode"); + Assertions.assertNull(createRequest.getPeriod()); + Assertions.assertEquals("P2W", createRequest.getRawPeriod()); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionCreateRequest( + REQUEST_INFO, "USD", descriptors, items, (String) null, "taxCode")); + } + + @Test + public void testModifyAddItemPriceIsBoxedAndRequired() throws Exception { + Assertions.assertNotNull(AdvancedCommerceSubscriptionModifyAddItem.class.getConstructor(String.class, String.class, String.class, Long.class)); + Assertions.assertNotNull(AdvancedCommerceSubscriptionModifyAddItem.class.getMethod("price", Long.class)); + Assertions.assertThrows(NoSuchMethodException.class, + () -> AdvancedCommerceSubscriptionModifyAddItem.class.getConstructor(String.class, String.class, String.class, long.class)); + Assertions.assertThrows(NullPointerException.class, () -> new AdvancedCommerceSubscriptionModifyAddItem("sku", "description", "name", null)); + AdvancedCommerceSubscriptionModifyAddItem item = new AdvancedCommerceSubscriptionModifyAddItem("sku", "description", "name", 1000L); + Assertions.assertEquals(Long.valueOf(1000L), item.getPrice()); + Assertions.assertThrows(NullPointerException.class, () -> item.price(null)); + Assertions.assertThrows(NullPointerException.class, () -> item.setPrice(null)); + } + + @Test + public void testConsumptionRequestBooleansAreBoxedAndRequired() throws Exception { + ConsumptionRequest request = new ConsumptionRequest(false, DeliveryStatus.DELIVERED, false); + Assertions.assertEquals(Boolean.FALSE, request.getCustomerConsented()); + Assertions.assertEquals(Boolean.FALSE, request.getSampleContentProvided()); + Assertions.assertEquals(Boolean.class, ConsumptionRequest.class.getMethod("getCustomerConsented").getReturnType()); + Assertions.assertEquals(Boolean.class, ConsumptionRequest.class.getMethod("getSampleContentProvided").getReturnType()); + Assertions.assertEquals(Map.of("customerConsented", false, "sampleContentProvided", false, "deliveryStatus", "DELIVERED"), serialize(request)); + assertEqualObjects(request, new ConsumptionRequest(false, "DELIVERED", false)); + assertNotEqualObjects(request, new ConsumptionRequest(true, DeliveryStatus.DELIVERED, false)); + + Assertions.assertThrows(NullPointerException.class, () -> new ConsumptionRequest(null, DeliveryStatus.DELIVERED, true)); + Assertions.assertThrows(NullPointerException.class, () -> new ConsumptionRequest(true, DeliveryStatus.DELIVERED, null)); + Assertions.assertThrows(NullPointerException.class, () -> new ConsumptionRequest(null, "DELIVERED", true)); + Assertions.assertThrows(NullPointerException.class, () -> new ConsumptionRequest(true, "DELIVERED", null)); + Assertions.assertThrows(NullPointerException.class, () -> request.customerConsented(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setCustomerConsented(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.sampleContentProvided(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setSampleContentProvided(null)); + } + + private static final Set EXPECTED_ADDERS = Set.of( + "AdvancedCommercePriceIncreaseInfo.addDependentSKU", + "AdvancedCommerceRenewalInfo.addItem", + "AdvancedCommerceRequestRefundRequest.addItem", + "AdvancedCommerceSubscriptionChangeMetadataRequest.addItem", + "AdvancedCommerceSubscriptionCreateRequest.addItem", + "AdvancedCommerceSubscriptionMigrateRequest.addItem", + "AdvancedCommerceSubscriptionMigrateRequest.addRenewalItem", + "AdvancedCommerceSubscriptionModifyInAppRequest.addAddItem", + "AdvancedCommerceSubscriptionModifyInAppRequest.addChangeItem", + "AdvancedCommerceSubscriptionModifyInAppRequest.addRemoveItem", + "AdvancedCommerceSubscriptionPriceChangeItem.addDependentSKU", + "AdvancedCommerceSubscriptionPriceChangeRequest.addItem", + "AdvancedCommerceSubscriptionReactivateInAppRequest.addItem", + "AdvancedCommerceTransactionInfo.addItem", + "AdvancedCommerceTransactionItem.addRefund", + "CheckTestNotificationResponse.addSendAttempt", + "GetCustomerGroupsResponse.addGroup", + "GetGroupMembersResponse.addMember", + "GetImageListResponse.addImageIdentifier", + "GetMessageListResponse.addMessageIdentifier", + "GroupEntry.addRole", + "HistoryResponse.addSignedTransaction", + "JWSRenewalInfoDecodedPayload.addEligibleWinBackOfferId", + "MassExtendRenewalDateRequest.addStorefrontCountryCode", + "NotificationHistoryResponse.addNotificationHistory", + "NotificationHistoryResponseItem.addSendAttempt", + "OrderLookupResponse.addSignedTransaction", + "RefundHistoryResponse.addSignedTransaction", + "StatusResponse.addData", + "SubscriptionGroupIdentifierItem.addLastTransaction", + "Summary.addStorefrontCountryCode", + "UploadMessageRequestBody.addBulletPoint"); + + private static List> modelClasses() throws Exception { + String pkg = AppTransaction.class.getPackageName(); + URL root = AppTransaction.class.getProtectionDomain().getCodeSource().getLocation(); + List> classes = new ArrayList<>(); + String[] names = new File(new File(root.toURI()), pkg.replace('.', File.separatorChar)).list(); + Assertions.assertNotNull(names); + Arrays.sort(names); + for (String fileName : names) { + if (fileName.endsWith(".class") && !fileName.contains("$")) { + classes.add(Class.forName(pkg + "." + fileName.substring(0, fileName.length() - ".class".length()))); + } + } + return classes; + } + + private static Object sampleElement(Class type) throws Exception { + return type == String.class ? "abc" : newInstance(type); + } + + private static String upperFirst(String s) { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + + @Test + public void testEveryListFieldHasANullRejectingAdderNamedAfterTheSingularJsonKey() throws Exception { + Set found = new TreeSet<>(); + for (Class type : modelClasses()) { + if (type.isEnum() || type.isInterface() || Modifier.isAbstract(type.getModifiers())) { + continue; + } + for (Field field : type.getDeclaredFields()) { + JsonProperty property = field.getAnnotation(JsonProperty.class); + if (property == null || field.getType() != List.class) { + continue; + } + String key = property.value(); + String adderName = "add" + upperFirst(key.endsWith("s") ? key.substring(0, key.length() - 1) : key); + Class elementType = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]; + Method adder = type.getMethod(adderName, elementType); + Assertions.assertEquals(type, adder.getReturnType(), adderName); + Assertions.assertFalse(adder.isAnnotationPresent(Deprecated.class), adderName); + found.add(type.getSimpleName() + "." + adderName); + + Object instance = newInstance(type); + if (property.required()) { + field.setAccessible(true); + field.set(instance, new ArrayList<>()); + } + InvocationTargetException e = Assertions.assertThrows(InvocationTargetException.class, () -> adder.invoke(instance, (Object) null)); + Assertions.assertInstanceOf(NullPointerException.class, e.getCause(), type.getSimpleName() + "." + adderName); + Object element = sampleElement(elementType); + Assertions.assertSame(instance, adder.invoke(instance, element)); + Assertions.assertSame(instance, adder.invoke(instance, element)); + Method getter = type.getMethod("get" + upperFirst(field.getName())); + Assertions.assertEquals(List.of(element, element), getter.invoke(instance)); + } + } + Assertions.assertEquals(new TreeSet<>(EXPECTED_ADDERS), found); + } + + @Test + public void testPreviousAdderNamesWereRemoved() { + List> removed = List.of( + List.of(GetCustomerGroupsResponse.class, "addGroupsItem"), + List.of(GetGroupMembersResponse.class, "addMembersItem"), + List.of(GroupEntry.class, "addRolesItem"), + List.of(HistoryResponse.class, "addSignedTransactionsItem"), + List.of(MassExtendRenewalDateRequest.class, "addStorefrontCountryCodesItem"), + List.of(NotificationHistoryResponse.class, "addNotificationHistoryItem"), + List.of(OrderLookupResponse.class, "addSignedTransactionsItem"), + List.of(RefundHistoryResponse.class, "addSignedTransactionsItem"), + List.of(StatusResponse.class, "addDataItem"), + List.of(SubscriptionGroupIdentifierItem.class, "addLastTransactionsItem"), + List.of(Summary.class, "addStorefrontCountryCodesItem")); + for (List r : removed) { + Class type = (Class) r.get(0); + Assertions.assertTrue(Arrays.stream(type.getMethods()).noneMatch(m -> m.getName().equals(r.get(1))), + type.getSimpleName() + "." + r.get(1)); + } + } + + @Test + public void testModelsHaveNoDeprecatedMembers() throws Exception { + Set deprecatedTypes = new TreeSet<>(); + for (Class type : modelClasses()) { + if (type.isAnnotationPresent(Deprecated.class)) { + deprecatedTypes.add(type.getSimpleName()); + } + for (Method method : type.getDeclaredMethods()) { + Assertions.assertFalse(method.isAnnotationPresent(Deprecated.class), type.getSimpleName() + "." + method.getName()); + } + for (Constructor constructor : type.getDeclaredConstructors()) { + Assertions.assertFalse(constructor.isAnnotationPresent(Deprecated.class), constructor.toString()); + } + for (Field field : type.getDeclaredFields()) { + Assertions.assertFalse(field.isAnnotationPresent(Deprecated.class), type.getSimpleName() + "." + field.getName()); + } + } + Assertions.assertEquals(new TreeSet<>(List.of("ConsumptionRequestV1", "DeliveryStatusV1", "RefundPreferenceV1")), deprecatedTypes); + Assertions.assertThrows(NoSuchMethodException.class, () -> AdvancedCommerceRequestInfo.class.getMethod("consistencyToken")); + Assertions.assertThrows(NoSuchMethodException.class, + () -> UploadMessageRequestBody.class.getConstructor(String.class, String.class, UploadMessageImage.class)); + } + + @Test + public void testBulletPointAdderKeepsTheMaximumCount() { + UploadMessageRequestBody body = new UploadMessageRequestBody("header", "body"); + for (int i = 0; i < 5; i++) { + body.addBulletPoint(new BulletPoint("text " + i, UUID.randomUUID(), "alt text")); + } + Assertions.assertThrows(IllegalArgumentException.class, + () -> body.addBulletPoint(new BulletPoint("text 5", UUID.randomUUID(), "alt text"))); + Assertions.assertEquals(5, body.getBulletPoints().size()); + } + + @Test + public void testAdvancedCommerceRequestAddersStillRejectNull() { + AdvancedCommerceSubscriptionPriceChangeItem item = new AdvancedCommerceSubscriptionPriceChangeItem("sku", 1000L); + Assertions.assertThrows(NullPointerException.class, () -> item.addDependentSKU(null)); + Assertions.assertThrows(IllegalArgumentException.class, () -> item.addDependentSKU("x".repeat(129))); + Assertions.assertEquals(List.of("dependent"), item.addDependentSKU("dependent").getDependentSKUs()); + } + + @Test + public void testSkuMemberNames() throws Exception { + AdvancedCommerceSubscriptionModifyChangeItem modifyChangeItem = new AdvancedCommerceSubscriptionModifyChangeItem( + "sku", "description", "name", "current", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE); + Assertions.assertEquals("current", modifyChangeItem.getCurrentSku()); + Assertions.assertEquals("sku", modifyChangeItem.getSku()); + Assertions.assertEquals(String.class, AdvancedCommerceSubscriptionModifyChangeItem.class.getDeclaredField("currentSku").getType()); + Assertions.assertEquals(String.class, AdvancedCommerceSubscriptionChangeMetadataItem.class.getDeclaredField("currentSku").getType()); + Assertions.assertEquals(String.class, AdvancedCommerceRenewalItem.class.getDeclaredField("sku").getType()); + Assertions.assertEquals(String.class, AdvancedCommerceTransactionItem.class.getDeclaredField("sku").getType()); + Assertions.assertEquals(String.class, AdvancedCommerceSubscriptionChangeMetadataItem.class.getDeclaredField("sku").getType()); + Assertions.assertNotNull(AdvancedCommerceRenewalItem.class.getMethod("getSku")); + Assertions.assertNotNull(AdvancedCommerceTransactionItem.class.getMethod("getSku")); + Assertions.assertNotNull(AdvancedCommerceSubscriptionChangeMetadataItem.class.getMethod("getCurrentSku")); + + for (String alias : List.of("currentSKU", "getCurrentSKU", "setCurrentSKU")) { + Assertions.assertTrue(Arrays.stream(AdvancedCommerceSubscriptionModifyChangeItem.class.getMethods()) + .noneMatch(m -> m.getName().equals(alias)), alias); + } + modifyChangeItem.setCurrentSku("current2"); + Map json = serialize(modifyChangeItem); + Assertions.assertEquals("current2", json.get("currentSKU")); + Assertions.assertEquals("sku", json.get("SKU")); + ObjectMapper defaultObjectMapper = new ObjectMapper(); + Map defaultJson = defaultObjectMapper.readValue(defaultObjectMapper.writeValueAsString(modifyChangeItem), Map.class); + Assertions.assertEquals("current2", defaultJson.get("currentSKU")); + Assertions.assertFalse(defaultJson.containsKey("currentSku")); + Assertions.assertEquals("decoded", defaultObjectMapper.readValue( + "{\"currentSKU\": \"decoded\"}", AdvancedCommerceSubscriptionModifyChangeItem.class).getCurrentSku()); + } + + @Test + public void testDescriptorsFieldsArePrivate() throws Exception { + for (String name : List.of("description", "displayName", "unknownFields")) { + Assertions.assertTrue(Modifier.isPrivate(AdvancedCommerceDescriptors.class.getDeclaredField(name).getModifiers()), name); + } + AdvancedCommerceSubscriptionMigrateDescriptors descriptors = new AdvancedCommerceSubscriptionMigrateDescriptors("description", "name"); + Assertions.assertEquals("description", descriptors.getDescription()); + Assertions.assertEquals("name", descriptors.getDisplayName()); + Assertions.assertEquals(Map.of("description", "description", "displayName", "name"), serialize(descriptors)); + assertEqualObjects(descriptors, new AdvancedCommerceSubscriptionMigrateDescriptors("description", "name")); + assertNotEqualObjects(descriptors, new AdvancedCommerceSubscriptionMigrateDescriptors("description", "name2")); + assertNotEqualObjects(descriptors, new AdvancedCommerceDescriptors("description", "name")); + } + + @Test + public void testDecodedRetentionMessagingResponsesSerializeNullValues() throws Exception { + Assertions.assertNull(DefaultConfigurationResponse.class.getAnnotation(JsonInclude.class)); + Assertions.assertNull(RealtimeUrlResponse.class.getAnnotation(JsonInclude.class)); + Assertions.assertNotNull(DefaultConfigurationRequest.class.getAnnotation(JsonInclude.class)); + Assertions.assertNotNull(RealtimeUrlRequest.class.getAnnotation(JsonInclude.class)); + + Assertions.assertEquals("{\"realtimeURL\":null}", objectMapper.writeValueAsString(newInstance(RealtimeUrlResponse.class))); + Assertions.assertEquals("{\"messageIdentifier\":null}", objectMapper.writeValueAsString(newInstance(DefaultConfigurationResponse.class))); + RealtimeUrlResponse decoded = objectMapper.readValue("{\"realtimeURL\": \"https://example.com/realtime\"}", RealtimeUrlResponse.class); + Assertions.assertEquals("{\"realtimeURL\":\"https://example.com/realtime\"}", objectMapper.writeValueAsString(decoded)); + } + + @Test + public void testAppTransactionHasAPublicNoArgConstructor() throws Exception { + Assertions.assertTrue(Modifier.isPublic(AppTransaction.class.getConstructor().getModifiers())); + Assertions.assertEquals(1, AppTransaction.class.getDeclaredConstructors().length); + Assertions.assertEquals(new AppTransaction(), new AppTransaction()); + } + + @Test + public void testSummaryRequestIdentifierIsAUuid() throws Exception { + Summary summary = objectMapper.readValue("{\"requestIdentifier\": \"EFB27071-45A4-4ACA-9854-2A1E9146F265\"}", Summary.class); + Assertions.assertEquals(UUID.fromString("efb27071-45a4-4aca-9854-2a1e9146f265"), summary.getRequestIdentifier()); + Assertions.assertEquals(UUID.class, Summary.class.getMethod("getRequestIdentifier").getReturnType()); + Assertions.assertThrows(JsonMappingException.class, + () -> objectMapper.readValue("{\"requestIdentifier\": \"not-a-uuid\"}", Summary.class)); + } + + @Test + public void testDecodedModelsCheckTheirDocumentedLimits() throws Exception { + Assertions.assertEquals(12, objectMapper.readValue("{\"billingPeriodNumber\": 12}", TransactionCommitmentInfo.class).getBillingPeriodNumber()); + Assertions.assertEquals(100000, objectMapper.readValue("{\"revocationPercentage\": 100000}", JWSTransactionDecodedPayload.class).getRevocationPercentage()); + Assertions.assertEquals(List.of("USA"), objectMapper.readValue("{\"storefrontCountryCodes\": [\"USA\"]}", Summary.class).getStorefrontCountryCodes()); + String requestIdentifier = "a".repeat(128); + Assertions.assertEquals(requestIdentifier, objectMapper.readValue("{\"requestIdentifier\": \"" + requestIdentifier + "\"}", MassExtendRenewalDateResponse.class).getRequestIdentifier()); + Assertions.assertEquals(requestIdentifier, objectMapper.readValue("{\"requestIdentifier\": \"" + requestIdentifier + "\"}", MassExtendRenewalDateStatusResponse.class).getRequestIdentifier()); + String realtimeURL = "a".repeat(256); + Assertions.assertEquals(realtimeURL, objectMapper.readValue("{\"realtimeURL\": \"" + realtimeURL + "\"}", RealtimeUrlResponse.class).getRealtimeURL()); + + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"billingPeriodNumber\": 0}", TransactionCommitmentInfo.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"billingPeriodNumber\": 13}", TransactionCommitmentInfo.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"revocationPercentage\": -1}", JWSTransactionDecodedPayload.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"revocationPercentage\": 100001}", JWSTransactionDecodedPayload.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"storefrontCountryCodes\": [\"USAA\"]}", Summary.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"requestIdentifier\": \"" + requestIdentifier + "a\"}", MassExtendRenewalDateResponse.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"requestIdentifier\": \"" + requestIdentifier + "a\"}", MassExtendRenewalDateStatusResponse.class)); + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue("{\"realtimeURL\": \"" + realtimeURL + "a\"}", RealtimeUrlResponse.class)); + } + + @Test + public void testEnumConstantsFollowTheDocumentationOrder() { + Assertions.assertEquals(List.of(TokenType.ACQUISITION, TokenType.SERVICES, TokenType.CORE_TECHNOLOGY), List.of(TokenType.values())); + Assertions.assertEquals(List.of(PurchasePlatform.MAC_OS, PurchasePlatform.IOS, PurchasePlatform.TV_OS, PurchasePlatform.VISION_OS), + List.of(PurchasePlatform.values())); + List subtypes = List.of(Subtype.values()); + Assertions.assertEquals(List.of(Subtype.UNREPORTED, Subtype.CREATED, Subtype.ACTIVE_TOKEN_REMINDER), subtypes.subList(subtypes.size() - 3, subtypes.size())); + List types = List.of(NotificationTypeV2.values()); + Assertions.assertEquals(List.of(NotificationTypeV2.ONE_TIME_CHARGE, NotificationTypeV2.PRICE_CHANGE, NotificationTypeV2.METADATA_UPDATE, + NotificationTypeV2.MIGRATION, NotificationTypeV2.RESCIND_CONSENT), types.subList(types.size() - 5, types.size())); + } + + @Test + public void testConstructorsTakeBaseMembersThenRequiredFieldsInDocumentationOrder() { + AdvancedCommerceOffer offer = new AdvancedCommerceOffer(AdvancedCommerceOfferPeriod.P1M, 2, 500L, AdvancedCommerceOfferReason.ACQUISITION); + Assertions.assertEquals(500L, offer.getPrice()); + Assertions.assertEquals(AdvancedCommerceOfferPeriod.P1M, offer.getPeriod()); + Assertions.assertEquals(2, offer.getPeriodCount()); + Assertions.assertEquals(AdvancedCommerceOfferReason.ACQUISITION, offer.getReason()); + assertEqualObjects(offer, new AdvancedCommerceOffer("P1M", 2, 500L, "ACQUISITION")); + + AdvancedCommerceOneTimeChargeItem item = new AdvancedCommerceOneTimeChargeItem("description", "display name", "sku", 1000L); + AdvancedCommerceOneTimeChargeCreateRequest oneTimeChargeCreateRequest = new AdvancedCommerceOneTimeChargeCreateRequest(REQUEST_INFO, "USD", item, "taxCode"); + Assertions.assertEquals(REQUEST_INFO, oneTimeChargeCreateRequest.getRequestInfo()); + Assertions.assertEquals("USD", oneTimeChargeCreateRequest.getCurrency()); + Assertions.assertEquals("taxCode", oneTimeChargeCreateRequest.getTaxCode()); + Assertions.assertEquals(item, oneTimeChargeCreateRequest.getItem()); + + AdvancedCommerceRequestRefundItem refundItem = new AdvancedCommerceRequestRefundItem("sku", "LEGAL", "FULL", true); + Assertions.assertEquals("sku", refundItem.getSku()); + Assertions.assertEquals("FULL", refundItem.getRawRefundType()); + Assertions.assertEquals(true, refundItem.getRevoke()); + Assertions.assertEquals("LEGAL", refundItem.getRawRefundReason()); + assertEqualObjects(refundItem, new AdvancedCommerceRequestRefundItem("sku", AdvancedCommerceRefundReason.LEGAL, AdvancedCommerceRefundType.FULL, true)); + AdvancedCommerceRequestRefundRequest refundRequest = new AdvancedCommerceRequestRefundRequest(REQUEST_INFO, List.of(refundItem), false); + Assertions.assertEquals(REQUEST_INFO, refundRequest.getRequestInfo()); + Assertions.assertEquals(List.of(refundItem), refundRequest.getItems()); + Assertions.assertEquals(false, refundRequest.getRefundRiskingPreference()); + + AdvancedCommerceSubscriptionChangeMetadataItem changeMetadataItem = new AdvancedCommerceSubscriptionChangeMetadataItem("current", "LATER"); + Assertions.assertEquals("LATER", changeMetadataItem.getRawEffective()); + Assertions.assertEquals("current", changeMetadataItem.getCurrentSku()); + + AdvancedCommerceDescriptors descriptors = new AdvancedCommerceDescriptors("description", "display name"); + List createItems = List.of(new AdvancedCommerceSubscriptionCreateItem("sku", "description", "display name", 1000L)); + AdvancedCommerceSubscriptionCreateRequest createRequest = new AdvancedCommerceSubscriptionCreateRequest(REQUEST_INFO, "USD", descriptors, createItems, "P1M", "taxCode"); + Assertions.assertEquals("USD", createRequest.getCurrency()); + Assertions.assertEquals("taxCode", createRequest.getTaxCode()); + Assertions.assertEquals(AdvancedCommercePeriod.P1M, createRequest.getPeriod()); + Assertions.assertEquals(descriptors, createRequest.getDescriptors()); + Assertions.assertEquals(createItems, createRequest.getItems()); + + AdvancedCommerceSubscriptionMigrateDescriptors migrateDescriptors = new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name"); + List migrateItems = List.of(new AdvancedCommerceSubscriptionMigrateItem("sku", "description", "display name")); + AdvancedCommerceSubscriptionMigrateRequest migrateRequest = new AdvancedCommerceSubscriptionMigrateRequest(REQUEST_INFO, migrateDescriptors, migrateItems, "targetProductId", "taxCode"); + Assertions.assertEquals("targetProductId", migrateRequest.getTargetProductId()); + Assertions.assertEquals(migrateDescriptors, migrateRequest.getDescriptors()); + Assertions.assertEquals("taxCode", migrateRequest.getTaxCode()); + Assertions.assertEquals(migrateItems, migrateRequest.getItems()); + + AdvancedCommerceSubscriptionRevokeRequest revokeRequest = new AdvancedCommerceSubscriptionRevokeRequest(REQUEST_INFO, "LEGAL", true, "FULL"); + Assertions.assertEquals("LEGAL", revokeRequest.getRawRefundReason()); + Assertions.assertEquals("FULL", revokeRequest.getRawRefundType()); + Assertions.assertEquals(true, revokeRequest.getRefundRiskingPreference()); + + ConsumptionRequest consumptionRequest = new ConsumptionRequest(true, DeliveryStatus.DELIVERED, false); + Assertions.assertEquals(true, consumptionRequest.getCustomerConsented()); + Assertions.assertEquals(false, consumptionRequest.getSampleContentProvided()); + Assertions.assertEquals(DeliveryStatus.DELIVERED, consumptionRequest.getDeliveryStatus()); + + ExternalPurchaseToken token = new ExternalPurchaseToken("b2158121-7af9-49d4-9561-1f588205523e", 1698148950000L, 55555L, "com.example"); + Assertions.assertEquals(55555L, token.getAppAppleId()); + Assertions.assertEquals("com.example", token.getBundleId()); + Assertions.assertEquals(1698148950000L, token.getTokenCreationDate()); + Assertions.assertEquals("b2158121-7af9-49d4-9561-1f588205523e", token.getExternalPurchaseId()); + + AdvancedCommerceDescriptors ruleDescriptors = new AdvancedCommerceDescriptors("description", "display name"); + Assertions.assertEquals("description", ruleDescriptors.getDescription()); + Assertions.assertEquals("display name", ruleDescriptors.getDisplayName()); + AdvancedCommerceSubscriptionMigrateDescriptors ruleMigrateDescriptors = new AdvancedCommerceSubscriptionMigrateDescriptors("description", "display name"); + Assertions.assertEquals("description", ruleMigrateDescriptors.getDescription()); + Assertions.assertEquals("display name", ruleMigrateDescriptors.getDisplayName()); + for (AdvancedCommerceSubscriptionModifyPeriodChange periodChange : List.of( + new AdvancedCommerceSubscriptionModifyPeriodChange(AdvancedCommerceEffective.IMMEDIATELY, AdvancedCommercePeriod.P1M), + new AdvancedCommerceSubscriptionModifyPeriodChange("IMMEDIATELY", "P1M"))) { + Assertions.assertEquals("IMMEDIATELY", periodChange.getRawEffective()); + Assertions.assertEquals("P1M", periodChange.getRawPeriod()); + } + + AdvancedCommerceSubscriptionModifyChangeItem changeItem = new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", + "current", AdvancedCommerceEffective.IMMEDIATELY, 1000L, AdvancedCommerceReason.UPGRADE); + AdvancedCommerceSubscriptionModifyChangeItem rawChangeItem = new AdvancedCommerceSubscriptionModifyChangeItem("sku", "description", "display name", + "current", "IMMEDIATELY", 1000L, "UPGRADE"); + for (AdvancedCommerceSubscriptionModifyChangeItem i : List.of(changeItem, rawChangeItem)) { + Assertions.assertEquals("current", i.getCurrentSku()); + Assertions.assertEquals("description", i.getDescription()); + Assertions.assertEquals("display name", i.getDisplayName()); + Assertions.assertEquals("IMMEDIATELY", i.getRawEffective()); + Assertions.assertEquals(1000L, i.getPrice()); + Assertions.assertEquals("UPGRADE", i.getRawReason()); + Assertions.assertEquals("sku", i.getSku()); + } + } + + @Test + public void testSilentOrderConstructorsKeepTheirV520Order() { + AdvancedCommerceOneTimeChargeItem oneTimeChargeItem = new AdvancedCommerceOneTimeChargeItem("description", "display name", "sku", 1000L); + Assertions.assertEquals("description", oneTimeChargeItem.getDescription()); + Assertions.assertEquals("display name", oneTimeChargeItem.getDisplayName()); + Assertions.assertEquals("sku", oneTimeChargeItem.getSku()); + Assertions.assertEquals(1000L, oneTimeChargeItem.getPrice()); + + BulletPoint bulletPoint = new BulletPoint("text", UUID.fromString("b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901"), "alt text"); + Assertions.assertEquals("text", bulletPoint.getText()); + Assertions.assertEquals(UUID.fromString("b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901"), bulletPoint.getImageIdentifier()); + Assertions.assertEquals("alt text", bulletPoint.getAltText()); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayloadTest.java b/src/test/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayloadTest.java index 88457c84..9f11d8b1 100644 --- a/src/test/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayloadTest.java +++ b/src/test/java/com/apple/itunes/storekit/model/JWSTransactionDecodedPayloadTest.java @@ -92,6 +92,8 @@ public void testTransactionDecoding() throws IOException, NoSuchAlgorithmExcepti Assertions.assertEquals(1698150000000L, commitment.getCommitmentExpiresDate()); Assertions.assertEquals(119880L, commitment.getCommitmentPrice()); Assertions.assertEquals(12, commitment.getTotalBillingPeriods()); + Assertions.assertEquals("11111", transaction.getPreviousOriginalTransactionId()); + Assertions.assertNull(transaction.getUnknownFields()); } @Test @@ -138,5 +140,25 @@ public void testTransactionWithRevocationDecoding() throws IOException, NoSuchAl Assertions.assertEquals(RevocationType.REFUND_PRORATED, transaction.getRevocationType()); Assertions.assertEquals("REFUND_PRORATED", transaction.getRawRevocationType()); Assertions.assertEquals(50000, transaction.getRevocationPercentage()); + Assertions.assertNull(transaction.getPreviousOriginalTransactionId()); + } + + @Test + public void testTransactionWithAssignmentRevocationDecoding() throws IOException, NoSuchAlgorithmException, VerificationException { + String signedTransaction = SignedDataCreator.createSignedDataFromJson("models/signedTransactionWithAssignmentRevocation.json"); + + JWSTransactionDecodedPayload transaction = TestingUtility.getSignedPayloadVerifier().verifyAndDecodeTransaction(signedTransaction); + + Assertions.assertEquals("12345", transaction.getOriginalTransactionId()); + Assertions.assertEquals("23456", transaction.getTransactionId()); + Assertions.assertEquals(5, transaction.getQuantity()); + Assertions.assertEquals(InAppOwnershipType.ASSIGNED, transaction.getInAppOwnershipType()); + Assertions.assertEquals("ASSIGNED", transaction.getRawInAppOwnershipType()); + Assertions.assertEquals(1698148950000L, transaction.getRevocationDate()); + Assertions.assertEquals(RevocationType.ASSIGNMENT_REVOKE, transaction.getRevocationType()); + Assertions.assertEquals("ASSIGNMENT_REVOKE", transaction.getRawRevocationType()); + Assertions.assertNull(transaction.getRevocationReason()); + Assertions.assertNull(transaction.getRevocationPercentage()); + Assertions.assertNull(transaction.getUnknownFields()); } } diff --git a/src/test/java/com/apple/itunes/storekit/model/RealtimeResponseBodyTest.java b/src/test/java/com/apple/itunes/storekit/model/RealtimeResponseBodyTest.java index 0281ddf6..f1535077 100644 --- a/src/test/java/com/apple/itunes/storekit/model/RealtimeResponseBodyTest.java +++ b/src/test/java/com/apple/itunes/storekit/model/RealtimeResponseBodyTest.java @@ -46,9 +46,7 @@ public void testRealtimeResponseBodyWithAlternateProduct() throws Exception { // Create a RealtimeResponseBody with an AlternateProduct UUID messageId = UUID.fromString("b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901"); String productId = "com.example.alternate.product"; - AlternateProduct alternateProduct = new AlternateProduct() - .messageIdentifier(messageId) - .productId(productId) + AlternateProduct alternateProduct = new AlternateProduct(messageId, productId) .billingPlanType(BillingPlanType.MONTHLY); RealtimeResponseBody responseBody = new RealtimeResponseBody().alternateProduct(alternateProduct); diff --git a/src/test/java/com/apple/itunes/storekit/model/RequiredFieldsTest.java b/src/test/java/com/apple/itunes/storekit/model/RequiredFieldsTest.java new file mode 100644 index 00000000..91382974 --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/model/RequiredFieldsTest.java @@ -0,0 +1,448 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.apple.itunes.storekit.util.SignedDataCreator; +import com.apple.itunes.storekit.util.TestingUtility; +import com.apple.itunes.storekit.verification.SignedDataVerifier; +import com.apple.itunes.storekit.verification.VerificationException; +import com.apple.itunes.storekit.verification.VerificationStatus; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.fasterxml.jackson.databind.exc.ValueInstantiationException; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class RequiredFieldsTest { + + private static final String REQUEST_IDENTIFIER = "fdf964a4-233b-486c-aac1-97d8d52688ac"; + private static final UUID MESSAGE_IDENTIFIER = UUID.fromString("b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901"); + + private static final ObjectMapper objectMapper = createObjectMapper(); + + private static ObjectMapper createObjectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + return objectMapper; + } + + static Stream> modelsWithRequiredFields() { + return Stream.of( + AlternateProduct.class, + ConsumptionRequestV1.class, + DefaultConfigurationRequest.class, + ExtendRenewalDateRequest.class, + MassExtendRenewalDateRequest.class, + NotificationHistoryRequest.class, + AdvancedCommerceSubscriptionPriceChangeRequest.class, + DecodedRealtimeRequestBody.class, + DefaultConfigurationResponse.class, + ExternalPurchaseToken.class, + PerformanceTestConfig.class, + PerformanceTestResponse.class, + PerformanceTestResponseTimes.class, + PerformanceTestResultResponse.class, + RealtimeUrlResponse.class, + AdvancedCommerceRequestRefundResponse.class, + AdvancedCommerceSubscriptionCancelResponse.class, + AdvancedCommerceSubscriptionChangeMetadataResponse.class, + AdvancedCommerceSubscriptionMigrateResponse.class, + AdvancedCommerceSubscriptionPriceChangeResponse.class, + AdvancedCommerceSubscriptionRevokeResponse.class); + } + + @ParameterizedTest + @MethodSource("modelsWithRequiredFields") + public void testNoPublicNoArgumentConstructor(Class modelClass) { + for (Constructor constructor : modelClass.getDeclaredConstructors()) { + if (constructor.getParameterCount() == 0) { + Assertions.assertFalse(Modifier.isPublic(constructor.getModifiers())); + } + } + } + + @Test + public void testConsumptionRequestV1RequiredFields() throws JsonProcessingException { + Function typed = args -> new ConsumptionRequestV1((AccountTenure) args[6], (UUID) args[5], (ConsumptionStatus) args[1], (Boolean) args[0], (DeliveryStatusV1) args[4], (LifetimeDollarsPurchased) args[9], (LifetimeDollarsRefunded) args[8], (Platform) args[2], (PlayTime) args[7], (Boolean) args[3], (UserStatus) args[10]); + Object[] typedArguments = {true, ConsumptionStatus.NOT_CONSUMED, Platform.NON_APPLE, false, DeliveryStatusV1.DID_NOT_DELIVER_DUE_TO_SERVER_OUTAGE, UUID.fromString("7389a31a-fb6d-4569-a2a6-db7d85d84813"), AccountTenure.THIRTY_DAYS_TO_NINETY_DAYS, PlayTime.ONE_DAY_TO_FOUR_DAYS, LifetimeDollarsRefunded.ZERO_DOLLARS, LifetimeDollarsPurchased.TWO_THOUSAND_DOLLARS_OR_GREATER, UserStatus.LIMITED_ACCESS}; + Function raw = args -> new ConsumptionRequestV1((Integer) args[6], (UUID) args[5], (Integer) args[1], (Boolean) args[0], (Integer) args[4], (Integer) args[9], (Integer) args[8], (Integer) args[2], (Integer) args[7], (Boolean) args[3], (Integer) args[10]); + Object[] rawArguments = {true, 1, 2, false, 3, UUID.fromString("7389a31a-fb6d-4569-a2a6-db7d85d84813"), 4, 5, 1, 7, 4}; + assertEachArgumentRequired(typed, typedArguments, 5); + assertEachArgumentRequired(raw, rawArguments, 5); + + ConsumptionRequestV1 request = typed.apply(typedArguments); + Assertions.assertEquals(raw.apply(rawArguments), request); + Assertions.assertEquals(Set.of("customerConsented", "consumptionStatus", "platform", "sampleContentProvided", "deliveryStatus", "appAccountToken", "accountTenure", "playTime", "lifetimeDollarsRefunded", "lifetimeDollarsPurchased", "userStatus"), serialize(request).keySet()); + + Object[] withoutAppAccountToken = typedArguments.clone(); + withoutAppAccountToken[5] = null; + Assertions.assertEquals("", serialize(typed.apply(withoutAppAccountToken)).get("appAccountToken")); + + Assertions.assertThrows(NullPointerException.class, () -> request.customerConsented(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.platform(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setPlayTime(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setRawUserStatus(null)); + Assertions.assertEquals(UserStatus.LIMITED_ACCESS, request.getUserStatus()); + } + + @Test + public void testExtendRenewalDateRequestRequiredFields() throws JsonProcessingException { + assertEachArgumentRequired(args -> new ExtendRenewalDateRequest((Integer) args[0], (ExtendReasonCode) args[1], (String) args[2]), + new Object[]{45, ExtendReasonCode.CUSTOMER_SATISFACTION, REQUEST_IDENTIFIER}); + assertEachArgumentRequired(args -> new ExtendRenewalDateRequest((Integer) args[0], (Integer) args[1], (String) args[2]), + new Object[]{45, 1, REQUEST_IDENTIFIER}); + + ExtendRenewalDateRequest request = new ExtendRenewalDateRequest(45, ExtendReasonCode.CUSTOMER_SATISFACTION, REQUEST_IDENTIFIER); + Assertions.assertEquals(Map.of("extendByDays", 45, "extendReasonCode", 1, "requestIdentifier", REQUEST_IDENTIFIER), serialize(request)); + Assertions.assertThrows(NullPointerException.class, () -> request.extendByDays(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setRequestIdentifier(null)); + Assertions.assertEquals(45, request.getExtendByDays()); + Assertions.assertEquals(REQUEST_IDENTIFIER, request.getRequestIdentifier()); + } + + @Test + public void testMassExtendRenewalDateRequestRequiredFields() throws JsonProcessingException { + assertEachArgumentRequired(args -> new MassExtendRenewalDateRequest((String) args[2], (Integer) args[0], (ExtendReasonCode) args[1], (String) args[3]), + new Object[]{45, ExtendReasonCode.OTHER, REQUEST_IDENTIFIER, "com.example.productId"}); + assertEachArgumentRequired(args -> new MassExtendRenewalDateRequest((String) args[2], (Integer) args[0], (Integer) args[1], (String) args[3]), + new Object[]{45, 2, REQUEST_IDENTIFIER, "com.example.productId"}); + + MassExtendRenewalDateRequest request = new MassExtendRenewalDateRequest(REQUEST_IDENTIFIER, 45, ExtendReasonCode.OTHER, "com.example.productId"); + Assertions.assertEquals(Map.of("extendByDays", 45, "extendReasonCode", 2, "requestIdentifier", REQUEST_IDENTIFIER, "productId", "com.example.productId"), serialize(request)); + Assertions.assertThrows(NullPointerException.class, () -> request.productId(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setExtendByDays(null)); + Assertions.assertEquals("com.example.productId", request.getProductId()); + } + + @Test + public void testNotificationHistoryRequestRequiredFields() throws JsonProcessingException { + assertEachArgumentRequired(args -> new NotificationHistoryRequest((Long) args[0], (Long) args[1]), + new Object[]{1698148900000L, 1698148950000L}); + + NotificationHistoryRequest request = new NotificationHistoryRequest(1698148900000L, 1698148950000L); + Assertions.assertEquals(Map.of("startDate", 1698148900000L, "endDate", 1698148950000L), serialize(request)); + Assertions.assertThrows(NullPointerException.class, () -> request.startDate(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setEndDate(null)); + Assertions.assertEquals(1698148950000L, request.getEndDate()); + } + + @Test + public void testAlternateProductRequiredFields() throws JsonProcessingException { + assertEachArgumentRequired(args -> new AlternateProduct((UUID) args[0], (String) args[1]), + new Object[]{MESSAGE_IDENTIFIER, "com.example.product"}); + + AlternateProduct alternateProduct = new AlternateProduct(MESSAGE_IDENTIFIER, "com.example.product"); + Assertions.assertEquals(Map.of("messageIdentifier", MESSAGE_IDENTIFIER.toString(), "productId", "com.example.product"), serialize(alternateProduct)); + Assertions.assertThrows(NullPointerException.class, () -> alternateProduct.messageIdentifier(null)); + Assertions.assertThrows(NullPointerException.class, () -> alternateProduct.setProductId(null)); + Assertions.assertEquals("com.example.product", alternateProduct.getProductId()); + } + + @Test + public void testDecodedModelConstructorsRequireFields() { + PerformanceTestConfig config = new PerformanceTestConfig(10L, 500L, 95, 60000L, 100L); + PerformanceTestResponseTimes responseTimes = new PerformanceTestResponseTimes(120L, 100L, 200L, 250L, 400L); + + assertEachArgumentRequired(args -> new ExternalPurchaseToken((String) args[3], (Long) args[2], (Long) args[0], (String) args[1]), + new Object[]{55555L, "com.example", 1698148950000L, "b2158121-7af9-49d4-9561-1f588205523e"}); + assertEachArgumentRequired(args -> new PerformanceTestConfig((Long) args[0], (Long) args[3], (Integer) args[4], (Long) args[2], (Long) args[1]), + new Object[]{10L, 100L, 60000L, 500L, 95}); + assertEachArgumentRequired(args -> new PerformanceTestResponseTimes((Long) args[0], (Long) args[1], (Long) args[2], (Long) args[3], (Long) args[4]), + new Object[]{120L, 100L, 200L, 250L, 400L}); + assertEachArgumentRequired(args -> new PerformanceTestResponse((PerformanceTestConfig) args[0], (UUID) args[1]), + new Object[]{config, UUID.fromString("c4b87a1d-2e3f-4a5b-9c6d-7e8f9a0b1c2d")}); + assertEachArgumentRequired(args -> new PerformanceTestResultResponse((PerformanceTestConfig) args[0], castFailures(args[6]), (Integer) args[4], (PerformanceTestResponseTimes) args[5], (PerformanceTestStatus) args[2], (Integer) args[3], (String) args[1]), + new Object[]{config, "https://example.com/retention", PerformanceTestStatus.PASS, 98, 0, responseTimes, Map.of(SendAttemptResult.TIMED_OUT, 1)}); + assertEachArgumentRequired(args -> new PerformanceTestResultResponse((PerformanceTestConfig) args[0], castRawFailures(args[6]), (Integer) args[4], (PerformanceTestResponseTimes) args[5], (String) args[2], (Integer) args[3], (String) args[1]), + new Object[]{config, "https://example.com/retention", "PASS", 98, 0, responseTimes, Map.of("TIMED_OUT", 1)}); + + PerformanceTestResultResponse result = new PerformanceTestResultResponse(config, Map.of(SendAttemptResult.TIMED_OUT, 1), 0, responseTimes, PerformanceTestStatus.PASS, 98, "https://example.com/retention"); + Assertions.assertEquals(Map.of("TIMED_OUT", 1), result.getRawFailures()); + Assertions.assertThrows(NullPointerException.class, () -> result.setResult(null)); + Assertions.assertThrows(NullPointerException.class, () -> result.failures(null)); + Assertions.assertThrows(NullPointerException.class, () -> responseTimes.setP99(null)); + Assertions.assertThrows(NullPointerException.class, () -> config.totalRequests(null)); + } + + static Stream requiredResponseKeys() { + return Stream.of( + required("models/getDefaultMessageResponse.json", DefaultConfigurationResponse.class, "messageIdentifier"), + required("models/getRealtimeUrlResponse.json", RealtimeUrlResponse.class, "realtimeURL"), + required("models/performanceTestResponse.json", PerformanceTestResponse.class, "config", "requestId", + "config.maxConcurrentRequests", "config.totalRequests", "config.totalDuration", "config.responseTimeThreshold", "config.successRateThreshold"), + required("models/performanceTestResultResponse.json", PerformanceTestResultResponse.class, "config", "target", "result", "successRate", "numPending", "responseTimes", "failures", + "responseTimes.average", "responseTimes.p50", "responseTimes.p90", "responseTimes.p95", "responseTimes.p99"), + required("models/decodedRealtimeRequest.json", DecodedRealtimeRequestBody.class, "originalTransactionId", "appAppleId", "productId", "userLocale", "requestIdentifier", "signedDate", "environment"), + required("models/signedExternalPurchaseTokenNotification.json", ResponseBodyV2DecodedPayload.class, + "externalPurchaseToken.externalPurchaseId", "externalPurchaseToken.tokenCreationDate", "externalPurchaseToken.appAppleId", "externalPurchaseToken.bundleId"), + required("models/advancedCommerceOffer.json", AdvancedCommerceOffer.class, "price", "period", "periodCount", "reason"), + required("models/advancedCommerceDescriptors.json", AdvancedCommerceDescriptors.class, "displayName", "description"), + required("models/advancedCommerceRequestRefundResponse.json", AdvancedCommerceRequestRefundResponse.class, "signedTransactionInfo"), + required("models/advancedCommerceSubscriptionCancelResponse.json", AdvancedCommerceSubscriptionCancelResponse.class, "signedRenewalInfo", "signedTransactionInfo"), + required("models/advancedCommerceSubscriptionChangeMetadataResponse.json", AdvancedCommerceSubscriptionChangeMetadataResponse.class, "signedRenewalInfo", "signedTransactionInfo"), + required("models/advancedCommerceSubscriptionMigrateResponse.json", AdvancedCommerceSubscriptionMigrateResponse.class, "signedRenewalInfo", "signedTransactionInfo"), + required("models/advancedCommerceSubscriptionPriceChangeResponse.json", AdvancedCommerceSubscriptionPriceChangeResponse.class, "signedRenewalInfo", "signedTransactionInfo"), + required("models/advancedCommerceSubscriptionRevokeResponse.json", AdvancedCommerceSubscriptionRevokeResponse.class, "signedRenewalInfo", "signedTransactionInfo") + ).flatMap(arguments -> arguments); + } + + @ParameterizedTest + @MethodSource("requiredResponseKeys") + public void testDecodingFailsWhenRequiredKeyIsMissing(String resource, Class type, String key) throws IOException { + String json = TestingUtility.readFile(resource); + Assertions.assertDoesNotThrow(() -> objectMapper.readValue(json, type)); + + MismatchedInputException e = Assertions.assertThrows(MismatchedInputException.class, () -> objectMapper.readValue(withoutKey(json, key), type)); + Assertions.assertTrue(e.getMessage().contains("'" + lastSegment(key) + "'"), e.getMessage()); + } + + @ParameterizedTest + @MethodSource("requiredResponseKeys") + public void testDecodingFailsWhenRequiredKeyIsNull(String resource, Class type, String key) throws IOException { + String json = TestingUtility.readFile(resource); + + Assertions.assertThrows(JsonMappingException.class, () -> objectMapper.readValue(withNullValue(json, key), type)); + } + + @Test + public void testVerifyAndDecodeNotificationFailsWhenRequiredKeyIsMissing() throws Exception { + String json = withoutKey(TestingUtility.readFile("models/signedExternalPurchaseTokenNotification.json"), "externalPurchaseToken.bundleId"); + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + String signedNotification = SignedDataCreator.createSignedData(json); + + VerificationException e = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeNotification(signedNotification)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, e.getStatus()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + } + + @Test + public void testVerifyAndDecodeRealtimeRequestFailsWhenRequiredKeyIsMissing() throws Exception { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + String json = TestingUtility.readFile("models/decodedRealtimeRequest.json"); + Assertions.assertNotNull(verifier.verifyAndDecodeRealtimeRequest(SignedDataCreator.createSignedData(json))); + String signedRequest = SignedDataCreator.createSignedData(withoutKey(json, "requestIdentifier")); + + VerificationException e = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRealtimeRequest(signedRequest)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, e.getStatus()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + } + + @Test + public void testMergedAdvancedCommerceTypesAreRequiredToBuild() { + assertEachArgumentRequired(args -> new AdvancedCommerceOffer((AdvancedCommerceOfferPeriod) args[1], (Integer) args[2], (Long) args[0], (AdvancedCommerceOfferReason) args[3]), + new Object[]{1000L, AdvancedCommerceOfferPeriod.P1M, 1, AdvancedCommerceOfferReason.ACQUISITION}); + assertEachArgumentRequired(args -> new AdvancedCommerceOffer((String) args[1], (Integer) args[2], (Long) args[0], (String) args[3]), + new Object[]{1000L, "P1M", 1, "ACQUISITION"}); + assertEachArgumentRequired(args -> new AdvancedCommerceDescriptors((String) args[0], (String) args[1]), + new Object[]{"description", "display name"}); + + AdvancedCommerceOffer offer = new AdvancedCommerceOffer(AdvancedCommerceOfferPeriod.P1M, 1, 1000L, AdvancedCommerceOfferReason.ACQUISITION); + Assertions.assertThrows(NullPointerException.class, () -> offer.price(null)); + Assertions.assertThrows(NullPointerException.class, () -> offer.setRawReason(null)); + AdvancedCommerceDescriptors descriptors = new AdvancedCommerceDescriptors("description", "display name"); + Assertions.assertThrows(NullPointerException.class, () -> descriptors.displayName(null)); + Assertions.assertThrows(NullPointerException.class, () -> descriptors.setDescription(null)); + + Assertions.assertThrows(IllegalArgumentException.class, () -> new AdvancedCommerceOffer(AdvancedCommerceOfferPeriod.P1M, 13, 1000L, AdvancedCommerceOfferReason.ACQUISITION)); + Assertions.assertThrows(IllegalArgumentException.class, () -> new AdvancedCommerceDescriptors("description", "A".repeat(31))); + } + + static Stream advancedCommerceSignedKeys() { + return Stream.of("models/signedTransaction.json", "models/signedRenewalInfo.json").flatMap(resource -> Stream.of( + Arguments.of(resource, "descriptors.displayName"), Arguments.of(resource, "descriptors.description"), + Arguments.of(resource, "offer.price"), Arguments.of(resource, "offer.period"), + Arguments.of(resource, "offer.periodCount"), Arguments.of(resource, "offer.reason"))); + } + + @ParameterizedTest + @MethodSource("advancedCommerceSignedKeys") + public void testMergedAdvancedCommerceTypesWithoutARequiredKeyFailToDecodeInSignedData(String resource, String key) throws Exception { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + ObjectNode payload = advancedCommercePayload(resource); + Assertions.assertDoesNotThrow(() -> verifyAndDecode(verifier, resource, payload)); + + ObjectNode missing = payload.deepCopy(); + advancedCommerceObject(missing, key).remove(lastSegment(key)); + VerificationException e = Assertions.assertThrows(VerificationException.class, () -> verifyAndDecode(verifier, resource, missing)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, e.getStatus()); + Assertions.assertInstanceOf(MismatchedInputException.class, e.getCause()); + + ObjectNode withNull = payload.deepCopy(); + advancedCommerceObject(withNull, key).putNull(lastSegment(key)); + e = Assertions.assertThrows(VerificationException.class, () -> verifyAndDecode(verifier, resource, withNull)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, e.getStatus()); + } + + static Stream advancedCommerceSignedValuesOutsideTheLimits() { + return Stream.of("models/signedTransaction.json", "models/signedRenewalInfo.json").flatMap(resource -> Stream.of( + Arguments.of(resource, "offer.periodCount", 13), Arguments.of(resource, "offer.periodCount", 0), + Arguments.of(resource, "descriptors.displayName", "A".repeat(31)), + Arguments.of(resource, "descriptors.description", "A".repeat(46)))); + } + + @ParameterizedTest + @MethodSource("advancedCommerceSignedValuesOutsideTheLimits") + public void testMergedAdvancedCommerceTypesOutsideTheRequestLimitsFailToDecodeInSignedData(String resource, String key, Object value) throws Exception { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + ObjectNode payload = advancedCommercePayload(resource); + Assertions.assertDoesNotThrow(() -> verifyAndDecode(verifier, resource, payload)); + + ObjectNode outside = payload.deepCopy(); + advancedCommerceObject(outside, key).putPOJO(lastSegment(key), value); + VerificationException e = Assertions.assertThrows(VerificationException.class, () -> verifyAndDecode(verifier, resource, outside)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, e.getStatus()); + Assertions.assertInstanceOf(ValueInstantiationException.class, e.getCause()); + Assertions.assertInstanceOf(IllegalArgumentException.class, e.getCause().getCause()); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("signedAdvancedCommerceResources") + public void testMergedAdvancedCommerceTypesAtTheRequestLimitsDecodeInSignedData(String resource) throws Exception { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + for (int periodCount : new int[]{1, 12}) { + ObjectNode payload = advancedCommercePayload(resource); + ((ObjectNode) payload.get("advancedCommerceInfo").get("descriptors")).put("displayName", "A".repeat(30)).put("description", "B".repeat(45)); + advancedCommerceObject(payload, "offer.periodCount").put("periodCount", periodCount); + + Object decoded = verifyAndDecode(verifier, resource, payload); + AdvancedCommerceDescriptors descriptors; + AdvancedCommerceOffer offer; + if (decoded instanceof JWSRenewalInfoDecodedPayload) { + AdvancedCommerceRenewalInfo info = ((JWSRenewalInfoDecodedPayload) decoded).getAdvancedCommerceInfo(); + descriptors = info.getDescriptors(); + offer = info.getItems().get(0).getOffer(); + } else { + AdvancedCommerceTransactionInfo info = ((JWSTransactionDecodedPayload) decoded).getAdvancedCommerceInfo(); + descriptors = info.getDescriptors(); + offer = info.getItems().get(0).getOffer(); + } + Assertions.assertEquals("A".repeat(30), descriptors.getDisplayName()); + Assertions.assertEquals("B".repeat(45), descriptors.getDescription()); + Assertions.assertEquals(5000L, offer.getPrice()); + Assertions.assertEquals(AdvancedCommerceOfferPeriod.P1M, offer.getPeriod()); + Assertions.assertEquals(periodCount, offer.getPeriodCount()); + Assertions.assertEquals(AdvancedCommerceOfferReason.ACQUISITION, offer.getReason()); + } + } + + static Stream signedAdvancedCommerceResources() { + return Stream.of("models/signedTransaction.json", "models/signedRenewalInfo.json"); + } + + @Test + public void testAdvancedCommerceTransactionWithoutDescriptorsAndOfferDecodes() throws Exception { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(); + ObjectNode transactionJson = (ObjectNode) objectMapper.readTree(TestingUtility.readFile("models/signedTransaction.json")); + ObjectNode transactionInfo = (ObjectNode) transactionJson.get("advancedCommerceInfo"); + transactionInfo.remove(List.of("descriptors", "period")); + Assertions.assertFalse(transactionInfo.get("items").get(0).has("offer")); + + JWSTransactionDecodedPayload transaction = verifier.verifyAndDecodeTransaction(SignedDataCreator.createSignedData(objectMapper.writeValueAsString(transactionJson))); + AdvancedCommerceTransactionInfo info = transaction.getAdvancedCommerceInfo(); + Assertions.assertNull(info.getDescriptors()); + Assertions.assertNull(info.getPeriod()); + Assertions.assertNull(info.getItems().get(0).getOffer()); + Assertions.assertEquals("com.example.sku.premium", info.getItems().get(0).getSku()); + } + + private static ObjectNode advancedCommercePayload(String resource) throws IOException { + ObjectNode payload = (ObjectNode) objectMapper.readTree(TestingUtility.readFile(resource)); + ((ObjectNode) payload.get("advancedCommerceInfo").get("items").get(0)).putObject("offer") + .put("price", 5000).put("period", "P1M").put("periodCount", 3).put("reason", "ACQUISITION"); + return payload; + } + + private static ObjectNode advancedCommerceObject(ObjectNode payload, String key) { + ObjectNode info = (ObjectNode) payload.get("advancedCommerceInfo"); + return (ObjectNode) (key.startsWith("descriptors.") ? info.get("descriptors") : info.get("items").get(0).get("offer")); + } + + private static Object verifyAndDecode(SignedDataVerifier verifier, String resource, ObjectNode payload) throws Exception { + String signed = SignedDataCreator.createSignedData(objectMapper.writeValueAsString(payload)); + return resource.contains("RenewalInfo") ? verifier.verifyAndDecodeRenewalInfo(signed) : verifier.verifyAndDecodeTransaction(signed); + } + + private static Stream required(String resource, Class type, String... keys) { + return Arrays.stream(keys).map(key -> Arguments.of(resource, type, key)); + } + + private static void assertEachArgumentRequired(Function constructor, Object[] arguments, int... nullableArguments) { + Assertions.assertNotNull(constructor.apply(arguments.clone())); + Set nullable = IntStream.of(nullableArguments).boxed().collect(Collectors.toSet()); + for (int i = 0; i < arguments.length; i++) { + Object[] withNull = arguments.clone(); + withNull[i] = null; + if (nullable.contains(i)) { + Assertions.assertDoesNotThrow(() -> constructor.apply(withNull)); + } else { + Assertions.assertThrows(NullPointerException.class, () -> constructor.apply(withNull)); + } + } + } + + @SuppressWarnings("unchecked") + private static Map castFailures(Object failures) { + return (Map) failures; + } + + @SuppressWarnings("unchecked") + private static Map castRawFailures(Object failures) { + return (Map) failures; + } + + @SuppressWarnings("unchecked") + private static Map serialize(Object value) throws JsonProcessingException { + return objectMapper.readValue(objectMapper.writeValueAsString(value), Map.class); + } + + private static String withoutKey(String json, String path) throws JsonProcessingException { + ObjectNode root = (ObjectNode) objectMapper.readTree(json); + parentOf(root, path).remove(lastSegment(path)); + return objectMapper.writeValueAsString(root); + } + + private static String withNullValue(String json, String path) throws JsonProcessingException { + ObjectNode root = (ObjectNode) objectMapper.readTree(json); + parentOf(root, path).putNull(lastSegment(path)); + return objectMapper.writeValueAsString(root); + } + + private static ObjectNode parentOf(ObjectNode root, String path) { + String[] segments = path.split("\\."); + ObjectNode node = root; + for (int i = 0; i < segments.length - 1; i++) { + node = (ObjectNode) node.get(segments[i]); + } + Assertions.assertTrue(node.has(lastSegment(path))); + return node; + } + + private static String lastSegment(String path) { + return path.substring(path.lastIndexOf('.') + 1); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayloadTest.java b/src/test/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayloadTest.java index 94f37dbb..83bddcc0 100644 --- a/src/test/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayloadTest.java +++ b/src/test/java/com/apple/itunes/storekit/model/ResponseBodyV2DecodedPayloadTest.java @@ -14,6 +14,7 @@ import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Set; +import java.util.UUID; public class ResponseBodyV2DecodedPayloadTest { @@ -96,7 +97,7 @@ public void testSummaryNotificationDecoding() throws IOException, NoSuchAlgorith Assertions.assertEquals(41234L, notification.getSummary().getAppAppleId()); Assertions.assertEquals("com.example", notification.getSummary().getBundleId()); Assertions.assertEquals("com.example.product", notification.getSummary().getProductId()); - Assertions.assertEquals("efb27071-45a4-4aca-9854-2a1e9146f265", notification.getSummary().getRequestIdentifier()); + Assertions.assertEquals(UUID.fromString("efb27071-45a4-4aca-9854-2a1e9146f265"), notification.getSummary().getRequestIdentifier()); Assertions.assertEquals(List.of("CAN", "USA", "MEX"), notification.getSummary().getStorefrontCountryCodes()); Assertions.assertEquals(5, notification.getSummary().getSucceededCount()); Assertions.assertEquals(2, notification.getSummary().getFailedCount()); @@ -170,6 +171,30 @@ protected void verifyNotification(String bundleId, Long appAppleId, Environment Assertions.assertEquals(1698149000000L, notification.getExternalPurchaseToken().getTokenExpirationDate()); } + @Test + public void testExternalPurchaseTokenCoreTechnologyNotificationDecoding() throws IOException, NoSuchAlgorithmException, VerificationException { + String signedNotification = SignedDataCreator.createSignedDataFromJson("models/signedExternalPurchaseTokenCoreTechnologyNotification.json"); + + SignedDataVerifier verifier = new SignedDataVerifier(Set.of(new ByteArrayInputStream(TestingUtility.readBytes("certs/testCA.der"))), "com.example", 1234L, Environment.LOCAL_TESTING, false) { + @Override + protected void verifyNotification(String bundleId, Long appAppleId, Environment notificationEnv) { + Assertions.assertEquals("com.example", bundleId); + Assertions.assertEquals(55555, appAppleId); + Assertions.assertEquals(Environment.PRODUCTION, notificationEnv); + } + }; + + ResponseBodyV2DecodedPayload notification = verifier.verifyAndDecodeNotification(signedNotification); + + Assertions.assertEquals(NotificationTypeV2.EXTERNAL_PURCHASE_TOKEN, notification.getNotificationType()); + Assertions.assertEquals(Subtype.UNREPORTED, notification.getSubtype()); + Assertions.assertNotNull(notification.getExternalPurchaseToken()); + Assertions.assertEquals("b2158121-7af9-49d4-9561-1f588205523e", notification.getExternalPurchaseToken().getExternalPurchaseId()); + Assertions.assertEquals(TokenType.CORE_TECHNOLOGY, notification.getExternalPurchaseToken().getTokenType()); + Assertions.assertEquals("CORE_TECHNOLOGY", notification.getExternalPurchaseToken().getRawTokenType()); + Assertions.assertNull(notification.getExternalPurchaseToken().getTokenExpirationDate()); + } + @Test public void testRescindConsentNotificationDecoding() throws IOException, NoSuchAlgorithmException, VerificationException { String signedNotification = SignedDataCreator.createSignedDataFromJson("models/signedRescindConsentNotification.json"); diff --git a/src/test/java/com/apple/itunes/storekit/model/RetentionMessagingModelsTest.java b/src/test/java/com/apple/itunes/storekit/model/RetentionMessagingModelsTest.java new file mode 100644 index 00000000..aa6211ec --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/model/RetentionMessagingModelsTest.java @@ -0,0 +1,149 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.model; + +import com.apple.itunes.storekit.util.TestingUtility; +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class RetentionMessagingModelsTest { + + private static final UUID MESSAGE_IDENTIFIER = UUID.fromString("a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890"); + private static final UUID IMAGE_IDENTIFIER = UUID.fromString("b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901"); + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final ObjectMapper clientObjectMapper = createClientObjectMapper(); + + private static ObjectMapper createClientObjectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker() + .withFieldVisibility(JsonAutoDetect.Visibility.ANY) + .withGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withIsGetterVisibility(JsonAutoDetect.Visibility.NONE) + .withSetterVisibility(JsonAutoDetect.Visibility.NONE) + .withCreatorVisibility(JsonAutoDetect.Visibility.NONE)); + return mapper; + } + + @Test + public void testDefaultConfigurationResponseWithUnknownFields() throws Exception { + String json = TestingUtility.readFile("models/getDefaultMessageResponseWithUnknownFields.json"); + + for (ObjectMapper mapper : List.of(clientObjectMapper, objectMapper)) { + DefaultConfigurationResponse response = mapper.readValue(json, DefaultConfigurationResponse.class); + + Assertions.assertEquals(MESSAGE_IDENTIFIER, response.getMessageIdentifier()); + Assertions.assertEquals(Map.of("unknownField", "unknown_value"), response.getUnknownFields()); + } + } + + @Test + public void testRealtimeUrlResponseWithUnknownFields() throws Exception { + String json = TestingUtility.readFile("models/getRealtimeUrlResponseWithUnknownFields.json"); + + for (ObjectMapper mapper : List.of(clientObjectMapper, objectMapper)) { + RealtimeUrlResponse response = mapper.readValue(json, RealtimeUrlResponse.class); + + Assertions.assertEquals("https://example.com/realtime", response.getRealtimeURL()); + Assertions.assertEquals(Map.of("unknownField", "unknown_value"), response.getUnknownFields()); + } + } + + @Test + public void testRealtimeUrlResponseValidation() { + String maxUrl = "https://example.com/" + "a".repeat(256 - "https://example.com/".length()); + RealtimeUrlResponse response = new RealtimeUrlResponse(maxUrl); + Assertions.assertEquals(maxUrl, response.getRealtimeURL()); + Assertions.assertEquals(maxUrl, response.realtimeURL(maxUrl).getRealtimeURL()); + + Assertions.assertThrows(IllegalArgumentException.class, () -> new RealtimeUrlResponse(maxUrl + "a")); + Assertions.assertThrows(IllegalArgumentException.class, () -> response.realtimeURL(maxUrl + "a")); + Assertions.assertThrows(IllegalArgumentException.class, () -> response.setRealtimeURL(maxUrl + "a")); + + Assertions.assertThrows(NullPointerException.class, () -> new RealtimeUrlResponse(null)); + Assertions.assertThrows(NullPointerException.class, () -> response.realtimeURL(null)); + Assertions.assertThrows(NullPointerException.class, () -> response.setRealtimeURL(null)); + } + + @Test + public void testRealtimeUrlRequestValidation() { + String maximumLengthUrl = "https://example.com/" + "a".repeat(256 - "https://example.com/".length()); + RealtimeUrlRequest request = new RealtimeUrlRequest(maximumLengthUrl); + Assertions.assertEquals(maximumLengthUrl, request.getRealtimeURL()); + + Assertions.assertThrows(IllegalArgumentException.class, () -> new RealtimeUrlRequest(maximumLengthUrl + "a")); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.realtimeURL(maximumLengthUrl + "a")); + Assertions.assertThrows(IllegalArgumentException.class, () -> request.setRealtimeURL(maximumLengthUrl + "a")); + Assertions.assertThrows(NullPointerException.class, () -> new RealtimeUrlRequest(null)); + } + + @Test + public void testDefaultConfigurationRequestRequiresMessageIdentifier() throws Exception { + DefaultConfigurationRequest request = new DefaultConfigurationRequest(MESSAGE_IDENTIFIER); + Assertions.assertEquals("{\"messageIdentifier\":\"a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890\"}", clientObjectMapper.writeValueAsString(request)); + + Assertions.assertThrows(NullPointerException.class, () -> new DefaultConfigurationRequest(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.messageIdentifier(null)); + Assertions.assertThrows(NullPointerException.class, () -> request.setMessageIdentifier(null)); + Assertions.assertEquals(MESSAGE_IDENTIFIER, request.getMessageIdentifier()); + } + + @Test + public void testBulletPointRequiresImageIdentifier() throws Exception { + BulletPoint bulletPoint = new BulletPoint("Text", IMAGE_IDENTIFIER, "Alt text"); + + Assertions.assertThrows(NullPointerException.class, () -> new BulletPoint("Text", null, "Alt text")); + Assertions.assertThrows(NullPointerException.class, () -> bulletPoint.imageIdentifier(null)); + Assertions.assertThrows(NullPointerException.class, () -> bulletPoint.setImageIdentifier(null)); + Assertions.assertEquals(IMAGE_IDENTIFIER, bulletPoint.getImageIdentifier()); + Assertions.assertEquals("{\"altText\":\"Alt text\",\"imageIdentifier\":\"b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901\",\"text\":\"Text\"}", clientObjectMapper.writeValueAsString(bulletPoint)); + } + + @Test + public void testUploadMessageImageRequiresImageIdentifier() throws Exception { + UploadMessageImage image = new UploadMessageImage(IMAGE_IDENTIFIER, "Alt text"); + + Assertions.assertThrows(NullPointerException.class, () -> new UploadMessageImage(null, "Alt text")); + Assertions.assertThrows(NullPointerException.class, () -> image.imageIdentifier(null)); + Assertions.assertThrows(NullPointerException.class, () -> image.setImageIdentifier(null)); + Assertions.assertEquals(IMAGE_IDENTIFIER, image.getImageIdentifier()); + Assertions.assertEquals("{\"imageIdentifier\":\"b2c3d4e5-f6a7-8901-b2c3-d4e5f6a78901\",\"altText\":\"Alt text\"}", clientObjectMapper.writeValueAsString(image)); + } + + @Test + public void testUploadMessageRequestBodyBulletPointsValidation() { + BulletPoint bulletPoint = new BulletPoint("Text", IMAGE_IDENTIFIER, "Alt text"); + UploadMessageRequestBody body = new UploadMessageRequestBody("Header", "Body"); + + List maximumBulletPoints = List.of(bulletPoint, bulletPoint, bulletPoint, bulletPoint, bulletPoint); + Assertions.assertEquals(maximumBulletPoints, body.bulletPoints(maximumBulletPoints).getBulletPoints()); + body.setBulletPoints(null); + Assertions.assertNull(body.getBulletPoints()); + + List tooManyBulletPoints = new ArrayList<>(maximumBulletPoints); + tooManyBulletPoints.add(bulletPoint); + Assertions.assertThrows(IllegalArgumentException.class, () -> body.bulletPoints(tooManyBulletPoints)); + Assertions.assertThrows(IllegalArgumentException.class, () -> body.setBulletPoints(tooManyBulletPoints)); + + List bulletPointsWithNull = Arrays.asList(bulletPoint, null); + Assertions.assertThrows(IllegalArgumentException.class, () -> body.bulletPoints(bulletPointsWithNull)); + Assertions.assertThrows(IllegalArgumentException.class, () -> body.setBulletPoints(bulletPointsWithNull)); + Assertions.assertNull(body.getBulletPoints()); + } + + @Test + public void testPromotionalOfferSignatureV1NoArgConstructorIsProtected() throws Exception { + Assertions.assertTrue(Modifier.isProtected(PromotionalOfferSignatureV1.class.getDeclaredConstructor().getModifiers())); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreatorTest.java b/src/test/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreatorTest.java index c99c5706..35265d19 100644 --- a/src/test/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreatorTest.java +++ b/src/test/java/com/apple/itunes/storekit/offers/IntroductoryOfferEligibilitySignatureCreatorTest.java @@ -2,7 +2,9 @@ package com.apple.itunes.storekit.offers; +import com.apple.itunes.storekit.util.TestSigningUtility; import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -26,7 +28,7 @@ void testSignatureCreator() throws Exception { IntroductoryOfferEligibilitySignatureCreator signatureCreator = new IntroductoryOfferEligibilitySignatureCreator(new String(key.readAllBytes()), KEY_ID, ISSUER_ID, BUNDLE_ID); String signature = signatureCreator.createSignature(PRODUCT_ID, ALLOW_INTRODUCTORY_OFFER, TRANSACTION_ID); Assertions.assertNotNull(signature); - DecodedJWT decodedJWT = JWT.decode(signature); + DecodedJWT decodedJWT = JWT.require(Algorithm.ECDSA256(TestSigningUtility.getTestSigningPublicKey(), null)).build().verify(signature); // Header Assertions.assertEquals("JWT", decodedJWT.getType()); Assertions.assertEquals("ES256", decodedJWT.getAlgorithm()); diff --git a/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreatorTest.java b/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreatorTest.java index efb891b3..07093bc3 100644 --- a/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreatorTest.java +++ b/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferSignatureCreatorTest.java @@ -2,21 +2,93 @@ package com.apple.itunes.storekit.offers; +import com.apple.itunes.storekit.util.TestSigningUtility; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.Signature; +import java.util.Base64; import java.util.UUID; class PromotionalOfferSignatureCreatorTest { + private static final String NONCE = "20fba8a0-2b80-4a7d-a17f-85c1854727f8"; + private static final long TIMESTAMP = 1698148900000L; + @Test void testSignatureCreator() throws Exception { try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { Assertions.assertNotNull(key); PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId"); - String signature = signatureCreator.createSignature("productId", "offerId", "appAccountToken", UUID.fromString("20fba8a0-2b80-4a7d-a17f-85c1854727f8"), 1698148900000L); + String signature = signatureCreator.createSignature("productId", "offerId", "appAccountToken", UUID.fromString(NONCE), TIMESTAMP); Assertions.assertNotNull(signature); + Assertions.assertTrue(verifySignature(signature, "bundleId", "keyId", "productId", "offerId", "appaccounttoken", NONCE, String.valueOf(TIMESTAMP))); + Assertions.assertFalse(verifySignature(signature, "bundleId", "keyId", "productId", "offerId", "appAccountToken", NONCE, String.valueOf(TIMESTAMP))); + } + } + + @Test + void testAppAccountTokenMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId"); + String signature = signatureCreator.createSignature("productId", "offerId", null, UUID.fromString(NONCE), TIMESTAMP); + Assertions.assertTrue(verifySignature(signature, "bundleId", "keyId", "productId", "offerId", "", NONCE, String.valueOf(TIMESTAMP))); + } + } + + @Test + void testProductIdentifierMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId"); + Assertions.assertThrows(IllegalArgumentException.class, () -> signatureCreator.createSignature(null, "offerId", "appAccountToken", UUID.fromString(NONCE), TIMESTAMP)); + } + } + + @Test + void testSubscriptionOfferIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId"); + Assertions.assertThrows(IllegalArgumentException.class, () -> signatureCreator.createSignature("productId", null, "appAccountToken", UUID.fromString(NONCE), TIMESTAMP)); } } + + @Test + void testNonceMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + PromotionalOfferSignatureCreator signatureCreator = new PromotionalOfferSignatureCreator(new String(key.readAllBytes()), "keyId", "bundleId"); + Assertions.assertThrows(IllegalArgumentException.class, () -> signatureCreator.createSignature("productId", "offerId", "appAccountToken", null, TIMESTAMP)); + } + } + + @Test + void testKeyIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + String signingKey = new String(key.readAllBytes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new PromotionalOfferSignatureCreator(signingKey, null, "bundleId")); + } + } + + @Test + void testBundleIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + String signingKey = new String(key.readAllBytes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new PromotionalOfferSignatureCreator(signingKey, "keyId", null)); + } + } + + private static boolean verifySignature(String signature, String... payloadParts) throws Exception { + String payload = String.join("\u2063", payloadParts); + Signature verifier = Signature.getInstance("SHA256withECDSA"); + verifier.initVerify(TestSigningUtility.getTestSigningPublicKey()); + verifier.update(payload.getBytes(StandardCharsets.UTF_8)); + return verifier.verify(Base64.getDecoder().decode(signature)); + } } diff --git a/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreatorTest.java b/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreatorTest.java index 5de45103..324159d4 100644 --- a/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreatorTest.java +++ b/src/test/java/com/apple/itunes/storekit/offers/PromotionalOfferV2SignatureCreatorTest.java @@ -2,7 +2,9 @@ package com.apple.itunes.storekit.offers; +import com.apple.itunes.storekit.util.TestSigningUtility; import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.impl.JWTParser; import com.auth0.jwt.interfaces.DecodedJWT; import org.junit.jupiter.api.Assertions; @@ -27,7 +29,7 @@ void testSignatureCreator() throws Exception { PromotionalOfferV2SignatureCreator signatureCreator = new PromotionalOfferV2SignatureCreator(new String(key.readAllBytes()), KEY_ID, ISSUER_ID, BUNDLE_ID); String signature = signatureCreator.createSignature(PRODUCT_ID, OFFER_IDENTIFIER, TRANSACTION_ID); Assertions.assertNotNull(signature); - DecodedJWT decodedJWT = JWT.decode(signature); + DecodedJWT decodedJWT = JWT.require(Algorithm.ECDSA256(TestSigningUtility.getTestSigningPublicKey(), null)).build().verify(signature); // Header Assertions.assertEquals("JWT", decodedJWT.getType()); Assertions.assertEquals("ES256", decodedJWT.getAlgorithm()); @@ -75,6 +77,33 @@ void testProductIdMissing() throws Exception { } } + @Test + void testKeyIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + String signingKey = new String(key.readAllBytes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new PromotionalOfferV2SignatureCreator(signingKey, null, ISSUER_ID, BUNDLE_ID)); + } + } + + @Test + void testIssuerIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + String signingKey = new String(key.readAllBytes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new PromotionalOfferV2SignatureCreator(signingKey, KEY_ID, null, BUNDLE_ID)); + } + } + + @Test + void testBundleIdMissing() throws Exception { + try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { + Assertions.assertNotNull(key); + String signingKey = new String(key.readAllBytes()); + Assertions.assertThrows(IllegalArgumentException.class, () -> new PromotionalOfferV2SignatureCreator(signingKey, KEY_ID, ISSUER_ID, null)); + } + } + @Test void testNonceIsProvided() throws Exception { try (InputStream key = this.getClass().getClassLoader().getResourceAsStream("certs/testSigningKey.p8")) { diff --git a/src/test/java/com/apple/itunes/storekit/util/SignedDataCreator.java b/src/test/java/com/apple/itunes/storekit/util/SignedDataCreator.java index 0a51e67b..f2822bd9 100644 --- a/src/test/java/com/apple/itunes/storekit/util/SignedDataCreator.java +++ b/src/test/java/com/apple/itunes/storekit/util/SignedDataCreator.java @@ -13,7 +13,10 @@ public class SignedDataCreator { public static String createSignedDataFromJson(String path) throws IOException, NoSuchAlgorithmException { - String json = TestingUtility.readFile(path); + return createSignedData(TestingUtility.readFile(path)); + } + + public static String createSignedData(String json) throws NoSuchAlgorithmException { KeyPairGenerator ec = KeyPairGenerator.getInstance("EC"); ec.initialize(256); return JWT.create() diff --git a/src/test/java/com/apple/itunes/storekit/util/TestSigningUtility.java b/src/test/java/com/apple/itunes/storekit/util/TestSigningUtility.java new file mode 100644 index 00000000..36b32a6b --- /dev/null +++ b/src/test/java/com/apple/itunes/storekit/util/TestSigningUtility.java @@ -0,0 +1,62 @@ +// Copyright (c) 2026 Apple Inc. Licensed under MIT License. + +package com.apple.itunes.storekit.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TestSigningUtility { + + private static final String TEST_SIGNING_PUBLIC_KEY_BASE64_ENCODED = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErPJyxEu2/oKCrJaaTVTrq39DKJ2XcN6W+k8UvGf+Y/lDWNbFitQocabsDUvSN0edHH3UKP5QPTz4cOlyIPMrXQ=="; + + public static ECPublicKey getTestSigningPublicKey() throws GeneralSecurityException { + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(TEST_SIGNING_PUBLIC_KEY_BASE64_ENCODED)); + return (ECPublicKey) KeyFactory.getInstance("EC").generatePublic(keySpec); + } + + public static String createSignedDataWithTestCertificateChain(String payload) throws IOException, GeneralSecurityException { + return createSignedDataWithTestCertificateChain(payload, Algorithm.ECDSA256(getTestLeafPrivateKey())); + } + + public static String createSignedDataWithTestCertificateChain(String payload, Algorithm algorithm) throws IOException { + List x5c = List.of(readCertificate("certs/testLeaf.pem"), readCertificate("certs/testIntermediate.pem"), readCertificate("certs/testCA.pem")); + return JWT.create() + .withHeader(Map.of("x5c", x5c)) + .withPayload(payload) + .sign(algorithm); + } + + private static ECPrivateKey getTestLeafPrivateKey() throws IOException, GeneralSecurityException { + org.bouncycastle.asn1.sec.ECPrivateKey sec1Key = org.bouncycastle.asn1.sec.ECPrivateKey.getInstance(decodePem("certs/testLeaf.key")); + PrivateKeyInfo privateKeyInfo = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, sec1Key.getParametersObject()), sec1Key); + return (ECPrivateKey) KeyFactory.getInstance("EC").generatePrivate(new PKCS8EncodedKeySpec(privateKeyInfo.getEncoded())); + } + + private static String readCertificate(String path) throws IOException { + return Base64.getEncoder().encodeToString(decodePem(path)); + } + + private static byte[] decodePem(String path) throws IOException { + Matcher matcher = Pattern.compile("-----BEGIN [A-Z ]+-----([^-]+)-----END [A-Z ]+-----").matcher(TestingUtility.readFile(path)); + if (!matcher.find()) { + throw new IllegalArgumentException(); + } + return Base64.getDecoder().decode(matcher.group(1).replaceAll("\\s", "")); + } +} diff --git a/src/test/java/com/apple/itunes/storekit/verification/ChainVerifierTest.java b/src/test/java/com/apple/itunes/storekit/verification/ChainVerifierTest.java index 331f6aa4..34fbea44 100644 --- a/src/test/java/com/apple/itunes/storekit/verification/ChainVerifierTest.java +++ b/src/test/java/com/apple/itunes/storekit/verification/ChainVerifierTest.java @@ -5,16 +5,20 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; import org.mockito.Mockito; import java.io.ByteArrayInputStream; +import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.security.PublicKey; +import java.security.cert.CertPathValidator; import java.security.cert.CertPathValidatorException; import java.time.Clock; import java.time.Instant; import java.util.Base64; import java.util.Date; +import java.util.Map; import java.util.Set; public class ChainVerifierTest { @@ -225,6 +229,62 @@ public void testOcspResponseCachingWithSlightlyDifferentChains() throws Verifica Mockito.verify(mockedChainVerifier, Mockito.times(2)).verifyChainWithoutCaching(Mockito.any(), Mockito.anyBoolean(), Mockito.any()); } + @Test + public void testOcspResponseCachingWhenEntryIsRemovedDuringLookup() throws Exception { + String[] chain = new String[] { + LEAF_CERT_BASE64_ENCODED, + INTERMEDIATE_CA_BASE64_ENCODED, + ROOT_CA_BASE64_ENCODED + }; + mockedChainVerifier.verifyChain(chain, true, EFFECTIVE_DATE); + Field cacheField = ChainVerifier.class.getDeclaredField("verifiedPublicKeyCache"); + cacheField.setAccessible(true); + Map cache = (Map) cacheField.get(mockedChainVerifier); + Mockito.when(clock.instant()).thenAnswer(invocation -> { + cache.clear(); + return Instant.ofEpochMilli(CLOCK_DATE + 1_000); + }); + PublicKey cachedKey = mockedChainVerifier.verifyChain(chain, true, EFFECTIVE_DATE); + Assertions.assertSame(publicKey, cachedKey); + Mockito.verify(mockedChainVerifier, Mockito.times(1)).verifyChainWithoutCaching(Mockito.any(), Mockito.anyBoolean(), Mockito.any()); + } + + @Test + public void testOcspNetworkFailureIsRetryable() throws Exception { + ChainVerifier verifier = getChainVerifier(ROOT_CA_BASE64_ENCODED); + CertPathValidator realCertPathValidator = CertPathValidator.getInstance("PKIX"); + CertPathValidator certPathValidator = Mockito.mock(CertPathValidator.class); + Mockito.when(certPathValidator.getRevocationChecker()).thenReturn(realCertPathValidator.getRevocationChecker()); + Mockito.when(certPathValidator.validate(Mockito.any(), Mockito.any())).thenThrow(new CertPathValidatorException(null, null, null, -1, CertPathValidatorException.BasicReason.UNDETERMINED_REVOCATION_STATUS)); + try (MockedStatic mockedCertPathValidator = Mockito.mockStatic(CertPathValidator.class)) { + mockedCertPathValidator.when(() -> CertPathValidator.getInstance("PKIX")).thenReturn(certPathValidator); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyChain(new String[] { + LEAF_CERT_BASE64_ENCODED, + INTERMEDIATE_CA_BASE64_ENCODED, + ROOT_CA_BASE64_ENCODED + }, true, EFFECTIVE_DATE)); + Assertions.assertEquals(VerificationStatus.RETRYABLE_VERIFICATION_FAILURE, exception.getStatus()); + } + } + + @Test + public void testOcspFailureWithOtherReasonIsNotRetryable() throws Exception { + ChainVerifier verifier = getChainVerifier(ROOT_CA_BASE64_ENCODED); + CertPathValidator realCertPathValidator = CertPathValidator.getInstance("PKIX"); + CertPathValidator certPathValidator = Mockito.mock(CertPathValidator.class); + Mockito.when(certPathValidator.getRevocationChecker()).thenReturn(realCertPathValidator.getRevocationChecker()); + Mockito.when(certPathValidator.validate(Mockito.any(), Mockito.any())).thenThrow(new CertPathValidatorException(null, null, null, -1, CertPathValidatorException.BasicReason.REVOKED)); + try (MockedStatic mockedCertPathValidator = Mockito.mockStatic(CertPathValidator.class)) { + mockedCertPathValidator.when(() -> CertPathValidator.getInstance("PKIX")).thenReturn(certPathValidator); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyChain(new String[] { + LEAF_CERT_BASE64_ENCODED, + INTERMEDIATE_CA_BASE64_ENCODED, + ROOT_CA_BASE64_ENCODED + }, true, EFFECTIVE_DATE)); + Assertions.assertEquals(VerificationStatus.INVALID_CHAIN, exception.getStatus()); + } + } + /** * The following test will communicate with Apple's OCSP servers, disable this test for offline testing */ diff --git a/src/test/java/com/apple/itunes/storekit/verification/SignedDataVerifierTest.java b/src/test/java/com/apple/itunes/storekit/verification/SignedDataVerifierTest.java index 76fa69ee..1b0a527c 100644 --- a/src/test/java/com/apple/itunes/storekit/verification/SignedDataVerifierTest.java +++ b/src/test/java/com/apple/itunes/storekit/verification/SignedDataVerifierTest.java @@ -3,17 +3,22 @@ package com.apple.itunes.storekit.verification; import com.apple.itunes.storekit.model.AdvancedCommerceTransactionInfo; +import com.apple.itunes.storekit.model.AppTransaction; +import com.apple.itunes.storekit.model.DecodedRealtimeRequestBody; import com.apple.itunes.storekit.model.Environment; import com.apple.itunes.storekit.model.JWSRenewalInfoDecodedPayload; import com.apple.itunes.storekit.model.JWSTransactionDecodedPayload; import com.apple.itunes.storekit.model.NotificationTypeV2; import com.apple.itunes.storekit.model.ResponseBodyV2DecodedPayload; import com.apple.itunes.storekit.util.SignedDataCreator; +import com.apple.itunes.storekit.util.TestSigningUtility; import com.apple.itunes.storekit.util.TestingUtility; +import com.auth0.jwt.algorithms.Algorithm; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.io.IOException; +import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; public class SignedDataVerifierTest { @@ -60,6 +65,114 @@ public void testWrongEnvironmentForServerNotification() throws IOException { Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); } + @Test + public void testWrongEnvironmentForTransaction() throws IOException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example"); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeTransaction(TestingUtility.readFile("mock_signed_data/transactionInfo"))); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + + @Test + public void testWrongEnvironmentForRenewalInfo() throws IOException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example"); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRenewalInfo(TestingUtility.readFile("mock_signed_data/renewalInfo"))); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + + @Test + public void testAppTransactionDecoding() throws VerificationException, IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", 531412L); + AppTransaction appTransaction = verifier.verifyAndDecodeAppTransaction(createSignedProductionAppTransaction()); + Assertions.assertEquals(Environment.PRODUCTION, appTransaction.getReceiptType()); + Assertions.assertEquals(531412L, appTransaction.getAppAppleId()); + } + + @Test + public void testWrongBundleIdForAppTransaction() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example.x", 531412L); + String signedAppTransaction = createSignedProductionAppTransaction(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeAppTransaction(signedAppTransaction)); + Assertions.assertEquals(VerificationStatus.INVALID_APP_IDENTIFIER, exception.getStatus()); + } + + @Test + public void testWrongAppAppleIdForAppTransaction() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", 1234L); + String signedAppTransaction = createSignedProductionAppTransaction(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeAppTransaction(signedAppTransaction)); + Assertions.assertEquals(VerificationStatus.INVALID_APP_IDENTIFIER, exception.getStatus()); + } + + @Test + public void testWrongEnvironmentForAppTransaction() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.SANDBOX, "com.example", 531412L); + String signedAppTransaction = createSignedProductionAppTransaction(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeAppTransaction(signedAppTransaction)); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + + @Test + public void testRealtimeRequestDecoding() throws VerificationException, IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", 531412L); + DecodedRealtimeRequestBody request = verifier.verifyAndDecodeRealtimeRequest(createSignedProductionRealtimeRequest()); + Assertions.assertEquals(Environment.PRODUCTION, request.getEnvironment()); + Assertions.assertEquals(531412L, request.getAppAppleId()); + } + + @Test + public void testWrongAppAppleIdForRealtimeRequest() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", 1234L); + String signedRequest = createSignedProductionRealtimeRequest(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRealtimeRequest(signedRequest)); + Assertions.assertEquals(VerificationStatus.INVALID_APP_IDENTIFIER, exception.getStatus()); + } + + @Test + public void testWrongEnvironmentForRealtimeRequest() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.SANDBOX, "com.example", 531412L); + String signedRequest = createSignedProductionRealtimeRequest(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRealtimeRequest(signedRequest)); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + + @Test + public void testUnrecognizedAlgorithm() throws IOException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", 531412L); + String payload = TestingUtility.readFile("models/appTransaction.json").replace("\"LocalTesting\"", "\"Production\""); + String signedAppTransaction = TestSigningUtility.createSignedDataWithTestCertificateChain(payload, Algorithm.HMAC256("secret")); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeAppTransaction(signedAppTransaction)); + Assertions.assertEquals(VerificationStatus.VERIFICATION_FAILURE, exception.getStatus()); + Assertions.assertEquals("Verification failed with status VERIFICATION_FAILURE. Unrecognized JWT algorithm: HS256", exception.getMessage()); + } + + @Test + public void testProductionEnvironmentRequiresAppAppleId() { + IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> TestingUtility.getSignedPayloadVerifier(Environment.PRODUCTION, "com.example", null)); + Assertions.assertEquals("appAppleId is required when the environment is Production", exception.getMessage()); + } + + @Test + public void testMissingBundleIdIsInvalidAppIdentifier() throws IOException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.SANDBOX, null); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeTransaction(TestingUtility.readFile("mock_signed_data/transactionInfo"))); + Assertions.assertEquals(VerificationStatus.INVALID_APP_IDENTIFIER, exception.getStatus()); + } + + @Test + public void testMissingEnvironmentIsInvalidEnvironment() throws IOException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(null, "com.example"); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRenewalInfo(TestingUtility.readFile("mock_signed_data/renewalInfo"))); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + + @Test + public void testMissingEnvironmentIsInvalidEnvironmentForRealtimeRequest() throws IOException, GeneralSecurityException { + SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(null, "com.example", 531412L); + String signedRequest = createSignedProductionRealtimeRequest(); + VerificationException exception = Assertions.assertThrows(VerificationException.class, () -> verifier.verifyAndDecodeRealtimeRequest(signedRequest)); + Assertions.assertEquals(VerificationStatus.INVALID_ENVIRONMENT, exception.getStatus()); + } + @Test public void testRenewalInfoDecoding() throws VerificationException, IOException { SignedDataVerifier verifier = TestingUtility.getSignedPayloadVerifier(Environment.SANDBOX, "com.example"); @@ -105,4 +218,14 @@ public void testNonAsciiDataDecodingIsIndependentOfTheDefaultCharset() throws Ve Assertions.assertEquals("\u30d7\u30ec\u30df\u30a2\u30e0\u6a5f\u80fd", advancedCommerceInfo.getItems().get(0).getDescription()); Assertions.assertEquals("\u30d7\u30ec\u30df\u30a2\u30e0", advancedCommerceInfo.getItems().get(0).getDisplayName()); } + + private static String createSignedProductionAppTransaction() throws IOException, GeneralSecurityException { + String payload = TestingUtility.readFile("models/appTransaction.json").replace("\"LocalTesting\"", "\"Production\""); + return TestSigningUtility.createSignedDataWithTestCertificateChain(payload); + } + + private static String createSignedProductionRealtimeRequest() throws IOException, GeneralSecurityException { + String payload = TestingUtility.readFile("models/decodedRealtimeRequest.json").replace("\"LocalTesting\"", "\"Production\""); + return TestSigningUtility.createSignedDataWithTestCertificateChain(payload); + } } diff --git a/src/test/resources/models/appTransaction.json b/src/test/resources/models/appTransaction.json index 9313c31c..c347e60b 100644 --- a/src/test/resources/models/appTransaction.json +++ b/src/test/resources/models/appTransaction.json @@ -11,5 +11,6 @@ "deviceVerificationNonce": "48ccfa42-7431-4f22-9908-7e88983e105a", "preorderDate": 1698148700000, "appTransactionId": "71134", - "originalPlatform": "iOS" + "originalPlatform": "iOS", + "storeType": "CONSUMER" } \ No newline at end of file diff --git a/src/test/resources/models/consumptionPercentageOutOfRangeError.json b/src/test/resources/models/consumptionPercentageOutOfRangeError.json new file mode 100644 index 00000000..03a28ccc --- /dev/null +++ b/src/test/resources/models/consumptionPercentageOutOfRangeError.json @@ -0,0 +1,4 @@ +{ + "errorCode": 4000207, + "errorMessage": "Invalid request. The consumption percentage is outside the valid range." +} \ No newline at end of file diff --git a/src/test/resources/models/getCustomerGroupsResponse.json b/src/test/resources/models/getCustomerGroupsResponse.json new file mode 100644 index 00000000..54be137e --- /dev/null +++ b/src/test/resources/models/getCustomerGroupsResponse.json @@ -0,0 +1,22 @@ +{ + "groups": [ + { + "groupId": "900000000000000000", + "groupType": "ORGANIZATION", + "roles": [ + { + "productId": "example.productId.one", + "role": "ADMIN" + }, + { + "productId": "example.productId.two", + "role": "NONE" + } + ] + }, + { + "groupId": "900000000000000001", + "groupType": "CONSUMER" + } + ] +} diff --git a/src/test/resources/models/getCustomerGroupsResponseWithUnknownValues.json b/src/test/resources/models/getCustomerGroupsResponseWithUnknownValues.json new file mode 100644 index 00000000..dbb91ff8 --- /dev/null +++ b/src/test/resources/models/getCustomerGroupsResponseWithUnknownValues.json @@ -0,0 +1,17 @@ +{ + "groups": [ + { + "groupId": "900000000000000002", + "groupType": "UNKNOWN_GROUP_TYPE", + "roles": [ + { + "productId": "example.productId.three", + "role": "UNKNOWN_ROLE", + "unknownRoleField": "unknown_role_value" + } + ], + "unknownGroupField": "unknown_group_value" + } + ], + "unknownField": "unknown_value" +} diff --git a/src/test/resources/models/getDefaultMessageResponseWithUnknownFields.json b/src/test/resources/models/getDefaultMessageResponseWithUnknownFields.json new file mode 100644 index 00000000..961ffae4 --- /dev/null +++ b/src/test/resources/models/getDefaultMessageResponseWithUnknownFields.json @@ -0,0 +1,4 @@ +{ + "messageIdentifier": "a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890", + "unknownField": "unknown_value" +} diff --git a/src/test/resources/models/getGroupMembersResponse.json b/src/test/resources/models/getGroupMembersResponse.json new file mode 100644 index 00000000..42e5c3bc --- /dev/null +++ b/src/test/resources/models/getGroupMembersResponse.json @@ -0,0 +1,12 @@ +{ + "members": [ + { + "appTransactionId": "700000000000000000" + }, + { + "appTransactionId": "700000000000000001" + } + ], + "paginationToken": "pagination_token_output", + "hasMore": true +} diff --git a/src/test/resources/models/getRealtimeUrlResponseWithUnknownFields.json b/src/test/resources/models/getRealtimeUrlResponseWithUnknownFields.json new file mode 100644 index 00000000..d3d4b3a9 --- /dev/null +++ b/src/test/resources/models/getRealtimeUrlResponseWithUnknownFields.json @@ -0,0 +1,4 @@ +{ + "realtimeURL": "https://example.com/realtime", + "unknownField": "unknown_value" +} diff --git a/src/test/resources/models/groupNotFoundError.json b/src/test/resources/models/groupNotFoundError.json new file mode 100644 index 00000000..f573291a --- /dev/null +++ b/src/test/resources/models/groupNotFoundError.json @@ -0,0 +1,4 @@ +{ + "errorCode": 4040022, + "errorMessage": "Group not found." +} diff --git a/src/test/resources/models/invalidGroupIdError.json b/src/test/resources/models/invalidGroupIdError.json new file mode 100644 index 00000000..ffba9c88 --- /dev/null +++ b/src/test/resources/models/invalidGroupIdError.json @@ -0,0 +1,4 @@ +{ + "errorCode": 4000225, + "errorMessage": "Invalid request. The group ID is invalid." +} diff --git a/src/test/resources/models/invalidLimitError.json b/src/test/resources/models/invalidLimitError.json new file mode 100644 index 00000000..a340b417 --- /dev/null +++ b/src/test/resources/models/invalidLimitError.json @@ -0,0 +1,4 @@ +{ + "errorCode": 4000004, + "errorMessage": "Invalid request limit." +} diff --git a/src/test/resources/models/signedExternalPurchaseTokenCoreTechnologyNotification.json b/src/test/resources/models/signedExternalPurchaseTokenCoreTechnologyNotification.json new file mode 100644 index 00000000..4ac90ac0 --- /dev/null +++ b/src/test/resources/models/signedExternalPurchaseTokenCoreTechnologyNotification.json @@ -0,0 +1,14 @@ +{ + "notificationType": "EXTERNAL_PURCHASE_TOKEN", + "subtype": "UNREPORTED", + "notificationUUID": "002e14d5-51f5-4503-b5a8-c3a1af68eb20", + "version": "2.0", + "signedDate": 1698148900000, + "externalPurchaseToken": { + "externalPurchaseId": "b2158121-7af9-49d4-9561-1f588205523e", + "tokenCreationDate": 1698148950000, + "appAppleId": 55555, + "bundleId": "com.example", + "tokenType": "CORE_TECHNOLOGY" + } + } diff --git a/src/test/resources/models/signedTransaction.json b/src/test/resources/models/signedTransaction.json index 3d405b64..02dc9cea 100644 --- a/src/test/resources/models/signedTransaction.json +++ b/src/test/resources/models/signedTransaction.json @@ -62,5 +62,6 @@ "commitmentExpiresDate": 1698150000000, "commitmentPrice": 119880, "totalBillingPeriods": 12 - } + }, + "previousOriginalTransactionId": "11111" } \ No newline at end of file diff --git a/src/test/resources/models/signedTransactionWithAssignmentRevocation.json b/src/test/resources/models/signedTransactionWithAssignmentRevocation.json new file mode 100644 index 00000000..3ef9cc08 --- /dev/null +++ b/src/test/resources/models/signedTransactionWithAssignmentRevocation.json @@ -0,0 +1,24 @@ +{ + "originalTransactionId": "12345", + "transactionId": "23456", + "webOrderLineItemId": "34343", + "bundleId": "com.example", + "productId": "com.example.product", + "subscriptionGroupIdentifier": "55555", + "purchaseDate": 1698148900000, + "originalPurchaseDate": 1698148800000, + "expiresDate": 1698149000000, + "quantity": 5, + "type": "Auto-Renewable Subscription", + "inAppOwnershipType": "ASSIGNED", + "signedDate": 1698148900000, + "revocationDate": 1698148950000, + "environment": "LocalTesting", + "storefront": "USA", + "storefrontId": "143441", + "transactionReason": "PURCHASE", + "price": 10990, + "currency": "USD", + "appTransactionId": "71134", + "revocationType": "ASSIGNMENT_REVOKE" +} diff --git a/src/test/resources/models/subscriptionDoesNotExistError.json b/src/test/resources/models/subscriptionDoesNotExistError.json new file mode 100644 index 00000000..7de813ad --- /dev/null +++ b/src/test/resources/models/subscriptionDoesNotExistError.json @@ -0,0 +1,4 @@ +{ + "errorCode": 4030008, + "errorMessage": "The subscription doesn't exist." +} \ No newline at end of file