Do developer products automatically proceed in studio or it just doesn't work?

So I made a membership system, but I want to prevent people from buying more memberships while they already own one, I made a value into the player so I could check, when I write the statement like:

if player.Membership.Value == true then
       return Enum.ProductPurchaseDecision.NotProcessedYet
      return Enum.ProductPurchaseDecision.PurchaseGranted

It basically checks if the player owns a subscription, if it doesn’t then it will proceed the purchase, if it does then it should cancel it only I don’t know why it doesn’t work, can somebody help?

1 Like

Hey. This part is abrupt. Can you provide a wider scope for better understanding?

1 Like

Like for example,

I buy a membership, once i buy it I cannot purchase another subscription because I already own one, but I do not know how to cancel the prompt if they already own one (Which I already tested using a player value)

Because If i cancel prompt from client exploiter will find a way to prompt it anyway, then they buy it and say they got scammed and want a refund.

You’d either need to store their purchase in a data store or use a gamepass instead

1 Like

Subscriptions are monthly, it’s not forever

This simplistic implementation is essentially correct. If a user is not eligible to buy something, and your ProcessReceipt callback knows about this, returning NotProcessedYet is the way to go. Eventually, Roblox will stop invoking your callback and refund their money.

However, a better user experience is checking this eligibility before even prompting them for a purchase. You don’t want the player’s money to be in escrow while your game can already tell they can’t receive a product. If an exploiter is prompting purchases for themselves, then that’s their problem. Just make sure your game is not indicating that a purchase was granted when in actuality nothing’s changed.

1 Like

You right, i will still check from client and server, but yeah it’s exploiters own fault if they prompt it, they cannot make up an excuse, my game is scripted from scratch so there is no possible way prompting it other way, anyways thank you for your advice

This is important context. In this case, instead of storing their membership status as a boolean, you should probably store a timestamp (a number) in which their membership will expire. The logic is pretty straightforward.

  • A player’s membership is defined as an expiration time in UTC format (use os.time() for this)
  • A player’s membership is valid if and only if their expire time is in the future (os.time() < expireTime)
  • When a player buys membership (ProcessReceipt):
    • Move their expire time to the current time if it was in the past. (math.max(now, expireTime))
    • Then, move their expire time forward the amount of time they just purchased. (expireTime += boughtTime)

This logic handles new memberships, expired memberships, and membership extensions. If you don’t want purchases to fail, this is the way to go.

1 Like

I already use a time value for it in it’s player, os.time() < untildate etc etc, but yeah, I’ll try my best securing it.