diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 4d5d7029cb..3872d6ca05 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -1911,16 +1911,16 @@ public: err += etc_error; } - // The GodotPaymentV3 module was converted to the GodotPayment plugin in Godot 3.2.2, + // The GodotPaymentV3 module was converted to the external GodotGooglePlayBilling plugin in Godot 3.2.2, // this check helps users to notice the change to ensure that they change their settings. String modules = ProjectSettings::get_singleton()->get("android/modules"); if (modules.find("org/godotengine/godot/GodotPaymentV3") != -1) { - bool godot_payment_enabled = p_preset->get("plugins/" + GODOT_PAYMENT.name); - if (!godot_payment_enabled) { + bool godot_google_play_billing_enabled = p_preset->get("plugins/GodotGooglePlayBilling"); + if (!godot_google_play_billing_enabled) { valid = false; err += TTR("Invalid \"GodotPaymentV3\" module included in the \"android/modules\" project setting (changed in Godot 3.2.2).\n" - "Replace it by the \"GodotPayment\" plugin, which should be enabled in the \"Plugins\" preset section.\n" - "Note that the singleton was also renamed from \"GodotPayments\" to \"GodotPayment\"."); + "Replace it with the first-party \"GodotGooglePlayBilling\" plugin.\n" + "Note that the singleton was also renamed from \"GodotPayments\" to \"GodotGooglePlayBilling\"."); err += "\n"; } } diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index 80c6be0fae..821a4dc584 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -97,13 +97,6 @@ task copyReleaseAARToAppModule(type: Copy) { include('godot-lib.release.aar') } -task copyGodotPaymentPluginToAppModule(type: Copy) { - dependsOn ':plugins:godotpayment:assembleRelease' - from('plugins/godotpayment/build/outputs/aar') - into('app/libs/plugins') - include('GodotPayment.release.aar') -} - /** * Copy the Godot android library archive release file into the root bin directory. * Depends on the library build task to ensure the AAR file is generated prior to copying. @@ -161,7 +154,6 @@ task generateGodotTemplates(type: GradleBuild) { } } - dependsOn 'copyGodotPaymentPluginToAppModule' finalizedBy 'zipCustomBuild' } diff --git a/platform/android/java/plugins/.gitkeep b/platform/android/java/plugins/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/platform/android/java/plugins/godotpayment/build.gradle b/platform/android/java/plugins/godotpayment/build.gradle deleted file mode 100644 index fb3aa8bba2..0000000000 --- a/platform/android/java/plugins/godotpayment/build.gradle +++ /dev/null @@ -1,32 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion versions.compileSdk - buildToolsVersion versions.buildTools - - defaultConfig { - minSdkVersion versions.minSdk - targetSdkVersion versions.targetSdk - } - - libraryVariants.all { variant -> - variant.outputs.all { output -> - output.outputFileName = "GodotPayment.${variant.name}.aar" - } - } - -} - -dependencies { - implementation libraries.supportCoreUtils - implementation libraries.v4Support - implementation 'com.android.billingclient:billing:2.2.1' - - if (rootProject.findProject(":lib")) { - compileOnly project(":lib") - } else if (rootProject.findProject(":godot:lib")) { - compileOnly project(":godot:lib") - } else { - compileOnly fileTree(dir: 'libs', include: ['godot-lib*.aar']) - } -} diff --git a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml b/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml deleted file mode 100644 index 61afa03799..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/AndroidManifest.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java deleted file mode 100644 index 016ea3715a..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/GodotPayment.java +++ /dev/null @@ -1,240 +0,0 @@ -/*************************************************************************/ -/* GodotPayment.java */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ - -package org.godotengine.godot.plugin.payment; - -import org.godotengine.godot.Dictionary; -import org.godotengine.godot.Godot; -import org.godotengine.godot.plugin.GodotPlugin; -import org.godotengine.godot.plugin.SignalInfo; -import org.godotengine.godot.plugin.payment.utils.GodotPaymentUtils; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.collection.ArraySet; - -import com.android.billingclient.api.AcknowledgePurchaseParams; -import com.android.billingclient.api.AcknowledgePurchaseResponseListener; -import com.android.billingclient.api.BillingClient; -import com.android.billingclient.api.BillingClientStateListener; -import com.android.billingclient.api.BillingFlowParams; -import com.android.billingclient.api.BillingResult; -import com.android.billingclient.api.ConsumeParams; -import com.android.billingclient.api.ConsumeResponseListener; -import com.android.billingclient.api.Purchase; -import com.android.billingclient.api.PurchasesUpdatedListener; -import com.android.billingclient.api.SkuDetails; -import com.android.billingclient.api.SkuDetailsParams; -import com.android.billingclient.api.SkuDetailsResponseListener; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Set; - -public class GodotPayment extends GodotPlugin implements PurchasesUpdatedListener, BillingClientStateListener { - - private final BillingClient billingClient; - private final HashMap skuDetailsCache = new HashMap<>(); // sku → SkuDetails - - public GodotPayment(Godot godot) { - super(godot); - - billingClient = BillingClient - .newBuilder(getActivity()) - .enablePendingPurchases() - .setListener(this) - .build(); - } - - public void startConnection() { - billingClient.startConnection(this); - } - - public void endConnection() { - billingClient.endConnection(); - } - - public boolean isReady() { - return this.billingClient.isReady(); - } - - public Dictionary queryPurchases(String type) { - Purchase.PurchasesResult result = billingClient.queryPurchases(type); - - Dictionary returnValue = new Dictionary(); - if (result.getBillingResult().getResponseCode() == BillingClient.BillingResponseCode.OK) { - returnValue.put("status", 0); // OK = 0 - returnValue.put("purchases", GodotPaymentUtils.convertPurchaseListToDictionaryObjectArray(result.getPurchasesList())); - } else { - returnValue.put("status", 1); // FAILED = 1 - returnValue.put("response_code", result.getBillingResult().getResponseCode()); - returnValue.put("debug_message", result.getBillingResult().getDebugMessage()); - } - - return returnValue; - } - - public void querySkuDetails(final String[] list, String type) { - List skuList = Arrays.asList(list); - - SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder() - .setSkusList(skuList) - .setType(type); - - billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { - @Override - public void onSkuDetailsResponse(BillingResult billingResult, - List skuDetailsList) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - for (SkuDetails skuDetails : skuDetailsList) { - skuDetailsCache.put(skuDetails.getSku(), skuDetails); - } - emitSignal("sku_details_query_completed", (Object)GodotPaymentUtils.convertSkuDetailsListToDictionaryObjectArray(skuDetailsList)); - } else { - emitSignal("sku_details_query_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), list); - } - } - }); - } - - public void acknowledgePurchase(final String purchaseToken) { - AcknowledgePurchaseParams acknowledgePurchaseParams = - AcknowledgePurchaseParams.newBuilder() - .setPurchaseToken(purchaseToken) - .build(); - billingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() { - @Override - public void onAcknowledgePurchaseResponse(BillingResult billingResult) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("purchase_acknowledged", purchaseToken); - } else { - emitSignal("purchase_acknowledgement_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), purchaseToken); - } - } - }); - } - - public void consumePurchase(String purchaseToken) { - ConsumeParams consumeParams = ConsumeParams.newBuilder() - .setPurchaseToken(purchaseToken) - .build(); - - billingClient.consumeAsync(consumeParams, new ConsumeResponseListener() { - @Override - public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("purchase_consumed", purchaseToken); - } else { - emitSignal("purchase_consumption_error", billingResult.getResponseCode(), billingResult.getDebugMessage(), purchaseToken); - } - } - }); - } - - @Override - public void onBillingSetupFinished(BillingResult billingResult) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { - emitSignal("connected"); - } else { - emitSignal("connect_error", billingResult.getResponseCode(), billingResult.getDebugMessage()); - } - } - - @Override - public void onBillingServiceDisconnected() { - emitSignal("disconnected"); - } - - public Dictionary purchase(String sku) { - if (!skuDetailsCache.containsKey(sku)) { - emitSignal("purchase_error", null, "You must query the sku details and wait for the result before purchasing!"); - } - - SkuDetails skuDetails = skuDetailsCache.get(sku); - BillingFlowParams purchaseParams = BillingFlowParams.newBuilder() - .setSkuDetails(skuDetails) - .build(); - - BillingResult result = billingClient.launchBillingFlow(getActivity(), purchaseParams); - - Dictionary returnValue = new Dictionary(); - if (result.getResponseCode() == BillingClient.BillingResponseCode.OK) { - returnValue.put("status", 0); // OK = 0 - } else { - returnValue.put("status", 1); // FAILED = 1 - returnValue.put("response_code", result.getResponseCode()); - returnValue.put("debug_message", result.getDebugMessage()); - } - - return returnValue; - } - - @Override - public void onPurchasesUpdated(final BillingResult billingResult, @Nullable final List list) { - if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) { - emitSignal("purchases_updated", (Object)GodotPaymentUtils.convertPurchaseListToDictionaryObjectArray(list)); - } else { - emitSignal("purchase_error", billingResult.getResponseCode(), billingResult.getDebugMessage()); - } - } - - @NonNull - @Override - public String getPluginName() { - return "GodotPayment"; - } - - @NonNull - @Override - public List getPluginMethods() { - return Arrays.asList("startConnection", "endConnection", "purchase", "querySkuDetails", "isReady", "queryPurchases", "acknowledgePurchase", "consumePurchase"); - } - - @NonNull - @Override - public Set getPluginSignals() { - Set signals = new ArraySet<>(); - - signals.add(new SignalInfo("connected")); - signals.add(new SignalInfo("disconnected")); - signals.add(new SignalInfo("connect_error", Integer.class, String.class)); - signals.add(new SignalInfo("purchases_updated", Object[].class)); - signals.add(new SignalInfo("purchase_error", Integer.class, String.class)); - signals.add(new SignalInfo("sku_details_query_completed", Object[].class)); - signals.add(new SignalInfo("sku_details_query_error", Integer.class, String.class, String[].class)); - signals.add(new SignalInfo("purchase_acknowledged", String.class)); - signals.add(new SignalInfo("purchase_acknowledgement_error", Integer.class, String.class, String.class)); - signals.add(new SignalInfo("purchase_consumed", String.class)); - signals.add(new SignalInfo("purchase_consumption_error", Integer.class, String.class, String.class)); - - return signals; - } -} diff --git a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java b/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java deleted file mode 100644 index f569c1b8bf..0000000000 --- a/platform/android/java/plugins/godotpayment/src/main/java/org/godotengine/godot/plugin/payment/utils/GodotPaymentUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.godotengine.godot.plugin.payment.utils; - -import org.godotengine.godot.Dictionary; - -import com.android.billingclient.api.Purchase; -import com.android.billingclient.api.SkuDetails; - -import java.util.List; - -public class GodotPaymentUtils { - public static Dictionary convertPurchaseToDictionary(Purchase purchase) { - Dictionary dictionary = new Dictionary(); - dictionary.put("order_id", purchase.getOrderId()); - dictionary.put("package_name", purchase.getPackageName()); - dictionary.put("purchase_state", Integer.valueOf(purchase.getPurchaseState())); - dictionary.put("purchase_time", Long.valueOf(purchase.getPurchaseTime())); - dictionary.put("purchase_token", purchase.getPurchaseToken()); - dictionary.put("signature", purchase.getSignature()); - dictionary.put("sku", purchase.getSku()); - dictionary.put("is_acknowledged", Boolean.valueOf(purchase.isAcknowledged())); - dictionary.put("is_auto_renewing", Boolean.valueOf(purchase.isAutoRenewing())); - return dictionary; - } - - public static Dictionary convertSkuDetailsToDictionary(SkuDetails details) { - Dictionary dictionary = new Dictionary(); - dictionary.put("sku", details.getSku()); - dictionary.put("title", details.getTitle()); - dictionary.put("description", details.getDescription()); - dictionary.put("price", details.getPrice()); - dictionary.put("price_currency_code", details.getPriceCurrencyCode()); - dictionary.put("price_amount_micros", Long.valueOf(details.getPriceAmountMicros())); - dictionary.put("free_trial_period", details.getFreeTrialPeriod()); - dictionary.put("icon_url", details.getIconUrl()); - dictionary.put("introductory_price", details.getIntroductoryPrice()); - dictionary.put("introductory_price_amount_micros", Long.valueOf(details.getIntroductoryPriceAmountMicros())); - dictionary.put("introductory_price_cycles", details.getIntroductoryPriceCycles()); - dictionary.put("introductory_price_period", details.getIntroductoryPricePeriod()); - dictionary.put("original_price", details.getOriginalPrice()); - dictionary.put("original_price_amount_micros", Long.valueOf(details.getOriginalPriceAmountMicros())); - dictionary.put("subscription_period", details.getSubscriptionPeriod()); - dictionary.put("type", details.getType()); - dictionary.put("is_rewarded", Boolean.valueOf(details.isRewarded())); - return dictionary; - } - - public static Object[] convertPurchaseListToDictionaryObjectArray(List purchases) { - Object[] purchaseDictionaries = new Object[purchases.size()]; - - for (int i = 0; i < purchases.size(); i++) { - purchaseDictionaries[i] = GodotPaymentUtils.convertPurchaseToDictionary(purchases.get(i)); - } - - return purchaseDictionaries; - } - - public static Object[] convertSkuDetailsListToDictionaryObjectArray(List skuDetails) { - Object[] skuDetailsDictionaries = new Object[skuDetails.size()]; - - for (int i = 0; i < skuDetails.size(); i++) { - skuDetailsDictionaries[i] = GodotPaymentUtils.convertSkuDetailsToDictionary(skuDetails.get(i)); - } - - return skuDetailsDictionaries; - } -} diff --git a/platform/android/plugin/godot_plugin_config.h b/platform/android/plugin/godot_plugin_config.h index 5bc0fc3a58..ea3c7b4f55 100644 --- a/platform/android/plugin/godot_plugin_config.h +++ b/platform/android/plugin/godot_plugin_config.h @@ -86,17 +86,18 @@ struct PluginConfig { /* * Set of prebuilt plugins. + * Currently unused, this is just for future reference: */ -static const PluginConfig GODOT_PAYMENT = { - /*.valid_config =*/true, - /*.last_updated =*/0, - /*.name =*/"GodotPayment", - /*.binary_type =*/"local", - /*.binary =*/"res://android/build/libs/plugins/GodotPayment.release.aar", - /*.local_dependencies =*/{}, - /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), - /*.custom_maven_repos =*/{} -}; +// static const PluginConfig MY_PREBUILT_PLUGIN = { +// /*.valid_config =*/true, +// /*.last_updated =*/0, +// /*.name =*/"GodotPayment", +// /*.binary_type =*/"local", +// /*.binary =*/"res://android/build/libs/plugins/GodotPayment.release.aar", +// /*.local_dependencies =*/{}, +// /*.remote_dependencies =*/String("com.android.billingclient:billing:2.2.1").split("|"), +// /*.custom_maven_repos =*/{} +// }; static inline String resolve_local_dependency_path(String plugin_config_dir, String dependency_path) { String absolute_path; @@ -125,7 +126,7 @@ static inline PluginConfig resolve_prebuilt_plugin(PluginConfig prebuilt_plugin, static inline Vector get_prebuilt_plugins(String plugins_base_dir) { Vector prebuilt_plugins; - prebuilt_plugins.push_back(resolve_prebuilt_plugin(GODOT_PAYMENT, plugins_base_dir)); + // prebuilt_plugins.push_back(resolve_prebuilt_plugin(MY_PREBUILT_PLUGIN, plugins_base_dir)); return prebuilt_plugins; }