From 83bb7c3b6cdd56f300aa8e95028a7f349fe3272d Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Thu, 19 Jan 2017 09:18:19 +0100 Subject: [PATCH] handle new subscriptions --- .../habitica/HabiticaPurchaseVerifier.java | 41 +++++++++++++-- .../habitica/events/UserSubscribedEvent.java | 4 ++ .../ui/fragments/SubscriptionFragment.java | 21 ++++++-- .../habitrpgwrapper/lib/api/ApiService.java | 4 ++ .../models/SubscriptionValidationRequest.java | 9 ++++ .../android/habitica/HabiticaApplication.java | 18 +++++++ .../habitica/ReleaseDeveloperModule.java | 13 +++++ .../habitica/proxy/CrashlyticsProxyImpl.java | 50 +++++++++++++++++++ 8 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/events/UserSubscribedEvent.java create mode 100644 Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/SubscriptionValidationRequest.java create mode 100644 Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/HabiticaApplication.java create mode 100644 Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/ReleaseDeveloperModule.java create mode 100644 Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/proxy/CrashlyticsProxyImpl.java diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java index 1809e6e18..9a7282eaa 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/HabiticaPurchaseVerifier.java @@ -1,11 +1,14 @@ package com.habitrpg.android.habitica; +import com.habitrpg.android.habitica.events.UserSubscribedEvent; import com.habitrpg.android.habitica.helpers.PurchaseTypes; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult; +import com.magicmicky.habitrpgwrapper.lib.models.SubscriptionValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.Transaction; import com.playseeds.android.sdk.Seeds; +import org.greenrobot.eventbus.EventBus; import org.solovyev.android.checkout.BasePurchaseVerifier; import org.solovyev.android.checkout.Purchase; import org.solovyev.android.checkout.RequestListener; @@ -51,12 +54,11 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier { requestListener.onSuccess(verifiedPurchases); } else { - PurchaseValidationRequest validationRequest = new PurchaseValidationRequest(); - validationRequest.transaction = new Transaction(); - validationRequest.transaction.receipt = purchase.data; - validationRequest.transaction.signature = purchase.signature; - if (PurchaseTypes.allGemTypes.contains(purchase.sku)) { + PurchaseValidationRequest validationRequest = new PurchaseValidationRequest(); + validationRequest.transaction = new Transaction(); + validationRequest.transaction.receipt = purchase.data; + validationRequest.transaction.signature = purchase.signature; apiHelper.apiService.validatePurchase(validationRequest).subscribe(purchaseValidationResult -> { purchasedOrderList.add(purchase.orderId); @@ -92,7 +94,36 @@ public class HabiticaPurchaseVerifier extends BasePurchaseVerifier { requestListener.onError(purchases.indexOf(purchase), new Exception()); }); } else if (PurchaseTypes.allSubscriptionTypes.contains(purchase.sku)) { + SubscriptionValidationRequest validationRequest = new SubscriptionValidationRequest(); + validationRequest.transaction = new Transaction(); + validationRequest.transaction.receipt = purchase.data; + validationRequest.transaction.signature = purchase.signature; + validationRequest.sku = purchase.sku; + apiHelper.apiService.validateSubscription(validationRequest).subscribe(purchaseValidationResult -> { + purchasedOrderList.add(purchase.orderId); + verifiedPurchases.add(purchase); + + requestListener.onSuccess(verifiedPurchases); + + EventBus.getDefault().post(new UserSubscribedEvent()); + }, throwable -> { + if (throwable.getClass().equals(HttpException.class)) { + HttpException error = (HttpException) throwable; + APIHelper.ErrorResponse res = apiHelper.getErrorResponse((HttpException) throwable); + if (error.code() == 401) { + if (res.message.equals("RECEIPT_ALREADY_USED")) { + purchasedOrderList.add(purchase.orderId); + + verifiedPurchases.add(purchase); + + requestListener.onSuccess(verifiedPurchases); + return; + } + } + } + requestListener.onError(purchases.indexOf(purchase), new Exception()); + }); } } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/events/UserSubscribedEvent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/events/UserSubscribedEvent.java new file mode 100644 index 000000000..43afed555 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/events/UserSubscribedEvent.java @@ -0,0 +1,4 @@ +package com.habitrpg.android.habitica.events; + +public class UserSubscribedEvent { +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.java index a983965ab..8e7833e7b 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/SubscriptionFragment.java @@ -4,6 +4,7 @@ import com.habitrpg.android.habitica.APIHelper; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.components.AppComponent; import com.habitrpg.android.habitica.events.BoughtGemsEvent; +import com.habitrpg.android.habitica.events.UserSubscribedEvent; import com.habitrpg.android.habitica.helpers.PurchaseTypes; import com.habitrpg.android.habitica.proxy.ifce.CrashlyticsProxy; import com.habitrpg.android.habitica.ui.SubscriptionDetailsView; @@ -13,6 +14,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.HabitRPGUser; import com.magicmicky.habitrpgwrapper.lib.models.SubscriptionPlan; import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; import org.solovyev.android.checkout.ActivityCheckout; import org.solovyev.android.checkout.BillingRequests; import org.solovyev.android.checkout.Checkout; @@ -80,7 +82,6 @@ public class SubscriptionFragment extends BaseFragment implements GemPurchaseAct private GemPurchaseActivity listener; private BillingRequests billingRequests; - private Inventory inventory; private HabitRPGUser user; private boolean hasLoadedSubscriptionOptions; @@ -92,12 +93,22 @@ public class SubscriptionFragment extends BaseFragment implements GemPurchaseAct super.onCreateView(inflater, container, savedInstanceState); - apiHelper.apiService.getUser().compose(apiHelper.configureApiCallObserver()) - .subscribe(this::setUser, throwable -> {}); + fetchUser(null); return inflater.inflate(R.layout.fragment_subscription, container, false); } + @Override + public void onDestroyView() { + super.onDestroyView(); + } + + @Subscribe + public void fetchUser(@Nullable UserSubscribedEvent event) { + apiHelper.apiService.getUser().compose(apiHelper.configureApiCallObserver()) + .subscribe(this::setUser, throwable -> {}); + } + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -120,7 +131,7 @@ public class SubscriptionFragment extends BaseFragment implements GemPurchaseAct public void setupCheckout() { final ActivityCheckout checkout = listener.getActivityCheckout(); if (checkout != null) { - inventory = checkout.makeInventory(); + Inventory inventory = checkout.makeInventory(); inventory.load(Inventory.Request.create() .loadAllPurchases().loadSkus(ProductTypes.SUBSCRIPTION, PurchaseTypes.allSubscriptionTypes), @@ -236,11 +247,13 @@ public class SubscriptionFragment extends BaseFragment implements GemPurchaseAct this.subscriptionDetailsView.setVisibility(View.VISIBLE); this.subscriptionDetailsView.setPlan(plan); this.subscribeBenefitsTitle.setText(R.string.subscribe_prompt_thanks); + this.subscriptionOptions.setVisibility(View.GONE); } else { if (!hasLoadedSubscriptionOptions) { return; } this.subscriptionOptions.setVisibility(View.VISIBLE); + this.subscriptionDetailsView.setVisibility(View.GONE); } this.loadingIndicator.setVisibility(View.GONE); } diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java index 5641255f8..a93703bcb 100644 --- a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/api/ApiService.java @@ -14,6 +14,7 @@ import com.magicmicky.habitrpgwrapper.lib.models.PurchaseValidationResult; import com.magicmicky.habitrpgwrapper.lib.models.Quest; import com.magicmicky.habitrpgwrapper.lib.models.Shop; import com.magicmicky.habitrpgwrapper.lib.models.Status; +import com.magicmicky.habitrpgwrapper.lib.models.SubscriptionValidationRequest; import com.magicmicky.habitrpgwrapper.lib.models.Tag; import com.magicmicky.habitrpgwrapper.lib.models.TaskDirectionData; import com.magicmicky.habitrpgwrapper.lib.models.UserAuth; @@ -243,6 +244,9 @@ public interface ApiService { @POST("/iap/android/verify") Observable> validatePurchase(@Body PurchaseValidationRequest request); + @POST("/iap/android/subscribe") + Observable> validateSubscription(@Body SubscriptionValidationRequest request); + @POST("user/custom-day-start") Observable> changeCustomDayStart(@Body Map updateObject); diff --git a/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/SubscriptionValidationRequest.java b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/SubscriptionValidationRequest.java new file mode 100644 index 000000000..8f54368a6 --- /dev/null +++ b/Habitica/src/main/java/com/magicmicky/habitrpgwrapper/lib/models/SubscriptionValidationRequest.java @@ -0,0 +1,9 @@ +package com.magicmicky.habitrpgwrapper.lib.models; + + +public class SubscriptionValidationRequest { + + public Transaction transaction; + public String sku; + +} diff --git a/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/HabiticaApplication.java b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/HabiticaApplication.java new file mode 100644 index 000000000..0d9f5117a --- /dev/null +++ b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/HabiticaApplication.java @@ -0,0 +1,18 @@ +package com.habitrpg.android.habitica; + +import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.components.DaggerAppComponent; +import com.habitrpg.android.habitica.modules.AppModule; + +import android.content.Context; + +public class HabiticaApplication extends HabiticaBaseApplication { + @Override + protected AppComponent initDagger() { + return DaggerAppComponent.builder() + .appModule(new AppModule(this)) + .developerModule(new ReleaseDeveloperModule()) + .build(); + } + +} diff --git a/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/ReleaseDeveloperModule.java b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/ReleaseDeveloperModule.java new file mode 100644 index 000000000..2421ebed3 --- /dev/null +++ b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/ReleaseDeveloperModule.java @@ -0,0 +1,13 @@ +package com.habitrpg.android.habitica; + + +import com.habitrpg.android.habitica.modules.DeveloperModule; +import com.habitrpg.android.habitica.proxy.CrashlyticsProxyImpl; +import com.habitrpg.android.habitica.proxy.ifce.CrashlyticsProxy; + +//change debug proxy here by override methods +public class ReleaseDeveloperModule extends DeveloperModule { + @Override protected CrashlyticsProxy provideCrashlyticsProxy() { + return new CrashlyticsProxyImpl(); + } +} diff --git a/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/proxy/CrashlyticsProxyImpl.java b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/proxy/CrashlyticsProxyImpl.java new file mode 100644 index 000000000..8302568ba --- /dev/null +++ b/Habitica/src/releasedebuggable/java/com/habitrpg/android/habitica/proxy/CrashlyticsProxyImpl.java @@ -0,0 +1,50 @@ +package com.habitrpg.android.habitica.proxy; + + +import com.crashlytics.android.Crashlytics; +import com.crashlytics.android.core.CrashlyticsCore; +import com.habitrpg.android.habitica.proxy.ifce.CrashlyticsProxy; + +import android.content.Context; + +import io.fabric.sdk.android.Fabric; + +public class CrashlyticsProxyImpl implements CrashlyticsProxy { + @Override + public void init(Context context) { + Crashlytics crashlytics = new Crashlytics.Builder() + .core(new CrashlyticsCore.Builder().build()) + .build(); + Fabric.with(context, crashlytics); + } + + + @Override + public void logException(Throwable t) { + Crashlytics.logException(t); + } + + @Override + public void setString(String key, String value) { + Crashlytics.setString(key, value); + } + + @Override + public void setUserIdentifier(String identifier) { + if (Crashlytics.getInstance().core != null && identifier != null) { + Crashlytics.getInstance().core.setUserIdentifier(identifier); + } + } + + @Override + public void setUserName(String name) { + if (Crashlytics.getInstance().core != null && name != null) { + Crashlytics.getInstance().core.setUserName(name); + } + } + + @Override + public void fabricLogE(String s1, String s2, Exception e) { + Fabric.getLogger().e(s1,s2,e); + } +}