SDK configuration

Initialising the SDK

The initialisation must be done as soon as possible to catch the purchase . On iOS, initialise the SDK in your AppDelegate method didFinishLaunchingWithOptions to allow promoted In-App Purchase and support PSD2. This initialisation will allow tyou to access producst prices instantly later in the app.

You will need an API Key that you can find in your App settings in the Purchasely Console.

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
import Purchasely
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
Purchasely.start(withAPIKey: "API_KEY", appUserId: "USER_ID")
return true
}
Objective-C
#import <Purchasely/Purchasely-Swift.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[Purchasely startWithAPIKey:@"API_KEY" appUserId:@"USER_ID" eventDelegate:nil uiDelegate:nil logLevel: LogLevelInfo];
return YES;
}
Kotlin
import io.purchasely.ext.Purchasely
Purchasely.Builder(applicationContext)
.apiKey("API_KEY")
.logLevel(LogLevel.DEBUG) // set to warning or error for release
.userId("USER_ID")
.eventListener(eventListener)
.stores(listOf(GoogleStore(), HuaweiStore()))
.build()
// When you are ready for Purchasely to initialize,
// you must call start() method that will grab configuration and products
// from the selected stores.
Purchasely.start()
Java
List<Store> stores = new ArrayList();
stores.add(new GoogleStore(), new HuaweiStore());
new Purchasely.Builder(getApplicationContext())
.apiKey("API_KEY")
.logLevel(LogLevel.DEBUG) // set to warning or error for release
.userId("USER_ID")
.eventListener(this)
.stores(stores)
.build();
// When you are ready for Purchasely to initialize,
// you must call start() method that will grab configuration and products
// from the selected stores.
Purchasely.start();
React Native
import Purchasely from 'react-native-purchasely';
/**
* @params String apiKey
* @params StringArray stores : may be Google, Amazon and Huawei
* @params String userId
* @params Purchasley.LogLevel logLevel
* @params boolean observerMode
**/
Purchasely.startWithAPIKey(
'API_KEY',
['Google'],
'USER_ID',
Purchasely.logLevelDebug,
false
);
Cordova
/**
* @params String apiKey
* @params StringArray stores : may be Google, Amazon and Huawei
* @params String userId
* @params Purchasley.LogLevel logLevel
* @params boolean observerMode
**/
Purchasely.startWithAPIKey('API_KEY', ['Google'], null, Purchasely.LogLevel.DEBUG, false);

The userID parameter is optional and allows you to associate the purchase to a user instead of a device.

The eventDelegate/eventListener parameter is optional and allows you to listen to all purchases events. You should implement it at least to know when the purchase is successfull.

The uiDelegate / uiListener parameter is optional and allows you to override UI dialog presented to user in case of error or success.

The logLevel parameter is optional and will display logs from the SDK according to the level set. We advise you to set it to warning or error for production

The stores parameter (for Android apps) is optional but purchase won't work without it. You need to pass a list of stores that are enabled for your application. The first store available in the user device will be the store used to make a purchase. In this sample, Google Play Billing will be used if available in user device, Huawei Mobile Services will be used otherwise.

The observerMode parameter is optional and allows you to use Purchasely with another In-App purchase system to prepare a migration. More details in our dedicated section.

Setting-up the User Id

Once your user is logged in and you can send us a userId, please do it otherwise the purchase will be tied to the device and your user won't be able to enjoy from another device. Setting it will allow you to tie a purchase to a user to use it on other devices.

This ID will be passed to the Webhook so that your backend can identify the user and unlock the access. If our backend made a migration of user purchases and notified your backend, we will set the refresh variable in the callback to true.

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
Purchasely.userLogin(with: "123456789")
Objective-C
[Purchasely userLoginWith:@"123456789"];
Kotlin
Purchasely.userLogin("123456789") { refresh ->
if (refresh) {
//you can call your backend to refresh user information
}
}
Java
Purchasely.userLogin("123456789", refresh -> {
if(refresh) {
//you can call your backend to refresh user information
}
return null;
});
React Native
Purchasely.userLogin('123456789').then((refresh) => {
if (refresh) {
//call your backend to refresh user information
}
});
Cordova
Purchasely.userLogin('user_id', refresh => {
if(refresh) {
// You can call your back-end to refresh user information
}
});

To remove the user (logged out) you can perform a :

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
Purchasely.userLogout()
Objective-C
[Purchasely userLogout];
Kotlin
Purchasely.userLogout()
Java
Purchasely.userLogout();
React Native
Purchasely.userLogout();
Cordova
Purchasely.userLogout()

If your app allows anonymous purchases, keep the AppUserId to nil and have a look at our article.

Notifying the SDK when the app is ready / loaded

The SDK needs to display messages above your UI. It can be the continuation of a purchase started on the App Store, the result from a notification linking to our product, …

Your app needs to tell Purchasely SDK when it is ready to be covered by our UI.

This is done to handle cases like:

  • a loading screen that dismisses upon completion

  • an on boarding that needs to be displayed before purchasing

  • a subscribe process mandatory for app usage

When your app is ready, call the following method and the SDK will handle the continuation of whatever was in progress (purchase, push message, …)

This is mandatory to be able to handle Promoted In-App Purchases and Deeplinks automations.

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
// Call me in your viewDidAppear
Purchasely.isReadyToPurchase(true)
Objective-C
[Purchasely isReadyToPurchase: true];
Kotlin
Purchasely.isReadyToPurchase = true
Java
Purchasely.setIsReadyToPurchase(true);
React Native
Purchasely.isReadyToPurchase(true);
Cordova
Purchasely.isReadyToPurchase(true);

You can set it back to false when the app goes in the background when you have a screen that blocks UI in background mode and that is dismissed when the app is in foreground (like in banking apps).

Presenting products

Purchasely handles all the presentation of your products (aka paywalls) which are configured in the back office.

You can ask for the SDK to give you the UIViewController / androidx.fragment.app.Fragmentpresenting the purchase by calling the following :

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
let paywallCtrl = Purchasely.presentationController(with: "my_presentation_id"
completion: { (result, plan) in
switch result {
case .purchased:
break
case .restored:
break
case .cancelled:
break
@unknown default:
break
}
})
present(paywallCtrl, animated: true)
Objective-C
UIViewController *ctrl = [Purchasely presentationControllerWith:@"my_presentation_id"
completion:^(enum PLYProductViewControllerResult result, PLYPlan * _Nullable plan) {
switch (result) {
case PLYProductViewControllerResultPurchased:
break;
case PLYProductViewControllerResultRestored:
break;
case PLYProductViewControllerResultCancelled:
break;
default:
break;
}
}];
[self presentViewController:ctrl animated:YES completion:nil];
Kotlin
Purchasely.presentationFragment(
presentationId = "my_presentation_id"
) { result, plan ->
/* You can set a callback to know when your user purchased a product */
when(result) {
PLYProductViewResult.PURCHASED -> Log.d("Purchasely", "Purchased $plan")
PLYProductViewResult.CANCELLED -> Log.d("Purchasely", "Cancelled purchase of $plan")
PLYProductViewResult.RESTORED -> Log.d("Purchasely", "Restored $plan")
}
}
supportFragmentManager.beginTransaction()
.addToBackStack(null) //optional
.replace(R.id.inappFragment, fragment, "InAppFragment")
.commitAllowingStateLoss()
Java
Fragment fragment = Purchasely.presentationFragment("my_presentation_id", new ProductViewResultListener() {
@Override
public void onResult(@NotNull PLYProductViewResult result, @Nullable PLYPlan plan) {
/* You can set a callback to know when your user purchased a product */
switch (result) {
case PURCHASED:
break;
case CANCELLED:
break;
case RESTORED:
break;
}
}
});
getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(R.id.inappFragment, fragment, "InAppFragment")
.commitAllowingStateLoss();
React Native
try {
const result = await Purchasely.presentPresentationWithIdentifier('my_presentation_id');
console.log('Presentation View Result: ' + result.result);
if (result.plan != null) {
console.log('Plan Vendor ID: ' + result.plan.vendorId);
console.log('Plan Name: ' + result.plan.name);
}
} catch (e) {
console.log(e);
}
Cordova
Purchasely.presentPresentationWithIdentifier(
'my_presentation_id',
(callback) => {
console.log(callback);
if(callback.result == Purchasely.PurchaseResult.CANCELLED) {
console.log("User cancelled purchased");
} else {
console.log("User purchased " + callback.plan.name);
}
},
(error) => {
console.log("Error with purchase : " + error);
}
);

The callback PLYProductViewControllerResult(iOS) / ProductViewResultListener (Android) is optional, you can set to null if you do not need it.

You can be alerted if the purchase was made by listening to the Notifications or by implementing the optional completion block

You can also get the presentation of a specific product of plan:

Swift
Objective-C
Kotlin
Java
React Native
Cordova
Swift
// Default presentation for a product
let paywallProductCtrl = Purchasely.productController(with: "my_product_id")
present(paywallProductCtrl, animated: true)
// Default presentation for a plan
let paywallPlanCtrl = Purchasely.planController(with: "my_plan_id")
present(paywallPlanCtrl, animated: true)
Objective-C
// Default presentation for a product
UIViewController *paywallProductCtrl = [Purchasely productControllerFor:@"my_product_id"
with:nil
completion:nil];
[self presentViewController:paywallProductCtrl animated:YES completion:nil];
// Default presentation for a plan
UIViewController *paywallPlanCtrl = [Purchasely planControllerFor:@"my_plan_id"
with:nil
completion:nil];
[self presentViewController:paywallPlanCtrl animated:YES completion:nil];
Kotlin
// Default presentation for a product
val productFragment = Purchasely.productFragment("my_product_id") { result, plan ->
//plan bought, restored or cancelled
}
// Default presentation for a plan
val planFragment = Purchasely.planFragment("my_plan_id") { result, plan ->
//plan bought, restored or cancelled
}
Java
// Default presentation for a product
Fragment productFragment = Purchasely.productFragment("my_product_id", null, new ProductViewResultListener() {
@Override
public void onResult(@NotNull PLYProductViewResult result, @Nullable PLYPlan plan) {
//plan bought, restored or cancelled
}
});
// Default presentation for a plan
Fragment planFragment = Purchasely.planFragment("my_plan_id", null, new ProductViewResultListener() {
@Override
public void onResult(@NotNull PLYProductViewResult result, @Nullable PLYPlan plan) {
//plan bought, restored or cancelled
}
});
React Native
// Default presentation for a product
try {
await Purchasely.presentProductWithIdentifier('my_product_id', null);
} catch (e) {
console.log(e);
}
// Default presentation for a plan
try {
await Purchasely.presentPlanWithIdentifier('my_plan_id', null);
} catch (e) {
console.log(e);
}
Cordova
// Default presentation for a product
Purchasely.presentProductWithIdentifier("my_product_id", null);
// Default presentation for a plan
Purchasely.presentPlanWithIdentifier("my_plan_id", null);

Unlock content / service once a purchase is made

Once the purchase is made to Apple Servers, registered in our systems, Purchasely sends a local Notification in the NotificationCenter. You can use it to unlock the content or refresh it.

You can catch it like this

Swift
Objective-C
Kotlin
Java
ReactNative
Cordova
Swift
NotificationCenter.default.addObserver(self, selector: #selector(reloadContent(_:)), name: .ply_purchasedSubscription, object: nil)
Objective-C
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reloadContent)
name: @"ply_purchasedSubscription"
object:nil];
Kotlin
Purchasely.livePurchase().observe(this) { plan: PLYPlan? ->
reloadContent(plan)
}
Purchasely.purchaseListener = purchaseListener
Java
// You can use LiveData
Purchasely.livePurchase().observe(this, (plan) -> {
reloadContent(plan);
});
// Or PurchaseListener
Purchasely.setPurchaseListener(purchaseListener);
ReactNative
Purchasely.addPurchasedListener(() => {
// User has successfully purchased a product, reload content
});
Cordova
Purchasely.purchasedSubscription(() => {
// User has successfully purchased a product, reload content
});

And use it like that

Swift
Objective-C
Kotlin
Java
Swift
@objc func reloadContent(_ notification: Notification) {
// Reload the content
}
Objective-C
- (void)reloadContent: (NSNotification *)aNotification {
// Reload the content
}
Kotlin
private fun reloadContent(plan: PLYPlan?) {
//Reload the content
}
//Instance of PurchaseListener
private val purchaseListener: PurchaseListener = object : PurchaseListener {
override fun onPurchaseStateChanged(@NotNull state: State) {
if (state is State.PurchaseComplete) {
reloadContent(state.plan)
} else if (state is State.RestorationComplete) {
reloadContent(state.plan)
}
}
}
Java
private void reloadContent(@Nullable PLYPlan plan) {
//Reload the content
}
//Instance of PurchaseListener
private PurchaseListener purchaseListener = new PurchaseListener() {
@Override
public void onPurchaseStateChanged(@NotNull State state) {
if(state instanceof State.PurchaseComplete) {
PLYPlan plan = ((State.PurchaseComplete) state).getPlan();
reloadContent(plan);
} else if(state instanceof State.RestorationComplete) {
PLYPlan plan = ((State.RestorationComplete) state).getPlan();
reloadContent(plan);
}
}
};

For example, this can be done in every controller that displays premium content. That way you won't have to reload the content each time the controller is displayed unless a payment was made

Close SDK (Android)

When done with Purchasely, you should call close() to remove all references to your activities. This method must only be called when you won't be using our SDK in the current user session. If you need to use our SDK again after calling close() then you need to call Purchasely.Builder() and Purchasely.start().

For example you can call this method in the onDestroy() method of your main activity

Kotlin
Java
ReactNative
Cordova
Kotlin
override fun onDestroy() {
super.onDestroy()
Purchasely.close()
}
Java
@Override
protected void onDestroy() {
super.onDestroy();
Purchasely.close();
}
ReactNative
Purchasely.close();
Cordova
Purchasely.close();