diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.java deleted file mode 100644 index 4f6e5a3fe..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.getcapacitor.community.stripe; - -import android.content.ContentResolver; -import android.content.res.Resources; -import android.net.Uri; -import com.getcapacitor.Logger; -import com.getcapacitor.NativePlugin; -import com.getcapacitor.Plugin; -import com.getcapacitor.PluginCall; -import com.getcapacitor.PluginMethod; -import com.getcapacitor.community.stripe.googlepay.GooglePayExecutor; -import com.getcapacitor.community.stripe.helper.MetaData; -import com.getcapacitor.community.stripe.paymentflow.PaymentFlowExecutor; -import com.getcapacitor.community.stripe.paymentsheet.PaymentSheetExecutor; -import com.stripe.android.PaymentConfiguration; -import com.stripe.android.Stripe; -import com.stripe.android.core.AppInfo; -import com.stripe.android.googlepaylauncher.GooglePayLauncher; -import com.stripe.android.paymentsheet.PaymentSheet; -import java.util.Objects; -import org.jetbrains.annotations.NotNull; - -@NativePlugin(name = "Stripe", requestCodes = { 9972, 50000, 50001, 6000 }) -public class StripePlugin extends Plugin { - - private String publishableKey; - private String paymentSheetCallbackId; - private String paymentFlowCallbackId; - private String googlePayCallbackId; - - private String identityVerificationCallbackId; - - private MetaData metaData; - - private static final String APP_INFO_NAME = "@capacitor-community/stripe"; - - private final PaymentSheetExecutor paymentSheetExecutor = new PaymentSheetExecutor( - this::getContext, - this::getActivity, - this::notifyListeners, - getLogTag() - ); - - private final PaymentFlowExecutor paymentFlowExecutor = new PaymentFlowExecutor( - this::getContext, - this::getActivity, - this::notifyListeners, - getLogTag() - ); - - private final GooglePayExecutor googlePayExecutor = new GooglePayExecutor( - this::getContext, - this::getActivity, - this::notifyListeners, - getLogTag() - ); - - @Override - public void load() { - metaData = new MetaData(this::getContext); - if (metaData.enableGooglePay) { - this.publishableKey = metaData.publishableKey; - - PaymentConfiguration.init(getContext(), metaData.publishableKey, metaData.stripeAccount); - Stripe.setAppInfo(AppInfo.create(APP_INFO_NAME)); - - this.googlePayExecutor.googlePayLauncher = new GooglePayLauncher( - getActivity(), - new GooglePayLauncher.Config( - metaData.googlePayEnvironment, - metaData.countryCode, - metaData.displayName, - metaData.emailAddressRequired, - new GooglePayLauncher.BillingAddressConfig( - metaData.billingAddressRequired, - Objects.equals(metaData.billingAddressFormat, "Full") - ? GooglePayLauncher.BillingAddressConfig.Format.Full - : GooglePayLauncher.BillingAddressConfig.Format.Min, - metaData.phoneNumberRequired - ), - metaData.existingPaymentMethodRequired - ), - (boolean isReady) -> this.googlePayExecutor.isAvailable = isReady, - (@NotNull GooglePayLauncher.Result result) -> this.googlePayExecutor.onGooglePayResult(bridge, googlePayCallbackId, result) - ); - } else { - Logger.info("Plugin didn't prepare Google Pay."); - } - - this.paymentSheetExecutor.paymentSheet = new PaymentSheet(getActivity(), result -> { - this.paymentSheetExecutor.onPaymentSheetResult(bridge, paymentSheetCallbackId, result); - }); - - this.paymentFlowExecutor.flowController = PaymentSheet.FlowController.create( - getActivity(), - paymentOption -> { - this.paymentFlowExecutor.onPaymentOption(bridge, paymentFlowCallbackId, paymentOption); - }, - result -> { - this.paymentFlowExecutor.onPaymentFlowResult(bridge, paymentFlowCallbackId, result); - } - ); - - if (metaData.enableIdentifier) { - Resources resources = getActivity().getApplicationContext().getResources(); - int resourceId = resources.getIdentifier("ic_launcher", "mipmap", getActivity().getPackageName()); - Uri icon = new Uri.Builder() - .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - .authority(resources.getResourcePackageName(resourceId)) - .appendPath(resources.getResourceTypeName(resourceId)) - .appendPath(resources.getResourceEntryName(resourceId)) - .build(); - } - } - - @PluginMethod - public void initialize(final PluginCall call) { - try { - publishableKey = call.getString("publishableKey"); - - if (publishableKey == null || publishableKey.equals("")) { - call.reject("you must provide a valid key"); - return; - } - - String stripeAccountId = call.getString("stripeAccount", null); - - PaymentConfiguration.init(getContext(), publishableKey, stripeAccountId); - Stripe.setAppInfo(AppInfo.create(APP_INFO_NAME)); - call.resolve(); - } catch (Exception e) { - call.reject("unable to set publishable key: " + e.getLocalizedMessage(), e); - } - } - - @PluginMethod - public void createPaymentSheet(final PluginCall call) { - paymentSheetExecutor.createPaymentSheet(call); - } - - @PluginMethod - public void presentPaymentSheet(final PluginCall call) { - paymentSheetCallbackId = call.getCallbackId(); - bridge.saveCall(call); - - paymentSheetExecutor.presentPaymentSheet(call); - } - - @PluginMethod - public void createPaymentFlow(final PluginCall call) { - paymentFlowExecutor.createPaymentFlow(call); - } - - @PluginMethod - public void presentPaymentFlow(final PluginCall call) { - paymentFlowCallbackId = call.getCallbackId(); - bridge.saveCall(call); - - paymentFlowExecutor.presentPaymentFlow(call); - } - - @PluginMethod - public void confirmPaymentFlow(final PluginCall call) { - paymentFlowCallbackId = call.getCallbackId(); - bridge.saveCall(call); - - paymentFlowExecutor.confirmPaymentFlow(call); - } - - @PluginMethod - public void isApplePayAvailable(final PluginCall call) { - call.unimplemented("Not implemented on Android."); - } - - @PluginMethod - public void createApplePay(final PluginCall call) { - call.unimplemented("Not implemented on Android."); - } - - @PluginMethod - public void presentApplePay(final PluginCall call) { - call.unimplemented("Not implemented on Android."); - } - - @PluginMethod - public void isGooglePayAvailable(final PluginCall call) { - googlePayExecutor.isGooglePayAvailable(call); - } - - @PluginMethod - public void createGooglePay(final PluginCall call) { - googlePayExecutor.createGooglePay(call); - } - - @PluginMethod - public void presentGooglePay(final PluginCall call) { - googlePayCallbackId = call.getCallbackId(); - bridge.saveCall(call); - - googlePayExecutor.presentGooglePay(call); - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.kt new file mode 100644 index 000000000..d4f939ff1 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/StripePlugin.kt @@ -0,0 +1,213 @@ +package com.getcapacitor.community.stripe + +import android.content.ContentResolver +import android.net.Uri +import com.getcapacitor.JSObject +import com.getcapacitor.Logger +import com.getcapacitor.NativePlugin +import com.getcapacitor.Plugin +import com.getcapacitor.PluginCall +import com.getcapacitor.PluginMethod +import com.getcapacitor.community.stripe.googlepay.GooglePayExecutor +import com.getcapacitor.community.stripe.helper.MetaData +import com.getcapacitor.community.stripe.paymentflow.PaymentFlowExecutor +import com.getcapacitor.community.stripe.paymentsheet.PaymentSheetExecutor +import com.stripe.android.PaymentConfiguration +import com.stripe.android.Stripe +import com.stripe.android.core.AppInfo; +import com.stripe.android.googlepaylauncher.GooglePayLauncher +import com.stripe.android.paymentsheet.PaymentOptionCallback +import com.stripe.android.paymentsheet.PaymentSheet +import com.stripe.android.paymentsheet.PaymentSheetResult +import com.stripe.android.paymentsheet.PaymentSheetResultCallback +import com.stripe.android.paymentsheet.model.PaymentOption + +@NativePlugin(name = "Stripe", requestCodes = [9972, 50000, 50001, 6000]) +class StripePlugin : Plugin() { + private var publishableKey: String? = null + private var paymentSheetCallbackId: String? = null + private var paymentFlowCallbackId: String? = null + private var googlePayCallbackId: String? = null + + private val identityVerificationCallbackId: String? = null + + private var metaData: MetaData? = null + + private val paymentSheetExecutor = PaymentSheetExecutor( + { this.context }, + { this.activity }, + { eventName: String?, data: JSObject? -> this.notifyListeners(eventName, data) }, + logTag + ) + + private val paymentFlowExecutor = PaymentFlowExecutor( + { this.context }, + { this.activity }, + { eventName: String?, data: JSObject? -> this.notifyListeners(eventName, data) }, + logTag + ) + + private val googlePayExecutor = GooglePayExecutor( + { this.context }, + { this.activity }, + { eventName: String?, data: JSObject? -> this.notifyListeners(eventName, data) }, + logTag + ) + + override fun load() { + metaData = MetaData { this.context } + if (metaData!!.enableGooglePay) { + this.publishableKey = metaData!!.publishableKey + + PaymentConfiguration.init( + context, + metaData!!.publishableKey!!, + metaData!!.stripeAccount + ) + +// Stripe.appInfo(AppInfo.create(APP_INFO_NAME)) + + googlePayExecutor.googlePayLauncher = GooglePayLauncher( + activity, + GooglePayLauncher.Config( + metaData!!.googlePayEnvironment!!, + metaData!!.countryCode!!, + metaData!!.displayName!!, + metaData!!.emailAddressRequired!!, + GooglePayLauncher.BillingAddressConfig( + metaData!!.billingAddressRequired!!, + if (metaData!!.billingAddressFormat == "Full") GooglePayLauncher.BillingAddressConfig.Format.Full else GooglePayLauncher.BillingAddressConfig.Format.Min, + metaData!!.phoneNumberRequired!! + ), + metaData!!.existingPaymentMethodRequired!! + ), + { isReady: Boolean -> googlePayExecutor.isAvailable = isReady }, + { result: GooglePayLauncher.Result -> + googlePayExecutor.onGooglePayResult( + bridge, + googlePayCallbackId, + result + ) + } + ) + } else { + Logger.info("Plugin didn't prepare Google Pay.") + } + + paymentSheetExecutor.paymentSheet = PaymentSheet(activity) { result: PaymentSheetResult -> + paymentSheetExecutor.onPaymentSheetResult(bridge, paymentSheetCallbackId, result) + } + + paymentFlowExecutor.flowController = PaymentSheet.FlowController.create( + activity, + PaymentOptionCallback { paymentOption: PaymentOption? -> + paymentFlowExecutor.onPaymentOption(bridge, paymentFlowCallbackId, paymentOption) + }, + PaymentSheetResultCallback { result: PaymentSheetResult -> + paymentFlowExecutor.onPaymentFlowResult(bridge, paymentFlowCallbackId, result) + } + ) + + if (metaData!!.enableIdentifier) { + val resources = activity.applicationContext.resources + val resourceId = resources.getIdentifier("ic_launcher", "mipmap", activity.packageName) + val icon = Uri.Builder() + .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) + .authority(resources.getResourcePackageName(resourceId)) + .appendPath(resources.getResourceTypeName(resourceId)) + .appendPath(resources.getResourceEntryName(resourceId)) + .build() + } + } + + @PluginMethod + fun initialize(call: PluginCall) { + try { + publishableKey = call.getString("publishableKey") + + if (publishableKey == null || publishableKey == "") { + call.reject("you must provide a valid key") + return + } + + val stripeAccountId = call.getString("stripeAccount", null) + + PaymentConfiguration.init(context, publishableKey!!, stripeAccountId) +// setAppInfo.setAppInfo(AppInfo.create(APP_INFO_NAME)) + call.resolve() + } catch (e: Exception) { + call.reject("unable to set publishable key: " + e.localizedMessage, e) + } + } + + @PluginMethod + fun createPaymentSheet(call: PluginCall) { + paymentSheetExecutor.createPaymentSheet(call) + } + + @PluginMethod + fun presentPaymentSheet(call: PluginCall) { + paymentSheetCallbackId = call.callbackId + bridge.saveCall(call) + + paymentSheetExecutor.presentPaymentSheet(call) + } + + @PluginMethod + fun createPaymentFlow(call: PluginCall) { + paymentFlowExecutor.createPaymentFlow(call) + } + + @PluginMethod + fun presentPaymentFlow(call: PluginCall) { + paymentFlowCallbackId = call.callbackId + bridge.saveCall(call) + + paymentFlowExecutor.presentPaymentFlow(call) + } + + @PluginMethod + fun confirmPaymentFlow(call: PluginCall) { + paymentFlowCallbackId = call.callbackId + bridge.saveCall(call) + + paymentFlowExecutor.confirmPaymentFlow(call) + } + + @PluginMethod + fun isApplePayAvailable(call: PluginCall) { + call.unimplemented("Not implemented on Android.") + } + + @PluginMethod + fun createApplePay(call: PluginCall) { + call.unimplemented("Not implemented on Android.") + } + + @PluginMethod + fun presentApplePay(call: PluginCall) { + call.unimplemented("Not implemented on Android.") + } + + @PluginMethod + fun isGooglePayAvailable(call: PluginCall) { + googlePayExecutor.isGooglePayAvailable(call) + } + + @PluginMethod + fun createGooglePay(call: PluginCall) { + googlePayExecutor.createGooglePay(call) + } + + @PluginMethod + fun presentGooglePay(call: PluginCall) { + googlePayCallbackId = call.callbackId + bridge.saveCall(call) + + googlePayExecutor.presentGooglePay(call) + } + + companion object { + private const val APP_INFO_NAME = "@capacitor-community/stripe" + } +} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.java deleted file mode 100644 index dd360ce66..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.getcapacitor.community.stripe.googlepay; - -import android.app.Activity; -import android.content.Context; -import androidx.core.util.Supplier; -import com.getcapacitor.Bridge; -import com.getcapacitor.JSObject; -import com.getcapacitor.PluginCall; -import com.getcapacitor.community.stripe.models.Executor; -import com.google.android.gms.common.util.BiConsumer; -import com.stripe.android.googlepaylauncher.GooglePayLauncher; -import org.jetbrains.annotations.NotNull; - -public class GooglePayExecutor extends Executor { - - public GooglePayLauncher googlePayLauncher; - private final JSObject emptyObject = new JSObject(); - private String clientSecret; - private String currency; - public boolean isAvailable; - - public GooglePayExecutor( - Supplier contextSupplier, - Supplier activitySupplier, - BiConsumer notifyListenersFunction, - String pluginLogTag - ) { - super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "GooglePayExecutor"); - this.contextSupplier = contextSupplier; - } - - public void isGooglePayAvailable(final PluginCall call) { - if (isAvailable) { - call.resolve(); - } else { - call.unimplemented("Not implemented on Device."); - } - } - - public void createGooglePay(final PluginCall call) { - this.clientSecret = call.getString("paymentIntentClientSecret"); - this.currency = call.getString("currency", "USD"); - - if (this.clientSecret == null) { - String errorText = "Invalid Params. this method require paymentIntentClientSecret or setupIntentClientSecret, and customerId."; - notifyListenersFunction.accept(GooglePayEvents.FailedToLoad.getWebEventName(), new JSObject().put("error", errorText)); - call.reject(errorText); - return; - } - - notifyListenersFunction.accept(GooglePayEvents.Loaded.getWebEventName(), emptyObject); - call.resolve(); - } - - public void presentGooglePay(final PluginCall call) { - if (this.clientSecret != null && this.clientSecret.startsWith("seti_")) { - this.googlePayLauncher.presentForSetupIntent(this.clientSecret, currency); - } else { - this.googlePayLauncher.presentForPaymentIntent(this.clientSecret); - } - } - - public void onGooglePayResult(Bridge bridge, String callbackId, @NotNull GooglePayLauncher.Result result) { - PluginCall call = bridge.getSavedCall(callbackId); - - if (result instanceof GooglePayLauncher.Result.Completed) { - notifyListenersFunction.accept(GooglePayEvents.Completed.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", GooglePayEvents.Completed.getWebEventName())); - } else if (result instanceof GooglePayLauncher.Result.Canceled) { - notifyListenersFunction.accept(GooglePayEvents.Canceled.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", GooglePayEvents.Canceled.getWebEventName())); - } else if (result instanceof GooglePayLauncher.Result.Failed) { - notifyListenersFunction.accept( - GooglePayEvents.Failed.getWebEventName(), - new JSObject().put("error", ((GooglePayLauncher.Result.Failed) result).getError().getLocalizedMessage()) - ); - call.resolve(new JSObject().put("paymentResult", GooglePayEvents.Failed.getWebEventName())); - } - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.kt new file mode 100644 index 000000000..32cced009 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/googlepay/GooglePayExecutor.kt @@ -0,0 +1,87 @@ +package com.getcapacitor.community.stripe.googlepay + +import android.app.Activity +import android.content.Context +import androidx.core.util.Supplier +import com.getcapacitor.Bridge +import com.getcapacitor.JSObject +import com.getcapacitor.PluginCall +import com.getcapacitor.community.stripe.models.Executor +import com.google.android.gms.common.util.BiConsumer +import com.stripe.android.googlepaylauncher.GooglePayLauncher + +class GooglePayExecutor( + contextSupplier: Supplier, + activitySupplier: Supplier, + notifyListenersFunction: BiConsumer, + pluginLogTag: String +) : Executor( + contextSupplier, + activitySupplier, + notifyListenersFunction, + pluginLogTag, + "GooglePayExecutor" +) { + var googlePayLauncher: GooglePayLauncher? = null + private val emptyObject = JSObject() + private var clientSecret: String? = null + private var currency: String? = null + var isAvailable: Boolean = false + + init { + this.contextSupplier = contextSupplier + } + + fun isGooglePayAvailable(call: PluginCall) { + if (isAvailable) { + call.resolve() + } else { + call.unimplemented("Not implemented on Device.") + } + } + + fun createGooglePay(call: PluginCall) { + this.clientSecret = call.getString("paymentIntentClientSecret") + this.currency = call.getString("currency", "USD") + + if (this.clientSecret == null) { + val errorText = + "Invalid Params. this method require paymentIntentClientSecret or setupIntentClientSecret, and customerId." + notifyListenersFunction.accept( + GooglePayEvents.FailedToLoad.webEventName, + JSObject().put("error", errorText) + ) + call.reject(errorText) + return + } + + notifyListenersFunction.accept(GooglePayEvents.Loaded.webEventName, emptyObject) + call.resolve() + } + + fun presentGooglePay(call: PluginCall?) { + if (this.clientSecret != null && clientSecret!!.startsWith("seti_")) { + googlePayLauncher!!.presentForSetupIntent(clientSecret!!, currency!!) + } else { + googlePayLauncher!!.presentForPaymentIntent(clientSecret!!) + } + } + + fun onGooglePayResult(bridge: Bridge, callbackId: String?, result: GooglePayLauncher.Result) { + val call = bridge.getSavedCall(callbackId) + + if (result is GooglePayLauncher.Result.Completed) { + notifyListenersFunction.accept(GooglePayEvents.Completed.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", GooglePayEvents.Completed.webEventName)) + } else if (result is GooglePayLauncher.Result.Canceled) { + notifyListenersFunction.accept(GooglePayEvents.Canceled.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", GooglePayEvents.Canceled.webEventName)) + } else if (result is GooglePayLauncher.Result.Failed) { + notifyListenersFunction.accept( + GooglePayEvents.Failed.webEventName, + JSObject().put("error", (result as GooglePayLauncher.Result.Failed).error.getLocalizedMessage()) + ) + call.resolve(JSObject().put("paymentResult", GooglePayEvents.Failed.webEventName)) + } + } +} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.java deleted file mode 100644 index 008878793..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.getcapacitor.community.stripe.helper; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import androidx.core.util.Supplier; -import com.getcapacitor.Logger; -import com.stripe.android.googlepaylauncher.GooglePayEnvironment; - -public class MetaData { - - protected Supplier contextSupplier; - public boolean enableGooglePay; - public String publishableKey; - public String countryCode; - public String displayName; - public String stripeAccount; - public Boolean emailAddressRequired; - public Boolean phoneNumberRequired; - public Boolean billingAddressRequired; - public String billingAddressFormat; - public GooglePayEnvironment googlePayEnvironment; - - public Boolean existingPaymentMethodRequired; - - public boolean enableIdentifier; - - public MetaData(Supplier contextSupplier) { - this.contextSupplier = contextSupplier; - try { - ApplicationInfo appInfo = contextSupplier - .get() - .getPackageManager() - .getApplicationInfo(contextSupplier.get().getPackageName(), PackageManager.GET_META_DATA); - - enableGooglePay = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.enable_google_pay"); - publishableKey = appInfo.metaData.getString("com.getcapacitor.community.stripe.publishable_key"); - countryCode = appInfo.metaData.getString("com.getcapacitor.community.stripe.country_code"); - displayName = appInfo.metaData.getString("com.getcapacitor.community.stripe.merchant_display_name"); - stripeAccount = appInfo.metaData.getString("com.getcapacitor.community.stripe.stripe_account"); - emailAddressRequired = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.email_address_required"); - phoneNumberRequired = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.phone_number_required"); - billingAddressRequired = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.billing_address_required"); - billingAddressFormat = appInfo.metaData.getString("com.getcapacitor.community.stripe.billing_address_format"); - existingPaymentMethodRequired = appInfo.metaData.getBoolean( - "com.getcapacitor.community.stripe.google_pay_existing_payment_method_required" - ); - - // @deprecated. will remove at v6.0.0 - enableIdentifier = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.enableIdentifier"); - - boolean isTest = appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.google_pay_is_testing"); - if (isTest) { - googlePayEnvironment = GooglePayEnvironment.Test; - } else { - googlePayEnvironment = GooglePayEnvironment.Production; - } - } catch (Exception ignored) { - Logger.info("MetaData didn't be prepare fore Google Pay."); - } - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.kt new file mode 100644 index 000000000..91d5b3be0 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/helper/MetaData.kt @@ -0,0 +1,69 @@ +package com.getcapacitor.community.stripe.helper + +import android.content.Context +import android.content.pm.PackageManager +import androidx.core.util.Supplier +import com.getcapacitor.Logger +import com.stripe.android.googlepaylauncher.GooglePayEnvironment + +class MetaData(protected var contextSupplier: Supplier) { + var enableGooglePay: Boolean = false + var publishableKey: String? = null + var countryCode: String? = null + var displayName: String? = null + var stripeAccount: String? = null + var emailAddressRequired: Boolean? = null + var phoneNumberRequired: Boolean? = null + var billingAddressRequired: Boolean? = null + var billingAddressFormat: String? = null + var googlePayEnvironment: GooglePayEnvironment? = null + + var existingPaymentMethodRequired: Boolean? = null + + var enableIdentifier: Boolean = false + + init { + try { + val appInfo = contextSupplier + .get() + .packageManager + .getApplicationInfo(contextSupplier.get().packageName, PackageManager.GET_META_DATA) + + enableGooglePay = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.enable_google_pay") + publishableKey = + appInfo.metaData.getString("com.getcapacitor.community.stripe.publishable_key") + countryCode = + appInfo.metaData.getString("com.getcapacitor.community.stripe.country_code") + displayName = + appInfo.metaData.getString("com.getcapacitor.community.stripe.merchant_display_name") + stripeAccount = + appInfo.metaData.getString("com.getcapacitor.community.stripe.stripe_account") + emailAddressRequired = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.email_address_required") + phoneNumberRequired = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.phone_number_required") + billingAddressRequired = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.billing_address_required") + billingAddressFormat = + appInfo.metaData.getString("com.getcapacitor.community.stripe.billing_address_format") + existingPaymentMethodRequired = appInfo.metaData.getBoolean( + "com.getcapacitor.community.stripe.google_pay_existing_payment_method_required" + ) + + // @deprecated. will remove at v6.0.0 + enableIdentifier = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.enableIdentifier") + + val isTest = + appInfo.metaData.getBoolean("com.getcapacitor.community.stripe.google_pay_is_testing") + googlePayEnvironment = if (isTest) { + GooglePayEnvironment.Test + } else { + GooglePayEnvironment.Production + } + } catch (ignored: Exception) { + Logger.info("MetaData didn't be prepare fore Google Pay.") + } + } +} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.java deleted file mode 100644 index d35764e01..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.getcapacitor.community.stripe.models; - -import android.app.Activity; -import android.content.Context; -import androidx.core.util.Supplier; -import com.getcapacitor.JSObject; -import com.google.android.gms.common.util.BiConsumer; - -public abstract class Executor { - - protected Supplier contextSupplier; - protected final Supplier activitySupplier; - protected BiConsumer notifyListenersFunction; - protected final String logTag; - - // Eventually we can change the notification directly here! - protected void notifyListeners(String eventName, JSObject data) { - notifyListenersFunction.accept(eventName, data); - } - - public Executor( - Supplier contextSupplier, - Supplier activitySupplier, - BiConsumer notifyListenersFunction, - String pluginLogTag, - String executorTag - ) { - this.contextSupplier = contextSupplier; - this.activitySupplier = activitySupplier; - this.notifyListenersFunction = notifyListenersFunction; - this.logTag = pluginLogTag + "|" + executorTag; - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.kt new file mode 100644 index 000000000..95b62bfe3 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/models/Executor.kt @@ -0,0 +1,22 @@ +package com.getcapacitor.community.stripe.models + +import android.app.Activity +import android.content.Context +import androidx.core.util.Supplier +import com.getcapacitor.JSObject +import com.google.android.gms.common.util.BiConsumer + +abstract class Executor( + protected var contextSupplier: Supplier, + protected val activitySupplier: Supplier, + protected var notifyListenersFunction: BiConsumer, + pluginLogTag: String, + executorTag: String +) { + protected val logTag: String = "$pluginLogTag|$executorTag" + + // Eventually we can change the notification directly here! + protected fun notifyListeners(eventName: String, data: JSObject) { + notifyListenersFunction.accept(eventName, data) + } +} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.java deleted file mode 100644 index 5003078ac..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.getcapacitor.community.stripe.paymentflow; - -import android.app.Activity; -import android.content.Context; -import androidx.annotation.Nullable; -import androidx.core.util.Supplier; -import com.getcapacitor.Bridge; -import com.getcapacitor.JSObject; -import com.getcapacitor.PluginCall; -import com.getcapacitor.community.stripe.models.Executor; -import com.google.android.gms.common.util.BiConsumer; -import com.stripe.android.paymentsheet.PaymentSheet; -import com.stripe.android.paymentsheet.PaymentSheetResult; -import com.stripe.android.paymentsheet.model.PaymentOption; - -public class PaymentFlowExecutor extends Executor { - - public PaymentSheet.FlowController flowController; - private final JSObject emptyObject = new JSObject(); - private PaymentSheet.Configuration paymentConfiguration; - - public PaymentFlowExecutor( - Supplier contextSupplier, - Supplier activitySupplier, - BiConsumer notifyListenersFunction, - String pluginLogTag - ) { - super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "PaymentFlowExecutor"); - this.contextSupplier = contextSupplier; - } - - public void createPaymentFlow(final PluginCall call) { - String paymentIntentClientSecret = call.getString("paymentIntentClientSecret", null); - String setupIntentClientSecret = call.getString("setupIntentClientSecret", null); - String customerEphemeralKeySecret = call.getString("customerEphemeralKeySecret", null); - String customerId = call.getString("customerId", null); - - if (paymentIntentClientSecret == null && setupIntentClientSecret == null) { - String errorText = "Invalid Params. This method require paymentIntentClientSecret or setupIntentClientSecret."; - notifyListenersFunction.accept(PaymentFlowEvents.FailedToLoad.getWebEventName(), new JSObject().put("error", errorText)); - call.reject(errorText); - return; - } - - if (customerId != null && customerEphemeralKeySecret == null) { - String errorText = "Invalid Params. When you set customerId, you must set customerEphemeralKeySecret."; - notifyListenersFunction.accept(PaymentFlowEvents.FailedToLoad.getWebEventName(), new JSObject().put("error", errorText)); - call.reject(errorText); - return; - } - - String merchantDisplayName = call.getString("merchantDisplayName"); - - if (merchantDisplayName == null) { - merchantDisplayName = ""; - } - - Boolean enableGooglePay = call.getBoolean("enableGooglePay", false); - - final PaymentSheet.CustomerConfiguration customer = customerId != null - ? new PaymentSheet.CustomerConfiguration(customerId, customerEphemeralKeySecret) - : null; - - if (!enableGooglePay) { - paymentConfiguration = new PaymentSheet.Configuration(merchantDisplayName, customer); - } else { - Boolean GooglePayEnvironment = call.getBoolean("GooglePayIsTesting", false); - - PaymentSheet.GooglePayConfiguration.Environment environment = PaymentSheet.GooglePayConfiguration.Environment.Production; - - if (GooglePayEnvironment) { - environment = PaymentSheet.GooglePayConfiguration.Environment.Test; - } - - paymentConfiguration = new PaymentSheet.Configuration( - merchantDisplayName, - customer, - new PaymentSheet.GooglePayConfiguration(environment, call.getString("countryCode", "US")) - ); - } - - if (setupIntentClientSecret != null) { - flowController.configureWithSetupIntent(setupIntentClientSecret, paymentConfiguration, (success, error) -> { - if (success) { - notifyListenersFunction.accept(PaymentFlowEvents.Loaded.getWebEventName(), emptyObject); - call.resolve(); - } else { - notifyListenersFunction.accept( - PaymentFlowEvents.FailedToLoad.getWebEventName(), - new JSObject().put("error", error.getLocalizedMessage()) - ); - call.reject(error.getLocalizedMessage()); - } - }); - } else if (paymentIntentClientSecret != null) { - flowController.configureWithPaymentIntent(paymentIntentClientSecret, paymentConfiguration, (success, error) -> { - if (success) { - notifyListenersFunction.accept(PaymentFlowEvents.Loaded.getWebEventName(), emptyObject); - call.resolve(); - } else { - notifyListenersFunction.accept( - PaymentFlowEvents.FailedToLoad.getWebEventName(), - new JSObject().put("error", error.getLocalizedMessage()) - ); - call.reject(error.getLocalizedMessage()); - } - }); - } - } - - public void presentPaymentFlow(final PluginCall call) { - try { - notifyListenersFunction.accept(PaymentFlowEvents.Opened.getWebEventName(), emptyObject); - flowController.presentPaymentOptions(); - } catch (Exception ex) { - call.reject(ex.getLocalizedMessage(), ex); - } - } - - public void confirmPaymentFlow(final PluginCall call) { - try { - flowController.confirm(); - } catch (Exception ex) { - call.reject(ex.getLocalizedMessage(), ex); - } - } - - public void onPaymentOption(Bridge bridge, String callbackId, @Nullable PaymentOption paymentOption) { - PluginCall call = bridge.getSavedCall(callbackId); - if (paymentOption != null) { - notifyListenersFunction.accept( - PaymentFlowEvents.Created.getWebEventName(), - new JSObject().put("cardNumber", paymentOption.getLabel()) - ); - call.resolve(new JSObject().put("cardNumber", paymentOption.getLabel())); - } else { - notifyListenersFunction.accept(PaymentFlowEvents.Canceled.getWebEventName(), emptyObject); - call.reject("User close PaymentFlow Sheet"); - } - } - - public void onPaymentFlowResult(Bridge bridge, String callbackId, final PaymentSheetResult paymentSheetResult) { - PluginCall call = bridge.getSavedCall(callbackId); - - if (paymentSheetResult instanceof PaymentSheetResult.Canceled) { - notifyListenersFunction.accept(PaymentFlowEvents.Canceled.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", PaymentFlowEvents.Canceled.getWebEventName())); - } else if (paymentSheetResult instanceof PaymentSheetResult.Failed) { - notifyListenersFunction.accept( - PaymentFlowEvents.Failed.getWebEventName(), - new JSObject().put("error", ((PaymentSheetResult.Failed) paymentSheetResult).getError().getLocalizedMessage()) - ); - call.resolve(new JSObject().put("paymentResult", PaymentFlowEvents.Failed.getWebEventName())); - } else if (paymentSheetResult instanceof PaymentSheetResult.Completed) { - notifyListenersFunction.accept(PaymentFlowEvents.Completed.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", PaymentFlowEvents.Completed.getWebEventName())); - } - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.kt new file mode 100644 index 000000000..f5b1d5ee5 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentflow/PaymentFlowExecutor.kt @@ -0,0 +1,191 @@ +package com.getcapacitor.community.stripe.paymentflow + +import android.app.Activity +import android.content.Context +import androidx.core.util.Supplier +import com.getcapacitor.Bridge +import com.getcapacitor.JSObject +import com.getcapacitor.PluginCall +import com.getcapacitor.community.stripe.models.Executor +import com.google.android.gms.common.util.BiConsumer +import com.stripe.android.paymentsheet.PaymentSheet +import com.stripe.android.paymentsheet.PaymentSheet.FlowController.ConfigCallback +import com.stripe.android.paymentsheet.PaymentSheetResult +import com.stripe.android.paymentsheet.model.PaymentOption + +class PaymentFlowExecutor( + contextSupplier: Supplier, + activitySupplier: Supplier, + notifyListenersFunction: BiConsumer, + pluginLogTag: String +) : Executor( + contextSupplier, + activitySupplier, + notifyListenersFunction, + pluginLogTag, + "PaymentFlowExecutor" +) { + var flowController: PaymentSheet.FlowController? = null + private val emptyObject = JSObject() + private var paymentConfiguration: PaymentSheet.Configuration? = null + + init { + this.contextSupplier = contextSupplier + } + + fun createPaymentFlow(call: PluginCall) { + val paymentIntentClientSecret = call.getString("paymentIntentClientSecret", null) + val setupIntentClientSecret = call.getString("setupIntentClientSecret", null) + val customerEphemeralKeySecret = call.getString("customerEphemeralKeySecret", null) + val customerId = call.getString("customerId", null) + + if (paymentIntentClientSecret == null && setupIntentClientSecret == null) { + val errorText = + "Invalid Params. This method require paymentIntentClientSecret or setupIntentClientSecret." + notifyListenersFunction.accept( + PaymentFlowEvents.FailedToLoad.webEventName, + JSObject().put("error", errorText) + ) + call.reject(errorText) + return + } + + if (customerId != null && customerEphemeralKeySecret == null) { + val errorText = + "Invalid Params. When you set customerId, you must set customerEphemeralKeySecret." + notifyListenersFunction.accept( + PaymentFlowEvents.FailedToLoad.webEventName, + JSObject().put("error", errorText) + ) + call.reject(errorText) + return + } + + var merchantDisplayName = call.getString("merchantDisplayName") + + if (merchantDisplayName == null) { + merchantDisplayName = "" + } + + val enableGooglePay = call.getBoolean("enableGooglePay", false) + + val customer: PaymentSheet.CustomerConfiguration? = if (customerId != null + ) PaymentSheet.CustomerConfiguration(customerId, customerEphemeralKeySecret!!) + else null + + if (!enableGooglePay!!) { + paymentConfiguration = PaymentSheet.Configuration(merchantDisplayName, customer) + } else { + val GooglePayEnvironment = call.getBoolean("GooglePayIsTesting", false) + + var environment: PaymentSheet.GooglePayConfiguration.Environment = + PaymentSheet.GooglePayConfiguration.Environment.Production + + if (GooglePayEnvironment!!) { + environment = PaymentSheet.GooglePayConfiguration.Environment.Test + } + + paymentConfiguration = PaymentSheet.Configuration( + merchantDisplayName, + customer, + PaymentSheet.GooglePayConfiguration( + environment, + call.getString("countryCode", "US")!! + ) + ) + } + + if (setupIntentClientSecret != null) { + flowController!!.configureWithSetupIntent( + setupIntentClientSecret, + paymentConfiguration, + ConfigCallback { success: Boolean, error: Throwable? -> + if (success) { + notifyListenersFunction.accept( + PaymentFlowEvents.Loaded.webEventName, + emptyObject + ) + call.resolve() + } else { + notifyListenersFunction.accept( + PaymentFlowEvents.FailedToLoad.webEventName, + JSObject().put("error", error!!.localizedMessage) + ) + call.reject(error.localizedMessage) + } + }) + } else if (paymentIntentClientSecret != null) { + flowController!!.configureWithPaymentIntent( + paymentIntentClientSecret, + paymentConfiguration, + ConfigCallback { success: Boolean, error: Throwable? -> + if (success) { + notifyListenersFunction.accept( + PaymentFlowEvents.Loaded.webEventName, + emptyObject + ) + call.resolve() + } else { + notifyListenersFunction.accept( + PaymentFlowEvents.FailedToLoad.webEventName, + JSObject().put("error", error!!.localizedMessage) + ) + call.reject(error.localizedMessage) + } + }) + } + } + + fun presentPaymentFlow(call: PluginCall) { + try { + notifyListenersFunction.accept(PaymentFlowEvents.Opened.webEventName, emptyObject) + flowController!!.presentPaymentOptions() + } catch (ex: Exception) { + call.reject(ex.localizedMessage, ex) + } + } + + fun confirmPaymentFlow(call: PluginCall) { + try { + flowController!!.confirm() + } catch (ex: Exception) { + call.reject(ex.localizedMessage, ex) + } + } + + fun onPaymentOption(bridge: Bridge, callbackId: String?, paymentOption: PaymentOption?) { + val call = bridge.getSavedCall(callbackId) + if (paymentOption != null) { + notifyListenersFunction.accept( + PaymentFlowEvents.Created.webEventName, + JSObject().put("cardNumber", paymentOption.label) + ) + call.resolve(JSObject().put("cardNumber", paymentOption.label)) + } else { + notifyListenersFunction.accept(PaymentFlowEvents.Canceled.webEventName, emptyObject) + call.reject("User close PaymentFlow Sheet") + } + } + + fun onPaymentFlowResult( + bridge: Bridge, + callbackId: String?, + paymentSheetResult: PaymentSheetResult + ) { + val call = bridge.getSavedCall(callbackId) + + if (paymentSheetResult is PaymentSheetResult.Canceled) { + notifyListenersFunction.accept(PaymentFlowEvents.Canceled.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", PaymentFlowEvents.Canceled.webEventName)) + } else if (paymentSheetResult is PaymentSheetResult.Failed) { + notifyListenersFunction.accept( + PaymentFlowEvents.Failed.webEventName, + JSObject().put("error", (paymentSheetResult as PaymentSheetResult.Failed).error.getLocalizedMessage()) + ) + call.resolve(JSObject().put("paymentResult", PaymentFlowEvents.Failed.webEventName)) + } else if (paymentSheetResult is PaymentSheetResult.Completed) { + notifyListenersFunction.accept(PaymentFlowEvents.Completed.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", PaymentFlowEvents.Completed.webEventName)) + } + } +} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.java b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.java deleted file mode 100644 index 6fa2ee9ea..000000000 --- a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.getcapacitor.community.stripe.paymentsheet; - -import android.app.Activity; -import android.content.Context; -import androidx.core.util.Supplier; -import com.getcapacitor.Bridge; -import com.getcapacitor.JSObject; -import com.getcapacitor.PluginCall; -import com.getcapacitor.community.stripe.models.Executor; -import com.google.android.gms.common.util.BiConsumer; -import com.stripe.android.paymentsheet.PaymentSheet; -import com.stripe.android.paymentsheet.PaymentSheetResult; - -public class PaymentSheetExecutor extends Executor { - - public PaymentSheet paymentSheet; - private final JSObject emptyObject = new JSObject(); - private PaymentSheet.Configuration paymentConfiguration; - - private String paymentIntentClientSecret; - private String setupIntentClientSecret; - - public PaymentSheetExecutor( - Supplier contextSupplier, - Supplier activitySupplier, - BiConsumer notifyListenersFunction, - String pluginLogTag - ) { - super(contextSupplier, activitySupplier, notifyListenersFunction, pluginLogTag, "PaymentSheetExecutor"); - this.contextSupplier = contextSupplier; - } - - public void createPaymentSheet(final PluginCall call) { - paymentIntentClientSecret = call.getString("paymentIntentClientSecret", null); - setupIntentClientSecret = call.getString("setupIntentClientSecret", null); - - String customerEphemeralKeySecret = call.getString("customerEphemeralKeySecret", null); - String customerId = call.getString("customerId", null); - - if (paymentIntentClientSecret == null && setupIntentClientSecret == null) { - String errorText = "Invalid Params. This method require paymentIntentClientSecret or setupIntentClientSecret."; - notifyListenersFunction.accept(PaymentSheetEvents.FailedToLoad.getWebEventName(), new JSObject().put("error", errorText)); - call.reject(errorText); - return; - } - - if (customerId != null && customerEphemeralKeySecret == null) { - String errorText = "Invalid Params. When you set customerId, you must set customerEphemeralKeySecret."; - notifyListenersFunction.accept(PaymentSheetEvents.FailedToLoad.getWebEventName(), new JSObject().put("error", errorText)); - call.reject(errorText); - return; - } - - String merchantDisplayName = call.getString("merchantDisplayName"); - - if (merchantDisplayName == null) { - merchantDisplayName = ""; - } - - Boolean enableGooglePay = call.getBoolean("enableGooglePay", false); - - final PaymentSheet.CustomerConfiguration customer = customerId != null - ? new PaymentSheet.CustomerConfiguration(customerId, customerEphemeralKeySecret) - : null; - - PaymentSheet.BillingDetailsCollectionConfiguration billingDetailsCollectionConfiguration = null; - JSObject bdCollectionConfiguration = call.getObject("billingDetailsCollectionConfiguration", null); - if (bdCollectionConfiguration != null) { - String emailCollectionMode = bdCollectionConfiguration.getString("email"); - String nameCollectionMode = bdCollectionConfiguration.getString("name"); - String phoneCollectionMode = bdCollectionConfiguration.getString("phone"); - String addressCollectionMode = bdCollectionConfiguration.getString("address"); - billingDetailsCollectionConfiguration = new PaymentSheet.BillingDetailsCollectionConfiguration( - (nameCollectionMode != null && nameCollectionMode.equals("always")) - ? PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Always - : PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Automatic, - (phoneCollectionMode != null && phoneCollectionMode.equals("always")) - ? PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Always - : PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Automatic, - (emailCollectionMode != null && emailCollectionMode.equals("always")) - ? PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Always - : PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode.Automatic, - (addressCollectionMode != null && addressCollectionMode.equals("full")) - ? PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode.Full - : PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode.Automatic, - false - ); - } - - if (!enableGooglePay) { - if (bdCollectionConfiguration != null) { - paymentConfiguration = new PaymentSheet.Configuration.Builder(merchantDisplayName) - .customer(customer) - .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) - .build(); - } else { - paymentConfiguration = new PaymentSheet.Configuration.Builder(merchantDisplayName).customer(customer).build(); - } - } else { - Boolean GooglePayEnvironment = call.getBoolean("GooglePayIsTesting", false); - - PaymentSheet.GooglePayConfiguration.Environment environment = PaymentSheet.GooglePayConfiguration.Environment.Production; - - if (GooglePayEnvironment) { - environment = PaymentSheet.GooglePayConfiguration.Environment.Test; - } - - if (bdCollectionConfiguration != null) { - paymentConfiguration = new PaymentSheet.Configuration.Builder(merchantDisplayName) - .customer(customer) - .googlePay(new PaymentSheet.GooglePayConfiguration(environment, call.getString("countryCode", "US"))) - .billingDetailsCollectionConfiguration(billingDetailsCollectionConfiguration) - .build(); - } else { - paymentConfiguration = new PaymentSheet.Configuration.Builder(merchantDisplayName) - .customer(customer) - .googlePay(new PaymentSheet.GooglePayConfiguration(environment, call.getString("countryCode", "US"))) - .build(); - } - } - - notifyListenersFunction.accept(PaymentSheetEvents.Loaded.getWebEventName(), emptyObject); - call.resolve(); - } - - public void presentPaymentSheet(final PluginCall call) { - try { - if (paymentIntentClientSecret != null) { - paymentSheet.presentWithPaymentIntent(paymentIntentClientSecret, paymentConfiguration); - } else { - paymentSheet.presentWithSetupIntent(setupIntentClientSecret, paymentConfiguration); - } - } catch (Exception ex) { - call.reject(ex.getLocalizedMessage(), ex); - } - } - - public void onPaymentSheetResult(Bridge bridge, String callbackId, final PaymentSheetResult paymentSheetResult) { - PluginCall call = bridge.getSavedCall(callbackId); - - if (paymentSheetResult instanceof PaymentSheetResult.Canceled) { - notifyListenersFunction.accept(PaymentSheetEvents.Canceled.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", PaymentSheetEvents.Canceled.getWebEventName())); - } else if (paymentSheetResult instanceof PaymentSheetResult.Failed) { - notifyListenersFunction.accept( - PaymentSheetEvents.Failed.getWebEventName(), - new JSObject().put("message", ((PaymentSheetResult.Failed) paymentSheetResult).getError().getLocalizedMessage()) - ); - notifyListenersFunction.accept(PaymentSheetEvents.Failed.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", PaymentSheetEvents.Failed.getWebEventName())); - } else if (paymentSheetResult instanceof PaymentSheetResult.Completed) { - notifyListenersFunction.accept(PaymentSheetEvents.Completed.getWebEventName(), emptyObject); - call.resolve(new JSObject().put("paymentResult", PaymentSheetEvents.Completed.getWebEventName())); - } - } -} diff --git a/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.kt b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.kt new file mode 100644 index 000000000..1c9123398 --- /dev/null +++ b/packages/payment/android/src/main/java/com/getcapacitor/community/stripe/paymentsheet/PaymentSheetExecutor.kt @@ -0,0 +1,194 @@ +package com.getcapacitor.community.stripe.paymentsheet + +import android.app.Activity +import android.content.Context +import androidx.core.util.Supplier +import com.getcapacitor.Bridge +import com.getcapacitor.JSObject +import com.getcapacitor.PluginCall +import com.getcapacitor.community.stripe.models.Executor +import com.google.android.gms.common.util.BiConsumer +import com.stripe.android.paymentsheet.PaymentSheet +import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.AddressCollectionMode +import com.stripe.android.paymentsheet.PaymentSheet.BillingDetailsCollectionConfiguration.CollectionMode +import com.stripe.android.paymentsheet.PaymentSheetResult + +class PaymentSheetExecutor( + contextSupplier: Supplier, + activitySupplier: Supplier, + notifyListenersFunction: BiConsumer, + pluginLogTag: String +) : Executor( + contextSupplier, + activitySupplier, + notifyListenersFunction, + pluginLogTag, + "PaymentSheetExecutor" +) { + var paymentSheet: PaymentSheet? = null + private val emptyObject = JSObject() + private var paymentConfiguration: PaymentSheet.Configuration? = null + + private var paymentIntentClientSecret: String? = null + private var setupIntentClientSecret: String? = null + + init { + this.contextSupplier = contextSupplier + } + + fun createPaymentSheet(call: PluginCall) { + paymentIntentClientSecret = call.getString("paymentIntentClientSecret", null) + setupIntentClientSecret = call.getString("setupIntentClientSecret", null) + + val customerEphemeralKeySecret = call.getString("customerEphemeralKeySecret", null) + val customerId = call.getString("customerId", null) + + if (paymentIntentClientSecret == null && setupIntentClientSecret == null) { + val errorText = + "Invalid Params. This method require paymentIntentClientSecret or setupIntentClientSecret." + notifyListenersFunction.accept( + PaymentSheetEvents.FailedToLoad.webEventName, + JSObject().put("error", errorText) + ) + call.reject(errorText) + return + } + + if (customerId != null && customerEphemeralKeySecret == null) { + val errorText = + "Invalid Params. When you set customerId, you must set customerEphemeralKeySecret." + notifyListenersFunction.accept( + PaymentSheetEvents.FailedToLoad.webEventName, + JSObject().put("error", errorText) + ) + call.reject(errorText) + return + } + + var merchantDisplayName = call.getString("merchantDisplayName") + + if (merchantDisplayName == null) { + merchantDisplayName = "" + } + + val enableGooglePay = call.getBoolean("enableGooglePay", false) + + val customer: PaymentSheet.CustomerConfiguration? = if (customerId != null + ) PaymentSheet.CustomerConfiguration(customerId, customerEphemeralKeySecret!!) + else null + + var billingDetailsCollectionConfiguration: PaymentSheet.BillingDetailsCollectionConfiguration? = null + val bdCollectionConfiguration = + call.getObject("billingDetailsCollectionConfiguration", null) + if (bdCollectionConfiguration != null) { + val emailCollectionMode = bdCollectionConfiguration.getString("email") + val nameCollectionMode = bdCollectionConfiguration.getString("name") + val phoneCollectionMode = bdCollectionConfiguration.getString("phone") + val addressCollectionMode = bdCollectionConfiguration.getString("address") + billingDetailsCollectionConfiguration = + PaymentSheet.BillingDetailsCollectionConfiguration( + if ((nameCollectionMode != null && nameCollectionMode == "always") + ) CollectionMode.Always else CollectionMode.Automatic, + if ((phoneCollectionMode != null && phoneCollectionMode == "always") + ) CollectionMode.Always else CollectionMode.Automatic, + if ((emailCollectionMode != null && emailCollectionMode == "always") + ) CollectionMode.Always else CollectionMode.Automatic, + if ((addressCollectionMode != null && addressCollectionMode == "full") + ) AddressCollectionMode.Full else AddressCollectionMode.Automatic, + false + ) + } + + if (!enableGooglePay!!) { + paymentConfiguration = if (bdCollectionConfiguration != null) { + PaymentSheet.Configuration( + merchantDisplayName, + customer, + billingDetailsCollectionConfiguration = billingDetailsCollectionConfiguration!! + ) + } else { + PaymentSheet.Configuration( + merchantDisplayName, + customer, + ) + } + } else { + val GooglePayEnvironment = call.getBoolean("GooglePayIsTesting", false) + + var environment: PaymentSheet.GooglePayConfiguration.Environment = + PaymentSheet.GooglePayConfiguration.Environment.Production + + if (GooglePayEnvironment!!) { + environment = PaymentSheet.GooglePayConfiguration.Environment.Test + } + + paymentConfiguration = if (bdCollectionConfiguration != null) { + PaymentSheet.Configuration( + merchantDisplayName, + customer, + billingDetailsCollectionConfiguration = billingDetailsCollectionConfiguration!!, + googlePay = PaymentSheet.GooglePayConfiguration( + environment, + call.getString("countryCode", "US")!! + ), + ) + } else { + PaymentSheet.Configuration( + merchantDisplayName, + customer, + googlePay = PaymentSheet.GooglePayConfiguration( + environment, + call.getString("countryCode", "US")!! + ), + ) + } + } + + notifyListenersFunction.accept(PaymentSheetEvents.Loaded.webEventName, emptyObject) + call.resolve() + } + + fun presentPaymentSheet(call: PluginCall) { + try { + if (paymentIntentClientSecret != null) { + paymentSheet!!.presentWithPaymentIntent( + paymentIntentClientSecret!!, + paymentConfiguration + ) + } else { + paymentSheet!!.presentWithSetupIntent( + setupIntentClientSecret!!, + paymentConfiguration + ) + } + } catch (ex: Exception) { + call.reject(ex.localizedMessage, ex) + } + } + + fun onPaymentSheetResult( + bridge: Bridge, + callbackId: String?, + paymentSheetResult: PaymentSheetResult + ) { + val call = bridge.getSavedCall(callbackId) + + if (paymentSheetResult is PaymentSheetResult.Canceled) { + notifyListenersFunction.accept(PaymentSheetEvents.Canceled.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", PaymentSheetEvents.Canceled.webEventName)) + } else if (paymentSheetResult is PaymentSheetResult.Failed) { + notifyListenersFunction.accept( + PaymentSheetEvents.Failed.webEventName, + JSObject().put( + "message", + (paymentSheetResult as PaymentSheetResult.Failed).error.getLocalizedMessage() + ) + ) + notifyListenersFunction.accept(PaymentSheetEvents.Failed.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", PaymentSheetEvents.Failed.webEventName)) + } else if (paymentSheetResult is PaymentSheetResult.Completed) { + notifyListenersFunction.accept(PaymentSheetEvents.Completed.webEventName, emptyObject) + call.resolve(JSObject().put("paymentResult", PaymentSheetEvents.Completed.webEventName)) + } + } +}