@@ -11,13 +11,16 @@ import com.android.billingclient.api.BillingClientStateListener
11
11
import com.android.billingclient.api.BillingFlowParams
12
12
import com.android.billingclient.api.BillingFlowParams.ProductDetailsParams
13
13
import com.android.billingclient.api.BillingResult
14
+ import com.android.billingclient.api.ConsumeParams
14
15
import com.android.billingclient.api.ProductDetails
15
16
import com.android.billingclient.api.ProductDetailsResult
16
17
import com.android.billingclient.api.Purchase
18
+ import com.android.billingclient.api.Purchase.PurchaseState
17
19
import com.android.billingclient.api.PurchasesUpdatedListener
18
20
import com.android.billingclient.api.QueryProductDetailsParams
19
21
import com.android.billingclient.api.QueryPurchasesParams
20
22
import com.android.billingclient.api.acknowledgePurchase
23
+ import com.android.billingclient.api.consumePurchase
21
24
import com.android.billingclient.api.queryProductDetails
22
25
import com.android.billingclient.api.queryPurchasesAsync
23
26
import dagger.hilt.android.qualifiers.ApplicationContext
@@ -26,10 +29,12 @@ import kotlinx.coroutines.CoroutineScope
26
29
import kotlinx.coroutines.launch
27
30
import kotlinx.coroutines.suspendCancellableCoroutine
28
31
import kotlinx.coroutines.withContext
32
+ import org.edx.mobile.extenstion.decodeToString
29
33
import org.edx.mobile.extenstion.encodeToString
30
34
import org.edx.mobile.extenstion.resumeIfActive
31
35
import org.edx.mobile.injection.DataSourceDispatcher
32
36
import org.edx.mobile.logger.Logger
37
+ import org.edx.mobile.model.api.EnrolledCoursesResponse.ProductInfo
33
38
import javax.inject.Inject
34
39
import javax.inject.Singleton
35
40
@@ -125,16 +130,20 @@ class BillingProcessor @Inject constructor(
125
130
* Called to purchase the new product. Query the product details and launch the purchase flow.
126
131
*
127
132
* @param activity active activity to launch our billing flow from
128
- * @param productId Product Id to be purchased
129
133
* @param userId User Id of the purchaser
134
+ * @param productInfo Course and Product info to purchase
130
135
*/
131
- suspend fun purchaseItem (activity : Activity , productId : String , userId : Long ) {
136
+ suspend fun purchaseItem (
137
+ activity : Activity ,
138
+ userId : Long ,
139
+ productInfo : ProductInfo ,
140
+ ) {
132
141
if (isReadyOrConnect()) {
133
- val response = querySyncDetails(productId )
142
+ val response = querySyncDetails(productInfo.storeSku )
134
143
logger.debug(" Getting Purchases -> ${response.billingResult} " )
135
144
136
145
response.productDetailsList?.first()?.let {
137
- launchBillingFlow(activity, it, userId)
146
+ launchBillingFlow(activity, it, userId, productInfo.courseSku )
138
147
}
139
148
} else {
140
149
listener.onPurchaseCancel(BillingResponseCode .BILLING_UNAVAILABLE , " " )
@@ -152,7 +161,8 @@ class BillingProcessor @Inject constructor(
152
161
private fun launchBillingFlow (
153
162
activity : Activity ,
154
163
productDetails : ProductDetails ,
155
- userId : Long
164
+ userId : Long ,
165
+ courseSku : String ,
156
166
) {
157
167
val productDetailsParamsList = listOf (
158
168
ProductDetailsParams .newBuilder()
@@ -163,6 +173,7 @@ class BillingProcessor @Inject constructor(
163
173
val billingFlowParams = BillingFlowParams .newBuilder()
164
174
.setProductDetailsParamsList(productDetailsParamsList)
165
175
.setObfuscatedAccountId(userId.encodeToString())
176
+ .setObfuscatedProfileId(courseSku.encodeToString())
166
177
.build()
167
178
168
179
billingClient.launchBillingFlow(activity, billingFlowParams)
@@ -232,7 +243,18 @@ class BillingProcessor @Inject constructor(
232
243
QueryPurchasesParams .newBuilder()
233
244
.setProductType(BillingClient .ProductType .INAPP )
234
245
.build()
235
- ).purchasesList
246
+ ).purchasesList.filter { it.purchaseState == PurchaseState .PURCHASED }
247
+ }
248
+
249
+ suspend fun consumePurchase (purchaseToken : String ): BillingResult {
250
+ isReadyOrConnect()
251
+ val result = billingClient.consumePurchase(
252
+ ConsumeParams
253
+ .newBuilder()
254
+ .setPurchaseToken(purchaseToken)
255
+ .build()
256
+ )
257
+ return result.billingResult
236
258
}
237
259
238
260
companion object {
@@ -251,3 +273,7 @@ class BillingProcessor @Inject constructor(
251
273
252
274
fun ProductDetails.OneTimePurchaseOfferDetails.getPriceAmount (): Double =
253
275
this .priceAmountMicros.toDouble().div(BillingProcessor .MICROS_TO_UNIT )
276
+
277
+ fun Purchase.getCourseSku (): String? {
278
+ return this .accountIdentifiers?.obfuscatedProfileId?.decodeToString()
279
+ }
0 commit comments