Skip to content

Commit d7c8f55

Browse files
authored
Merge pull request #63 from dietmap/add-free-trial-info-to-notifications
update status notification model and add free trial info to server no…
2 parents cda3b37 + 6d82bc5 commit d7c8f55

File tree

6 files changed

+36
-41
lines changed

6 files changed

+36
-41
lines changed

src/main/kotlin/com/dietmap/yaak/api/appstore/subscription/StatusUpdateNotification.kt

+11-9
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@ import com.fasterxml.jackson.annotation.JsonProperty
77
import java.io.Serializable
88

99
data class StatusUpdateNotification(
10-
@get:JsonProperty("environment") val environment: String?,
11-
@get:JsonProperty("notification_type") val notificationType: String?,
12-
@get:JsonProperty("latest_receipt") val latestReceipt: String?,
13-
@get:JsonProperty("latest_receipt_info") val latestReceiptInfo: LatestReceiptInfo,
14-
@get:JsonProperty("expiration_intent") val expirationIntent: String?,
1510
@get:JsonProperty("auto_renew_adam_id") val autoRenewAdamId: String?,
16-
@get:JsonProperty("auto_renew_status") val autoRenewStatus: Boolean?,
1711
@get:JsonProperty("auto_renew_product_id") val autoRenewProductId: String?,
12+
@get:JsonProperty("auto_renew_status") val autoRenewStatus: Boolean?,
1813
@get:JsonProperty("auto_renew_status_change_date") val autoRenewStatusChangeDate: String?,
19-
@get:JsonProperty("auto_renew_status_change_date_pst") val autoRenewStatusChangeDatePst: String?,
2014
@get:JsonProperty("auto_renew_status_change_date_ms") val autoRenewStatusChangeDateMs: Long?,
21-
@get:JsonProperty("unified_receipt") val unifiedReceipt: UnifiedReceipt?
15+
@get:JsonProperty("auto_renew_status_change_date_pst") val autoRenewStatusChangeDatePst: String?,
16+
@get:JsonProperty("bid") val bid: String?,
17+
@get:JsonProperty("bvrs") val bvrs: String?,
18+
@get:JsonProperty("environment") val environment: String?,
19+
@get:JsonProperty("expiration_intent") val expirationIntent: String?,
20+
@get:JsonProperty("notification_type") val notificationType: String?,
21+
@get:JsonProperty("original_transaction_id") val originalTransactionId: String?,
22+
@get:JsonProperty("password") val password: String?,
23+
@get:JsonProperty("unified_receipt") val unifiedReceipt: UnifiedReceipt
2224
) : Serializable
2325

2426

@@ -27,7 +29,7 @@ data class UnifiedReceipt(
2729
@get:JsonProperty("latest_receipt") val latestReceipt: String?,
2830
@get:JsonProperty("latest_receipt_info") val latestReceiptInfo: Collection<LatestReceiptInfo>?,
2931
@get:JsonProperty("pending_renewal_info") val pendingRenewalInfo: Collection<PendingRenewalInfo>?,
30-
@get:JsonProperty("status") val latestExpiredReceiptInfo: String?
32+
@get:JsonProperty("status") val status: String?
3133
) : Serializable
3234

3335

src/main/kotlin/com/dietmap/yaak/api/appstore/subscription/SubscriptionController.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class SubscriptionController(private val subscriptionService: AppStoreSubscripti
4444
}
4545

4646
/**
47-
* Handler for Server 2 Server notifications
47+
* Handler for Server 2 Server notifications in version 1
4848
*/
4949
@PostMapping("/statusUpdateNotification")
5050
fun handleStatusUpdateNotification(@Valid @RequestBody statusUpdateNotification: StatusUpdateNotification): ResponseEntity<Any> {

src/main/kotlin/com/dietmap/yaak/domain/appstore/AppStoreSubscriptionService.kt

+9-17
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,10 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
2222

2323
fun handleInitialPurchase(tenant: String?, subscriptionPurchaseRequest: SubscriptionPurchaseRequest) : UserAppSubscriptionOrder? {
2424
val receiptResponse = appStoreClient(tenant).verifyReceipt(ReceiptRequest(subscriptionPurchaseRequest.receipt))
25-
2625
logger.debug { "handleInitialPurchase: ReceiptResponse: $receiptResponse" }
27-
2826
if (receiptResponse.isValid()) {
29-
3027
val latestReceiptInfo = receiptResponse.latestReceiptInfo!!.stream().findFirst().get()
31-
3228
var effectivePrice = subscriptionPurchaseRequest.price
33-
3429
// intro offer period purchase
3530
if (latestReceiptInfo.isInIntroOfferPeriod && subscriptionPurchaseRequest.effectivePrice != null) {
3631
effectivePrice = subscriptionPurchaseRequest.effectivePrice
@@ -48,7 +43,8 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
4843
appMarketplace = AppMarketplace.APP_STORE,
4944
expiryTimeMillis = latestReceiptInfo.expiresDateMs,
5045
discountCode = subscriptionPurchaseRequest.discountCode,
51-
appStoreReceipt = subscriptionPurchaseRequest.receipt
46+
appStoreReceipt = subscriptionPurchaseRequest.receipt,
47+
isTrialPeriod = latestReceiptInfo.isTrialPeriod
5248
)
5349

5450
return userAppClient.sendSubscriptionNotification(notification)
@@ -61,15 +57,10 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
6157

6258
fun handleAutoRenewal(tenant: String?, subscriptionRenewRequest: SubscriptionRenewRequest) {
6359
val receiptResponse = appStoreClient(tenant).verifyReceipt(ReceiptRequest(subscriptionRenewRequest.receipt))
64-
6560
logger.debug { "handleAutoRenewal: ReceiptResponse: $receiptResponse" }
66-
6761
if (receiptResponse.isValid()) {
68-
6962
if (receiptResponse.latestReceiptInfo != null) {
70-
7163
val latestReceiptInfo = receiptResponse.latestReceiptInfo.stream().findFirst().get()
72-
7364
val notification = UserAppSubscriptionNotification(
7465
notificationType = NotificationType.SUBSCRIPTION_RENEWED,
7566
description = "Subscription renewal from AppStore",
@@ -81,11 +72,11 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
8172
countryCode = null,
8273
currencyCode = null,
8374
discountCode = subscriptionRenewRequest.discountCode,
84-
appStoreReceipt = subscriptionRenewRequest.receipt
75+
appStoreReceipt = subscriptionRenewRequest.receipt,
76+
isTrialPeriod = latestReceiptInfo.isTrialPeriod
8577
)
8678

8779
val subscriptionOrder = userAppClient.sendSubscriptionNotification(notification);
88-
8980
checkArgument(subscriptionOrder != null) { "Could not process SubscriptionRenewRequest $subscriptionRenewRequest in user app" }
9081
}
9182
} else {
@@ -99,7 +90,7 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
9990
logger.debug { "Processing StatusUpdateNotification: ${statusUpdateNotification.notificationType}" }
10091

10192
var notificationType = NotificationType.SUBSCRIPTION_PURCHASED
102-
val latestReceiptInfo = statusUpdateNotification.latestReceiptInfo
93+
val latestReceiptInfo = statusUpdateNotification.unifiedReceipt.latestReceiptInfo?.maxBy { it.purchaseDateMs }!!
10394

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

@@ -119,7 +110,7 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
119110
}
120111

121112
// a customer downgrades
122-
AppStoreNotificationType.DID_CHANGE_RENEWAL_PREF, AppStoreNotificationType.DID_CHANGE_RENEWAL_STATUS -> {
113+
AppStoreNotificationType.DID_CHANGE_RENEWAL_PREF -> {
123114
// auto_renewal_product_id - product customer will auto renew at
124115
// skipping it
125116
// latest_receipt_info.original_transaction_id
@@ -158,7 +149,7 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
158149
// latest_receipt_info.expires_date_ms - date when the subscription will expire
159150
}
160151

161-
AppStoreNotificationType.DID_RENEW -> {
152+
AppStoreNotificationType.DID_RENEW, AppStoreNotificationType.DID_CHANGE_RENEWAL_STATUS -> {
162153
// restore service for a renewed subscription
163154
// update customer's subscription to active / subscribe
164155

@@ -186,7 +177,8 @@ class AppStoreSubscriptionService(private val userAppClient: UserAppClient, priv
186177
countryCode = null,
187178
currencyCode = null,
188179
discountCode = null,
189-
appStoreReceipt = statusUpdateNotification.latestReceipt
180+
appStoreReceipt = statusUpdateNotification.unifiedReceipt.latestReceipt,
181+
isTrialPeriod = latestReceiptInfo.isTrialPeriod
190182
)
191183

192184
logger.debug {"Sending UserAppSubscriptionNotification: $notification" }

src/main/kotlin/com/dietmap/yaak/domain/googleplay/GooglePlaySubscriptionService.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class GooglePlaySubscriptionService(val androidPublisherService: AndroidPublishe
4848
orderingUserId = purchaseRequest.orderingUserId ?: subscription[USER_ACCOUNT_ID_KEY] as String?,
4949
discountCode = purchaseRequest.discountCode,
5050
expiryTimeMillis = subscription.expiryTimeMillis,
51-
googlePlayPurchaseDetails = GooglePlayPurchaseDetails(purchaseRequest.packageName, purchaseRequest.subscriptionId, purchaseRequest.purchaseToken)
51+
googlePlayPurchaseDetails = GooglePlayPurchaseDetails(purchaseRequest.packageName, purchaseRequest.subscriptionId, purchaseRequest.purchaseToken),
52+
isTrialPeriod = subscription.paymentState == PAYMENT_FREE_TRIAL_CODE
5253
))
5354

5455
checkArgument(notificationResponse != null) { "Could not create subscription order ${subscription.orderId} in user app" }

src/main/kotlin/com/dietmap/yaak/domain/userapp/UserAppSubscriptionNotification.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ data class UserAppSubscriptionNotification(
2525
val orderingUserId: String? = String(),
2626
val discountCode: String? = String(),
2727
val appStoreReceipt: String? = String(),
28-
val googlePlayPurchaseDetails: GooglePlayPurchaseDetails? = null
28+
val googlePlayPurchaseDetails: GooglePlayPurchaseDetails? = null,
29+
val isTrialPeriod: Boolean? = false
2930
)
3031

3132
enum class NotificationType {

src/test/kotlin/com/dietmap/yaak/api/appstore/subscription/SubscriptionControllerTest.kt

+11-12
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,26 @@ internal class SubscriptionControllerTest : SupportController() {
1818
@MockBean
1919
private lateinit var userAppClient: UserAppClient
2020

21-
@Mock
22-
private lateinit var latestReceiptInfo: LatestReceiptInfo
23-
2421
@Mock
2522
private lateinit var unifiedReceipt: UnifiedReceipt
2623

2724

2825
private val testStatusUpdateNotification: StatusUpdateNotification = StatusUpdateNotification(
29-
"sandbox", "CANCEL", "cancellationDate", latestReceiptInfo, "",
30-
"latestExpiredReceipt", true, "", "autoRenewProductId",
31-
"autoRenewStatusChangeDate", 12323230, unifiedReceipt)
26+
"adamId", "sandbox", true, "cancellationDate", 1,
27+
"latestExpiredReceipt", "1", "", "autoRenewProductId",
28+
"autoRenewStatusChangeDate", "CANEL", "123", "123", unifiedReceipt
29+
)
3230

3331
@Test
3432
fun `simulate subscription status update notification`() {
3533
this.mockMvc.perform(
36-
MockMvcRequestBuilders.post("/api/appstore/subscriptions/statusUpdateNotification")
37-
.contentType(MediaType.APPLICATION_JSON)
38-
.content(asJsonString(testStatusUpdateNotification))
39-
.accept(MediaType.APPLICATION_JSON))
40-
.andDo(MockMvcResultHandlers.print())
41-
.andExpect(MockMvcResultMatchers.status().isOk)
34+
MockMvcRequestBuilders.post("/api/appstore/subscriptions/statusUpdateNotification")
35+
.contentType(MediaType.APPLICATION_JSON)
36+
.content(asJsonString(testStatusUpdateNotification))
37+
.accept(MediaType.APPLICATION_JSON)
38+
)
39+
.andDo(MockMvcResultHandlers.print())
40+
.andExpect(MockMvcResultMatchers.status().isOk)
4241
}
4342

4443
}

0 commit comments

Comments
 (0)