I have very little idea how I am supposed to use this API correctly because of the following payment processing grace period behaviour, described in the documentation:
Subscription renewal payments can have some processing time. Payment history doesn’t return a table for this period. However, in order to preserve a user’s subscription experience during the processing period, GetUserSubscriptionStatusAsync() returns IsSubscribed: true for the given user. Don’t grant durable items or currency type subscription benefits to the user until after payment has been confirmed for the current cycle.
Source: MarketplaceService | Documentation - Roblox Creator Hub
Ideally we should be able to use GetUserSubscriptionStatusAsync to obtain all information relevant to whether a subscription should be considered active or not.
However it is missing this one piece of critical information, which the documentation itself recommends we check: whether the player’s payment has been processed or not.
To correctly query this extra bit of information, we are required to perform a whole other MarketplaceService request (GetUserSubscriptionPaymentHistoryAsync), including correctly handling errors and so on. This is a single boolean that could have just been part of the original GetUserSubscriptionStatusAsync API.
This is extremely annoying on its own, but there is also another problem: How are we expected to synchronize the two separate API requests so that we always have relevant information and an accurate understanding of which subscription period the player is currently in?
The documentation seems to hint that we need to use time APIs like DateTime to decide what the current subscription cycle is. This is concerning to me because my understanding is that any server’s idea of the current time may vary quite a bit (up to 10-30 minutes-ish based on things like ProfileService). Which means at period boundaries we may suffer incorrect subscription behaviour in our games.
Problems at period boundaries could also happen without the timestamp variance, due to things like how we developers choose to store, cache, use, etc. the results of the requests, which again is another complexity we developers should not be exposed to since it directly affects the correctness of the monetization of our games.
The reliance on timestamps is also itself a symptom of a larger problem, which is that the subscription status and payment history APIs themselves do not return any information we could use for synchronization between them. For example if the return value of both APIs always contained a unique “period ID” value (or the period start/end time) then we could use that check if a particular period had been subscribed to and had its payment processed successfully. But the subscription status API in particular does not give that information, so we are forced to rely on what are effectively heuristics from unrelated APIs like DateTime.