the observerMode parameter is replaced by a more comprehensive runningMode
the confirmPurchaseHandler parameter is replaced by paywallActionsInterceptor
Grab new events and properties
Expect null controllers / fragments
Even if you don't use observer mode or new modes you will have to adapt your code
Some of the new modes block the display of the paywall. In that case the paywall is not returned.
This is the reason why the following methods are not returning optionals:
productController
planController
presentationController
Migrate the Purchase interceptor
Purchase interceptor was used to trigger app specific code before triggering the purchase using Purchasely.
It could be used to display specific terms and conditions, present a parental gate or perform a purchase using your own code or a third party subscription tool.
If you are using Purchase interceptor you probably have some code like that:
Purchasely.setConfimPurchaseHandler { [weak self](paywallController, processToPayment)in// Display the terms of use to your user self?.presentTermsAndConditions(above: paywallController) { (userAcceptedTerms) in// Don't forget to notify the SDK by calling `processToPayment`processToPayment(userAcceptedTerms) }}
Purchasely.setConfirmPurchaseHandler { activity, processToPayment ->//if there is no activity then there is nothing to displayif (activity ==null) return@setConfirmPurchaseHandler//call your method to display your view //and return boolean result to processToPaymentpresentTermsAndConditions(activity) { userAcceptedTerms ->// Don't forget to notify the SDK by calling `processToPayment`processToPayment(userAcceptedTerms) }}
Purchasely.setConfirmPurchaseHandler((activity, listener) -> {//if there is no activity then there is nothing to displayif (activity ==null) return;/* call your method to display your view and return boolean result to processToPayment listener.processToPayment(userAcceptedTerms); */presentTermsAndConditions(activity, listener);});//You can also use the method for kotlin with Function interface
Purchasely.setPurchaseCompletionCallback(() => {//Present your own screen before purchaseconsole.log('Received callback from user tapped on purchase button');//Call this method to continue to payment flow when you close your screenPurchasely.processToPayment(true);});
Purchasely.setConfirmPurchaseHandler(onPurchaseTapped => {//Present your own screen before purchase//Call this method to continue to payment flow when you close your screenPurchasely.processToPayment(true);})java
it should be changed to something like that:
Purchasely.setPaywallActionsInterceptor { [weak self](action, parameters, presentationInfo, proceed)inswitch action {// Intercept the tap on purchase to display the terms and conditioncase .purchase: self?.presentTermsAndConditions(above: presentationInfo?.controller) { (userAcceptedTerms) inproceed(userAcceptedTerms) }default:proceed(true)break }}
[Purchasely setPaywallActionsInterceptor:^(enum PLYPresentationAction action, PLYPresentationActionParameters *parameters, PLYPresentationInfo *info, void (^ proceed)(BOOL)) {
switch (action) {
// Intercept the tap on purchase to display the terms and condition
case PLYPresentationActionPurchase:{
[self presentTermsAndConditionsAbove:info.controller completion:^(BOOL userAcceptedTerms) {
proceed(userAcceptedTerms);
}];
break;
}
default:
proceed(YES);
break;
}
}];
Purchasely.setPaywallActionsInterceptor((info, action, parameters, listener) -> {//if there is no activity then there is nothing to displayif (info ==null||info.getActivity() ==null) return;switch (action) {case PURCHASE://present your terms and call //listener.processAction(true) if accepted//or listener.processAction(false) if not to cancel purchasepresentTermsAndConditions(info.getActivity(), listener);break;default:listener.processAction(true); }});
Purchasely.setPaywallActionInterceptorCallback((result) => {console.log('Received action from paywall '+result.info.presentationId);if (result.action ===PLYPaywallAction.PURCHASE) {console.log('User wants to purchase');//If you want to intercept it, close paywall and display your screenPurchasely.closePaywall(); } else {console.log('Action unknown '+result.action);Purchasely.onProcessAction(true); } });
Purchasely.setPaywallActionInterceptor((result) => {console.log('Received action from paywall'+result.info.presentationId);if (result.action ===Purchasely.PaywallAction.purchase) {console.log('User wants to purchase');//If you want to intercept it, close paywall and display your screenPurchasely.closePaywall(); } else {console.log('Action unknown '+result.action);Purchasely.onProcessAction(true); }});
If your are intercepting several actions (purchase, login, …) you must add a case and should only have one call to Purchasely.setPaywallActionsInterceptor
Migrate the Login interceptor
Every presentation, has an Already subscribed? Sign-in button to let your customers connect to unlock a feature / access a content.
To intercept the tap on this button you had to use the loginTappedHandler interceptor
Purchasely.setLoginTappedHandler { (paywallController, isLoggedIn) in// Get your login controller loginCtrl =LoginViewController()// Configure the response to notify Purchasely that it needs to reload (if needed) loginCtrl.configure(with: isLoggedIn) paywallController.present(loginCtrl, animated:true, completion:nil)}
[Purchasely setLoginTappedHandler:^(UIViewController * paywallController, void (^ isLoggedIn)(BOOL)) {
// Get your login controller
LoginViewController *loginCtrl = LoginViewController()
// Configure the response to notify Purchasely that it needs to reload (if needed)
[loginCtrl configureWith: isLoggedIn];
[paywallController presentViewController:loginCtrl animated:YES completion:nil];
}];
Purchasely.setLoginTappedHandler { activity, isLoggedIn ->// If there is no activity then there is nothing to displayif (activity ==null) return@setLoginTappedHandler// Call your method to display your view // and return boolean result to userLoggedInpresentLogin(activity) { userLoggedIn ->// Don't forget to notify the SDK by calling `isLoggedIn`isLoggedIn(userLoggedIn) }}
Purchasely.setLoginTappedHandler((activity, listener) -> {//if there is no activity then there is nothing to displayif (activity ==null) return;/* call your method to display your view and return boolean result to listener listener.userLoggedIn(userLoggedIn); */presentLogin(activity, listener);});//You can also use the method for kotlin with Function interface
Purchasely.setLoginTappedCallback(() => {//Present your own screen for user to log inconsole.log('Received callback from user tapped on sign in button');//Call this method with true to update Purchasely Paywall if user logged inPurchasely.onUserLoggedIn(true);});
Purchasely.setLoginTappedHandler(onLoginTapped => {//Present your own screen for user to log in//Call this method with true to update Purchasely Paywall if user logged inPurchasely.onUserLoggedIn(true);});
With SDK v3 this feature is moved to the paywall actions interceptor and your code should change to something like that:
Purchasely.setPaywallActionsInterceptor { [weak self](action, parameters, presentationInfo, proceed)inswitch action {// Intercept the tap on logincase .login:// When the user has completed the process// Pass true to reload the paywall or dismiss the paywall if the user already has an active subscription self?.presentLogin(above: presentationInfo?.controller) { (loggedIn) inproceed(loggedIn) }default:proceed(true)break }}
[Purchasely setPaywallActionsInterceptor:^(enum PLYPresentationAction action, PLYPresentationActionParameters *parameters, PLYPresentationInfo *info, void (^ proceed)(BOOL)) {
switch (action) {
// Intercept the tap on purchase to display the terms and condition
case PLYPresentationActionPurchase:{
[self presentTermsAndConditionsAbove:info.controller completion:^(BOOL userAcceptedTerms) {
proceed(userAcceptedTerms);
}];
break;
}
default:
proceed(YES);
break;
}
}];
Purchasely.setPaywallActionsInterceptor { info, action, parameters, processAction ->if (info?.activity ==null) return@setPaywallActionsInterceptorwhen(action) { PLYPresentationAction.LOGIN -> {// Call your method to display your view // and return boolean result to userLoggedInpresentLogin(info.activity) { userLoggedIn ->// Don't forget to notify the SDK by calling `processAction`processAction(userLoggedIn) } }else-> { Log.d("PLYActionInterceptor", action.value+" "+ parameters)processAction(true) } }}
Purchasely.setPaywallActionsInterceptor((info, action, parameters, listener) -> {//if there is no activity then there is nothing to displayif (info ==null||info.getActivity() ==null) return;switch (action) {case LOGIN:// call your method to display your view// and return boolean result to listener// listener.processAction(true);presentLogin(info.getActivity(), listener);break;default:listener.processAction(true); }});
Purchasely.setPaywallActionInterceptorCallback((result) => {if (result.action ===PLYPaywallAction.LOGIN) {console.log('User wants to login');//Present your own screen for user to log inPurchasely.closePaywall();Purchasely.userLogin('MY_USER_ID');//Call this method to update Purchasely PaywallPurchasely.onProcessAction(true); } else {Purchasely.onProcessAction(true); }});
Purchasely.setPaywallActionInterceptorCallback((result) => {if (result.action ===PLYPaywallAction.LOGIN) {console.log('User wants to login');//Present your own screen for user to log inPurchasely.closePaywall();Purchasely.userLogin('MY_USER_ID');//Call this method to update Purchasely PaywallPurchasely.onProcessAction(true); } else {Purchasely.onProcessAction(true); } });
If your are intercepting several action (purchase, login, …) you must add a case and should only have one call to Purchasely.setPaywallActionsInterceptor