Alternatives to update Stripe

nelson_martinsnelson_martins Member ✭✭

Recently got a notification that the library of Stripe being used was going to become obsolete, for which I need to update them to keep having credit card payments via app.

I've been using the Component present in the Xamarin Component Store and the version Stripe has officially on nuget doesn't seem to be the same as the Component.

What are the alternatives I have to keep using Stripe on Xamarin projects? If possible, I'd like to avoid using native libraries ( double the work to keep them working ).

Best Answer

  • Accepted Answer

    I apologize for the late answer. I have found a solution to upgrade the Stripe reference to make it work again, here's what you need to do:

    • Search for the Stripe.net nuget and add it to your project;
    • For the code, I went with the following code ( I've omitted some code since it used some methods that are not relevant for this case )

      private async void MakeStripePayment( String cardNumber, DateTime cardExpirationDate, String cardSecurityCode ) {
          StripeToken
              stripeToken = null;
      
          try {
              StripeConfiguration.SetApiKey( /* set the api key here */ );
      
              StripeCreditCardOptions
                  stripeCreditCardOptions = new StripeCreditCardOptions() {
                      Number = cardNumber,
                      ExpirationYear = cardExpirationDate.Year,
                      ExpirationMonth = cardExpirationDate.Month,
                      Cvc = cardSecurityCode
                  };
      
              StripeTokenCreateOptions
                  stripeTokenCreateOptions = new StripeTokenCreateOptions() {
                      Card = stripeCreditCardOptions,
                  };
      
              StripeTokenService
                  tokenService = new StripeTokenService();
      
              stripeToken = await tokenService.CreateAsync( stripeTokenCreateOptions );
          } catch( Exception exception ) {
              StripeException
                  stripeException = exception.InnerException as StripeException;
      
              if( stripeException != null ) {
                  Dictionary<String, Int32>
                      stripeErrorDictionary = new Dictionary<String, String>() {
                          // Error messages from stripe.com/docs/api#errors
                          { "invalid_number", "The card number is not a valid credit card number." },
                          { "invalid_expiry_month", "The card's expiration month is invalid." },
                          { "invalid_expiry_year", "The card's expiration year is invalid." },
                          { "invalid_cvc", "The card's security code is invalid." },
                          { "invalid_swipe_data", "The card's swipe data is invalid." },
                          { "incorrect_number", "The card number is incorrect." },
                          { "expired_card", "The card has expired." },
                          { "incorrect_cvc", "The card's security code is incorrect." },
                          { "incorrect_zip", "The card's zip code failed validation." },
                          { "card_declined", "The card was declined." },
                          { "missing", "There is no card on a customer that is being charged." },
                          { "processing_error", "An error occurred while processing the card." },
                      };
      
                  String
                      errorMessage = "";
      
                  if( stripeErrorDictionary.ContainsKey( stripeException.StripeError.Code ) ) {
                      errorMessage = stripeErrorDictionary[ stripeException.StripeError.Code ];
                  } else {
                      errorMessage = "An unknown error occurred.";
                  }
      
                  // Show error
      
                  return;
              }
          }
      
          if( stripeToken == null ) {
              // Show error.
      
              return;
          }
      
          // Use 'stripeToken.Id' as the token to make your payments
      }
      
    • Then go to your Android project, right click and select Properties, select Android Options, click on the Advanced button ( bottom of the window ) and change the SSL/TLS implementation to Native TLS 1.2+

    From there on it should work, I don't remember doing anything else related to Stripe.

Answers

  • asmykasmyk Member ✭✭

    @NelsonMartins Did you find a decision? I don't see in nugget package StripeView

  • nelson_martinsnelson_martins Member ✭✭
    Accepted Answer

    I apologize for the late answer. I have found a solution to upgrade the Stripe reference to make it work again, here's what you need to do:

    • Search for the Stripe.net nuget and add it to your project;
    • For the code, I went with the following code ( I've omitted some code since it used some methods that are not relevant for this case )

      private async void MakeStripePayment( String cardNumber, DateTime cardExpirationDate, String cardSecurityCode ) {
          StripeToken
              stripeToken = null;
      
          try {
              StripeConfiguration.SetApiKey( /* set the api key here */ );
      
              StripeCreditCardOptions
                  stripeCreditCardOptions = new StripeCreditCardOptions() {
                      Number = cardNumber,
                      ExpirationYear = cardExpirationDate.Year,
                      ExpirationMonth = cardExpirationDate.Month,
                      Cvc = cardSecurityCode
                  };
      
              StripeTokenCreateOptions
                  stripeTokenCreateOptions = new StripeTokenCreateOptions() {
                      Card = stripeCreditCardOptions,
                  };
      
              StripeTokenService
                  tokenService = new StripeTokenService();
      
              stripeToken = await tokenService.CreateAsync( stripeTokenCreateOptions );
          } catch( Exception exception ) {
              StripeException
                  stripeException = exception.InnerException as StripeException;
      
              if( stripeException != null ) {
                  Dictionary<String, Int32>
                      stripeErrorDictionary = new Dictionary<String, String>() {
                          // Error messages from stripe.com/docs/api#errors
                          { "invalid_number", "The card number is not a valid credit card number." },
                          { "invalid_expiry_month", "The card's expiration month is invalid." },
                          { "invalid_expiry_year", "The card's expiration year is invalid." },
                          { "invalid_cvc", "The card's security code is invalid." },
                          { "invalid_swipe_data", "The card's swipe data is invalid." },
                          { "incorrect_number", "The card number is incorrect." },
                          { "expired_card", "The card has expired." },
                          { "incorrect_cvc", "The card's security code is incorrect." },
                          { "incorrect_zip", "The card's zip code failed validation." },
                          { "card_declined", "The card was declined." },
                          { "missing", "There is no card on a customer that is being charged." },
                          { "processing_error", "An error occurred while processing the card." },
                      };
      
                  String
                      errorMessage = "";
      
                  if( stripeErrorDictionary.ContainsKey( stripeException.StripeError.Code ) ) {
                      errorMessage = stripeErrorDictionary[ stripeException.StripeError.Code ];
                  } else {
                      errorMessage = "An unknown error occurred.";
                  }
      
                  // Show error
      
                  return;
              }
          }
      
          if( stripeToken == null ) {
              // Show error.
      
              return;
          }
      
          // Use 'stripeToken.Id' as the token to make your payments
      }
      
    • Then go to your Android project, right click and select Properties, select Android Options, click on the Advanced button ( bottom of the window ) and change the SSL/TLS implementation to Native TLS 1.2+

    From there on it should work, I don't remember doing anything else related to Stripe.

  • nelson_martinsnelson_martins Member ✭✭

    @asmyk I've posted the solution I used, care to see if it works for you too?

  • asmykasmyk Member ✭✭

    @NelsonMartins I have to use StripeView where the validation of credit card type is presented. But I don't see StripeView in the Stripe.Net nugget package. StripeView is presented in the Stripe Xamarin component only

  • nelson_martinsnelson_martins Member ✭✭

    @asmyk Unfortunately I didn't use the StripeView on the project. Have you tried to keep the Component on the project and using the StripeView as you previously did, and then using the new nuget to perform the payment by passing the credit card info ( credit card number, expiration date and cvc )?

  • asmykasmyk Member ✭✭

    @NelsonMartins no, I didn't. With new VS for Mac version, I have to remove all components from the project. But It seems Stripe.Net nugget package doesn't support all features that Stripe Xamarin Component has.

  • prachijignayprachijignay Member ✭✭

    @asmyk Did you find any work around?
    I am trying to implement stripe.net nuget and i too have similar issue of not having stripe view.

  • asmykasmyk Member ✭✭

    @prachijignay I think this view will not be implemented by stripe.net nugget author, because it is not necessary to stripe module. I will plan to implement the same view in future, but not sure when it will be. If you find this implementation somewhere or will do this view in your projects, I will be thankful to get an implementation too.

  • prachijignayprachijignay Member ✭✭

    Hello @asmyk and @NelsonMartins
    I have implemented stripe view.
    Please have a look.
    Still need some updates as you will see after using it.

    User Control - StripeControl.xaml

    <ContentView.Resources>



    </ContentView.Resources>
    <ContentView.Content>

    <StackLayout.WidthRequest>

    </StackLayout.WidthRequest>
    <StackLayout.HeightRequest>

    </StackLayout.HeightRequest>

    <Entry.FontSize>

    </Entry.FontSize>
    <Entry.Behaviors>

    </Entry.Behaviors>
    <Entry.WidthRequest>

    </Entry.WidthRequest>


    <Entry.FontSize>

    </Entry.FontSize>
    <Entry.Behaviors>

    </Entry.Behaviors>
    <Entry.WidthRequest>

    </Entry.WidthRequest>


    <Entry.FontSize>

    </Entry.FontSize>
    <Entry.Behaviors>

    </Entry.Behaviors>
    <Entry.WidthRequest>

    </Entry.WidthRequest>


    <Entry.FontSize>

    </Entry.FontSize>
    <Entry.Behaviors>

    </Entry.Behaviors>
    <Entry.WidthRequest>

    </Entry.WidthRequest>

            </Entry>
        </StackLayout>
    </ContentView.Content>
    

    Converter - CreditCardNumberConverter.cs

    namespace CondoControlCentralApp.Converters
    {
    public class CreditCardNumberConverter : IValueConverter
    {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
    try
    {
    if (value is string val)
    {
    var builder = new StringBuilder(Regex.Replace(val, @\D, ""));

                    foreach (var i in Enumerable.Range(0, builder.Length / 4).Reverse())
                        builder.Insert(4 * i + 4, "-");
    
                    return builder.ToString().Trim();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                return Regex.Replace(value.ToString(), @"\D", "");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    

    }

    Behaviour - CreditCardLengthBehaviour.cs
    namespace CondoControlCentralApp.Behaviors
    {
    public class CreditCardLengthBehaviour : Behavior
    {
    static readonly BindableProperty LengthRestrictionProperty = BindableProperty.Create<CreditCardLengthBehaviour, int>(p => p.LengthRestriction, defaultValue: 19, defaultBindingMode: BindingMode.OneWay);
    public VisualElement FocusOn { get; set; }

        public int LengthRestriction
        {
            get { return (int)GetValue(LengthRestrictionProperty); }
            set { SetValue(LengthRestrictionProperty, value); }
        }
    
        protected override void OnAttachedTo(Entry bindable)
        {
            bindable.TextChanged += HandleTextChanged;
            base.OnAttachedTo(bindable);
            bindable.Completed += BindableOnCompleted;
        }
    
        private void BindableOnCompleted(object sender, EventArgs e)
        {
            FocusOn?.Focus();
        }
    
        void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            var obj = (Entry)sender;
            var value = obj.Text;
            if (value.Length >= LengthRestriction)
            {
                value = e.NewTextValue.Substring(0, LengthRestriction);
    
                obj.Text = value;
                FocusOn?.Focus();
            }
        }
    
        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.TextChanged -= HandleTextChanged;
            base.OnDetachingFrom(bindable);
            bindable.Completed -= BindableOnCompleted;
        }
    }
    

    }

    Still there is some issue on when you try to insert the digits in between for CreditCard, it appends at last only. if I want to update the number, I have to delete all the numbers and retype.

    Please let me know if you can find any workaround to overcome this problem.

    Thanks

  • prachijignayprachijignay Member ✭✭
    edited June 6

    Do post your comments if there is any error.

  • asmykasmyk Member ✭✭

    @prachijignay Can you post your code with a code tag? it seems you missed some part of your code

  • prachijignayprachijignay Member ✭✭

    Please have a look @asmyk

    User Control - StripeControl.xaml
    <?xml version="1.0" encoding="UTF-8"?> <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="********.UserControls.StripeControl" xmlns:behaviors="clr-namespace:********.Behaviors;assembly=CondoControlCentralApp" xmlns:converters="clr-namespace:********.Converters;assembly=CondoControlCentralApp"> <ContentView.Resources> <ResourceDictionary> <converters:CreditCardNumberConverter x:Key="cnvCC"></converters:CreditCardNumberConverter> </ResourceDictionary> </ContentView.Resources> <ContentView.Content> <StackLayout Padding="10,10,10,10" Orientation="Horizontal" HorizontalOptions="CenterAndExpand" VerticalOptions="Center"> <StackLayout.WidthRequest> <OnPlatform x:TypeArguments="x:Double" Android="270" iOS="270" /> </StackLayout.WidthRequest> <StackLayout.HeightRequest> <OnPlatform x:TypeArguments="x:Double" Android="20" iOS="20" /> </StackLayout.HeightRequest> <Entry Text="{Binding CreditCardNumber, Mode=TwoWay, Converter={StaticResource cnvCC}}" x:Name="CreditCardNumber" Placeholder="card number" Keyboard="Numeric"> <Entry.FontSize> <OnPlatform x:TypeArguments="x:Double" Android="14" iOS="12" /> </Entry.FontSize> <Entry.Behaviors> <behaviors:CreditCardLengthBehaviour LengthRestriction="19" FocusOn="{x:Reference ExpiryMonth}" /> </Entry.Behaviors> <Entry.WidthRequest> <OnPlatform x:TypeArguments="x:Double" Android="160" iOS="160" /> </Entry.WidthRequest> </Entry> <Entry Text="{Binding ExpiryMonth}" x:Name="ExpiryMonth" Placeholder="mm" Keyboard="Numeric"> <Entry.FontSize> <OnPlatform x:TypeArguments="x:Double" Android="14" iOS="12" /> </Entry.FontSize> <Entry.Behaviors> <behaviors:CreditCardLengthBehaviour LengthRestriction="2" FocusOn="{x:Reference ExpiryYear}" /> </Entry.Behaviors> <Entry.WidthRequest> <OnPlatform x:TypeArguments="x:Double" Android="30" iOS="30" /> </Entry.WidthRequest> </Entry> <Entry Text="{Binding ExpiryYear}" x:Name="ExpiryYear" Placeholder="yy" Keyboard="Numeric"> <Entry.FontSize> <OnPlatform x:TypeArguments="x:Double" Android="14" iOS="12" /> </Entry.FontSize> <Entry.Behaviors> <behaviors:CreditCardLengthBehaviour LengthRestriction="2" FocusOn="{x:Reference CVC}" /> </Entry.Behaviors> <Entry.WidthRequest> <OnPlatform x:TypeArguments="x:Double" Android="30" iOS="30" /> </Entry.WidthRequest> </Entry> <Entry Text="{Binding CVC}" x:Name="CVC" Placeholder="cvc" Keyboard="Numeric"> <Entry.FontSize> <OnPlatform x:TypeArguments="x:Double" Android="14" iOS="12" /> </Entry.FontSize> <Entry.Behaviors> <behaviors:CreditCardLengthBehaviour LengthRestriction="3" /> </Entry.Behaviors> <Entry.WidthRequest> <OnPlatform x:TypeArguments="x:Double" Android="40" iOS="30" /> </Entry.WidthRequest> </Entry> </StackLayout> </ContentView.Content> </ContentView>

    Code behind - StripeControl.xaml.cs
    `
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;

    namespace ******.UserControls
    {
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class StripeControl : ContentView
    {
    public StripeControl ()
    {
    InitializeComponent ();
    }
    }
    }
    `
    Behaviour - CreditCardLengthBehaviour.cs

    `
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using Xamarin.Forms;

    namespace *******.Behaviors
    {
    public class CreditCardLengthBehaviour : Behavior
    {
    static readonly BindableProperty LengthRestrictionProperty = BindableProperty.Create<CreditCardLengthBehaviour, int>(p => p.LengthRestriction, defaultValue: 19, defaultBindingMode: BindingMode.OneWay);
    public VisualElement FocusOn { get; set; }

        public int LengthRestriction
        {
            get { return (int)GetValue(LengthRestrictionProperty); }
            set { SetValue(LengthRestrictionProperty, value); }
        }
    
        protected override void OnAttachedTo(Entry bindable)
        {
            bindable.TextChanged += HandleTextChanged;
            base.OnAttachedTo(bindable);
            bindable.Completed += BindableOnCompleted;
        }
    
        private void BindableOnCompleted(object sender, EventArgs e)
        {
            FocusOn?.Focus();
        }
    
        void HandleTextChanged(object sender, TextChangedEventArgs e)
        {
            var obj = (Entry)sender;
            var value = obj.Text;
            if (value.Length >= LengthRestriction)
            {
                value = e.NewTextValue.Substring(0, LengthRestriction);
    
                obj.Text = value;
                FocusOn?.Focus();
            }
        }
    
        protected override void OnDetachingFrom(Entry bindable)
        {
            bindable.TextChanged -= HandleTextChanged;
            base.OnDetachingFrom(bindable);
            bindable.Completed -= BindableOnCompleted;
        }
    }
    

    }

    `
    Converter - CreditCardNumberConverter.cs

    `
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using CondoControlCentralApp.BLL.Models.Enums;
    using Xamarin.Forms;

    namespace ********.Converters
    {
    public class CreditCardNumberConverter : IValueConverter
    {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
    try
    {
    if (value is string val)
    {
    var builder = new StringBuilder(Regex.Replace(val, @\D, ""));

                    foreach (var i in Enumerable.Range(0, builder.Length / 4).Reverse())
                        builder.Insert(4 * i + 4, "-");
    
                    return builder.ToString().Trim();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                return Regex.Replace(value.ToString(), @"\D", "");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    

    }

    `

    Please have a look at the code now. And do let me know if i am missing anything.
    PS. I have used the methods provided by @nelson_martins to generate stripe token.

    Thanks

  • prachijignayprachijignay Member ✭✭

    @asmyk
    User Control - StripeControl.xaml

    <ContentView xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="CondoControlCentralApp.UserControls.StripeControl"
                 xmlns:behaviors="clr-namespace:CondoControlCentralApp.Behaviors;assembly=CondoControlCentralApp"
                 xmlns:converters="clr-namespace:CondoControlCentralApp.Converters;assembly=CondoControlCentralApp">
        <ContentView.Resources>
            <ResourceDictionary>
                <converters:CreditCardNumberConverter x:Key="cnvCC"></converters:CreditCardNumberConverter>
            </ResourceDictionary>
        </ContentView.Resources>
        <ContentView.Content>
            <StackLayout Padding="10,10,10,10"
                         Orientation="Horizontal"
                         HorizontalOptions="CenterAndExpand"
                         VerticalOptions="Center">
                <StackLayout.WidthRequest>
                    <OnPlatform x:TypeArguments="x:Double"
                                Android="270"
                                iOS="270" />
                </StackLayout.WidthRequest>
                <StackLayout.HeightRequest>
                    <OnPlatform x:TypeArguments="x:Double"
                                Android="20"
                                iOS="20" />
                </StackLayout.HeightRequest>
                <Entry Text="{Binding CreditCardNumber, Mode=TwoWay, Converter={StaticResource cnvCC}}"
                       x:Name="CreditCardNumber"
                       Placeholder="card number"
                       Keyboard="Numeric">
                    <Entry.FontSize>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="14"
                                    iOS="12" />
                    </Entry.FontSize>
                    <Entry.Behaviors>
                        <behaviors:CreditCardLengthBehaviour LengthRestriction="19"
                                                             FocusOn="{x:Reference ExpiryMonth}" />
                    </Entry.Behaviors>
                    <Entry.WidthRequest>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="160"
                                    iOS="160" />
                    </Entry.WidthRequest>
                </Entry>
                <Entry Text="{Binding ExpiryMonth}"
                       x:Name="ExpiryMonth"
                       Placeholder="mm"
                       Keyboard="Numeric">
                    <Entry.FontSize>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="14"
                                    iOS="12" />
                    </Entry.FontSize>
                    <Entry.Behaviors>
                        <behaviors:CreditCardLengthBehaviour LengthRestriction="2"
                                                             FocusOn="{x:Reference ExpiryYear}" />
                    </Entry.Behaviors>
                    <Entry.WidthRequest>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="30"
                                    iOS="30" />
                    </Entry.WidthRequest>
                </Entry>
                <Entry Text="{Binding ExpiryYear}"
                       x:Name="ExpiryYear"
                       Placeholder="yy"
                       Keyboard="Numeric">
                    <Entry.FontSize>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="14"
                                    iOS="12" />
                    </Entry.FontSize>
                    <Entry.Behaviors>
                        <behaviors:CreditCardLengthBehaviour LengthRestriction="2"
                                                             FocusOn="{x:Reference CVC}" />
                    </Entry.Behaviors>
                    <Entry.WidthRequest>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="30"
                                    iOS="30" />
                    </Entry.WidthRequest>
                </Entry>
                <Entry Text="{Binding CVC}"
                       x:Name="CVC"
                       Placeholder="cvc"
                       Keyboard="Numeric">
                    <Entry.FontSize>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="14"
                                    iOS="12" />
                    </Entry.FontSize>
                    <Entry.Behaviors>
                        <behaviors:CreditCardLengthBehaviour LengthRestriction="3" />
                    </Entry.Behaviors>
                    <Entry.WidthRequest>
                        <OnPlatform x:TypeArguments="x:Double"
                                    Android="40"
                                    iOS="30" />
                    </Entry.WidthRequest>
    
                </Entry>
            </StackLayout>
        </ContentView.Content>
    </ContentView>
    

    Converter - CreditCardNumberConverter.cs

        using System;
        using System.Collections.Generic;
        using System.Globalization;
        using System.Linq;
        using System.Text;
        using System.Text.RegularExpressions;
        using System.Threading.Tasks;
        using CondoControlCentralApp.BLL.Models.Enums;
        using Xamarin.Forms;
    
        namespace CondoControlCentralApp.Converters
        {
            public class CreditCardNumberConverter : IValueConverter
            {
                public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    try
                    {
                        if (value is string val)
                        {
                            var builder = new StringBuilder(Regex.Replace(val, @"\D", ""));
    
                            foreach (var i in Enumerable.Range(0, builder.Length / 4).Reverse())
                                builder.Insert(4 * i + 4, "-");
    
                            return builder.ToString().Trim();
                        }
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    return null;
                }
    
                public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
                {
                    try
                    {
                        return Regex.Replace(value.ToString(), @"\D", "");
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }
        }
    

    Behaviour - CreditCardLengthBehaviour.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    using Xamarin.Forms;
    
    namespace CondoControlCentralApp.Behaviors
    {
        public class CreditCardLengthBehaviour : Behavior<Entry>
        {
            static readonly BindableProperty LengthRestrictionProperty = BindableProperty.Create<CreditCardLengthBehaviour, int>(p => p.LengthRestriction, defaultValue: 19, defaultBindingMode: BindingMode.OneWay);
            public VisualElement FocusOn { get; set; }
    
            public int LengthRestriction
            {
                get { return (int)GetValue(LengthRestrictionProperty); }
                set { SetValue(LengthRestrictionProperty, value); }
            }
    
            protected override void OnAttachedTo(Entry bindable)
            {
                bindable.TextChanged += HandleTextChanged;
                base.OnAttachedTo(bindable);
                bindable.Completed += BindableOnCompleted;
            }
    
            private void BindableOnCompleted(object sender, EventArgs e)
            {
                FocusOn?.Focus();
            }
    
            void HandleTextChanged(object sender, TextChangedEventArgs e)
            {
                var obj = (Entry)sender;
                var value = obj.Text;
                if (value.Length >= LengthRestriction)
                {
                    value = e.NewTextValue.Substring(0, LengthRestriction);
    
                    obj.Text = value;
                    FocusOn?.Focus();
                }
            }
    
            protected override void OnDetachingFrom(Entry bindable)
            {
                bindable.TextChanged -= HandleTextChanged;
                base.OnDetachingFrom(bindable);
                bindable.Completed -= BindableOnCompleted;
            }
        }
    }
    
  • prachijignayprachijignay Member ✭✭

    @asmyk am i missing anything here?

Sign In or Register to comment.