diff --git a/appstore/model.go b/appstore/model.go index 45095da..4c93b22 100644 --- a/appstore/model.go +++ b/appstore/model.go @@ -76,16 +76,27 @@ type ( CancellationDatePST string `json:"cancellation_date_pst,omitempty"` } + // The GracePeriodDate type indicates the grace period date for the subscription + GracePeriodDate struct { + GracePeriodDate string `json:"grace_period_expires_date,omitempty"` + GracePeriodDateMS string `json:"grace_period_expires_date_ms,omitempty"` + GracePeriodDatePST string `json:"grace_period_expires_date_pst,omitempty"` + } + // The InApp type has the receipt attributes InApp struct { - Quantity string `json:"quantity"` - ProductID string `json:"product_id"` - TransactionID string `json:"transaction_id"` - OriginalTransactionID string `json:"original_transaction_id"` - WebOrderLineItemID string `json:"web_order_line_item_id,omitempty"` + Quantity string `json:"quantity"` + ProductID string `json:"product_id"` + TransactionID string `json:"transaction_id"` + OriginalTransactionID string `json:"original_transaction_id"` + WebOrderLineItemID string `json:"web_order_line_item_id,omitempty"` + PromotionalOfferID string `json:"promotional_offer_id"` + SubscriptionGroupIdentifier string `json:"subscription_group_identifier"` IsTrialPeriod string `json:"is_trial_period"` IsInIntroOfferPeriod string `json:"is_in_intro_offer_period,omitempty"` + IsUpgraded string `json:"is_upgraded"` + ExpiresDate PurchaseDate @@ -121,6 +132,8 @@ type ( SubscriptionPriceConsentStatus string `json:"price_consent_status"` ProductID string `json:"product_id"` OriginalTransactionID string `json:"original_transaction_id"` + + GracePeriodDate } // The IAPResponse type has the response properties diff --git a/appstore/notification.go b/appstore/notification.go index 4a38b82..5f340a2 100644 --- a/appstore/notification.go +++ b/appstore/notification.go @@ -9,7 +9,10 @@ const ( // Subscription was canceled by Apple customer support. NotificationTypeCancel NotificationType = "CANCEL" // Automatic renewal was successful for an expired subscription. + // Deprecated: DID_RECOVER should be used instead of RENEWAL NotificationTypeRenewal NotificationType = "RENEWAL" + // Expired subscription recovered through a billing retry. + NotificationTypeDidRecover NotificationType = "DID_RECOVER" // Customer renewed a subscription interactively after it lapsed. NotificationTypeInteractiveRenewal NotificationType = "INTERACTIVE_RENEWAL" // Customer changed the plan that takes affect at the next subscription renewal. Current active plan is not affected. @@ -53,6 +56,14 @@ type NotificationReceipt struct { CancellationDate } +type NotificationUnifiedReceipt struct { + Status string `json:"status"` + Environment Environment `json:"environment"` + LatestReceipt string `json:"latest_receipt"` + LatestReceiptInfo []InApp `json:"latest_receipt_info"` + PendingRenewalInfo []PendingRenewalInfo `json:"pending_renewal_info,omitempty"` +} + type SubscriptionNotification struct { Environment NotificationEnvironment `json:"environment"` NotificationType NotificationType `json:"notification_type"` @@ -85,6 +96,9 @@ type SubscriptionNotification struct { LatestReceipt string `json:"latest_receipt"` LatestReceiptInfo NotificationReceipt `json:"latest_receipt_info"` + // In the new notifications above properties latest_receipt, latest_receipt_info are moved under this one + UnifiedReceipt NotificationUnifiedReceipt `json:"unified_receipt"` + // Posted only if the notification_type is RENEWAL or CANCEL or if renewal failed and subscription expired. LatestExpiredReceipt string `json:"latest_expired_receipt"` LatestExpiredReceiptInfo NotificationReceipt `json:"latest_expired_receipt_info"` diff --git a/playstore/validator_test.go b/playstore/validator_test.go index 6677c49..709a4b1 100644 --- a/playstore/validator_test.go +++ b/playstore/validator_test.go @@ -74,7 +74,7 @@ func TestNewWithClient(t *testing.T) { func TestAcknowledgeSubscription(t *testing.T) { t.Parallel() // Exception scenario - expected := "googleapi: Error 404: No application was found for the given package name., applicationNotFound" + expected := "googleapi: Error 400: Invalid Value, invalid" client, _ := New(jsonKey) ctx := context.Background() @@ -93,7 +93,7 @@ func TestAcknowledgeSubscription(t *testing.T) { func TestVerifySubscription(t *testing.T) { t.Parallel() // Exception scenario - expected := "googleapi: Error 404: No application was found for the given package name., applicationNotFound" + expected := "googleapi: Error 400: Invalid Value, invalid" client, _ := New(jsonKey) ctx := context.Background() @@ -121,7 +121,7 @@ func TestVerifySubscriptionAndroidPublisherError(t *testing.T) { func TestVerifyProduct(t *testing.T) { t.Parallel() // Exception scenario - expected := "googleapi: Error 404: No application was found for the given package name., applicationNotFound" + expected := "googleapi: Error 400: Invalid Value, invalid" client, _ := New(jsonKey) ctx := context.Background() @@ -159,7 +159,7 @@ func TestCancelSubscription(t *testing.T) { } client, _ = New(jsonKey) - expectedStr := "googleapi: Error 404: No application was found for the given package name., applicationNotFound" + expectedStr := "googleapi: Error 400: Invalid Value, invalid" actual = client.CancelSubscription(ctx, "package", "productID", "purchaseToken") if actual.Error() != expectedStr {