Payments Module for Unity

With the now.gg Payments module for Unity, you can implement in-app purchases within your game on Unity.

To implement in-app purchases using the now.gg Payments module:

  1. Download and Import the now.gg Payments Unity Module.
  2. Add required dependencies.
  3. Implement now.gg Payments to your project.

Download and Import the Module

The now.gg Payments Unity module is included as a Unity package file nowgg-payments-login.unitypackage.

Add the module to your Unity project:

  1. Download the package containing the latest version of now.gg Payments module for Unity.
  2. After you have downloaded the module, import it into your Unity project. To do this:
    • Click on Assets > Import Package > Custom Package, as shown below:
    • Select nowgg-payments-login.unitypackage that you previously downloaded.
    • Select all the listed files and click on Import.
      payments-login-unitypackage

Once all the module files have been imported, a folder named ‘NowGGSdk‘ will be added to your project. You can find this folder at the root of the Assets folder.

Note: Please do not modify the NowGGSdk folder, as it contains all the assets related to now.gg Payments.

Add Required Dependencies

This operation will download and add all the required dependencies to the Assets/Plugins/Android directory of your project using the Unity External Dependency Manager.

To add the required dependencies:

  • Click on Assets > External Dependency Manager > Android Resolver > Resolve.

Implement now.gg Payments

Once the now.gg Payments module has been imported, and the dependencies have been added; you can follow this section to implement now.gg Payments with your app/game.

Add Platform check to your Unity IAP implementation

To run the now.gg IAP service, the now.gg platform is required. The Unity IAP (or any other IAP services) should only be initialized when you are not running on the now.gg platform.

To check the platform, you should add the following code to your implementation so that Unity IAP is not activated when your app runs on the now.gg platform:

public void Start()
 {
 	 if (NowGG.Sdk.NowGGPaymentsSdkManager.IsNowGGIapAvailable())
            return;

	 // Your Unity IAP code here...
 }

Implement now.gg IAP in Unity

The following sections illustrate the implementation of the now.gg IAP functions, which you can call from your app/game in Unity.

Start by creating a class that contains the now.gg IAP implementation and attach it to a game object that you can use to initialize the in-app purchases.

1. Add Products and Initialize SDK

This step will allow you to add the in-app purchase products in your app/game and initialize the SDK.

For example, we have added two IAP consumable products with product id ‘coin1’ and ‘coin2’ and a non-consumable product with product id  ‘gunSkin’ in the following code.

Similarly, you can add other products with the corresponding product id that you have added within nowStudio.

Integration Flows

We have provided two workflows for you to integrate now.gg Payments. You may implement either one of them based on your requirements.

A. Use now.gg Login

In case the game integrates now.gg Login, we recommend this approach. The following workflow explains this approach:

  • The Payments module utilizes now.gg Login for user identification and the purchases are linked to the user’s now.gg account.
  • If a payment is initiated and now.gg Login is not present, the Payments module initiates now.gg Login.
B. Use existing in-game Login

In case the game does not integrate now.gg Login, we recommend this approach. The following workflow explains this approach:

  • The game does not integrate now.gg Login and just passes the user’s existing in-game user ID IN_GAME_ID to now.gg Payments module to identify the user and process the purchase.
A. Using now.gg Login Flow

With this flow, you can initialize now.gg Payments, use now.gg Login to identify the user making the purchase and process the product delivery after purchase.

The following sample code illustrates this flow to initialize IAP:

public void Start()
 {
	 // Only initialize Now.gg IAP if running on Now.gg platform
	 if (!NowGG.Sdk.NowGGPaymentsSdkManager.IsNowGGIapAvailable())
		 return;

	 NowGGProductBuilder.Instance.AddProduct("coin1", ProductType.Consumable);
	 NowGGProductBuilder.Instance.AddProduct("coin2", ProductType.Consumable);
	 NowGGProductBuilder.Instance.AddProduct("gunSkin", ProductType.NonConsumable);

	 NowGGPaymentsSdkManager.Instance.OnInitSuccess += OnInitSuccess;
	 NowGGPaymentsSdkManager.Instance.OnInitFailed += OnInitFailed;
	 NowGGPaymentsSdkManager.Instance.OnPurchaseCompleted += OnPurchaseProduct;
     NowGGPaymentsSdkManager.Instance.OnPurchaseFailed += OnPurchaseFailed;

	 NowGGPaymentsSdkManager.Instance.InitializeIap(PAYMENTS_APP_ID);
 }

Explanation:

  • An initial check is performed to ensure that you are initializing the now.gg Payments service on the now.gg platform.
  • The in-app products are added to the NowGGProductBuilder class.
  • InitializeIap function of the NowGGPaymentsSdkManager Class is called to initialize the Payments module using the PAYMENTS_APP_ID.
  • The SDK responses are recorded using the callback functions, as illustrated above.

Important Information:

  • PAYMENTS_APP_ID is a unique identifier for your app.
  • Each app that you add on the nowStudio generates a unique PAYMENTS_APP_ID.
    • The PAYMENTS_APP_ID can be found under ‘APP_ID for Payments‘ in the credentials section of nowStudio. More information.
B. Using existing in-game Login

With this flow, you can implement your existing in-game login to identify the user and process the product delivery after purchase.

To implement your existing in-game login with now.gg Payments module, you should pass the existing in-game user ID (IN_GAME_ID) while initializing Payments to identify your user, as illustrated in the following sample code:

public void Start()
 {
	 // Only initialize Now.gg IAP if running on Now.gg platform
	 if (!NowGG.Sdk.NowGGPaymentsSdkManager.IsNowGGIapAvailable())
		 return;

	 NowGGProductBuilder.Instance.AddProduct("coin1", ProductType.Consumable);
	 NowGGProductBuilder.Instance.AddProduct("coin2", ProductType.Consumable);
	 NowGGProductBuilder.Instance.AddProduct("gunSkin", ProductType.NonConsumable);

	 NowGGPaymentsSdkManager.Instance.OnInitSuccess += OnInitSuccess;
	 NowGGPaymentsSdkManager.Instance.OnInitFailed += OnInitFailed;
	 NowGGPaymentsSdkManager.Instance.OnPurchaseCompleted += OnPurchaseProduct;
     NowGGPaymentsSdkManager.Instance.OnPurchaseFailed += OnPurchaseFailed;

	 NowGGPaymentsSdkManager.Instance.InitializeIap(PAYMENTS_APP_ID, IN_GAME_ID);
 }

Important Information:

  • IN_GAME_ID is a unique identifier for your user.
    • Please ensure that your IN_GAME_ID is unique for every user.
  • Whenever IN_GAME_ID is passed while initializing IAP, now.gg login will not be presented to the user. Instead, the user will go directly through the payment flow.
  • Refund Processing (IN_GAME_ID Flow)– To process a refund for an order, please follow the process illustrated here.

2. Get Product Details

After successful initialization, you can get the product details in your app using the product id.

To get product details, refer to the following implementation:

private void OnInitSuccess()
 {
    Debug.Log($"IAP init success");
    Product coin1 = NowGGPaymentsSdkManager.Instance.GetProductWithID("coin1");

    // now you can get product details using product id
    string price = coin1.price;
    string currencyCode = coin1.priceCurrencyCode;
 }

 private void OnInitFailed(string reason)
 {
   Debug.Log($"IAP init failed {reason}");
 }

3. Initiate purchase

After you have the product details, you can initiate a product purchase. To do so, you have to call the PurchaseProduct() function as illustrated below:

public void PurchaseProduct(string productId)
 {
     NowGGPaymentsSdkManager.Instance.PurchaseProduct(productId);
 }

Note:

  • ProductId is a unique identifier for the in-app product(s) that you have defined within nowStudio for your specific App (App Id).
  • Product prices are fetched from the price template you created within the nowStudio.

4. Assigning the purchased products to a User

After a successful purchase, you can assign the in-app purchased product to the user. To do so, you can refer to the implementation below:

private PurchaseProcessingResult OnPurchaseProduct(PurchasedProduct purchasedProduct)
 {
     string orderId = purchasedProduct.orderId;
     string purchaseToken = purchasedProduct.purchaseToken;

     // A consumable product has been purchased by this user.
     if (String.Equals(purchasedProduct.productId, "coin1", StringComparison.Ordinal))
     {
         Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId));
         // The consumable item has been successfully purchased, add 100 coins to the player's in-game currency.
         // coin += 100;
     }
     else if (String.Equals(purchasedProduct.productId, "coin2", StringComparison.Ordinal))
     {
         Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId));
         // The consumable item has been successfully purchased, add 200 coins to the player's in-game currency.
         // coin += 200;
     }
     else
     {
         Debug.Log(string.Format("OnPurchaseProduct: FAIL. Unrecognized product: '{0}'", purchasedProduct.productId));
     }

     // Return a flag indicating whether this product has been received or if the application needs to be reminded of this purchase at the next app launch.
     // Return PurchaseProcessingResult.Pending if you want to be reminded of this purchase on the next launch of your app/game.
     // Return PurchaseProcessingResult.Complete to specify that this is a one-time purchase and you have allotted the purchased in-game item to the user.

     return PurchaseProcessingResult.Complete;
 }

Important Information

  • A purchaseToken is generated after a successful purchase and is a unique identifier.
  • An orderId is also generated for every order.
    • A copy of every purchase with the order id and other relevant information is also emailed to the user.

5. Confirm Pending Purchase

If you wish to process the purchase on your backend server or need to complete the purchase using another method based on your implementation, your app should return PurchaseProcessingResult.Pending from OnPurchaseProduct.

To complete the purchase flow, you can use the ConfirmPendingPurchase method to inform the now.gg IAP service that the app has made a record of the purchase.

void ConfirmPendingPurchase(PurchasedProduct purchasedProduct)
 {
   NowGGPaymentsSdkManager.Instance.ConfirmPendingPurchase(purchasedProduct);
 }

Note: Once the pending purchase is confirmed, the now.gg IAP service will not notify the app about the said purchase.


6. Query Pending Purchases

If you need to query for pending purchases, you can call the QueryPendingPurchases function of the NowGGPaymentsSdkManager class. This function will query all the pending purchases and call the OnPurchaseProduct callback along with the pending purchases.


7. Fetch Additional Products

If you wish to fetch additional products for purchase or refresh the details/metadata associated with the existing products, you can use the FetchAdditionalProducts function as illustrated below.

var newProducts = new System.Collections.Generic.Dictionary<string, ProductType>();
 newProducts.Add("coin2", ProductType.Consumable);
 newProducts.Add("coin3", ProductType.Consumable);

 NowGGPaymentsSdkManager.Instance.FetchAdditionalProducts(newProducts,
       () =>
       {
           //Additional products fetched can now be purchased.
           Debug.Log($"Successfully fetched additional products");
           Product coin1 = NowGGPaymentsSdkManager.Instance.GetProductWithID("coin1");
           string price = coin1.price;
           string currencyCode = coin1.priceCurrencyCode;
       },
      reason =>
      {
          Debug.Log($"Fetching additional products failed: {reason}");
      });

8. Handling Failed Purchases

Purchases may fail due to any number of reasons, including:

  • Network/connectivity issues
  • Payment failure
  • Configuration issues.

You may investigate and handle failed purchases by referring to the following implementation:

public void OnPurchaseFailed(int errorCode, string errorMessage)
 {
    Debug.Log($"OnPurchaseFailed: errorCode: {errorCode} and msg: {errorMessage}");
 }


Purchase Verification

Verifying the purchase enables you to establish the authenticity of a purchase. The best practice for reducing fraud is to authenticate every purchase before assigning the product to the user.

You can verify the purchases using either of the following two methods:

  • Using Verify Payment API.
  • Using a Public key.

1. Using VerifyPayment API

The first method to verify the purchase is using verifyPayment API. You can use this API to verify the purchases with our backend server.

To verify the purchase, call the verifyPayment API from your app backend server with purchaseToken and orderId, as illustrated in the following sample request code:

curl --location 'https://payments.now.gg/v1/console/order/verifyPayment'\
      --header 'publisherToken: <your_publisherToken_here>'\
      --header 'Content-Type: application/json'\
      --data '{
  "purchaseToken": "<your_purchaseToken_here>",
  "orderId": "<your_orderId_here>"
  }'
import requests
 import json

 url = "https://payments.now.gg/v1/console/order/verifyPayment"

 payload = json.dumps(
     {
         "purchaseToken": "<your_purchaseToken_here>",
         "orderId": "<your_orderId_here>",
     }
 )
 headers = {
     "publisherToken": "<your_publisherToken_here>",
     "Content-Type": "application/json",
 }

 response = requests.request("POST", url, headers=headers, data=payload)

 print(response.text)

Important Information

  • The verifyPayment API must be called from your app backend server.
  • The publisherToken can be found under the Account Information section of nowStudio. (More Information).
  • The purchaseToken and orderId are returned after a successful purchase. You can refer to the following document for more information:

2. Verify the purchases with your Public Key

You can either verify purchase(s) locally or use a backend server. However, we recommend using your backend server to verify a purchase.

The following code segment illustrates the verification of purchase(s) locally and using a backend server. You can refer to the Demo project for more details.

private PurchaseProcessingResult OnPurchaseProduct(PurchasedProduct purchasedProduct) {
    // If you want to do local verification, use this sample code
    bool isValidPurchase = PurchaseVerification.Instance.VerifyPurchaseLocally(
        BASE_64_ENCODED_PUBLIC_KEY,
        purchasedProduct.originalJson,
        purchasedProduct.signature); 

    // We recommend you to verify purchases on your backend server.
    // You need to send signature and original data to your backend server for verification.
    PurchaseVerification.Instance.VerifyValidSignatureOnBackend(
        purchasedProduct.originalJson,
        purchasedProduct.signature);

    // A consumable product has been purchased by this user.
    if (String.Equals(purchasedProduct.productId, "coin1", StringComparison.Ordinal))
    {
        Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId));
        // The consumable item has been successfully purchased, add 100 coins to the player's in-game currency.
        // coin += 100;
    } 
    else if (String.Equals(purchasedProduct.productId, "coin2", StringComparison.Ordinal)) 
    {
        Debug.Log(string.Format("OnPurchaseProduct: PASS. Product: '{0}'", purchasedProduct.productId));
        // The consumable item has been successfully purchased, add 200 coins to the player's in-game currency.
        // coin += 200;
    } 
    else 
    {
        Debug.Log(string.Format("OnPurchaseProduct: FAIL. Unrecognized product: '{0}'", purchasedProduct.productId));
    }

    return PurchaseProcessingResult.Complete;
}
Server Verification

The download package contains a sample implementation to verify a purchase using a backend server which you can use to write your own implementation.

The sample implementation includes-

  • PurchaseVerification class: Located in the Demo Project, it contains Unity-specific code to send purchase data and signature to the backend server.
  • Server.py: Located separately within the download package, it includes sample Python code to run a local server and perform backend verification.
Local Verification

We have provided a sample implementation within the download package for local verification of purchase. You can use the provided sample to write your own implementation.

In the sample implementation-

  • You can refer to the VerifyPurchaseLocally function of the PurchaseVerification class.

Important Information

×
Text copied to clipboard
Link copied to clipbord
Questions? Please reach out to us at dev-support@now.gg