iOS / Android Integration

Unity Integration

Integrate Stash Pay in Unity projects using the Stash Unity package wrapper.

The Unity package is a wrapper around stash-native. We recommend reading the native SDK docs to understand the full capability set and platform-specific behavior.

Requirements

  • Unity 2021.3+ (LTS recommended)
  • iOS 13.0+
  • Android API 21+

Install with UPM

In Unity:

  1. Open Window -> Package Manager
  2. Select + -> Add package from git URL
  3. Enter:
https://github.com/stashgg/stash-unity.git?path=Packages/gg.stash.unity

Add via manifest.json (alternative)

In Packages/manifest.json, add:

"gg.stash.unity": "https://github.com/stashgg/stash-unity.git?path=Packages/gg.stash.unity"

(Optional) Import sample

From Package Manager, open Stash for Unity -> Samples -> Stash Integration Sample -> Import.

Android dependency recommendation

For browser flows and to ensure compatibility since some older Unity versions may bundle outdated Android libraries add these dependencies in your Assets/Plugins/Android/mainTemplate.gradle:

dependencies {
    implementation 'androidx.browser:browser:1.7.0'
    implementation 'androidx.core:core:1.12.0'
    **DEPS**
}

androidx.browser is optional but recommended for Chrome Custom Tabs. androidx.core:1.12.0+ helps avoid compatibility issues when older plugin trees pin outdated AndroidX versions.

Presentation modes

Use StashNative.Instance from Stash.Native to call one of the checkout presentation methods offered by the native package.

Stash Native presentation methods overview

OpenCard

using Stash.Native;

void OpenCardCheckout(string checkoutUrl)
{
    var config = StashNativeCardConfig.Default;
    StashNative.Instance.OpenCard(
        checkoutUrl,
        dismissCallback: OnDismissed,
        successCallback: OnSuccess,
        failureCallback: OnFailure,
        config: config
    );
}

OpenModal

StashNative.Instance.OpenModal(
    checkoutUrl,
    dismissCallback: OnDismissed,
    successCallback: OnSuccess,
    failureCallback: OnFailure
);

OpenBrowser

StashNative.Instance.OpenBrowser(checkoutUrl);
// iOS only when returning to app:
StashNative.Instance.CloseBrowser();

Landscape games and portrait checkout

If your game is landscape-locked but you want checkout in portrait, enable forcePortrait for Stash SDK to swizzle the screen rotation logic at the runtime.

var config = StashNativeCardConfig.Default;
config.forcePortrait = true;

Recommended pattern for stable behavior:

  1. Save current Screen.orientation and autorotation settings.
  2. Lock orientation in Unity while card is presented.
  3. Restore settings in dismiss/success/failure callbacks after the checkout is over.

Android Backdrop

On Android, to avoid visual glitches (black or stretched Unity surface) when rotating from landscape to portrait checkout, you should capture a screenshot of the game and set it as the checkout backdrop by calling setBackdropBytes(...) before OpenCard(...). Use the simply use the following snippet to do this:

IEnumerator OpenPortraitCheckoutWithBackdrop(string checkoutUrl)
{
    var config = StashNativeCardConfig.Default;
    config.forcePortrait = true;

#if UNITY_ANDROID && !UNITY_EDITOR
    // Capture a frame right before opening checkout.
    yield return new WaitForEndOfFrame();
    var snap = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
    snap.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
    snap.Apply();
    byte[] imageBytes = snap.EncodeToPNG();
    Destroy(snap);

    using (var stashCard = new AndroidJavaClass("com.stash.stashnative.StashNativeCard"))
    {
        stashCard.CallStatic("setBackdropBytes", (object)imageBytes);
    }
#endif

    StashNative.Instance.OpenCard(
        checkoutUrl,
        dismissCallback: () =>
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            using (var stashCard = new AndroidJavaClass("com.stash.stashnative.StashNativeCard"))
            {
                // Clear to avoid reusing a stale image in later checkouts.
                stashCard.CallStatic("setBackdropBytes", (object)null);
            }
#endif
        },
        config: config
    );
}

If you see JNI warnings for byte[] on specific Unity/Android stacks, convert to sbyte[] before calling setBackdropBytes.

Android keep-alive service

Use keep-alive for checkout flows where users temporarily leave the Unity surface (It can be different payment methods, verification or browser absed checkout). On some Android devices, Unity can be suspended or killed while checkout runs in Custom Tabs or the system browser, and keep-alive reduces that risk by running a short foreground service during the payment window.

#if UNITY_ANDROID && !UNITY_EDITOR
StashNative.Instance.SetKeepAliveEnabled(true);
StashNative.Instance.SetKeepAliveConfig(new StashNativeKeepAliveConfig
{
    notificationTitle = "Payment in progress",
    notificationText = "Tap to return to the app",
    notificationIconResId = 0
});
#endif

Unity Editor simulator

Unity Editor Simulator Popup Example

The package includes an editor simulator for OpenCard and OpenModal so you can test flow and callbacks without deploying to a device.

  • Supported editor platforms: Windows and macOS
  • OpenBrowser is not simulated (it opens the system browser)

Detailed references

How is this guide?