diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0d8f028..01f181d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,20 +16,20 @@ android { minSdk = 24 targetSdk = 36 versionCode = 2 - versionName = "1.0.2+MK" + versionName = "1.0.2+BZ" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - // ---- Myket in-app billing ---- - val marketApplicationId = "ir.mservices.market" - val marketBindAddress = "ir.mservices.market.InAppBillingService.BIND" + // ---- Bazaar (Cafe Bazaar) in-app billing ---- + val marketApplicationId = "com.farsitel.bazaar" + val marketBindAddress = "ir.cafebazaar.pardakht.InAppBillingService.BIND" manifestPlaceholders["marketApplicationId"] = marketApplicationId manifestPlaceholders["marketBindAddress"] = marketBindAddress - manifestPlaceholders["marketPermission"] = "$marketApplicationId.BILLING" + manifestPlaceholders["marketPermission"] = "com.farsitel.bazaar.permission.PAY_THROUGH_BAZAAR" buildConfigField( "String", "IAB_PUBLIC_KEY", - "\"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDSaqJLDPxQZBZD/LGRsZOJ8m1hLVFedg/tnqebQusikVTNYSEjmP86i1TtXu/2b4E8hpkrqyNlNVvEg1lrHCpnxCh0tOubYiG6X/GEQtgOtIRuBzO3HM/r9w1HQm4gZOJc6DJO46Sxp3YbryJujp+pG8p7bU6zHp4zcqydCJ14QIDAQAB\"" + "\"MIHNMA0GCSqGSIb3DQEBAQUAA4G7ADCBtwKBrwDzw+tRS/C//9JebsgTQOPAJU3Qwg7aIOhO4wqPVMNCjkGQZH7MckLU8hC6Rrag8gakkGBROSN/J58W4q1wxFbaUgRiTvyM04ElE7tHHa8CKtNH3NSUFzCQkhqd+9mLGflmj7JEj6EaZLoTLfZYhQgGDpWNXwW9HmO2lygXkua6BUkelpafgAmLz/ojlBm+ByLdSVkXIaaGqs2GLLR4qZHiksljQskbv0T0Ccax8pcCAwEAAQ==\"" ) } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f429d7b..778c8e4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,11 +3,6 @@ xmlns:tools="http://schemas.android.com/tools"> - - - - - - helper.launchPurchaseFlow( + // محصول‌های بازار از نوع «اشتراک» هستند. + helper.launchSubscriptionPurchaseFlow( activity, sku, IabHelper.OnIabPurchaseFinishedListener { result, purchase -> @@ -71,7 +76,7 @@ class MyketPurchaseGateway( result.response == IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED -> cont.resume(PurchaseOutcome.AlreadyOwned) else -> - cont.resume(PurchaseOutcome.Error(result.message ?: "خطای پرداخت مایکت")) + cont.resume(PurchaseOutcome.Error(result.message ?: "خطای پرداخت بازار")) } }, payload @@ -81,8 +86,8 @@ class MyketPurchaseGateway( val purchase = when (outcome) { is PurchaseOutcome.Success -> outcome.purchase - PurchaseOutcome.AlreadyOwned -> recoverOwned(sku) - ?: return Result.failure(IllegalStateException("این محصول قبلاً خریداری شده است.")) + PurchaseOutcome.AlreadyOwned -> + return Result.failure(IllegalStateException("اشتراک شما از قبل فعال است.")) is PurchaseOutcome.Error -> return Result.failure(IllegalStateException(outcome.message)) } @@ -94,20 +99,13 @@ class MyketPurchaseGateway( Result.success(PurchaseResult(purchaseToken = token, orderId = purchase.orderId)) } - override suspend fun consume(purchaseToken: String): Result = mutex.withLock { - val purchase = pending[purchaseToken] ?: return Result.success(Unit) - val helper = helper ?: return Result.success(Unit) - runCatching { - suspendCancellableCoroutine { cont -> - helper.consumeAsync(purchase, IabHelper.OnConsumeFinishedListener { _, result -> - if (result.isSuccess) cont.resume(Unit) - else cont.resumeWithException(IllegalStateException(result.message ?: "خطای مصرفِ خرید")) - }) - } - }.onSuccess { pending.remove(purchaseToken) } + // اشتراکِ کافه‌بازار مصرف نمی‌شود؛ این متد بی‌اثر است. + override suspend fun consume(purchaseToken: String): Result { + pending.remove(purchaseToken) + return Result.success(Unit) } - /** اتصال به سرویس مایکت (یک‌بار). */ + /** اتصال به سرویس بازار (یک‌بار). */ private suspend fun ensureSetup(): Result { if (setupDone && helper != null) return Result.success(Unit) val newHelper = IabHelper(appContext, BuildConfig.IAB_PUBLIC_KEY) @@ -117,7 +115,7 @@ class MyketPurchaseGateway( newHelper.startSetup(IabHelper.OnIabSetupFinishedListener { result -> if (result.isSuccess) cont.resume(Unit) else cont.resumeWithException( - IllegalStateException(result.message ?: "اتصال به مایکت ناموفق بود") + IllegalStateException(result.message ?: "اتصال به بازار ناموفق بود") ) }) } @@ -129,22 +127,6 @@ class MyketPurchaseGateway( } } - /** بازیابیِ خریدِ مصرف‌نشدهٔ موجود (وقتی محصول قبلاً خریده شده). */ - private suspend fun recoverOwned(sku: String): Purchase? { - val helper = helper ?: return null - return runCatching { - suspendCancellableCoroutine { cont -> - helper.queryInventoryAsync( - false, - listOf(sku), - IabHelper.QueryInventoryFinishedListener { result, inventory -> - cont.resume(if (result.isSuccess) inventory.getPurchase(sku) else null) - } - ) - } - }.getOrNull() - } - private sealed interface PurchaseOutcome { data class Success(val purchase: Purchase) : PurchaseOutcome data object AlreadyOwned : PurchaseOutcome diff --git a/app/src/main/java/com/approagency/pharmacy/di/AppModule.kt b/app/src/main/java/com/approagency/pharmacy/di/AppModule.kt index 085515a..3e464ca 100644 --- a/app/src/main/java/com/approagency/pharmacy/di/AppModule.kt +++ b/app/src/main/java/com/approagency/pharmacy/di/AppModule.kt @@ -1,7 +1,7 @@ package com.approagency.pharmacy.di -import com.approagency.pharmacy.data.billing.MyketPurchaseGateway +import com.approagency.pharmacy.data.billing.BazaarPurchaseGateway import com.approagency.pharmacy.data.local.LocalDrugDataSource import com.approagency.pharmacy.data.local.SessionManager import com.approagency.pharmacy.data.local.database.LabDatabase @@ -115,8 +115,8 @@ val appModule= module { single { AuthRepositoryImpl(get(), get()) } - // درگاه پرداخت: روی شاخهٔ myket پیاده‌سازی مایکت. - single { MyketPurchaseGateway(androidContext(), get()) } + // درگاه پرداخت: روی شاخهٔ bazar پیاده‌سازی کافه‌بازار. + single { BazaarPurchaseGateway(androidContext(), get()) } factory { DrugHtmlParser() }