Implementing Feature

Now, you are ready to begin implementation of Billing feature. Our cross-platform Billing component acts as a bridge between your application and Store.

Use NPBinding.Billing to access billing features from your code.

Note

All the classes, datatypes related to the plugin are placed under namespace VoxelBusters.NativePlugins. Add this namespace in your script before accessing any of the features.

The interaction between user, your app and the Store is simple and straightforward. Take a look at the following illustration to get a better understanding about the workflow:

Getting information about Products

First thing, we need to do is dynamically load information of all the registered virtual products from the Store.

And to do that, we call RequestForBillingProducts. The Store verifies all the requested product identifiers and returns localised information of all the requested products by calling DidFinishRequestForBillingProductsEvent. Event data might also hold the description of the error that occurred while processing this request (if any).

public void RequestBillingProducts ()
{
    NPBinding.Billing.RequestForBillingProducts(NPSettings.Billing.Products);

    // At this point you can display an activity indicator to inform user that task is in progress
}

private void OnEnable ()
{
    // Register for callbacks
    Billing.DidFinishRequestForBillingProductsEvent        += OnDidFinishProductsRequest;
}

private void OnDisable ()
{
    // Deregister for callbacks
    Billing.DidFinishRequestForBillingProductsEvent        -= OnDidFinishProductsRequest;
}

private void OnDidFinishProductsRequest (BillingProduct[] _regProductsList, string _error)
{
    // Hide activity indicator

    // Handle response
    if (_error != null)
    {        
        // Something went wrong
    }
    else 
    {    
        // Inject code to display received products
    }
}

Make a Purchase

At this point, we have an user interface to display all the purchasable products. Now lets add the code to make purchase.

Consider, your user interface knows the product that user wants to purchase. What next? That is what we will implement now. In your BillingManager.cs add this code:

public void BuyItem (BillingProduct _product)
{
    if (NPBinding.Billing.IsProductPurchased(_product.ProductIdentifier))
    {
        // Show alert message that item is already purchased

        return;
    }

    // Call method to make purchase
    NPBinding.Billing.BuyProduct(_product);

    // At this point you can display an activity indicator to inform user that task is in progress
}

In BuyItem method, first we need to determine if specified product was previously purchased. As mentioned earlier, IAP has Non-Consumable products, which can be bought only once and it is our responsibility to ensure that it is available to a user in all the devices. Trying to purchase same item multiple times violates Store guidelines. So it is recommended to call IsProductPurchased before making a purchase request.

After determining that product is not yet purchased, we can make a payment request to the Store by calling BuyProduct. The Store shows a prompt asking for confirmation and then requests to enter account details. And after getting required information, Store processes the purchase request. Boom! Money in your bank!

But we are not done yet! You need to give back the promised content. And for that, you need to parse through the transaction details received from DidFinishProductPurchaseEvent and identify finished transaction.

private void OnDidFinishTransaction (BillingTransaction _transaction)
{
    if (_transaction != null)
    {

        if (_transaction.VerificationState == eBillingTransactionVerificationState.SUCCESS)
        {
            if (_transaction.TransactionState == eBillingTransactionState.PURCHASED)
            {
                // Your code to handle purchased products
            }
        }
    }
}

Also, update your OnEnable, OnDisable method with transaction event registration code.

private void OnEnable ()
{
    // Register for callbacks
    Billing.DidFinishRequestForBillingProductsEvent    += OnDidFinishProductsRequest;
    Billing.DidFinishProductPurchaseEvent            += OnDidFinishTransaction;
}

private void OnDisable ()
{
    // Deregister for callbacks
    Billing.DidFinishRequestForBillingProductsEvent    -= OnDidFinishProductsRequest;
    Billing.DidFinishProductPurchaseEvent            -= OnDidFinishTransaction;
}

Restore Purchases

In this section we will talk about making Non-Consumable purchases available to the user in all the devices.

Only non-consumable products are restorable. Consumable products won't be able to restore.

If your app has Non-Consumable products, you must implement a mechanism to restore old purchases. In fact, your app might get rejected if you fail to do so.

Initiate restoring the purchases by below code :

private void RestorePurchases ()
{
    NPBinding.Billing.RestorePurchases ();
}

Register for Billing.DidFinishRestoringPurchasesEvent to receive the callback to receive restored purchases.

private void OnEnable ()
{
    // Register for callbacks
    Billing.DidFinishRequestForBillingProductsEvent    += OnDidFinishProductsRequest;
    Billing.DidFinishProductPurchaseEvent            += OnDidFinishTransaction;

    // For receiving restored transactions.
    Billing.DidFinishRestoringPurchasesEvent        += OnDidFinishRestoringPurchases;

}

private void OnDisable ()
{
    // Deregister for callbacks
    Billing.DidFinishRequestForBillingProductsEvent    -= OnDidFinishProductsRequest;
    Billing.DidFinishProductPurchaseEvent            -= OnDidFinishTransaction;
    Billing.DidFinishRestoringPurchasesEvent        -= OnDidFinishRestoringPurchases;        
}

private void OnDidFinishRestoringPurchases (BillingTransaction[] _transactions, string _error)
{
    Debug.Log(string.Format("Received restore purchases response. Error = {0}.", _error.GetPrintableString()));

    if (_transactions != null)
    {                
        Debug.Log(string.Format("Count of transaction information received = {0}.", _transactions.Length));

        foreach (BillingTransaction _currentTransaction in _transactions)
        {
            Debug.Log("Product Identifier = "         + _currentTransaction.ProductIdentifier);
            Debug.Log("Transaction State = "        + _currentTransaction.TransactionState);
            Debug.Log("Verification State = "        + _currentTransaction.VerificationState);
            Debug.Log("Transaction Date[UTC] = "    + _currentTransaction.TransactionDateUTC);
            Debug.Log("Transaction Date[Local] = "    + _currentTransaction.TransactionDateLocal);
            Debug.Log("Transaction Identifier = "    + _currentTransaction.TransactionIdentifier);
            Debug.Log("Transaction Receipt = "        + _currentTransaction.TransactionReceipt);
            Debug.Log("Error = "                    + _currentTransaction.Error.GetPrintableString());
        }
    }
}

results matching ""

    No results matching ""