Skip to content

📦 Library to present Stash Pay & Stash Webshop links inside native applications.

Notifications You must be signed in to change notification settings

stashgg/stash-native

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

135 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stash for Android / iOS Lint Build & Deploy

Stash Native Logo

The stash-native package makes it simple to add Stash in-app purchases (IAPs) and webshops to your game or app. It delivers seamless, native-like payment flows and selection dialogs, which appear as system dialogs on Android and iOS through lightweight embedded webviews, while providing direct callbacks to your application.

Platforms

Platform Description
Android Android library (AAR).
iOS iOS framework (XCFramework).

Wrappers

If you're using one of the game engines listed below, we offer dedicated wrappers for this library. These wrappers provide ready-to-use interfaces for integrating Stash features into your project, along with added development tools—such as full flow testing directly in the Unity Editor.

Engine Repository Compatibility
Unity Icon Unity stash-unity Unity 2019.4+ (LTS recommended)
Unreal Engine Icon Unreal Engine 5 stash-unreal (main) Unreal Engine 5.0+
Unreal Engine Icon Unreal Engine 4 stash-unreal (4.27-plus) Unreal Engine 4.27-plus

Downloads

Latest pre-built binaries are always available on Releases Page:

  • Android: stashnative-release.aar (or StashNative-<tag>.aar from releases)
  • iOS: StashNative.xcframework.zip

Sample Apps

Both platforms contain up-to-date sample apps that demonstrate the library usage and functions. You can run them from source

  • Android: ./Android/sample/ - Run with ./gradlew :sample:installDebug
  • iOS: ./iOS/Sample/ - Open StashNativeSample.xcodeproj in Xcode

or try them instantly in your browser using the Appetize online emulator:


Installation

Android

  1. Download StashNative-<tag>.aar from GitHub Releases and add it to your project (e.g. libs/).
  2. In your app's build.gradle:
dependencies {
    implementation files('libs/StashNative-<tag>.aar')
    implementation 'androidx.appcompat:appcompat:1.6.1'
    implementation 'androidx.browser:browser:1.7.0'
}

To build the AAR locally: cd Android && ./gradlew :stashnative:assembleRelease (output in stashnative/build/outputs/aar/).

iOS

XCFramework (recommended): Download StashNative.xcframework.zip from GitHub Releases, unzip it, add StashNative.xcframework to your Xcode project, and under Frameworks, Libraries, and Embedded Content set it to Embed & Sign.

Swift Package Manager: In Xcode choose File → Add Packages... and add https://github.com/stashgg/stash-native.git, then select the StashNative package for your target.

Manual integration: Copy all files from StashNative/Sources/StashNative/ into your project, add them to your target, and link SafariServices.framework and WebKit.framework.


Presentation Modes

The library provides three distinct ways to present Stash URLs within your app or game: openCard, openModal, and openBrowser. Each method lets you present different types of Stash experiences—such as Stash Pay checkout, Stash Web Shop, or Stash Opt-in—in a style that best fits your user flow. Details for each option are provided below.

openCard

Drawer-style card: slides up from the bottom on phones, centered on tablets. Suited for Stash Pay payment links or channel selection. Integrating Stash Pay

Android

StashNativeCard.CardConfig config = new StashNativeCard.CardConfig();  // or null for defaults
StashNativeCard.getInstance().openCard("https://testcard.stashpreview.com", config);

iOS (Swift)

let config = StashNativeCardConfig()  // or nil for defaults
StashNativeCard.sharedInstance().openCard(withURL: "https://testcard.stashpreview.com", config: config)

iOS (Objective-C)

StashNativeCardConfig *config = [[StashNativeCardConfig alloc] init];  // or nil for defaults
[[StashNativeCard sharedInstance] openCardWithURL:@"https://testcard.stashpreview.com" config:config];

Config

Pass a CardConfig (or nil/null) to control orientation and sizing. Pass nil/null for defaults.

Aspect Description
forcePortrait true: card opens portrait-locked (separate activity on Android, portrait-only on iOS). false (default): card appears in current orientation as an overlay.
Phone cardHeightRatioPortrait, cardWidthRatioLandscape, cardHeightRatioLandscape (0.1–1.0).
Tablet tabletWidthRatioPortrait, tabletHeightRatioPortrait, tabletWidthRatioLandscape, tabletHeightRatioLandscape (0.1–1.0).

Warning: If using forcePortrait, ensure your app supports portrait or can unlock to portrait while the card is shown.

Android

StashNativeCard.CardConfig config = new StashNativeCard.CardConfig();
config.forcePortrait = false;
config.cardHeightRatioPortrait = 0.68f;
// ... tabletWidthRatioPortrait, tabletHeightRatioPortrait, etc. (see table above)
stashNative.openCard(url, config);

iOS (Swift)

let config = StashNativeCardConfig()
config.forcePortrait = false
config.cardHeightRatioPortrait = 0.68
// ... tabletWidthRatioPortrait, tabletHeightRatioPortrait, etc. (see table above)
stashNative.openCard(withURL: url, config: config)

Callbacks

Event Description
Payment Success Called when the payment completes successfully.
Payment Failure Called when the payment fails.
Dialog Dismissed Called when the user dismisses the dialog.
Opt-In Response Called when a channel selection response is received.
Page Loaded Called when the page finishes loading (with load time).
Network Error Called when the page load fails (no connection, HTTP error, timeout).

Set a listener (Android) or delegate (iOS) before calling openCard or openModal. Same callback interface is used for both.

Android — implement StashNativeCardListener (or extend StashNativeCardListenerAdapter to override only the callbacks you need):

StashNativeCard.getInstance().setActivity(this);
StashNativeCard.getInstance().setListener(new StashNativeCard.StashNativeCardListener() {
    @Override
    public void onPaymentSuccess() {
        // Handle successful payment
    }

    @Override
    public void onPaymentFailure() {
        // Handle failed payment
    }

    @Override
    public void onDialogDismissed() {
        // User closed the card/modal
    }

    @Override
    public void onOptInResponse(String optinType) {
        // Channel selection response (e.g. "email", "sms")
    }

    @Override
    public void onPageLoaded(long loadTimeMs) {
        // Page finished loading
    }

    @Override
    public void onNetworkError() {
        // Load failed (no connection, HTTP error, or timeout)
    }
});

iOS (Swift) — set the delegate and implement StashNativeCardDelegate (all methods are optional):

StashNativeCard.sharedInstance().delegate = self
// In your class (e.g. ViewController):
extension YourViewController: StashNativeCardDelegate {
    func stashNativeCardDidCompletePayment() {
        // Handle successful payment
    }
    func stashNativeCardDidFailPayment() {
        // Handle failed payment
    }
    func stashNativeCardDidDismiss() {
        // User closed the card/modal
    }
    func stashNativeCardDidReceiveOpt(in optinType: String) {
        // Channel selection response
    }
    func stashNativeCardDidLoadPage(_ loadTimeMs: Double) {}
    func stashNativeCardDidEncounterNetworkError() {
        // Load failed (no connection, HTTP error, or timeout)
    }
}

iOS (Objective-C) — set the delegate and implement the optional protocol methods:

[StashNativeCard sharedInstance].delegate = self;

// In your class:
- (void)stashNativeCardDidCompletePayment {
    // Handle successful payment
}
- (void)stashNativeCardDidFailPayment {
    // Handle failed payment
}
- (void)stashNativeCardDidDismiss {
    // User closed the card/modal
}
- (void)stashNativeCardDidReceiveOptIn:(NSString *)optinType {
    // Channel selection response
}
- (void)stashNativeCardDidLoadPage:(double)loadTimeMs {}
- (void)stashNativeCardDidEncounterNetworkError {
    // Load failed
}

openModal

Centered modal on all devices. Same layout on phone and tablet; resizes on rotation. Suited for channel selection or an alternative checkout style. Stash Pay Opt-In

Android

StashNativeCard.ModalConfig config = new StashNativeCard.ModalConfig();  // or null for defaults
StashNativeCard.getInstance().openModal("https://testcard.stashpreview.com", config);

iOS (Swift)

let config = StashNativeModalConfig()  // or nil for defaults
StashNativeCard.sharedInstance().openModal(withURL: "https://testcard.stashpreview.com", config: config)

iOS (Objective-C)

StashNativeModalConfig *config = [[StashNativeModalConfig alloc] init];  // or nil for defaults
[[StashNativeCard sharedInstance] openModalWithURL:@"https://testcard.stashpreview.com" config:config];

Config

Pass a ModalConfig (or nil/null) to control drag bar, dismiss behavior, and sizing. Pass nil/null for defaults.

Aspect Description
Behavior showDragBar (default true), allowDismiss (default true).
Phone phoneWidthRatioPortrait, phoneHeightRatioPortrait, phoneWidthRatioLandscape, phoneHeightRatioLandscape (0.1–1.0).
Tablet tabletWidthRatioPortrait, tabletHeightRatioPortrait, tabletWidthRatioLandscape, tabletHeightRatioLandscape (0.1–1.0).

Android

StashNativeCard.ModalConfig config = new StashNativeCard.ModalConfig();
config.showDragBar = true;
config.allowDismiss = true;
// ... phoneWidthRatioPortrait, phoneHeightRatioPortrait, tablet ratios, etc. (see table above)
stashNative.openModal(url, config);

iOS (Swift)

let config = StashNativeModalConfig()
config.showDragBar = true
config.allowDismiss = true
// ... phoneWidthRatioPortrait, phoneHeightRatioPortrait, tablet ratios, etc. (see table above)
stashNative.openModal(withURL: url, config: config)

Callbacks

Same as openCard: same events and the same listener/delegate. Set it once as shown in the Callbacks section under openCard; it receives events for both card and modal.


openBrowser

Opens the URL in the platform browser (Chrome Custom Tabs on Android, SFSafariViewController on iOS). No in-app UI, no config, no callbacks. Use when you only need a simple browser view.

Android

StashNativeCard.getInstance().openBrowser("https://testcard.stashpreview.com");

iOS (Swift)

StashNativeCard.sharedInstance().openBrowser(withURL: "https://testcard.stashpreview.com")
// Optionally dismiss when handling a deeplink:
StashNativeCard.sharedInstance().closeBrowser()

iOS (Objective-C)

[[StashNativeCard sharedInstance] openBrowserWithURL:@"https://testcard.stashpreview.com"];
// Optionally dismiss when handling a deeplink:
[[StashNativeCard sharedInstance] closeBrowser];

On iOS, closeBrowser() dismisses the Safari view. On Android, closeBrowser() is a no-op (Chrome Custom Tabs cannot be closed by the app).


Versioning

This package follows Semantic Versioning (major.minor.patch):

  • Major: Breaking changes
  • Minor: New features (backward compatible)
  • Patch: Bug fixes

Support

About

📦 Library to present Stash Pay & Stash Webshop links inside native applications.

Resources

Stars

Watchers

Forks

Packages

No packages published