Fix gifting subscription flow

This commit is contained in:
Phillip Thelen 2018-12-30 19:44:37 +01:00
parent 498cf32162
commit 1cba3d3068
8 changed files with 118 additions and 42 deletions

View file

@ -848,8 +848,12 @@
<string name="gift_one_get_one_description">Gift a sub and get a sub free event going on now!</string>
<string name="gift_title">Who would you like to gift to?</string>
<string name="gift_one_get_one">Gift one, Get one!</string>
<string name="gift_one_get_one_detailed_description">While this promotion is active, youll receive a matching subscription automatically after sending your gift.</string>
<string name="gift_one_get_one_detailed_description">While this promotion is active, youll receive a matching subscription automatically after sending your gift.</string>
<string name="gift_subscription_subtitle">Choose the subscription youd like to gift below! This purchase wont automatically renew.</string>
<string name="send_gift">Send Gift</string>
<string name="server">Server</string>
<string name="gift_confirmation_title">Your gift was sent!</string>
<string name="gift_confirmation_text_g1g1">Your gifted subscription was sent and your subscription applied to your account.</string>
<string name="gift_confirmation_text">Your gifted subscription was sent and your subscription applied to your account.</string>
</resources>

View file

@ -226,7 +226,7 @@ abstract class HabiticaBaseApplication : MultiDexApplication() {
}
fun checkUserAuthentication(context: Context, hostConfig: HostConfig?): Boolean {
if (hostConfig == null || hostConfig.api == null || hostConfig.api == "" || hostConfig.user == null || hostConfig.user == "") {
if (hostConfig?.api == null || hostConfig.api == "" || hostConfig.user == "") {
startActivity(IntroActivity::class.java, context)
return false

View file

@ -3,9 +3,9 @@ package com.habitrpg.android.habitica;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import androidx.annotation.NonNull;
import com.habitrpg.android.habitica.data.ApiClient;
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent;
import com.habitrpg.android.habitica.events.UserSubscribedEvent;
import com.habitrpg.android.habitica.helpers.PurchaseTypes;
import com.habitrpg.android.habitica.models.IAPGift;
@ -13,6 +13,7 @@ import com.habitrpg.android.habitica.models.PurchaseValidationRequest;
import com.habitrpg.android.habitica.models.SubscriptionValidationRequest;
import com.habitrpg.android.habitica.models.Transaction;
import com.habitrpg.android.habitica.models.responses.ErrorResponse;
import com.habitrpg.android.habitica.proxy.CrashlyticsProxy;
import com.playseeds.android.sdk.Seeds;
import org.greenrobot.eventbus.EventBus;
@ -30,6 +31,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import androidx.annotation.NonNull;
import retrofit2.HttpException;
/**
@ -79,7 +81,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
purchasedOrderList.add(purchase.orderId);
requestListener.onSuccess(verifiedPurchases);
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
//TODO: find way to get $ price automatically.
if (purchase.sku.equals(PurchaseTypes.Purchase4Gems)) {
@ -100,6 +102,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
purchasedOrderList.add(purchase.orderId);
requestListener.onSuccess(verifiedPurchases);
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
return;
}
}
@ -124,6 +127,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
pendingGifts.remove(purchase.sku);
}
requestListener.onSuccess(verifiedPurchases);
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
}, throwable -> {
if (throwable.getClass().equals(retrofit2.adapter.rxjava2.HttpException.class)) {
HttpException error = (HttpException)throwable;
@ -133,6 +137,7 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier {
purchasedOrderList.add(purchase.orderId);
requestListener.onSuccess(verifiedPurchases);
EventBus.getDefault().post(new ConsumablePurchasedEvent(purchase));
return;
}
}

View file

@ -250,7 +250,7 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener;
}
override fun hasAuthenticationKeys(): Boolean {
return this.hostConfig.user != null
return this.hostConfig.user.isNotEmpty() && hostConfig.api.isNotEmpty()
}
private fun showConnectionProblemDialog(resourceMessageString: Int) {

View file

@ -0,0 +1,5 @@
package com.habitrpg.android.habitica.events
import org.solovyev.android.checkout.Purchase
class ConsumablePurchasedEvent(internal val purchase: Purchase)

View file

@ -1,9 +1,7 @@
package com.habitrpg.android.habitica.ui.activities
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.MotionEvent
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
@ -12,12 +10,10 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent
import com.instabug.library.InstabugTrackingDelegate
import io.reactivex.disposables.CompositeDisposable
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import com.instabug.library.InstabugTrackingDelegate
import android.view.MotionEvent
abstract class BaseActivity : AppCompatActivity() {

View file

@ -12,6 +12,7 @@ import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.PurchaseTypes
import com.habitrpg.android.habitica.helpers.RxErrorHandler
@ -23,6 +24,7 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
import com.playseeds.android.sdk.Seeds
import com.playseeds.android.sdk.inappmessaging.InAppMessageListener
import io.reactivex.functions.Consumer
import org.greenrobot.eventbus.Subscribe
import org.solovyev.android.checkout.*
import java.util.*
import javax.inject.Inject
@ -38,6 +40,7 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
internal val viewPager: androidx.viewpager.widget.ViewPager by bindView(R.id.viewPager)
internal var fragments: MutableList<CheckoutFragment> = ArrayList()
var isActive = false
var activityCheckout: ActivityCheckout? = null
private set
private var billingRequests: BillingRequests? = null
@ -91,28 +94,15 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
}, RxErrorHandler.handleEmptyError()))
}
override fun onResume() {
super.onResume()
override fun onStart() {
super.onStart()
setupCheckout()
activityCheckout?.destroyPurchaseFlow()
activityCheckout?.createPurchaseFlow(object : RequestListener<Purchase> {
override fun onSuccess(purchase: Purchase) {
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
override fun onSuccess(o: Any) {
//EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
if (purchase.sku == PurchaseTypes.Purchase84Gems) {
this@GemPurchaseActivity.showSeedsPromo(getString(R.string.seeds_interstitial_sharing), "store")
}
}
override fun onError(i: Int, e: Exception) {
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
}
})
}
}
override fun onError(i: Int, e: Exception) {
@ -140,9 +130,19 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
})
}
public override fun onPause() {
activityCheckout?.stop()
override fun onResume() {
super.onResume()
isActive = true
}
override fun onPause() {
super.onPause()
isActive = false
}
public override fun onStop() {
activityCheckout?.stop()
super.onStop()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -270,6 +270,13 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
})
}
@Subscribe
public fun onConsumablePurchased(event: ConsumablePurchasedEvent) {
if (isActive) {
consumePurchase(event.purchase)
}
}
interface CheckoutFragment {
fun setupCheckout()
@ -279,4 +286,18 @@ class GemPurchaseActivity : BaseActivity(), InAppMessageListener {
fun setBillingRequests(billingRequests: BillingRequests?)
}
private fun consumePurchase(purchase: Purchase) {
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
override fun onSuccess(result: Any) {
}
override fun onError(response: Int, e: Exception) {
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
}
})
}
}
}

View file

@ -1,12 +1,14 @@
package com.habitrpg.android.habitica.ui.activities
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.AttributeSet
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.core.view.isVisible
import com.habitrpg.android.habitica.HabiticaBaseApplication
@ -14,6 +16,7 @@ import com.habitrpg.android.habitica.HabiticaPurchaseVerifier
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.events.ConsumablePurchasedEvent
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.PurchaseTypes
import com.habitrpg.android.habitica.helpers.RemoteConfigManager
@ -25,11 +28,9 @@ import com.habitrpg.android.habitica.ui.helpers.bindView
import com.habitrpg.android.habitica.ui.views.social.UsernameLabel
import com.habitrpg.android.habitica.ui.views.subscriptions.SubscriptionOptionView
import io.reactivex.functions.Consumer
import org.greenrobot.eventbus.Subscribe
import org.solovyev.android.checkout.*
import javax.inject.Inject
import android.content.Intent
class GiftIAPActivity: BaseActivity() {
@ -100,9 +101,8 @@ class GiftIAPActivity: BaseActivity() {
}, RxErrorHandler.handleEmptyError()))
}
override fun onResume() {
super.onResume()
override fun onStart() {
super.onStart()
setupCheckout()
activityCheckout?.destroyPurchaseFlow()
@ -135,6 +135,10 @@ class GiftIAPActivity: BaseActivity() {
override fun onReady(billingRequests: BillingRequests, s: String, b: Boolean) {}
})
}
override fun onResume() {
super.onResume()
this.subscription1MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription1MonthNoRenew) })
this.subscription3MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription3MonthNoRenew) })
@ -142,17 +146,23 @@ class GiftIAPActivity: BaseActivity() {
this.subscription12MonthView?.setOnPurchaseClickListener(View.OnClickListener { selectSubscription(PurchaseTypes.Subscription12MonthNoRenew) })
}
override fun onPause() {
override fun onStop() {
activityCheckout?.stop()
super.onPause()
super.onStop()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
activityCheckout?.onActivityResult(requestCode, resultCode, data)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
}
return super.onOptionsItemSelected(item)
}
private fun updateButtonLabel(sku: Sku, price: String, subscriptions: Inventory.Product) {
val matchingView = buttonForSku(sku)
@ -197,9 +207,8 @@ class GiftIAPActivity: BaseActivity() {
}
private fun selectSubscription(sku: Sku) {
if (this.selectedSubscriptionSku != null) {
val oldButton = buttonForSku(this.selectedSubscriptionSku)
oldButton?.setIsPurchased(false)
for (thisSku in skus) {
buttonForSku(sku)?.setIsPurchased(false)
}
this.selectedSubscriptionSku = sku
val subscriptionOptionButton = buttonForSku(this.selectedSubscriptionSku)
@ -229,4 +238,40 @@ class GiftIAPActivity: BaseActivity() {
billingRequests?.purchase(ProductTypes.IN_APP, sku.id.code, null, it.purchaseFlow)
}
}
@Subscribe
public fun onConsumablePurchased(event: ConsumablePurchasedEvent) {
consumePurchase(event.purchase)
displayConfirmationDialog()
finish()
}
private fun displayConfirmationDialog() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert)
} else {
AlertDialog.Builder(this)
}
.setTitle(R.string.gift_confirmation_title)
.setMessage(if (remoteConfigManager.enableGiftOneGetOne()) R.string.gift_confirmation_text_g1g1 else R.string.gift_confirmation_text)
.setPositiveButton(android.R.string.ok) { dialog, _ ->
dialog.dismiss()
}
.show()
}
private fun consumePurchase(purchase: Purchase) {
if (PurchaseTypes.allGemTypes.contains(purchase.sku) || PurchaseTypes.allSubscriptionNoRenewTypes.contains(purchase.sku)) {
billingRequests?.consume(purchase.token, object : RequestListener<Any> {
override fun onSuccess(result: Any) {
}
override fun onError(response: Int, e: Exception) {
crashlyticsProxy.fabricLogE("PurchaseConsumeException", "Consume", e)
}
})
}
}
}