Unity OSP


One-Step Payment (OSP) is a simple and easy solution to implement Catappult billing. It consists of a URL that launches the AppCoins Wallet app to process the payment and then tells you to give the item to the end-user, depending on the result.


Unity plug-in

To help implement One-Step Payment using Unity, we have developed an Android Studio plug-in that will guide you step-by-step. You can read more about how you can use this plug-in here.

1. Create the C# Script

To implement OSP in Unity, create a script that contains the logic and can be added to the IAP buttons. Firstly create a dynamic and static value (product id and server URL), this way every button will have the server URL that contains the endpoint to get the OSP URL, but each button can have a different product associated.

public string productId;
//The url to get the one-step payment url
private static string SERVER_URL = "mygamestudio.com/url";

Then create a function that starts the OSP purchase flow and set it as the onClick listener for the associated button. To avoid repetition you can also store the Unity activity as a field and instantiate it on "Start".

//This two fields will be necessary later
private AndroidJavaObject activity;
private static int MATCH_DEFAULT_ONLY_ANDROID_PM =  65536;
void Start () {
    var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    activity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

void TaskOnClick(){

2. Get OSP URL from your server

To accomplish this step you first need a server with an endpoint that generates the OSP URL, the process of doing this is explained in our generic documentation (to check it, click here).

Then, to get the URL from the server you can use the UnityEngine.Networking classes like so:


In the GetUrlRequest you should add a field regarding the user id so that the server can build the URL with a reference to the user and when it's time to validate the purchase know to who should the product be assigned.

IEnumerator GetURL()
    var postData = new GetUrlRequest();
    postData.product = productId;
    var json = JsonUtility.ToJson(postData);
    byte[] bodyRaw = Encoding.UTF8.GetBytes(json);
    UnityWebRequest request = new UnityWebRequest(SERVER_URL, "POST", (DownloadHandler) new DownloadHandlerBuffer(), (UploadHandler) new UploadHandlerRaw(bodyRaw));
    request.SetRequestHeader("Content-Type", "application/json");
    yield return request.SendWebRequest();
    if (request.result != UnityWebRequest.Result.Success)
        yield break;
    var response = JsonUtility.FromJson<GetUrlResponse>(request.downloadHandler.text);
private class GetUrlRequest {
    public string product;
private class GetUrlResponse {
    public string url;

3. Create an Intent to process the payment

Inside the app/game, an intent with the URL should be opened either using the web browser (whenever the AppCoins Wallet is not installed), or via the AppCoins Wallet.

In some cases, the user chooses to open the URL with the browser when the AppCoins Wallet is already installed or even chooses the option to always open the URL with the browser. To avoid this add the following sample to trigger the One Step billing flow.

// This is the method called at the end of GetURL
void Purchase(string url)
       var intent = BuildTargetIntent(url);
       activity.Call("startActivity", intent);

// This method generates the intent with the provided One Step URL to target the
// AppCoins Wallet.
AndroidJavaObject BuildTargetIntent(string url) 
       var uriClass = new AndroidJavaClass("android.net.Uri");
       var uri = uriClass.CallStatic<AndroidJavaObject>("parse", url);
       AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent");
       AndroidJavaObject actionView = intentClass.GetStatic<AndroidJavaObject>("ACTION_VIEW");
       AndroidJavaObject intent = new AndroidJavaObject("android.content.Intent", actionView);
       intent.Call<AndroidJavaObject>("setData", uri);
       var appsList = GetAppsList(intent);
       var appsCount = appsList.Call<int>("size");
       for (int i=0; i<appsCount; i++) {
           var app = appsList.Call<AndroidJavaObject>("get", i);
           var packageName = app.Get<AndroidJavaObject>("activityInfo").Get<string>("packageName");
           if (packageName == "cm.aptoide.pt") {
               // If there's aptoide installed always choose Aptoide as default to open url
               intent.Call<AndroidJavaObject>("setPackage", packageName);
           } else if (packageName == "com.appcoins.wallet") {
               // If Aptoide is not installed and wallet is installed then choose Wallet
               // as default to open url
               intent.Call<AndroidJavaObject>("setPackage", packageName);
       return intent;
//Gets the apps that can run the intent
private AndroidJavaObject GetAppsList(AndroidJavaObject intent) 
       var packageManager = activity.Call<AndroidJavaObject>("getApplicationContext").Call<AndroidJavaObject>("getPackageManager");
       var appsList = packageManager.Call<AndroidJavaObject>("queryIntentActivities", intent, MATCH_DEFAULT_ONLY_ANDROID_PM);
       return appsList;

4. Create a web service endpoint to be used as the callback URL

The next steps are to prepare your server to handle the request to the callback URL and to assign the purchased item to the corresponding user, the steps on how to do this can be found on our generic documentation page (to check it, click here).