11

Is it possible to know is subscription was purchased as free trial? For now I can't find a way how to do it on server/device side.

Does anybody has suggestions how to do it?

Stafox
  • 1,007
  • 14
  • 25
  • I can't understand your question. So, you have an app and you want to figure out if the current user is in a trial mode or not, I am right? – Todor Kostov Nov 29 '16 at 13:29
  • @TodorKostov Yes, you're right. User bought the subscription, and I want to know is current period trial. – Stafox Nov 29 '16 at 13:37
  • On your server side just save the date until which the subscription is active and if the current time is bigger than the one you have in your database, just do whatever you want. You have to relate this subscription date to all accounts in your database. – Todor Kostov Nov 29 '16 at 13:45
  • If user cancel subscription and then buy the same again - it will be a problem for this solution. Because I have no possibility to link those purchases. – Stafox Nov 29 '16 at 13:46
  • There is no need to link the two purchases at all. If the your canceled the subscription and after 2 days (for example) buys a new one again, just save the new date. A canceled subscription means he / she no longer needs it. I don't see the relation between these two purchases. – Todor Kostov Nov 29 '16 at 13:51
  • Look, you buy subscription com.app.sub, which has trial period. So, you paid nothing. Then you cancel it. Then after several days you buy it again, but you have no more trial period for it. Device sends to server data about this subscription. I check it and how I can detect trial it or no? – Stafox Nov 29 '16 at 14:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/129355/discussion-between-todor-kostov-and-stafox). – Todor Kostov Nov 29 '16 at 14:13

2 Answers2

7

On 9th of June, 2017 at page https://developers.google.com/android-publisher/api-ref/purchases/subscriptions appeared info about new value for paymentState - 2 which means "Free trial".

Stafox
  • 1,007
  • 14
  • 25
1

[--------- NOT SECURE ---------]

After spending few days i will share my solution(on client side).

First you need to allow API access in Google play developer console and create service account(docs).

You will get account id similar to this : your-service@api-621**********846-16504.iam.gserviceaccount.com

IMPORTANT: add "View financial data" permission in Users & permissions section in Google developer account.

Also download p12 key and put it in your assets folder.

Code to get subscription details(you need to know the subscription token):

HttpTransport httpTransport = new NetHttpTransport();

    JsonFactory jsonFactory = new JacksonFactory();

    List<String> scopes = new ArrayList<String>();
    scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER);


    HttpRequestInitializer credential = null;

    try {

        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(context.getAssets().open("key.p12"), "notasecret".toCharArray());
        PrivateKey pk = (PrivateKey) keystore.getKey("privatekey", "notasecret".toCharArray());

        credential = new GoogleCredential.Builder().setJsonFactory(jsonFactory)
                .setTransport(httpTransport)
                .setServiceAccountId("your-service@api-621**********846-16504.iam.gserviceaccount.com")
                .setServiceAccountPrivateKey(pk)
                .setServiceAccountScopes(scopes)
                .build();

    } catch (GeneralSecurityException e) {

    } catch (IOException e) {

    }


    AndroidPublisher publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).build();
    AndroidPublisher.Purchases purchases = publisher.purchases();


    try {

        AndroidPublisher.Purchases.Subscriptions.Get get = purchases.subscriptions()
                .get(context.getPackageName(), Constants.SUBSCRIPTION_ID, subscription_token);

        final SubscriptionPurchase purchase = get.execute();

        if (purchase != null && purchase.getPaymentState() != null) {

            int paymentState = purchase.getPaymentState();

            if (paymentState == 0) {
                // Subscriber with payment pending
            } else if (paymentState == 1) {
                // Subscriber in good standing (paid)
            } else if (paymentState == 2) {
                // Subscriber in free trial
            }
        }


    } catch (IOException e) { }

get.execute() is network request so you need to run this code on separate thread(i used RxJava)

You need to use AndroidPublisher and Play Services Auth libraries

implementation 'com.google.apis:google-api-services-androidpublisher:v3-rev22-1.25.0'

implementation 'com.google.android.gms:play-services-auth:15.0.1'
Pavel Poley
  • 5,307
  • 4
  • 35
  • 66
  • 6
    It's a huge security threat to store such things as service account credentials inside the application. Especially with admin permissions. It means if someone extract these data he will able to revoke any payment. Also he will able to download financial reports and a lot of other actions. Even publish/unpublish apps. – Stafox Sep 13 '18 at 07:02
  • What if i add only permission "View financial data"? what is the secure way to verify it on client side? – Pavel Poley Sep 13 '18 at 14:23
  • Using that permission anybody who will obtain service account will able to download absolutely all finanacial reports for all time. The best way is develop the simple server API. I hope you already use the one to verfy purchase. So the server should return isTrial true/false. Detect this state possbile using paymentState ( https://developers.google.com/android-publisher/api-ref/purchases/subscriptions) – Stafox Sep 13 '18 at 14:42
  • So in other words without server there is no way do it securely? – Pavel Poley Sep 13 '18 at 14:55
  • I'm not sure, but hope using the latest biling sdk you shoud able to get paymentState on client side – Stafox Sep 14 '18 at 07:35