diff --git a/example/lib/screens/card_payments/no_webhook_payment_screen.dart b/example/lib/screens/card_payments/no_webhook_payment_screen.dart index e2c1bdafb..b35f42b62 100644 --- a/example/lib/screens/card_payments/no_webhook_payment_screen.dart +++ b/example/lib/screens/card_payments/no_webhook_payment_screen.dart @@ -43,6 +43,7 @@ class _NoWebhookPaymentScreenState extends State { CardField( preferredNetworks: [CardBrand.Amex], controller: controller, + numberHintText: '34556689232', ), SizedBox(height: 20), LoadingButton( @@ -75,9 +76,7 @@ class _NoWebhookPaymentScreenState extends State { ), Divider(), SizedBox(height: 20), - ResponseCard( - response: controller.details.toJson().toPrettyString(), - ) + ResponseCard(response: controller.details.toJson().toPrettyString()), ], ); } @@ -106,11 +105,10 @@ class _NoWebhookPaymentScreenState extends State { // 2. Create payment method final paymentMethod = await Stripe.instance.createPaymentMethod( - params: PaymentMethodParams.card( - paymentMethodData: PaymentMethodData( - billingDetails: billingDetails, + params: PaymentMethodParams.card( + paymentMethodData: PaymentMethodData(billingDetails: billingDetails), ), - )); + ); // 3. call API to create PaymentIntent final paymentIntentResult = await callNoWebhookPayEndpointMethodId( @@ -123,8 +121,9 @@ class _NoWebhookPaymentScreenState extends State { if (paymentIntentResult['error'] != null) { // Error during creating or confirming Intent if (context.mounted) { - scaffoldMessenger.showSnackBar(SnackBar( - content: Text('Error: ${paymentIntentResult['error']}'))); + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: ${paymentIntentResult['error']}')), + ); } return; } @@ -134,9 +133,11 @@ class _NoWebhookPaymentScreenState extends State { context.mounted) { // Payment succedeed - scaffoldMessenger.showSnackBar(SnackBar( - content: - Text('Success!: The payment was confirmed successfully!'))); + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Success!: The payment was confirmed successfully!'), + ), + ); return; } @@ -154,8 +155,9 @@ class _NoWebhookPaymentScreenState extends State { } else { // Payment succedeed if (context.mounted) { - scaffoldMessenger.showSnackBar(SnackBar( - content: Text('Error: ${paymentIntentResult['error']}'))); + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: ${paymentIntentResult['error']}')), + ); } } } @@ -170,15 +172,19 @@ class _NoWebhookPaymentScreenState extends State { Future confirmIntent(String paymentIntentId) async { final scaffoldMessenger = ScaffoldMessenger.of(context); final result = await callNoWebhookPayEndpointIntentId( - paymentIntentId: paymentIntentId); + paymentIntentId: paymentIntentId, + ); if (result['error'] != null && context.mounted) { - scaffoldMessenger - .showSnackBar(SnackBar(content: Text('Error: ${result['error']}'))); + scaffoldMessenger.showSnackBar( + SnackBar(content: Text('Error: ${result['error']}')), + ); } else { if (context.mounted) { - scaffoldMessenger.showSnackBar(SnackBar( - content: - Text('Success!: The payment was confirmed successfully!'))); + scaffoldMessenger.showSnackBar( + SnackBar( + content: Text('Success!: The payment was confirmed successfully!'), + ), + ); } } } @@ -189,9 +195,7 @@ class _NoWebhookPaymentScreenState extends State { final url = Uri.parse('$kApiUrl/charge-card-off-session'); final response = await http.post( url, - headers: { - 'Content-Type': 'application/json', - }, + headers: {'Content-Type': 'application/json'}, body: json.encode({'paymentIntentId': paymentIntentId}), ); return json.decode(response.body); @@ -206,14 +210,12 @@ class _NoWebhookPaymentScreenState extends State { final url = Uri.parse('$kApiUrl/pay-without-webhooks'); final response = await http.post( url, - headers: { - 'Content-Type': 'application/json', - }, + headers: {'Content-Type': 'application/json'}, body: json.encode({ 'useStripeSdk': useStripeSdk, 'paymentMethodId': paymentMethodId, 'currency': currency, - 'items': items + 'items': items, }), ); return json.decode(response.body); diff --git a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt index dc9c5f03d..00a5856b4 100644 --- a/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt +++ b/packages/stripe_android/android/src/main/kotlin/com/flutter/stripe/StripeSdkCardPlatformView.kt @@ -1,6 +1,7 @@ package com.flutter.stripe import android.content.Context +import android.util.Log import android.view.View import android.view.inputmethod.InputMethodManager import androidx.annotation.NonNull @@ -17,12 +18,12 @@ import io.flutter.plugin.platform.PlatformView class StripeSdkCardPlatformView( - private val context: Context, - channel: MethodChannel, - id: Int, - creationParams: Map?, - private val stripeSdkCardViewManager: CardFieldViewManager, - sdkAccessor: () -> StripeSdkModule + private val context: Context, + channel: MethodChannel, + id: Int, + creationParams: Map?, + private val stripeSdkCardViewManager: CardFieldViewManager, + sdkAccessor: () -> StripeSdkModule ) : PlatformView, MethodChannel.MethodCallHandler { private val themedContext = ThemedReactContext(sdkAccessor().reactContext, channel, sdkAccessor) @@ -40,7 +41,16 @@ class StripeSdkCardPlatformView( entry.value, ) } + // workaround to fix inconsistent naming between iOS and Android + if (creationParams?.containsKey("placeholder") == true) { + stripeSdkCardViewManager.getDelegate().setProperty( + cardView, + "placeholders", + creationParams["placeholder"]?.convertToReadable() + ) + } if (creationParams?.containsKey("cardDetails") == true) { + val value = ReadableMap(creationParams["cardDetails"] as Map) stripeSdkCardViewManager.setCardDetails(value, themedContext) @@ -82,19 +92,37 @@ class StripeSdkCardPlatformView( "requestFocus" -> { val binding = StripeCardInputWidgetBinding.bind(cardView.mCardWidget) binding.cardNumberEditText.requestFocus() - val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); + val imm = + context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + imm.toggleSoftInput( + InputMethodManager.SHOW_FORCED, + InputMethodManager.HIDE_IMPLICIT_ONLY + ); result.success(null) } + "clearFocus" -> { // Hide keyboard - val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + val imm = + context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(cardView.windowToken, 0) // Clear focus cardView.clearFocus() result.success(null) } - "focus", "blur", "clear" -> stripeSdkCardViewManager.receiveCommand(cardView, call.method, null) + "onPlaceholderChanged" -> { + stripeSdkCardViewManager.delegate.setProperty( + cardView, + "placeholders", + call.arguments.convertToReadable() + ) + } + "focus", "blur", "clear" -> stripeSdkCardViewManager.receiveCommand( + cardView, + call.method, + null + ) + else -> { stripeSdkCardViewManager.delegate.setProperty( cardView,