Transactions Validation

You should verify purchase details that your app receives in before providing the user access to what they have purchased. 

The client-side validation is already on board with the plugin. But the only safe way to validate a transaction is the server side validation. The approach and API for different platfrom are not close enough, so there is now unified API for validation.

However, you can get all required for validation info using native plugins API. See the iOS and Android guides.

But here are basic flows that you need to implement for any platform.

Flow #1

  • Purchase finished successfully
  •  Send validation info to your validation server
  • The server said that transaction is valid
  • Reward user
  • Finish the transaction. 

Flow #2

  • Purchase finished successfully
  •  Send validation info to your validation server
  • The server said that transaction is fraud
  • Notify user
  • Finish the transaction. 

Flow #3

  • Purchase finished successfully
  • Send validation info to your validation server
  • The server didn't respond (timeout) or crashed
  • Notify user, and say that transaction will be processed with the next session
  • DO NOT Finish the transaction. 

The small code sample that'll give you more understanding of how to combine cross-platform (Ultimate Mobile API) & non-cross-platform APIs of IOS and Android Native plugins.

using SA.iOS.StoreKit;
using SA.CrossPlatform.InApp;
using SA.Android.Vending.Billing;
...


public void OnTransactionUpdated(UM_iTransaction transaction) {

    //Transactions have been updated.
    //Let's act accordinaly
    switch (transaction.State) {
        case UM_TransactionState.Purchased:
        case UM_TransactionState.Restored:
           
            //Before we will provide conetent to the user we might want 
            //to make sure that purchase is valid, using server-side validation

            //let's see check the curreent platfrom
            switch(Application.platform) {
                case RuntimePlatform.Android:
                    //On android all the info we need is inside the orinial android transaction
                    //So let's get one.
                    string productId = transaction.ProductId;
                    AN_Inventory inventory = AN_Billing.Inventory;
                    AN_Purchase an_purchase = inventory.GetPurchaseByProductId(productId);

                    //Now you have acsses to the all data from the originla goole transaction object
                    //That you can send to yout server side and validate the purchase.
                    Debug.Log(an_purchase.OriginalJson);
     
                    break;
                case RuntimePlatform.IPhonePlayer:
                    //For iOS we need to validate the AppStoreReceipt. 
                    //So we need to get it using iOS Native
                    var receipt = ISN_SKPaymentQueue.AppStoreReceipt;

                    //You can now send receipt to your server side
                    Debug.Log("Receipt loaded, byte array length: " + receipt.Data.Length);
                    Debug.Log("Receipt As Base64 String" + receipt.AsBase64String);

                    break;
                default:
                    //We do not support other platfrom's yet, so no point to validate
                    break;
            }

        ...
        //We not interested in other cases for this example

    }
}