From dbaa185c1a1b700ff18b218f01ca99eefd229135 Mon Sep 17 00:00:00 2001 From: Semih ERDOGAN Date: Mon, 8 Mar 2021 10:32:39 +0300 Subject: [PATCH] project initialized --- .gitattributes | 7 + .gitignore | 3 + CHANGELOG.md | 12 + LICENSE | 21 ++ README.md | 96 ++++++ example/App.js | 23 ++ package.json | 24 ++ plugin.xml | 57 ++++ src/android/DeepwallCordovaPlugin.java | 425 +++++++++++++++++++++++++ src/android/plugin.gradle | 9 + src/ios/DeepwallCordovaPlugin.swift | 339 ++++++++++++++++++++ src/ios/bridging-header.h | 1 + www/DeepwallCordovaPlugin.js | 58 ++++ www/enums/DeepwallException.js | 14 + www/enums/EnvironmentStyles.js | 6 + www/enums/Environments.js | 5 + www/enums/ErrorCodes.js | 27 ++ www/enums/Events.js | 18 ++ www/enums/ProrationTypes.js | 7 + www/enums/PurchaseUpgradePolicy.js | 4 + www/enums/ValidateReceiptTypes.js | 6 + 21 files changed, 1162 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 example/App.js create mode 100755 package.json create mode 100755 plugin.xml create mode 100755 src/android/DeepwallCordovaPlugin.java create mode 100755 src/android/plugin.gradle create mode 100755 src/ios/DeepwallCordovaPlugin.swift create mode 100755 src/ios/bridging-header.h create mode 100755 www/DeepwallCordovaPlugin.js create mode 100755 www/enums/DeepwallException.js create mode 100755 www/enums/EnvironmentStyles.js create mode 100755 www/enums/Environments.js create mode 100755 www/enums/ErrorCodes.js create mode 100755 www/enums/Events.js create mode 100755 www/enums/ProrationTypes.js create mode 100755 www/enums/PurchaseUpgradePolicy.js create mode 100755 www/enums/ValidateReceiptTypes.js diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..615bba9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +*.pbxproj -text +/.github export-ignore +/example export-ignore +/.editorconfig export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/CHANGELOG.md export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a304d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +/.idea +/.vscode diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..48c1f6c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog +All notable changes to this project will be documented in this file. + +## [Unreleased](https://github.com/Teknasyon-Teknoloji/deepwall-cordova-sdk/compare/1.0.0...main) + + +--- + + +## 1.0.0 (2021-03-08) +### Added +- Initial release. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a716023 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2020 DeepWall. https://deepwall.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc137cc --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# DeepWall (deepwall-cordova-plugin) +* This package gives wrapper methods for deepwall sdks. [iOS](https://github.com/Teknasyon-Teknoloji/deepwall-ios-sdk) - [Android](https://github.com/Teknasyon-Teknoloji/deepwall-android-sdk) + +* Before implementing this package, you need to have **api_key** and list of **actions**. + +* You can get api_key and actions from [DeepWall Dashboard](https://console.deepwall.com/) + +--- + +## Getting started + +`$ cordova plugin add https://github.com/Teknasyon-Teknoloji/deepwall-cordova-sdk.git#1.0.0` + +* After adding plugin in the dependency section, + add `AndroidXEnabled` as `true` in the `config.xml` of your application. +```xml + +``` + +### Installation Notes +- **IOS** + - Set minimum ios version to `10.0` in `platforms/ios/Podfile` like: `platform :ios, '10.0'` + - Add `use_frameworks!` into `platforms/ios/Podfile` if not exists. + - Run `$ cd platforms/ios && pod install` + +- **ANDROID** + - Set `minSdkVersion` to `21 in` `platforms/android/app/build.gradle` + - Add `maven { url 'https://raw.githubusercontent.com/Teknasyon-Teknoloji/deepwall-android-sdk/master/' }` into `platforms/android/app/build.gradle` (Add into repositories under allprojects) + +--- + +## Usage + +### 1. Initialize DeepWall SDK +- On application start you need to initialize sdk with api key and environment. +```javascript +cordova.DeepwallCordovaPlugin.initialize("API_KEY", Environments.PRODUCTION, function(response){ + console.log(response); +}, function(error){ + console.log(error); +}); +``` + +### 2. set User Properties +- Before requesting any paywall you need to set UserProperties (device uuid, country, language). [See all parameters](https://github.com/Teknasyon-Teknoloji/deepwall-ios-sdk#configuration) +````javascript +cordova.DeepwallCordovaPlugin.setUserProperties('UNIQUE_DEVICE_ID_HERE (UUID)','en-us','us', EnvironmentStyles.LIGHT, function(response){ + console.log(response); +}, function(error){ + console.log(error); +}); +```` + +### 3. request Paywall +- After setting userProperties, you are ready for requesting paywall with an action name. You can find action name in DeepWall dashboard. You can send extra paramteres as well. +````javascript +cordova.DeepwallCordovaPlugin.requestPaywall('AppLaunch',{}, function(response){ + console.log(response); +}, function(error){ + console.log(error); +}); +```` + +### 4. close Paywall +- You can also close paywall using: +````javascript +cordova.DeepwallCordovaPlugin.closePaywall(function(response){ + console.log(response); +}, function(error){ + console.log(error); +}); +```` + +### 5. update userProperties +- If any of userProperties is changed you need to call updateUserProperties method. (For example if user changed application language) +````javascript +cordova.DeepwallCordovaPlugin.updateUserProperties('fr-fr','fr',EnvironmentStyles.LIGHT, function(response){ + console.log(response); +}, function(error){ + console.log(error); +}); +```` + +### 6. listen all Deepwall Events +- There is also bunch of events triggering before and after DeepWall Actions. You may listen any action like below. +````javascript +cordova.DeepwallCordovaPlugin.observeEvents(function(response){ + console.log(JSON.stringify(response)); + // access response.data +}, function(error){ + console.log(error); +}) +```` + +## Notes +- You may find complete list of _events_ in [enums/Events.js](./www/enums/Events.js) or [Native Sdk Page](https://github.com/Teknasyon-Teknoloji/deepwall-ios-sdk#event-handling) diff --git a/example/App.js b/example/App.js new file mode 100644 index 0000000..85c4583 --- /dev/null +++ b/example/App.js @@ -0,0 +1,23 @@ +// Wait for the deviceready event +// See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready +document.addEventListener('deviceready', onDeviceReady, false); + +function onDeviceReady() { + cordova.DeepwallCordovaPlugin.initialize('API_KEY', Environments.SANDBOX); + cordova.DeepwallCordovaPlugin.setUserProperties( + 'deepwall-test-device', + 'en', + 'en-en', + EnvironmentStyles.LIGHT + ); + + // Listen all events + cordova.DeepwallCordovaPlugin.observeEvents(function (response) { + console.log('Event SUCCESS: ', JSON.stringify(response)); + }, function (error) { + console.log('Event ERROR: ', error); + }); + + // Open Paywall + cordova.DeepwallCordovaPlugin.requestPaywall('Settings', extraData = {}); +} diff --git a/package.json b/package.json new file mode 100755 index 0000000..54219ed --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "cordova-plugin-deepwall", + "version": "1.0.0", + "description": "Deepwall Cordova Wrapper", + "homepage": "https://deepwall.com", + "repository": { + "type": "git", + "url": "https://github.com/Teknasyon-Teknoloji/deepwall-cordova-sdk.git" + }, + "cordova": { + "id": "cordova-plugin-deepwall", + "platforms": [ + "ios", + "android" + ] + }, + "keywords": [ + "ecosystem:cordova", + "cordova-ios", + "cordova-android" + ], + "author": "Deepwall", + "license": "MIT" +} diff --git a/plugin.xml b/plugin.xml new file mode 100755 index 0000000..0452d35 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,57 @@ + + + Deepwall + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/android/DeepwallCordovaPlugin.java b/src/android/DeepwallCordovaPlugin.java new file mode 100755 index 0000000..f47f254 --- /dev/null +++ b/src/android/DeepwallCordovaPlugin.java @@ -0,0 +1,425 @@ +package deepwallcordova; + +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.PluginResult; +import io.reactivex.functions.Consumer; +import manager.eventbus.EventBus; +import manager.eventbus.EventModel; +import manager.purchasekit.ValidationType; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import android.os.Bundle; +import androidx.annotation.NonNull; +import com.google.gson.Gson; +import deepwall.core.DeepWall; +import deepwall.core.models.*; +import java.util.*; +import android.util.Log; + +/** + * This class echoes a string called from JavaScript. + */ +public class DeepwallCordovaPlugin extends CordovaPlugin { + + private CallbackContext callback; + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + this.callback = callbackContext; + if(action.equals("initialize")) { + this.initialize(args.getString(0), args.getInt(1)); + return true; + } + else if(action.equals("observeEvents")) { + this.observeEvents(); + return true; + } + else if(action.equals("setUserProperties")) { + this.setUserProperties(args.getString(0), args.getString(1), args.getString(2), args.getInt(3)); + return true; + } + else if(action.equals("requestPaywall")) { + JSONObject extra = new JSONObject(args.getString(1)); + this.requestPaywall(args.getString(0), extra); + return true; + } + else if(action.equals("updateUserProperties")) { + this.updateUserProperties(args.getString(0), args.getString(1), args.getInt(2), args.getJSONObject(3)); + return true; + } + else if(action.equals("closePaywall")) { + this.closePayWall(); + return true; + } + else if(action.equals("hidePaywallLoadingIndicator")) { + this.hidePaywallLoadingIndicator(); + return true; + } + else if(action.equals("validateReceipt")) { + this.validateReceipt(args.getInt(0)); + return true; + } + else if(action.equals("consumeProduct")) { + this.consumeProduct(args.getString(0)); + return true; + } + else if(action.equals("setProductUpgradePolicy")) { + this.setProductUpgradePolicy(args.getInt(0), args.getInt(1)); + return true; + } + else if(action.equals("updateProductUpgradePolicy")) { + this.updateProductUpgradePolicy(args.getInt(0), args.getInt(1)); + return true; + } + else + return false; + } + + private void initialize(String apiKey, int environment){ + if (apiKey != null && apiKey.length() > 0) { + DeepWallEnvironment deepWallEnvironment = environment == 1? DeepWallEnvironment.SANDBOX : DeepWallEnvironment.PRODUCTION; + DeepWall.INSTANCE.initDeepWallWith(this.cordova.getActivity().getApplication(), this.cordova.getActivity(), apiKey, deepWallEnvironment); + callback.success("Deepwall initialize success"); + } else { + callback.error("Expected non-empty string arguments."); + } + } + + + private void setUserProperties(String uuid, String country, String language, int environmentStyle){ + if (uuid != null && country != null && language != null) { + DeepWallEnvironmentStyle theme = (environmentStyle == 0)? DeepWallEnvironmentStyle.LIGHT : DeepWallEnvironmentStyle.DARK; + DeepWall.INSTANCE.setUserProperties(uuid, country, language, this::success, theme); + callback.success("Deepwall setUserProperties success"); + } else { + callback.error("Expected non-empty string arguments."); + } + } + + private kotlin.Unit success(){return null;} + private void requestPaywall(String actionKey, JSONObject extraData) throws JSONException { + if (actionKey != null) { + Bundle bundle = new Bundle(); + if(extraData != null){ + Iterator iter = extraData.keys(); //This should be the iterator you want. + while(iter.hasNext()){ + String key = iter.next(); + if(extraData.get(key) instanceof Boolean){ + bundle.putBoolean(key, extraData.getBoolean(key)); + } + else if(extraData.get(key) instanceof Integer){ + bundle.putInt(key, extraData.getInt(key)); + } + else if(extraData.get(key) instanceof Double){ + bundle.putDouble(key, extraData.getDouble(key)); + } + else if(extraData.get(key) instanceof String){ + bundle.putString(key, extraData.getString(key)); + } + } + } + DeepWall.INSTANCE.showPaywall(this.cordova.getActivity(), actionKey, bundle, this::error); + callback.success("Deepwall requestPaywall success"); + } else { + callback.error("Expected non-empty string arguments."); + } + } + private kotlin.Unit error(String s){return null;} + private void updateUserProperties(String country, String language, int environmentStyle, JSONObject debugAdvertiseAttributions){ + if (country != null && language != null) { + DeepWallEnvironmentStyle theme = (environmentStyle == 0)? DeepWallEnvironmentStyle.LIGHT : DeepWallEnvironmentStyle.DARK; + DeepWall.INSTANCE.updateUserProperties(country, language, theme); + callback.success("Deepwall updateUserProperties success"); + } else { + callback.error("Expected non-empty string arguments."); + } + } + + private void closePayWall(){ + DeepWall.INSTANCE.closePaywall(); + callback.success("Deepwall closePaywall success"); + } + + private void hidePaywallLoadingIndicator(){ + //DeepWall.hidePaywallLoadingIndicator(); + callback.success("Deepwall hidePaywallLoadingIndicator success"); + } + + private void validateReceipt(int validationType){ + ValidationType validation; + switch (validationType) { + case 1 : validation = ValidationType.PURCHASE; break; + case 2 : validation = ValidationType.RESTORE; break; + case 3 : validation = ValidationType.AUTOMATIC; break; + default : validation = ValidationType.PURCHASE; break; + } + DeepWall.INSTANCE.validateReceipt(validation); + callback.success("Deepwall validateReceipt success"); + } + + private void consumeProduct(String productId) { + if (productId != null) { + DeepWall.INSTANCE.consumeProduct(productId); + callback.success("Deepwall consumeProduct success"); + } else { + callback.error("Expected non-empty string argument."); + } + } + + private void setProductUpgradePolicy(int prorationType, int upgradePolicy){ + ProrationType proration; + switch (prorationType) { + case 0 : proration = ProrationType.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY; break; + case 1 : proration = ProrationType.IMMEDIATE_WITH_TIME_PRORATION; break; + case 2 : proration = ProrationType.IMMEDIATE_WITHOUT_PRORATION; break; + case 3 : proration = ProrationType.IMMEDIATE_AND_CHARGE_PRORATED_PRICE; break; + case 4 : proration = ProrationType.DEFERRED; break; + case 5 : proration = ProrationType.NONE; break; + default : proration = ProrationType.NONE; break; + } + PurchaseUpgradePolicy policy; + switch (upgradePolicy) { + case 0 : policy = PurchaseUpgradePolicy.DISABLE_ALL_POLICIES; break; + case 1 : policy = PurchaseUpgradePolicy.ENABLE_ALL_POLICIES; break; + case 2 : policy = PurchaseUpgradePolicy.ENABLE_ONLY_UPGRADE; break; + case 3 : policy = PurchaseUpgradePolicy.ENABLE_ONLY_DOWNGRADE; break; + default : policy = PurchaseUpgradePolicy.DISABLE_ALL_POLICIES; break; + } + DeepWall.INSTANCE.setProductUpgradePolicy(proration, policy); + callback.success("Deepwall setProductUpgradePolicy success"); + + } + + private void updateProductUpgradePolicy(int prorationType, int upgradePolicy){ + ProrationType proration; + switch (prorationType) { + case 0 : proration = ProrationType.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY; break; + case 1 : proration = ProrationType.IMMEDIATE_WITH_TIME_PRORATION; break; + case 2 : proration = ProrationType.IMMEDIATE_WITHOUT_PRORATION; break; + case 3 : proration = ProrationType.IMMEDIATE_AND_CHARGE_PRORATED_PRICE; break; + case 4 : proration = ProrationType.DEFERRED; break; + case 5 : proration = ProrationType.NONE; break; + default : proration = ProrationType.NONE; break; + } + PurchaseUpgradePolicy policy; + switch (upgradePolicy) { + case 0 : policy = PurchaseUpgradePolicy.DISABLE_ALL_POLICIES; break; + case 1 : policy = PurchaseUpgradePolicy.ENABLE_ALL_POLICIES; break; + case 2 : policy = PurchaseUpgradePolicy.ENABLE_ONLY_UPGRADE; break; + case 3 : policy = PurchaseUpgradePolicy.ENABLE_ONLY_DOWNGRADE; break; + default : policy = PurchaseUpgradePolicy.DISABLE_ALL_POLICIES; break; + } + DeepWall.INSTANCE.updateProductUpgradePolicy(proration, policy); + callback.success("Deepwall updateProductUpgradePolicy success"); + } + + private final void observeEvents() { + EventBus.INSTANCE.subscribe((new Consumer() { + // $FF: synthetic method + // $FF: bridge method + public void accept(Object var1) throws Exception { + this.accept((EventModel)var1); + } + + public final void accept(EventModel it) throws Exception { + + JSONObject map = new JSONObject(); + JSONObject modelData = new JSONObject(); + Object dataObject; + int eventType = it.getType(); + if(eventType == DeepWallEvent.PAYWALL_OPENED.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.PaywallOpenedInfo"); + } + + PaywallOpenedInfo openedInfo = (PaywallOpenedInfo) dataObject; + modelData = convertJson(openedInfo); + map.put("data", modelData); + map.put("event", "deepWallPaywallOpened"); + + sendData(map); + } + else if(eventType == DeepWallEvent.DO_NOT_SHOW.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.PaywallActionShowDisabledInfo"); + } + + PaywallActionShowDisabledInfo actionInfo = (PaywallActionShowDisabledInfo) dataObject; + modelData = convertJson(actionInfo); + map.put("data", modelData); + map.put("event", "deepWallPaywallActionShowDisabled"); + sendData(map); + } + else if(eventType == DeepWallEvent.CLOSED.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.PaywallClosedInfo"); + } + + PaywallClosedInfo data = (PaywallClosedInfo) dataObject; + modelData = convertJson(data); + map.put("data", modelData); + map.put("event", "deepWallPaywallClosed"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_PURCHASING_PRODUCT.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.PaywallPurchasingProductInfo"); + } + + PaywallPurchasingProductInfo productInfo = (PaywallPurchasingProductInfo) dataObject; + modelData = convertJson(productInfo); + map.put("data", modelData); + map.put("event", "deepWallPaywallPurchasingProduct"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_PURCHASE_FAILED.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.SubscriptionErrorResponse"); + } + + SubscriptionErrorResponse errorResponse = (SubscriptionErrorResponse) dataObject; + modelData = convertJson(errorResponse); + map.put("data", modelData); + map.put("event", "deepWallPaywallPurchaseFailed"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_PURCHASE_SUCCESS.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.SubscriptionResponse"); + } + + SubscriptionResponse subResponse = (SubscriptionResponse) dataObject; + modelData = convertJson(subResponse); + map.put("data", modelData); + map.put("event", "deepWallPaywallPurchaseSuccess"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_RESPONSE_FAILURE.getValue()) { + map = new JSONObject(); + dataObject = it.getData(); + if (dataObject == null) { + throw new Exception("null cannot be cast to non-null type deepwall.core.models.PaywallFailureResponse"); + } + + PaywallFailureResponse failureResponse = (PaywallFailureResponse) dataObject; + modelData = convertJson(failureResponse); + map.put("data", modelData); + map.put("event", "deepWallPaywallResponseFailure"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_RESTORE_SUCCESS.getValue()) { + map = new JSONObject(); + map.put("data", String.valueOf(it.getData())); + map.put("event", "deepWallPaywallRestoreSuccess"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_RESTORE_FAILED.getValue()) { + map = new JSONObject(); + map.put("data", String.valueOf(it.getData())); + map.put("event", "deepWallPaywallRestoreFailed"); + sendData(map); + } + else if(eventType == DeepWallEvent.EXTRA_DATA.getValue()) { + dataObject = it.getData(); + if (dataObject != null) { + modelData = convertJson(dataObject); + } + + map.put("data", modelData); + map.put("event", "deepWallPaywallExtraDataReceived"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_REQUESTED.getValue()) { + map = new JSONObject(); + map.put("data", ""); + map.put("event", "deepWallPaywallRequested"); + sendData(map); + } + else if(eventType == DeepWallEvent.PAYWALL_RESPONSE_RECEIVED.getValue()) { + map = new JSONObject(); + map.put("data", ""); + map.put("event", "deepWallPaywallResponseReceived"); + sendData(map); + } + else if(eventType == DeepWallEvent.CONSUME_SUCCESS.getValue()) { + map = new JSONObject(); + map.put("data", ""); + map.put("event", "deepWallPaywallConsumeSuccess"); + sendData(map); + } + else if(eventType == DeepWallEvent.CONSUME_FAILURE.getValue()) { + map = new JSONObject(); + map.put("data", ""); + map.put("event", "deepWallPaywallConsumeFailure"); + sendData(map); + } + } + })); + } + + private void sendData(JSONObject map){ + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, map); + pluginResult.setKeepCallback(true); + callback.sendPluginResult(pluginResult); + } + + private final HashMap convertJsonToMap(JSONObject object) throws JSONException { + HashMap map = new HashMap(); + String key; + Object value; + for(Iterator keysItr = object.keys(); keysItr.hasNext(); map.put(key, value)) { + key = (String)keysItr.next(); + value = object.get(key); + if (value instanceof JSONArray) { + value = this.convertJsonToArray((JSONArray)value); + } else if (value instanceof JSONObject) { + value = this.convertJsonToMap((JSONObject)value); + } + } + + return map; + } + + private final JSONObject convertJson(Object model) throws JSONException { + Gson gson = new Gson(); + String jsonInString = gson.toJson(model); + return new JSONObject(jsonInString); + } + + private final ArrayList convertJsonToArray(JSONArray array) throws JSONException { + ArrayList list = new ArrayList(); + int i = 0; + int var4 = array.length() - 1; + if (i <= var4) { + while(true) { + Object value = array.get(i); + if (value instanceof JSONArray) { + value = this.convertJsonToArray((JSONArray)value); + } else if (value instanceof JSONObject) { + value = this.convertJsonToMap((JSONObject)value); + } + + list.add(value); + if (i == var4) { + break; + } + ++i; + } + } + + return list; + } +} diff --git a/src/android/plugin.gradle b/src/android/plugin.gradle new file mode 100755 index 0000000..9e933f1 --- /dev/null +++ b/src/android/plugin.gradle @@ -0,0 +1,9 @@ +repositories { + google() + jcenter() + maven { url 'https://raw.githubusercontent.com/Teknasyon-Teknoloji/deepwall-android-sdk/master/' } +} + +dependencies { + implementation 'deepwall:deepwall-core:2.2.0' +} \ No newline at end of file diff --git a/src/ios/DeepwallCordovaPlugin.swift b/src/ios/DeepwallCordovaPlugin.swift new file mode 100755 index 0000000..d558b89 --- /dev/null +++ b/src/ios/DeepwallCordovaPlugin.swift @@ -0,0 +1,339 @@ +import UIKit +import DeepWall +import Foundation + +@objc(DeepwallCordovaPlugin) class DeepwallCordovaPlugin : CDVPlugin, DeepWallNotifierDelegate { + + var eventsCallbackCommand : CDVInvokedUrlCommand? = nil + + @objc(initialize:) + func initialize(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (initialize)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [Any]{ + let apiKey = myArgs[0] as? String + let environment = myArgs[1] as? Int + var deepWallEnvironment : DeepWallEnvironment; + if (environment == 1){ + deepWallEnvironment = .sandbox + } + else{ + deepWallEnvironment = .production + } + DeepWall.initialize(apiKey: apiKey!, environment: deepWallEnvironment) + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (initialize)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(observeEvents:) + func observeEvents(command : CDVInvokedUrlCommand) + { + self.eventsCallbackCommand = command + DeepWall.shared.observeEvents(for: self) + } + + @objc(setUserProperties:) + func setUserProperties(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (setUserProperties)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [Any]{ + let uuid = myArgs[0] as? String + let country = myArgs[1] as? String + let language = myArgs[2] as? String + let properties = DeepWallUserProperties(uuid: uuid!, country: country!, language: language!) + DeepWall.shared.setUserProperties(properties) + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (setUserProperties)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(requestPaywall:) + func requestPaywall(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (requestPaywall)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [Any]{ + let actionKey = myArgs[0] as? String + let extra = myArgs[1] as? String + if let extraData = convertToDictionary(text: extra) { + DeepWall.shared.requestPaywall(action: actionKey!, in: self.viewController, extraData: extraData) + } + else{ + DeepWall.shared.requestPaywall(action: actionKey!, in: self.viewController, extraData: [:]) + } + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (requestPaywall)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(updateUserProperties:) + func updateUserProperties(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (updateUserProperties)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [Any]{ + let country = myArgs[0] as? String + let language = myArgs[1] as? String + let environmentStyle = myArgs[2] as? Int + let debugAdvertiseAttributions = myArgs[3] + let theme: DeepWallEnvironmentStyle = (environmentStyle == 0) ? .light : .dark + DeepWall.shared.updateUserProperties(country:country, language:language, environmentStyle:theme,debugAdvertiseAttributions:debugAdvertiseAttributions as? [String : String]) + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (updateUserProperties)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(closePaywall:) + func closePaywall(command : CDVInvokedUrlCommand) + { + DeepWall.shared.closePaywall() + } + + @objc(hidePaywallLoadingIndicator:) + func hidePaywallLoadingIndicator(command : CDVInvokedUrlCommand) + { + DeepWall.shared.hidePaywallLoadingIndicator() + } + + @objc(validateReceipt:) + func validateReceipt(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (validateReceipt)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [String: Any]{ + var validationType = myArgs["validationType"] as? Int + var validation:PloutosValidationType; + switch (validationType) { + case 1: validation = PloutosValidationType.purchase; break; + case 2: validation = PloutosValidationType.restore; break; + case 3: validation = PloutosValidationType.automatic; break + default: validation = PloutosValidationType.purchase; break; + } + DeepWall.shared.validateReceipt(for: validation) + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (validateReceipt)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(consumeProduct:) + func consumeProduct(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (consumeProduct)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [String: Any]{ + // TODO Implementation of consumeProduct method + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (consumeProduct)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(setProductUpgradePolicy:) + func setProductUpgradePolicy(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (setProductUpgradePolicy)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [String: Any]{ + // TODO Implementation of setProductUpgradePolicy method + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (setProductUpgradePolicy)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + @objc(updateProductUpgradePolicy:) + func updateProductUpgradePolicy(command : CDVInvokedUrlCommand) + { + guard let args = command.arguments else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "Could not recognize cordova arguments in method: (updateProductUpgradePolicy)") + self.commandDelegate.send(result, callbackId: command.callbackId) + return () + } + if let myArgs = args as? [String: Any]{ + // TODO Implementation of updateProductUpgradePolicy method + } else { + let result = CDVPluginResult(status: CDVCommandStatus_ERROR, messageAs: "iOS could not extract " + + "cordova arguments in method: (updateProductUpgradePolicy)") + self.commandDelegate.send(result, callbackId: command.callbackId) + } + } + + public func deepWallPaywallRequested() -> Void { + print("event:deepWallPaywallRequested"); + var mapData = [String: Any]() + mapData["data"] = "" + mapData["event"] = "deepWallPaywallRequested" + sendData(state: mapData) + } + + public func deepWallPaywallResponseReceived() -> Void { + print("event:deepWallPaywallResponseReceived"); + var mapData = [String: Any]() + mapData["data"] = "" + mapData["event"] = "deepWallPaywallResponseReceived" + sendData(state: mapData) + } + + public func deepWallPaywallOpened(_ model: DeepWallPaywallOpenedInfoModel) -> Void { + print("event:deepWallPaywallOpened"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["pageId"] = model.pageId + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallOpened" + sendData(state: mapData) + } + + public func deepWallPaywallNotOpened(_ model: DeepWallPaywallNotOpenedInfoModel) -> Void { + print("event:deepWallPaywallNotOpened"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["pageId"] = model.pageId + modelMap["reason"] = model.reason + modelMap["errorCode"] = model.errorCode + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallNotOpened" + sendData(state: mapData) + } + public func deepWallPaywallClosed(_ model: DeepWallPaywallClosedInfoModel) -> Void { + print("event:deepWallPaywallClosed"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["pageId"] = model.pageId + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallClosed" + sendData(state: mapData) + } + public func deepWallPaywallActionShowDisabled(_ model: DeepWallPaywallActionShowDisabledInfoModel) -> Void { + print("event:deepWallPaywallActionShowDisabled"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["pageId"] = model.pageId + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallActionShowDisabled" + sendData(state: mapData) + } + public func deepWallPaywallResponseFailure(_ model: DeepWallPaywallResponseFailedModel) -> Void { + print("event:deepWallPaywallResponseFailure"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["errorCode"] = model.errorCode + modelMap["reason"] = model.reason + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallResponseFailure" + sendData(state: mapData) + } + public func deepWallPaywallPurchasingProduct(_ model: DeepWallPaywallPurchasingProduct) -> Void { + print("event:deepWallPaywallPurchasingProduct"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["productCode"] = model.productCode + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallPurchasingProduct" + sendData(state: mapData) + } + public func deepWallPaywallPurchaseSuccess(_ model: DeepWallValidateReceiptResult) -> Void { + print("event:deepWallPaywallPurchaseSuccess"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["type"] = model.type.rawValue + modelMap["result"] = model.result?.toDictionary() as? [String: Any]; + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallPurchaseSuccess" + sendData(state: mapData) + } + public func deepWallPaywallPurchaseFailed(_ model: DeepWallPurchaseFailedModel) -> Void { + print("event:deepWallPaywallPurchaseFailed"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["productCode"] = model.productCode + modelMap["reason"] = model.reason + modelMap["errorCode"] = model.errorCode + modelMap["isPaymentCancelled"] = model.isPaymentCancelled + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallPurchaseFailed" + sendData(state: mapData) + } + public func deepWallPaywallRestoreSuccess() -> Void { + print("event:deepWallPaywallRestoreSuccess"); + var map = [String: Any]() + map["data"] = "" + map["event"] = "deepWallPaywallRestoreSuccess" + sendData(state: map) + } + public func deepWallPaywallRestoreFailed(_ model: DeepWallRestoreFailedModel) -> Void { + print("event:deepWallPaywallRestoreFailed"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["reason"] = model.reason.rawValue + modelMap["errorCode"] = model.errorCode + modelMap["errorText"] = model.errorText + modelMap["isPaymentCancelled"] = model.isPaymentCancelled + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallRestoreFailed" + sendData(state: mapData) + } + public func deepWallPaywallExtraDataReceived(_ model: [AnyHashable : Any]) -> Void { + print("event:deepWallPaywallExtraDataReceived"); + var mapData = [String: Any]() + var modelMap = [String: Any]() + modelMap["extraData"] = model as? [String: Any] + mapData["data"] = modelMap + mapData["event"] = "deepWallPaywallExtraDataReceived" + sendData(state: mapData) + } + + func sendData(state: Dictionary) { + print(state) + let result = CDVPluginResult(status: CDVCommandStatus_OK, messageAs: state) + self.commandDelegate.send(result, callbackId: self.eventsCallbackCommand?.callbackId) + } + + func convertToDictionary(text: String?) -> [String: Any]? { + if let data = text?.data(using: .utf8) { + do { + return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + } catch { + print(error.localizedDescription) + } + } + return nil + } + +} \ No newline at end of file diff --git a/src/ios/bridging-header.h b/src/ios/bridging-header.h new file mode 100755 index 0000000..48f14cf --- /dev/null +++ b/src/ios/bridging-header.h @@ -0,0 +1 @@ +#import \ No newline at end of file diff --git a/www/DeepwallCordovaPlugin.js b/www/DeepwallCordovaPlugin.js new file mode 100755 index 0000000..51d98ae --- /dev/null +++ b/www/DeepwallCordovaPlugin.js @@ -0,0 +1,58 @@ +var exec = require('cordova/exec'); +var PLUGIN = "DeepwallCordovaPlugin"; + +exports.initialize = function (apiKey, environment, success, error){ + exec(success, error, PLUGIN, 'initialize', [apiKey, environment]); +}; + +exports.observeEvents = function(success, error){ + exec(success, error, PLUGIN, 'observeEvents', []); +}; + +exports.setUserProperties = function(uuid, country, language, environmentStyle = EnvironmentStyle.LIGHT, success, error){ + if (uuid.isEmpty) { + throw new DeepwallException(ErrorCodes.USER_PROPERTIES_COUNTRY_REQUIRED); + } + if (country.isEmpty) { + throw new DeepwallException(ErrorCodes.USER_PROPERTIES_COUNTRY_REQUIRED); + } + if (language.isEmpty) { + throw new DeepwallException(ErrorCodes.USER_PROPERTIES_LANGUAGE_REQUIRED); + } + exec(success, error, PLUGIN, 'setUserProperties', [uuid, country, language, environmentStyle]); +}; + +exports.requestPaywall = function(actionKey, extraData = {}, success, error){ + exec(success, error, PLUGIN, 'requestPaywall', [actionKey, JSON.stringify(extraData)]); +}; + +exports.updateUserProperties = function(country, language, environmentStyle = EnvironmentStyle.LIGHT, debugAdvertiseAttributions = null, success, error){ + exec(success, error, PLUGIN, 'updateUserProperties', [country, language, environmentStyle, debugAdvertiseAttributions]); +}; + +exports.closePaywall = function(success, error){ + exec(success, error, PLUGIN, 'closePaywall', []); +}; + +exports.hidePaywallLoadingIndicator = function(success, error){ + exec(success, error, PLUGIN, 'hidePaywallLoadingIndicator',[]); +}; + +exports.validateReceipt = function(validationType, success, error){ + if (!Object.values(ValidateReceiptTypes).includes(validationType)) { + throw new DeepWallException(ErrorCodes.VALIDATE_RECEIPT_TYPE_NOT_VALID); + } + exec(success, error, PLUGIN, 'validateReceipt', [validationType]); +}; + +exports.consumeProduct = function(productId, success, error){ + exec(success, error, PLUGIN, 'consumeProduct', [productId]); +}; + +exports.setProductUpgradePolicy = function(prorationType, upgradePolicy, success, error){ + exec(success, error, PLUGIN, 'setProductUpgradePolicy', [prorationType, upgradePolicy]); +}; + +exports.updateProductUpgradePolicy = function(prorationType, upgradePolicy, success, error){ + exec(success, error, PLUGIN, 'updateProductUpgradePolicy', [prorationType, upgradePolicy]); +}; \ No newline at end of file diff --git a/www/enums/DeepwallException.js b/www/enums/DeepwallException.js new file mode 100755 index 0000000..56f5ab0 --- /dev/null +++ b/www/enums/DeepwallException.js @@ -0,0 +1,14 @@ +/** + * Custom Exception + */ +exports.DeepwallException = class extends Error { + constructor(error, meta) { + super(error.message); + + this.code = error.code; + + if (meta) { + this.meta = meta; + } + } +} diff --git a/www/enums/EnvironmentStyles.js b/www/enums/EnvironmentStyles.js new file mode 100755 index 0000000..a31c164 --- /dev/null +++ b/www/enums/EnvironmentStyles.js @@ -0,0 +1,6 @@ +/** + * EnvironmentStyles + */ +exports.AUTOMATIC = -7; +exports.LIGHT = 0; +exports.DARK = 1; diff --git a/www/enums/Environments.js b/www/enums/Environments.js new file mode 100755 index 0000000..1161776 --- /dev/null +++ b/www/enums/Environments.js @@ -0,0 +1,5 @@ +/** + * Environments + */ +exports.SANDBOX = 1; +exports.PRODUCTION = 2; diff --git a/www/enums/ErrorCodes.js b/www/enums/ErrorCodes.js new file mode 100755 index 0000000..a2197b2 --- /dev/null +++ b/www/enums/ErrorCodes.js @@ -0,0 +1,27 @@ +/** + * ErrorCodes + */ +exports.NATIVE_MODULE_NOT_FOUND = { + code: 101, + message: 'Native module "RNDeepWall" not found.', +}; +exports.NATIVE_MODULE_EVENT_EMITTER_NOT_FOUND = { + code: 121, + message: 'Native module "RNDeepWallEmitter" not found.', +}; +exports.USER_PROPERTIES_UUID_REQUIRED = { + code: 801, + message: 'Missing parameter "uuid" for UserProperties.', +}; +exports.USER_PROPERTIES_COUNTRY_REQUIRED = { + code: 802, + message: 'Missing parameter "country" for UserProperties.', +}; +exports.USER_PROPERTIES_LANGUAGE_REQUIRED = { + code: 803, + message: 'Missing parameter "language" for UserProperties.', +}; +exports.VALIDATE_RECEIPT_TYPE_NOT_VALID = { + code: 902, + message: 'Validate receipt type is not valid.', +}; diff --git a/www/enums/Events.js b/www/enums/Events.js new file mode 100755 index 0000000..a42be72 --- /dev/null +++ b/www/enums/Events.js @@ -0,0 +1,18 @@ +/** + * Events + */ +exports.PAYWALL_REQUESTED = 'deepWallPaywallRequested'; +exports.PAYWALL_RESPONSE_RECEIVED= 'deepWallPaywallResponseReceived'; +exports.PAYWALL_RESPONSE_FAILURE= 'deepWallPaywallResponseFailure'; +exports.PAYWALL_OPENED= 'deepWallPaywallOpened'; +exports.PAYWALL_NOT_OPENED= 'deepWallPaywallNotOpened'; +exports.PAYWALL_ACTION_SHOW_DISABLED= 'deepWallPaywallActionShowDisabled'; +exports.PAYWALL_CLOSED= 'deepWallPaywallClosed'; +exports.PAYWALL_EXTRA_DATA_RECEIVED= 'deepWallPaywallExtraDataReceived'; +exports.PAYWALL_PURCHASING_PRODUCT= 'deepWallPaywallPurchasingProduct'; +exports.PAYWALL_PURCHASE_SUCCESS= 'deepWallPaywallPurchaseSuccess'; +exports.PAYWALL_PURCHASE_FAILED= 'deepWallPaywallPurchaseFailed'; +exports.PAYWALL_RESTORE_SUCCESS= 'deepWallPaywallRestoreSuccess'; +exports.PAYWALL_RESTORE_FAILED= 'deepWallPaywallRestoreFailed'; +exports.PAYWALL_CONSUME_SUCCESS= 'deepWallPaywallConsumeSuccess'; +exports.PAYWALL_CONSUME_FAILURE= 'deepWallPaywallConsumeFailure'; diff --git a/www/enums/ProrationTypes.js b/www/enums/ProrationTypes.js new file mode 100755 index 0000000..79b768e --- /dev/null +++ b/www/enums/ProrationTypes.js @@ -0,0 +1,7 @@ +exports.NONE = 5; +exports.DEFERRED= 4; +exports.IMMEDIATE_AND_CHARGE_PRORATED_PRICE= 2; +exports.IMMEDIATE_WITHOUT_PRORATION= 3; +exports.IMMEDIATE_WITH_TIME_PRORATION= 1; +exports.UNKNOWN_SUBSCRIPTION_UPGRADE_DOWNGRADE_POLICY= 0; + diff --git a/www/enums/PurchaseUpgradePolicy.js b/www/enums/PurchaseUpgradePolicy.js new file mode 100755 index 0000000..cbd06ae --- /dev/null +++ b/www/enums/PurchaseUpgradePolicy.js @@ -0,0 +1,4 @@ +exports.DISABLE_ALL_POLICIES= 0; +exports.ENABLE_ALL_POLICIES= 1; +exports.ENABLE_ONLY_UPGRADE= 2; +exports.ENABLE_ONLY_DOWNGRADE= 3; diff --git a/www/enums/ValidateReceiptTypes.js b/www/enums/ValidateReceiptTypes.js new file mode 100755 index 0000000..b04d3f0 --- /dev/null +++ b/www/enums/ValidateReceiptTypes.js @@ -0,0 +1,6 @@ +/** + * ValidateReceiptTypes + */ +exports.PURCHASE = 1; +exports.RESTORE = 2; +exports.AUTOMATIC = 3;