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.
#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;
}
import io.purchasely.ext.PurchaselyPurchasely.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 { isConfigured ->}
List<Store> stores =newArrayList();stores.add(newGoogleStore(),newHuaweiStore());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(isConfigured -> {null;});
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);
/*** @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.
Purchasely.userLogin(with:"123456789")
[Purchasely userLoginWith:@"123456789"];
Purchasely.userLogin("123456789") { refresh ->if (refresh) {//you can call your backend to refresh user information }}
Purchasely.userLogin("123456789", refresh -> {if(refresh) {//you can call your backend to refresh user information }returnnull;});
Purchasely.userLogin('123456789').then((refresh) => {if (refresh) {//call your backend to refresh user information }});
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 :
Purchasely.userLogout()
[Purchasely userLogout];
Purchasely.userLogout()
Purchasely.userLogout();
Purchasely.userLogout();
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, …)
// Call me in your viewDidAppearPurchasely.isReadyToPurchase(true)
[Purchasely isReadyToPurchase: true];
Purchasely.isReadyToPurchase =true
Purchasely.setIsReadyToPurchase(true);
Purchasely.isReadyToPurchase(true);
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 :
let paywallCtrl = Purchasely.presentationController(with:"my_presentation_id" completion: { (result, plan) inswitch result {case .purchased:breakcase .restored:breakcase .cancelled:break@unknowndefault:break }})present(paywallCtrl, animated:true)
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()
Fragment fragment =Purchasely.presentationFragment("my_presentation_id",newProductViewResultListener() { @OverridepublicvoidonResult(@NotNullPLYProductViewResult result, @NullablePLYPlan 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();
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:
// Default presentation for a productlet paywallProductCtrl = Purchasely.productController(with:"my_product_id")present(paywallProductCtrl, animated:true)// Default presentation for a planlet paywallPlanCtrl = Purchasely.planController(with:"my_plan_id")present(paywallPlanCtrl, animated:true)
// 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];
// Default presentation for a productval productFragment = Purchasely.productFragment("my_product_id") { result, plan ->//plan bought, restored or cancelled}// Default presentation for a planval planFragment = Purchasely.planFragment("my_plan_id") { result, plan ->//plan bought, restored or cancelled}
// Default presentation for a productFragment productFragment =Purchasely.productFragment("my_product_id",null,newProductViewResultListener() { @OverridepublicvoidonResult(@NotNullPLYProductViewResult result, @NullablePLYPlan plan) {//plan bought, restored or cancelled }});// Default presentation for a planFragment planFragment =Purchasely.planFragment("my_plan_id",null,newProductViewResultListener() { @OverridepublicvoidonResult(@NotNullPLYProductViewResult result, @NullablePLYPlan plan) {//plan bought, restored or cancelled }});
// Default presentation for a producttry {awaitPurchasely.presentProductWithIdentifier('my_product_id',null);} catch (e) {console.log(e);}// Default presentation for a plantry {awaitPurchasely.presentPlanWithIdentifier('my_plan_id',null);} catch (e) {console.log(e);}
// Default presentation for a productPurchasely.presentProductWithIdentifier("my_product_id",null);// Default presentation for a planPurchasely.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 use LiveDataPurchasely.livePurchase().observe(this, (plan) -> {reloadContent(plan);});// Or PurchaseListenerPurchasely.setPurchaseListener(purchaseListener);
Purchasely.addPurchasedListener(() => {// User has successfully purchased a product, reload content});
Purchasely.purchasedSubscription(() => {// User has successfully purchased a product, reload content});
And use it like that
@objcfuncreloadContent(_notification: Notification) {// Reload the content }
- (void)reloadContent: (NSNotification *)aNotification {
// Reload the content
}
privatefunreloadContent(plan: PLYPlan?) {//Reload the content}//Instance of PurchaseListenerprivateval purchaseListener: PurchaseListener=object : PurchaseListener {overridefunonPurchaseStateChanged(@NotNull state: State) {if (state is State.PurchaseComplete) {reloadContent(state.plan) } elseif (state is State.RestorationComplete) {reloadContent(state.plan) } }}
privatevoidreloadContent(@NullablePLYPlan plan) {//Reload the content}//Instance of PurchaseListenerprivatePurchaseListener purchaseListener =newPurchaseListener() { @OverridepublicvoidonPurchaseStateChanged(@NotNullState state) {if(state instanceofState.PurchaseComplete) {PLYPlan plan = ((State.PurchaseComplete) state).getPlan();reloadContent(plan); } elseif(state instanceofState.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