Skip to content

Commit

Permalink
Merge pull request #60 from dietmap/modify-parsing-of-app-store-notif…
Browse files Browse the repository at this point in the history
…ication-request

Set 'notificationType' to string in AppStore subscription status noti…
  • Loading branch information
mhuta authored Oct 6, 2022
2 parents 98b6916 + fee5472 commit 586eda6
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import java.io.Serializable

data class StatusUpdateNotification(
@get:JsonProperty("environment") val environment: String?,
@get:JsonProperty("notification_type") val notificationType: AppStoreNotificationType,
@get:JsonProperty("notification_type") val notificationType: String?,
@get:JsonProperty("latest_receipt") val latestReceipt: String?,
@get:JsonProperty("latest_receipt_info") val latestReceiptInfo: LatestReceiptInfo,
@get:JsonProperty("expiration_intent") val expirationIntent: String?,
Expand Down Expand Up @@ -80,7 +80,34 @@ enum class AppStoreNotificationType(private val code: Int) {
/**
* User has entered a price increase flow
*/
PRICE_INCREASE_CONSENT(8);
PRICE_INCREASE_CONSENT(8),

/**
* Indicates that the customer initiated a refund request for a consumable in-app purchase,
* and the App Store is requesting that you provide consumption data
*/
CONSUMPTION_REQUEST(9),

/**
* Indicates that a customer’s subscription has successfully auto-renewed for a new transaction period.
* Provide the customer with access to the subscription’s content or service.
*/
DID_RENEW(10),

/**
* Indicates that the App Store successfully refunded a transaction for a consumable in-app purchase,
* a non-consumable in-app purchase, or a non-renewing subscription. The cancellation_date_ms contains
* the timestamp of the refunded transaction. The original_transaction_id and product_id identify
* the original transaction and product. The cancellation_reason contains the reason.
*/
REFUND(11),

/**
* Indicates that an in-app purchase the user was entitled to through Family Sharing is no longer
* available through sharing. StoreKit sends this notification when a purchaser disabled Family Sharing
* for a product, the purchaser (or family member) left the family group, or the purchaser asked for and received a refund.
*/
REVOKE(12);

companion object {
private val codes = values().associateBy(AppStoreNotificationType::code)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
var notificationType = NotificationType.SUBSCRIPTION_PURCHASED
val latestReceiptInfo = statusUpdateNotification.latestReceiptInfo

when (statusUpdateNotification.notificationType) {
when (val appStoreNotificationType = parseAppStoreNotificationTypeEnum(statusUpdateNotification.notificationType)) {

// A subscription is first purchased
AppStoreNotificationType.INITIAL_BUY -> {
Expand All @@ -119,14 +119,14 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
}

// a customer downgrades
AppStoreNotificationType.DID_CHANGE_RENEWAL_PREF -> {
AppStoreNotificationType.DID_CHANGE_RENEWAL_PREF, AppStoreNotificationType.DID_CHANGE_RENEWAL_STATUS -> {
// auto_renewal_product_id - product customer will auto renew at

// skipping it
// latest_receipt_info.original_transaction_id
}

// customer support issues a refund
AppStoreNotificationType.CANCEL -> {
AppStoreNotificationType.CANCEL, AppStoreNotificationType.REVOKE, AppStoreNotificationType.REFUND -> {
// suspend service with a cancellation date?

notificationType = NotificationType.SUBSCRIPTION_CANCELED
Expand Down Expand Up @@ -158,12 +158,20 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
// latest_receipt_info.expires_date_ms - date when the subscription will expire
}

AppStoreNotificationType.DID_CHANGE_RENEWAL_STATUS -> {
// skipping it
AppStoreNotificationType.DID_RENEW -> {
// restore service for a renewed subscription
// update customer's subscription to active / subscribe

notificationType = NotificationType.SUBSCRIPTION_RENEWED;
}

AppStoreNotificationType.PRICE_INCREASE_CONSENT -> {
// skipping it
null -> {
throw IllegalStateException("Missing or not recognised notification type.")
}

else -> {
logger.warn { "Notification type $appStoreNotificationType is not supported." }
return null
}
}

Expand All @@ -186,6 +194,9 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
return userAppClient.sendSubscriptionNotification(notification)
}

private fun parseAppStoreNotificationTypeEnum(appStoreNotificationValue: String?): AppStoreNotificationType? =
AppStoreNotificationType.values().find { it.name.equals(appStoreNotificationValue, ignoreCase = true) }

fun verifyReceipt(tenant: String?, receiptRequest: ReceiptRequest) = appStoreClient(tenant).verifyReceipt(receiptRequest)

private fun appStoreClient(tenant: String?) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal class SubscriptionControllerTest : SupportController() {


private val testStatusUpdateNotification: StatusUpdateNotification = StatusUpdateNotification(
"sandbox", AppStoreNotificationType.CANCEL, "cancellationDate", latestReceiptInfo, "",
"sandbox", "CANCEL", "cancellationDate", latestReceiptInfo, "",
"latestExpiredReceipt", true, "", "autoRenewProductId",
"autoRenewStatusChangeDate", 12323230, unifiedReceipt)

Expand Down

0 comments on commit 586eda6

Please sign in to comment.