After the purchase flow is launched with the required details and if the purchase result is success always validate the purchase token you received in the purchase object and then grant the entitlements. Grant the purchased features only on purchase token validation and not on receiving the purchase success callback because of man-in-middle attacks. These are quite common attacks that happen on apps. Also, we have a few apps that do this man-in-middle attack work.
For example, there is an app called Lucky Patcher. When you install this app and initiate a purchase on any other app to Google Play billing it hacks in the middle and gives a successful callback to the client app. So that even without purchase users get the grant to entitlements however it would be a loss to us. So never forget it is not about the result of in-app purchases like success or failure it should be about the validation of in-app purchases.
Always validate the purchase token received from play billing on success callback and then only grant the entitlements. The process here is while user clicks on a product hit an API get the transaction ID and product id and launch the billing flow and if the callback of purchase is a success then send the purchase token with transaction-id to the server for validation and wait until you receive a success callback from your server. This way we can reduce the risk of man-in-middle attacks to some extent.
On the server-side
There is an endpoint in Google Play Developer API where our backend communicates to the Google server using the details purchase token, package name, productId, and API key. If the purchase token is valid then the return result would be an object with info of purchase details.
For more details Check out purchases.products.get at Play Developer API