123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- package com.vpn.fastestvpnservice.viewmodels
- import android.app.Activity
- import android.content.Context
- import android.util.Base64
- import android.util.Log
- import androidx.activity.ComponentActivity
- import androidx.compose.runtime.livedata.observeAsState
- import androidx.compose.runtime.mutableStateOf
- import androidx.lifecycle.LiveData
- import androidx.lifecycle.MutableLiveData
- import androidx.lifecycle.ViewModel
- import com.android.billingclient.api.AcknowledgePurchaseParams
- import com.android.billingclient.api.BillingClient
- import com.android.billingclient.api.BillingClientStateListener
- import com.android.billingclient.api.BillingFlowParams
- import com.android.billingclient.api.BillingResult
- import com.android.billingclient.api.Purchase
- import com.android.billingclient.api.PurchasesUpdatedListener
- import com.android.billingclient.api.SkuDetails
- import com.android.billingclient.api.SkuDetailsParams
- import com.google.gson.Gson
- import com.google.gson.reflect.TypeToken
- import com.vpn.fastestvpnservice.R
- import de.blinkt.openvpn.core.App
- import com.vpn.fastestvpnservice.beans.DataResponse
- import com.vpn.fastestvpnservice.beans.DataResponseServers
- import com.vpn.fastestvpnservice.beans.Features
- import com.vpn.fastestvpnservice.beans.ProductFeatures
- import com.vpn.fastestvpnservice.beans.ServerData
- import com.vpn.fastestvpnservice.beans.SubscriptionPackageList
- import com.vpn.fastestvpnservice.customItems.getSelectedPosition
- import com.vpn.fastestvpnservice.helpers.BasePreferenceHelper
- import com.vpn.fastestvpnservice.retrofit.RetrofitNetworkHandling
- import com.vpn.fastestvpnservice.retrofit.WebServiceFactory
- import com.vpn.fastestvpnservice.screens.accountScreensAll.SubscriptionScreen
- import org.json.JSONArray
- import org.json.JSONObject
- import retrofit2.Call
- class SubscriptionViewModel constructor(context: Context, activity: ComponentActivity): ViewModel(), PurchasesUpdatedListener {
- var mutableLiveDataProducts = MutableLiveData<DataResponse<ArrayList<ProductFeatures>>>()
- var liveDataProducts: LiveData<DataResponse<ArrayList<ProductFeatures>>> = mutableLiveDataProducts
- val mutableLiveDataSubscription = MutableLiveData<DataResponseServers<ArrayList<ServerData>>>()
- var mutableLiveDataSkuDetails = MutableLiveData<MutableList<SkuDetails>>()
- var liveDataSkuDetails: LiveData<MutableList<SkuDetails>> = mutableLiveDataSkuDetails
- var mutableLiveDataProductsErrorStatus = MutableLiveData<Boolean>()
- var preferenceHelper: BasePreferenceHelper
- private var context: Context
- private var activity: ComponentActivity
- var mutableLiveDataNumber = MutableLiveData<Int>(0)
- val tag = "SubscriptionViewModel"
- val prefHelper = BasePreferenceHelper(context)
- private var skuDetailsList: List<SkuDetails>? = null
- var featuresList = MutableLiveData<MutableList<ProductFeatures>>()
- var featuresListSorted = MutableLiveData<MutableList<ProductFeatures>>()
- var featuresListSortedItems = MutableLiveData<MutableList<Features>>()
- var selectPriceList = MutableLiveData<MutableList<SubscriptionPackageList>>()
- private val billingClient: BillingClient by lazy {
- BillingClient.newBuilder(context)
- .setListener(this)
- .enablePendingPurchases()
- .build()
- }
- companion object {
- var selectedPosition: Int = 0
- }
- init {
- this.context = context
- this.activity = activity
- preferenceHelper = BasePreferenceHelper(context)
- }
- fun setSelectedPosition(num: Int) {
- Log.d("test_plan", "[1] num = $num")
- mutableLiveDataNumber.postValue(num)
- Log.d("test_plan", "[2] num = $num")
- }
- fun setProductsData(products: DataResponse<ArrayList<ProductFeatures>>) {
- mutableLiveDataProducts.value = products
- }
- fun getProducts(onProductResult: () -> Unit){
- WebServiceFactory.getInstance().getProducts().enqueue(
- RetrofitNetworkHandling<Any>(object :
- RetrofitNetworkHandling.ResponseCallback<Any>{
- override fun onSuccess(call: Call<Any>?, response: Any?) {
- try {
- val gson = Gson()
- val jsonString = gson.toJson(response)
- val type = object : TypeToken<DataResponse<ArrayList<ProductFeatures>>>() {}.type
- val data = gson.fromJson<DataResponse<ArrayList<ProductFeatures>>>(jsonString, type)
- Log.d("test_api_response_p", "Products try = ${data.status} ${data.message} ${data.data?.size}")
- data?.data?.let {
- preferenceHelper.saveFeaturesData(it)
- featuresList.value = it
- }
- if (data.data?.size == 0){
- onProductResult()
- }
- mutableLiveDataProducts.value = data
- mutableLiveDataProductsErrorStatus.value = false
- startConnection(getSelectedPosition())
- } catch (ex: Exception) {
- Log.d("test_api_response", "Products catch:")
- mutableLiveDataProductsErrorStatus.value = true
- }
- }
- override fun onFail(call: Call<Any>?, response: Any?) {
- Log.d("test_api_response", "Products onFail: ")
- mutableLiveDataProductsErrorStatus.value = true
- }
- override fun onError(call: Call<Any>?, response: Any?) {
- Log.d("test_api_response", "Products onError: ")
- mutableLiveDataProductsErrorStatus.value = true
- }
- }
- )
- )
- }
- fun create_subscription(transaction_id: String, receipt_data: String, productId: String) {
- Log.d("test_api_response", "create_subscription params = $transaction_id $receipt_data $productId")
- WebServiceFactory.getInstance().createSubscription(transaction_id, receipt_data, productId).enqueue(
- RetrofitNetworkHandling<Any>(object :
- RetrofitNetworkHandling.ResponseCallback<Any> {
- override fun onSuccess(call: Call<Any>?, response: Any?) {
- try {
- Log.d("test_api_response", "create_subscription try = $response")
- val gson = Gson()
- val jsonString = gson.toJson(response)
- val type = object : TypeToken<DataResponseServers<ArrayList<ServerData>>>() {}.type
- val data = gson.fromJson<DataResponseServers<ArrayList<ServerData>>>(jsonString, type)
- Log.d("test_api_response", "create_subscription try = ${data.status} ${data.message}")
- data?.let {
- mutableLiveDataSubscription.value = it
- }
- } catch (ex: Exception) {
- Log.d("test_api_response", "create_subscription catch = $response")
- }
- }
- override fun onFail(call: Call<Any>?, response: Any?) {
- Log.d("test_api_response", "create_subscription onFail = $response")
- }
- override fun onError(call: Call<Any>?, response: Any?) {
- Log.d("test_api_response", "create_subscription onError = $response")
- }
- })
- )
- }
- fun startConnection(selectedPosition: Int) {
- SubscriptionViewModel.selectedPosition = selectedPosition
- Log.d(tag, "startConnection Billing")
- billingClient.startConnection(object : BillingClientStateListener {
- override fun onBillingSetupFinished(billingResult: BillingResult) {
- if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
- Log.d(tag, "onBillingSetupFinished")
- Log.d(tag, "BILLING | startConnection | RESULT OK")
- onLoadProductsClicked()
- } else {
- Log.d(tag, "BILLING | startConnection | RESULT: ${billingResult.responseCode}")
- }
- }
- override fun onBillingServiceDisconnected() {
- Log.d(tag, "BILLING | onBillingServiceDisconnected | DISCONNECTED")
- }
- })
- }
- private fun onLoadProductsClicked() {
- Log.d(tag, "onLoadProductsClicked Billing")
- // val skuList = listOf("com.fastestvpn.vpn.one.month", "com.fastestvpn.vpn.one.year")
- val skuList: ArrayList<String> = ArrayList<String>()
- val identifierProduct = prefHelper.getFeaturesData()
- identifierProduct.forEachIndexed { index, productFeatures ->
- productFeatures.identifier?.let { skuList.add(it) }
- }
- skuList.forEachIndexed { index, s ->
- Log.d("skulist identidiers", s)
- }
- val skuDetailsListsSubs: MutableList<SkuDetails> = ArrayList<SkuDetails>()
- val params = SkuDetailsParams.newBuilder()
- params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP)
- billingClient.querySkuDetailsAsync(params.build())
- { billingResult, skuDetailsList ->
- if (billingResult.responseCode == BillingClient.BillingResponseCode.OK
- && skuDetailsList != null) {
- for (skuDetails in skuDetailsList) {
- Log.d(tag, "[1st] ${skuDetails.title} Billing")
- skuDetailsListsSubs.add(skuDetails)
- }
- params.setType(BillingClient.SkuType.SUBS)
- billingClient.querySkuDetailsAsync(params.build())
- { billingResults, skuDetailsLists ->
- if (billingResults.responseCode == BillingClient.BillingResponseCode.OK
- && skuDetailsLists != null) {
- for (skuDetails in skuDetailsLists) {
- Log.d(tag, "[2nd] ${skuDetails.title} Billing")
- skuDetailsListsSubs.add(skuDetails)
- }
- mutableLiveDataSkuDetails.postValue(skuDetailsListsSubs)
- // subscriptionProduct(selectedPosition, skuDetailsListsSubs, activity)
- initProductList(skuDetailsListsSubs)
- }
- }
- }
- }
- }
- fun subscriptionProduct(
- selectedPosition: Int,
- skuDetailsListsSubs: MutableList<SkuDetails>,
- activity: ComponentActivity
- ) {
- Log.d(tag, "subscriptionProduct Billing $skuDetailsListsSubs")
- if (skuDetailsListsSubs != null && skuDetailsListsSubs.isNotEmpty())
- {
- Log.d(tag, "subscriptionProduct IN Billing")
- val billingFlowParams = BillingFlowParams.newBuilder().setSkuDetails(
- skuDetailsListsSubs.get(selectedPosition)).build()
- billingClient.launchBillingFlow(activity, billingFlowParams)
- }
- }
- private fun initProductList(skuDetailsList: List<SkuDetails>) {
- Log.d("test_subscription_list", "skuDetailsList size = ${skuDetailsList.size}")
- this.skuDetailsList = skuDetailsList
- if (this.skuDetailsList?.size!! > 0) {
- Log.d("test_subscription_list", "skuDetailsList[2] size = ${skuDetailsList.size}")
- var boolValue: Boolean
- var freePeriod: String
- var title: String
- var selectFeatureListSorted = ArrayList<ProductFeatures>()
- val featuresListSortedData = ArrayList<ProductFeatures>()
- val selectPriceListData = ArrayList<SubscriptionPackageList>()
- featuresList.value?.let {
- for ((index, value) in skuDetailsList.withIndex()) {
- for ((indexed, values) in it.withIndex()) {
- if (value.sku == values.identifier) {
- Log.d("test_subscription_list", "Equal => $index + $indexed")
- featuresListSortedData.add(it.get(indexed))
- Log.d(
- "test_subscription_list",
- "featuresList: ${it.get(indexed).title} ${
- featuresListSortedData?.get(indexed)?.title
- }"
- )
- }
- }
- }
- }
- featuresListSorted.postValue(featuresListSortedData)
- featuresListSortedData.get(selectedPosition).features?.let {
- featuresListSortedItems.postValue(it)
- }
- val list = featuresListSorted.value
- Log.d("test_subscription_list", "featuresListSorted size = ${list?.size}")
- // featuresListSortedData.forEachIndexed { index, productFeatures ->
- // Log.d("test_subscription_list", "${productFeatures.title} + ${productFeatures.identifier} + ${productFeatures.price}")
- // }
- for ((index, value) in skuDetailsList.withIndex()) {
- // Log.d("test_subscription_list", value.title + " ," + value.freeTrialPeriod + "=>" + featuresList.value?.get(index)?.identifier)
- if (skuDetailsList.size > 1) {
- boolValue = index == 1
- } else {
- boolValue = index == 0
- }
- freePeriod = if (value.freeTrialPeriod == "P3D") {
- "Free for 3 days"
- } else if (value.freeTrialPeriod == "P1W") {
- "Free for 7 days"
- } else {
- ""
- }
- val planTitle = featuresListSortedData.get(index).title
- selectPriceListData.add(
- SubscriptionPackageList(
- planTitle ?: value.title, "Auto-Renewable", value.description, value.price,
- mutableStateOf(boolValue)
- )
- )
- }
- selectPriceListData.forEachIndexed { index, upgradePriceList ->
- Log.d(
- "test_subscription_list",
- "${upgradePriceList.packageDuration} ${upgradePriceList.planType} ${upgradePriceList.desc} ${upgradePriceList.price} ${upgradePriceList.isSelected.value}"
- )
- if (upgradePriceList.isSelected.value) {
- selectedPosition = index
- }
- }
- selectPriceList.postValue(selectPriceListData)
- }
- }
- override fun onPurchasesUpdated(p0: BillingResult, purchases: MutableList<Purchase>?) {
- if (purchases != null && purchases.size > 0) {
- Log.d("purchases_product", purchases.toString())
- parseDataAndMakeApiCall(purchases)
- }
- acknowledgePurchases(purchases)
- }
- private fun parseDataAndMakeApiCall(purchases: MutableList<Purchase>?) {
- try {
- val objectArray = JSONArray(Gson().toJson(purchases))
- val obj: JSONObject = objectArray.getJSONObject(0)
- val parsedJson = obj.getJSONObject("zzc")
- val nameValuePairs = parsedJson.getJSONObject("nameValuePairs")
- val orderId = nameValuePairs.getString("orderId")
- val productId = nameValuePairs.getString("productId")
- val packageName = nameValuePairs.getString("packageName")
- val purchaseToken = nameValuePairs.getString("purchaseToken")
- val billingCycle =
- productId.substring(productId.lastIndexOf('.') + 1) //removing pacakge name
- Log.d("purchases_product", billingCycle.toString())
- val receiptData = JSONObject()
- receiptData.put("orderId", orderId)
- receiptData.put("productId", productId)
- receiptData.put("packageName", packageName)
- receiptData.put("purchaseToken", purchaseToken)
- val receiptDataStr = receiptData.toString()
- val receiptDataStrEncoded: String =
- Base64.encodeToString(receiptDataStr.toByteArray(), Base64.NO_PADDING)
- create_subscription_Product(orderId, receiptDataStrEncoded, productId)
- // createOrder(billingCycle, orderId, receiptData)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- private fun create_subscription_Product(orderId: String, receiptData: String,
- productId: String) {
- Log.d("purchases_product", "$orderId, $receiptData, $productId")
- create_subscription(
- orderId, receiptData, productId
- )
- }
- private fun acknowledgePurchases(purchases: MutableList<Purchase>?) {
- val purchase = purchases?.first()
- if (purchase != null && !purchase.isAcknowledged
- && purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
- val acknowledgePurchaseParams =
- AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.purchaseToken)
- .build()
- billingClient.acknowledgePurchase(acknowledgePurchaseParams) { billingResult ->
- if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
- Log.d(
- "purchases_product",
- "AcknowledgePurchases success, responseCode: ${billingResult.responseCode}"
- )
- } else {
- Log.d(
- "purchases_product",
- "Can't allowMultiplePurchases, responseCode: ${billingResult.responseCode}"
- )
- }
- }
- }
- }
- }
|