Major short-comings with Billing API & Proposed Solutions

amardeep
Shopify Expert
18 0 17

I have an app published on Shopify App Store and one is in the making. Developing Shopify apps for more than an year, I believe they are major short-comings in the Billing API which make it a very tedious process for implementing & testing billing in Shopify Apps. I will list them down below. I really hope something gets done about these:

 

Consider the scenario:

- A Shopify App has some basic features available to use for free and some premium features which require a Premium subscription. 

- A user installs the app on 5 JAN 2019 and buys a Premium subscription plan on 10 JAN 2019.

- The user uses it for a few months on the Premium plan but then decided to switch to the free plan on 20 APR 2019. He cancels his app subscription but still keeping the app installed and using the free features.

- His last billing must have happened on 10 APR 2019 (10 JAN + 90 days). Since, he has cancelled the subscription he would still be charged for the full month. 

- Since he has paid for the full month in the last billing he is entitled to use our Premium Services until 10 MAY 2019 (10 APR + 30 days)

How do you suggest I can implement this in our app?

 

Things to consider

(I am using graphQL for these requests)

- Until the user cancels his subscription everything works as expected. For example, if I check user's activeSubscriptions on 16 APR 2019, it returns me with

 

"activeSubscriptions": [{
 "createdAt": "2019-01-10T00:00:00Z",
 "currentPeriodEnd": "2019-05-10T00:00:00Z",
 "id": "gid://shopify/AppSubscription/xxxxxx",
 "name": "Premium",
 "returnUrl": "https://xxxxxxxx.xxx",
 "status": "ACTIVE",
 "test": false,
 "trialDays": 0
}]

 

It shows one subscription which has status as "ACTIVE" and also currentPeriodEnd as "2019-05-10T00:00:00Z" .. which works great. I can check that the user has an active plan and also I can show the user that his current cycle ends on 10 MAY. No problems here but...

 

- If I check his activeSubscriptions after 20 APR 2019, it returns with

 

"activeSubscriptions": []

It comes as empty thereby making it difficult for me to know the user's "currentPeriodEnd", since he has already paid for the full month and should be able to use our app's Premium features until then.
I know the first thought that comes to mind at this point is, 'we should have saved the activeSubscription's id when he created it and then check the "currentPeriodEnd" of this subscription using this id'. Sure let's do that.

 

- When we check for allSubscriptions and check for the subscription with the ID we saved at the time of creation this is what we get 

"allSubscriptions": {
    "edges": [{
        "node": {
            "createdAt": "2019-01-10T00:00:00Z",
            "currentPeriodEnd": null,
            "id": "gid://shopify/AppSubscription/xxxxxx",
            "name": "Premium",
            "returnUrl": "https://xxxxxxxx.xxx",
            "status": "CANCELLED",
            "test": false,
            "trialDays": 0
        }
    }]
}

Status is correctly "CANCELLED" but guess what "currentPeriodEnd" is null now!! Making it impossible for our app to decided, should we continue providing Premium services to this customer or not. 

I know the next thought that comes to mind 'we should have saved the "currentPeriodEnd" in our database when the subscription was created'. Sure let's do that ...

 

- For the first month, saving the "currentPeriodEnd" in our database works great. I have a definite way of knowing the last date until which I need to provide Premium services, even if the user cancels his subscription. But for the second month, "currentPeriodEnd" gets updated in Shopify's system but I have no way of updating it in my database. 
'I know what you are thinking - "webhooks" ..right?'  . Sure, lets do that ...

 

- We subscribed to the topic APP_SUBSCRIPTIONS_UPDATE and then we wait .. and wait .. and wait! To our surprise, this webhook does not get fired when the "currentPeriodEnd" changes at the end of a monthly app subscription cycle. No way to update "currentPeriodEnd" in our database. 

 

-------

 

To make matters worse, the test charge for testing Billing APIs works very differently than the actual charge. The "currentPeriodEnd" in a test charge is the same as "createdAt" instead of "createdAt + 30 days" as in a real charge. I have detailed this issue in a separate thread https://community.shopify.com/c/Shopify-APIs-SDKs/GraphQL-appSubscriptionCreate-mutation-with-quot-t...

 

@Josh from Shopify has acknowledged that this is an issue and he would be logging a request to make the test charge behave same as a real charge. I don't know the current status of that request.

-----

Now, I don't know if I am missing something very obvious here but if I am, then please suggest a solution to the issues I am having.

 

It has been very difficult to work with Shopify's Billing API considering the fact that it is also compulsory to use Shopify Billing. Not been a pleasant experience as much as with other APIs of Shopify.

 

---

Proposed Solutions

I would like to propose a couple of solutions:

1. (Best solution in my opinion) Like I said above, "activeSubscriptions" works great when the subscription is active. When the user cancels his subscription, instead of returning empty array, "activeSubscriptions" should return the last subscription with status as "CANCELLED" and the "currentPeriodEnd" as the correct date until which the user has already paid for. Sample response 

"activeSubscriptions": [{
 "createdAt": "2019-01-10T00:00:00Z",
 "currentPeriodEnd": "2019-05-10T00:00:00Z",
 "id": "gid://shopify/AppSubscription/xxxxxx",
 "name": "Premium",
 "returnUrl": "https://xxxxxxxx.xxx",
 "status": "CANCELLED",
 "test": false,
 "trialDays": 0
}]

This will make it super easy for developers to decide what they want to do after the user cancels his subscription. Some developers who want to stop providing Premium services immediately on cancellation can check for "status" and the ones who want to provide Premium services until the user has paid for, can check for the "currentPeriodEnd" . I understand the naming activeSubscriptions may not be fitting this response but there can be another key name like "currentSubscriptions" or "lastActiveSubscription" etc.

 

2. (Workable solution) If the "activeSubscriptions " has to return an empty array after cancellation then please do not make the "currentPeriodEnd" as null for the previous subscriptions. A developer can save the subscription ID in his database at the time of its creation and check for its "currentPeriodEnd" even if the user has cancelled his subscription.

 

3. (Least effort but not the best one) Please fire webhooks under the topic APP_SUBSCRIPTIONS_UPDATE every time a user's monthly app cycle renews. In the webhook payload, a renewed "currentPeriodEnd" should be sent so that we can update this date in our database and check against it for a user. 

 

Ideally, all 3 should be implemented giving developers the choice to use the one to their liking but even if any of them can be implemented for now, it would really help developers give a smooth billing experience. 

 

@Josh & other Shopify staff, hope you are looking into this.

I am willing to contribute in any way possible to resolve this issue. 

Thanks & regards,

Amardeep Singh

 

p.s. @Jason @KarlOffenberger @HunkyBill @Jordan @Alex Bringing to your notice as well. Your inputs would be very helpful. Thanks.

Beautifully designed posts for social media. Inboxed daily!
Shopify App: Automatic Post Designer
Replies 3 (3)

Ryan
Shopify Staff
499 42 120

Hi @amardeep ,

 

Thanks for the detailed feedback. We've passed along the details internally and it has been shared with the Apps billing team.  We definitely see where there is room to improve on the billing API and while I can't promise anything, your feedback has been heard.

 

Best Regards,

Ryan

Ryan | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

petehouston
Tourist
3 0 3

@Ryan any progress on this?

Natashz
Tourist
7 0 14

Joining @amardeep in his request. 

Please provide with more detailed documentation as to when the webhook if firing.

We currently calculate the currentPeriodEnded by adding the plan interval (monthly or yearly) to the createdAt date.