public override void SetUpCell () { UIImage frontImage = cardHelper.CreditCardImage (CardType); CALayer layer = EntryEnclosingView.Layer; layer.CornerRadius = 4.0f; layer.MasksToBounds = true; layer.BorderColor = ColourHelper.GetColour ("0xC3C3C3FF").CGColor; layer.BorderWidth = 1; cardImage.Image = frontImage; PreviousCardNumber.Text = "xxxx " + LastFour; LengthForType = CardType == CardType.AMEX ? 4 : 3; entryField.ShouldChangeCharacters = (UITextField textView, NSRange NSRange, string replace) => { CSRange range = new CSRange ((int)NSRange.Location, (int)NSRange.Length); Complete = false; if (range.Length > 1) { return false; } if (replace.Length > 1) { return false; } if (replace.Length == 1 && !char.IsDigit (replace.ToCharArray () [0])) { return false; } if (textView.Text.Length + replace.Length - range.Length > LengthForType) { return false; } if(replace!=""&&textView.Text.Length + replace.Length==LengthForType) { var aStringBuilder = new StringBuilder (textView.Text); aStringBuilder.Remove (range.Location, range.Length); aStringBuilder.Insert (range.Location, replace); string newTextOrig = aStringBuilder.ToString (); CCV = newTextOrig; Complete = true; } DispatchQueue.MainQueue.DispatchAsync (() => { UpdateUI (); }); return true; }; entryField.BecomeFirstResponder (); }
void SetupCVTwo () { cvTwoText.ShouldChangeText = (UITextView textView, NSRange NSRange, string replace) => { if(replace!=""&&!Char.IsDigit(replace.ToCharArray()[0])) { return false; } CSRange range = new CSRange ((int)NSRange.Location, (int)NSRange.Length); if (replace.Length == 0) { if (textView.Text.Length == 0 || range.Location == 0) { // handle case of delete when there are no characters left to delete expiryText.BecomeFirstResponder (); if (expiryText.Text.Length == 5) { expiryText.Text = expiryText.Text.Remove (expiryText.Text.Length - 1); } } } if (cvTwoText.Text.Length== (Type == CardType.AMEX ? 4 : 3)&& replace.Length != 0) { return false; } scrollForward = false; string newTextOrig = ReplaceInPlace(range.Location, range.Length,textView.Text,replace); int newTextLen = newTextOrig.Length; if (newTextLen == cvTwoPlaceHolder.Text.Length) { var cIndex = cvTwoPlaceHolder.Text.IndexOf ("C"); CSRange ccvRange = new CSRange (cIndex, cvTwoPlaceHolder.Text.Substring (cIndex).Length); ccvRange.Length = Type == CardType.AMEX ? 4 : 3; ccv = newTextOrig.Substring (ccvRange.Location, ccvRange.Length); } updateText = true; if (newTextOrig.Length== (Type == CardType.AMEX ? 4 : 3)) { DismissKeyboardAction (); } return EndDelegate (cvTwoPlaceHolder, cvTwoText, newTextOrig); }; }
void SetupExpire () { expiryText.ShouldChangeText = (UITextView textView, NSRange NSRange, string replace) => { if(replace!=""&&!Char.IsDigit(replace.ToCharArray()[0])) { return false; } CSRange range = new CSRange ((int)NSRange.Location, (int)NSRange.Length); flashForError = false; updateText = false; scrollForward = false; deleting = false; ret = false; deletedSpace = false; if (replace.Length == 0) { updateText = true; deleting = true; if (textView.Text.Length != 0 && (range.Length != 0)) { // handle case of delete when there are no characters left to delete char c = textView.Text.Substring (range.Location, 1).ToCharArray () [0]; if (range.Location != 0 && range.Length == 1 && (c == ' ' || c == '/')) { range.Location--; range.Length++; deletedSpace = true; } } else { ccText.BecomeFirstResponder (); if (ccText.Text.Length == (cardHelper.LengthOfFormattedStringForType (Type))) { ccText.Text = ccText.Text.Remove (ccText.Text.Length - 1); } return EndDelegate (ccPlaceHolder, ccText, ccText.Text); } } var formattedText = ""; scrollForward = false; string newTextOrig =ReplaceInPlace(range.Location, range.Length,textView.Text,replace); int newTextLen = newTextOrig.Length; // Test for delete of a space or / if (deleting) { formattedText = newTextOrig.Substring (0, range.Location); updateText = true; return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } if (newTextLen > expiryPlaceHolder.Text.Length) { flashForError = true; return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } formattedText = newTextOrig; CSRange monthRange = new CSRange (expiryPlaceHolder.Text.IndexOf ("MM"), 2); if (newTextLen > monthRange.Location) { if (newTextOrig.Substring (monthRange.Location, 1).ToCharArray () [0] > '1') { // support short cut - we prepend a '0' for them formattedText =ReplaceInPlace(range.Location, range.Length,textView.Text,"0"+replace); newTextLen = newTextOrig.Length; } if (newTextLen >= (monthRange.Location + monthRange.Length)) { cardMonth = Int32.Parse (newTextOrig.Substring (monthRange.Location, monthRange.Length)); if (cardMonth < 1 || cardMonth > 12) { flashRecheckExpiryDateMessage (); return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } } } CSRange yearRange = new CSRange (expiryPlaceHolder.Text.IndexOf ("YY"), 2); if (newTextLen > yearRange.Location) { int proposedDecade = (newTextOrig.Substring (yearRange.Location, 1).ToCharArray () [0] - '0') * 10; int yearDecade = currentYear - (currentYear % 10); if (proposedDecade < yearDecade) { flashRecheckExpiryDateMessage (); return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } if (newTextLen >= (yearRange.Location + yearRange.Length)) { year = Int32.Parse (newTextOrig.Substring (yearRange.Location, yearRange.Length)); int diff = year - currentYear; if (diff < 0 || diff > 10) { flashRecheckExpiryDateMessage (); return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } if (diff == 0) { var todaysDate = DateTime.Today; int currentMonth = todaysDate.Month; if (cardMonth < currentMonth) { flashRecheckExpiryDateMessage (); return EndDelegate (expiryPlaceHolder, expiryText, formattedText); } } if (creditCardImage != ccBackImage) { UIViewAnimationOptions transType = (Type == CardType.AMEX) ? UIViewAnimationOptions.TransitionCrossDissolve : UIViewAnimationOptions.TransitionFlipFromBottom; UIImageView.Animate ( duration: 0.25f, delay: 0, options: transType, animation: () => { creditCardImage = ccBackImage; }, completion: () => { StatusHelpLabel.Text = "Please enter CV2"; }); } } } updateText = true; if (formattedText.Length == 5) { cvTwoText.BecomeFirstResponder (); } return EndDelegate (expiryPlaceHolder, expiryText, formattedText); }; }
void SetupCC () { ccText.ShouldChangeText = (UITextView textView, NSRange NSRange, string replace) => { if(replace!=""&&!Char.IsDigit(replace.ToCharArray()[0])) { return false; } CSRange range = new CSRange ((int)NSRange.Location, (int)NSRange.Length); var formattedText = ""; flashForError = false; updateText = false; scrollForward = false; deleting = false; ret = false; deletedSpace = false; cardMonth = 0; if (replace.Length == 0) { updateText = true; deleting = true; if (textView.Text.Length != 0) { // handle case of delete when there are no characters left to delete char c = textView.Text.Substring (range.Location, 1).ToCharArray () [0]; if (range.Location != 0 && range.Length == 1 && (c == ' ' || c == '/')) { range.Location--; range.Length++; deletedSpace = true; } } else { return false; } } string newTextOrig =ReplaceInPlace(range.Location, range.Length,textView.Text,replace); int newTextLen = newTextOrig.Length; // causes the cc entry field to scroll back if the user deletes back beyond the end of the cc number if (range.Location <= numberLength) { hasFullNumber = false; } if (textScroller.ContentOffset.X < 10f) { ccPlaceHolderWidthConstraint.Constant = 198f; } if (!hasFullNumber) { // scrolls backward int textViewLen = ccText.Text.Length; int formattedLen = ccPlaceHolder.Text.Length; if (textScroller.ContentOffset.X != 0) { textScroller.SetContentOffset (new PointF (0, 0), true); } UpdateCCimageWithTransitionTime (0, false, true); StatusHelpLabel.Text = "Enter Card Details"; string newText = newTextOrig.Replace (" ", String.Empty); int len = newText.Length; if (len < Card.CC_LEN_FOR_TYPE) { updateText = true; formattedText = newTextOrig; Type = CardType.UNKNOWN; } else { Type = cardHelper.GetCCType (newText); switch (Type) { case CardType.UNKNOWN: flashForError = true; break; case CardType.MAESTRO: if (!JudoSDKManager.MaestroAccepted) { flashForError = true; return EndDelegate (ccPlaceHolder, ccText, formattedText); } break; case CardType.AMEX: if (!JudoSDKManager.AmExAccepted) { flashForError = true; return EndDelegate (ccPlaceHolder, ccText, formattedText); } break; } if (len == Card.CC_LEN_FOR_TYPE) { ccPlaceHolder.Text = cardHelper.PromptStringForType (Type, true); cvTwoPlaceHolder.Text = cardHelper.CVTwoPromptForType (Type, true); cvTwoPlaceHolder.SetShowTextOffSet (Math.Min (0, 0)); } formattedText = cardHelper.FormatForViewing (newText); int lenForCard = cardHelper.LengthOfStringForType (Type); if (len < lenForCard) { updateText = true; } else if (len == lenForCard) { if (cardHelper.isValidNumber (newText)) { if (cardHelper.IsLuhnValid (newText)) { numberLength = cardHelper.LengthOfFormattedStringForType (Type); creditCardNum = newText; updateText = true; scrollForward = true; hasFullNumber = true; } else { FlashRecheckNumberMessage (); } } else { FlashRecheckNumberMessage (); } } } UpdateCCimageWithTransitionTime (0.25f); } return EndDelegate (ccPlaceHolder, ccText, formattedText); }; }
public override void SetUpCell () { countrySheet = new UIActionSheet ("Select Country"); countrySheet.TintColor = UIColor.Black; selectedCountry = BillingCountryOptions.BillingCountryOptionUK; HomeButton.TouchUpInside += (sender, ev) => { DismissKeyboardAction(); }; countrySheet.Clicked += delegate(object sender, UIButtonEventArgs button) { switch (button.ButtonIndex) { case (int) BillingCountryOptions.BillingCountryOptionUK: selectedCountry = BillingCountryOptions.BillingCountryOptionUK; break; case (int)BillingCountryOptions.BillingCountryOptionUSA: selectedCountry = BillingCountryOptions.BillingCountryOptionUSA; break; case (int)BillingCountryOptions.BillingCountryOptionCanada: selectedCountry = BillingCountryOptions.BillingCountryOptionCanada; break; case (int)BillingCountryOptions.BillingCountryOptionOther: selectedCountry = BillingCountryOptions.BillingCountryOptionOther; break; default: selectedCountry = BillingCountryOptions.BillingCountryOptionUK; break; } CountryLabel.Text = selectedCountry.ToDescriptionString (); }; foreach (BillingCountryOptions option in Enum.GetValues(typeof(BillingCountryOptions))) { countrySheet.AddButton (option.ToDescriptionString ()); } CountryButton.TouchUpInside += (sender, ev) => { if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad) { countrySheet.ShowInView(this.Superview); } else { countrySheet.ShowInView (UIApplication.SharedApplication.KeyWindow); } }; PostcodeTextField.Text = ""; PostcodeTextField.Font = JudoSDKManager.FIXED_WIDTH_FONT_SIZE_20;; PostcodeTextField.TextColor = UIColor.Black; PostcodeTextField.ShouldChangeCharacters = (UITextField textField, NSRange nsRange, string replacementString) => { CSRange range = new CSRange ((int)nsRange.Location, (int)nsRange.Length); DispatchQueue.MainQueue.DispatchAsync (() => { }); int textLengthAfter = textField.Text.Length + replacementString.Length - range.Length; if (textLengthAfter > 10) { return false; } return true; }; }
public override void SetUpCell () { StartDateTextField.ShouldChangeCharacters = (UITextField textField, NSRange nsRange, string replacementString) => { if(replacementString!=""&&!Char.IsDigit(replacementString.ToCharArray()[0])) { return false; } CSRange range = new CSRange ((int)nsRange.Location, (int)nsRange.Length); DispatchQueue.MainQueue.DispatchAsync (() => { UpdateUI (); }); bool changeText = true; if (range.Length > 1) { return false; } if (replacementString.Length > 1) { return false; } if (replacementString.Length == 1 && !char.IsDigit (replacementString.ToCharArray () [0])) { return false; } if (textField.Text.Length + replacementString.Length - range.Length > 5) { return false; } int textLengthAfter = (int)(textField.Text.Length + replacementString.Length - range.Length); if (replacementString.Length == 0 && range.Location < 2 && textField.Text.Contains ("/")) { textField.Text = textField.Text.Replace (@"/", @""); textLengthAfter--; } if (range.Length == 1 && textField.Text.Substring (range.Location, 1) == "/") { textField.Text = textField.Text.Substring (0, 1); textLengthAfter = 1; changeText = false; } if (range.Location == 1 && textField.Text.Length == 1) { var aStringBuilder = new StringBuilder (textField.Text); aStringBuilder.Remove (range.Location, range.Length); aStringBuilder.Insert (range.Location, replacementString); string newTextOrig = aStringBuilder.ToString (); string text = newTextOrig; if (Int32.Parse (text) > 12 || Int32.Parse (text) == 0) { FlashCheckDateLabel (); return false; } textField.Text = text; textField.Text = textField.Text + @"/"; textLengthAfter++; changeText = false; } else if (range.Location == 0 && textField.Text.Length == 0) { if (replacementString.Substring (0, 1).ToCharArray () [0] > '1') { var formatedString = string.Format (@"0{0}/", replacementString); var aStringBuilder = new StringBuilder (textField.Text); aStringBuilder.Remove (range.Location, range.Length); aStringBuilder.Insert (range.Location, formatedString); textField.Text = aStringBuilder.ToString (); textLengthAfter += 2; changeText = false; } } if (textLengthAfter >= 4) { var aStringBuilder = new StringBuilder (textField.Text); aStringBuilder.Remove (range.Location, range.Length); aStringBuilder.Insert (range.Location, replacementString); string textAfter = aStringBuilder.ToString (); int proposedDecade = (textAfter.ToCharArray () [3] - '0') * 10; int yearDecade = currentYear - (currentYear % 10); if (proposedDecade > yearDecade) { FlashCheckDateLabel (); return false; } if (textLengthAfter == 5) { if (!cardHelper.IsStartDateValid (textAfter)) { FlashCheckDateLabel (); return false; } var bStringBuilder = new StringBuilder (textField.Text); bStringBuilder.Remove (range.Location, range.Length); bStringBuilder.Insert (range.Location, replacementString); textField.Text = bStringBuilder.ToString (); DispatchQueue.MainQueue.DispatchAsync (() => { IssueNumberTextField.BecomeFirstResponder (); }); changeText = false; } } char[] placeHolder = "MM/YY".ToCharArray (); for (int iii = 0; iii < textLengthAfter; iii++) { placeHolder [iii] = ' '; } StartDatePlaceHolder.Text = new string (placeHolder); return changeText; }; IssueNumberTextField.ShouldChangeCharacters = (UITextField textField, NSRange nsRange, string replacementString) => { if(replacementString!=""&&!Char.IsDigit(replacementString.ToCharArray()[0])) { return false; } CSRange range = new CSRange ((int)nsRange.Location, (int)nsRange.Length); DispatchQueue.MainQueue.DispatchAsync (() => { UpdateUI (); }); if (range.Length > 1) { return false; } if (replacementString.Length > 1) { return false; } if (replacementString.Length == 1 && !char.IsDigit (replacementString.ToCharArray () [0])) { return false; } if (textField.Text.Length + replacementString.Length - range.Length > 3) { return false; } if (textField.Text.Length + replacementString.Length==3&&replacementString!="") { var aStringBuilder = new StringBuilder (textField.Text); aStringBuilder.Remove (range.Location, range.Length); aStringBuilder.Insert (range.Location, replacementString); textField.Text = aStringBuilder.ToString (); DismissKeyboardAction(); return true; } return true; }; }
public string FormatForViewing (string enteredNumber) { string cleaned = CleanNumber (enteredNumber); int len = cleaned.Length; if (len <= Card.CC_LEN_FOR_TYPE) return cleaned; CSRange r2 = new CSRange (); r2.Location = 0; CSRange r3 = new CSRange (); r3.Location = 0; CSRange r4 = new CSRange (); r4.Location = 0; string[] gaps = new string[]{ @"", @"", @"" }; int[] segmentLengths = new int[3] { 0, 0, 0 }; switch (GetCCType (enteredNumber)) { case CardType.VISA: case CardType.MASTERCARD: case CardType.DISCOVER: // { 4-4-4-4} case CardType.MAESTRO: segmentLengths [0] = 4; segmentLengths [1] = 4; segmentLengths [2] = 4; break; case CardType.AMEX: // {4-6-5} segmentLengths [0] = 6; segmentLengths [1] = 5; break; case CardType.DINERS_CLUB: // {4-6-4} segmentLengths [0] = 6; segmentLengths [1] = 4; break; default: return enteredNumber; } len -= Card.CC_LEN_FOR_TYPE; CSRange[] r = new CSRange[3]{ r2, r3, r4 }; int totalLen = Card.CC_LEN_FOR_TYPE; for (int idx = 0; idx < 3; ++idx) { int segLen = segmentLengths [idx]; r [idx].Location = totalLen; r [idx].Length = len >= segLen ? segLen : len; totalLen += segLen; len -= segLen; gaps [idx] = @" "; if (len <= 0) break; } string segment1 = enteredNumber.Substring (0, Card.CC_LEN_FOR_TYPE); string segment2 = r2.Location == 0 ? @"" : enteredNumber.Substring (r2.Location, r2.Length); string segment3 = r3.Location == 0 ? @"" : enteredNumber.Substring (r3.Location, r3.Length); ; string segment4 = r4.Location == 0 ? @"" : enteredNumber.Substring (r4.Location, r4.Length); ; string ret = string.Format (@"{0}{1}{2}{3}{4}{5}{6}", segment1, gaps [0], segment2, gaps [1], segment3, gaps [2], segment4); return ret; }
// http://www.regular-expressions.info/creditcard.html public CardType GetCCType (string proposedNumber) { Regex reg = new Regex (""); if (proposedNumber.Length < Card.CC_LEN_FOR_TYPE) return CardType.UNKNOWN; CardType lastcardtype = Enum.GetValues(typeof(CardType)).Cast<CardType>().Last(); for (int idx = 0; idx < (int)lastcardtype; ++idx) { switch (idx) { case (int)CardType.VISA: reg = visaTypeReg; break; case (int)CardType.MASTERCARD: reg = mcTypeReg; break; case (int)CardType.AMEX: reg = amexTypeReg; break; case (int)CardType.MAESTRO: reg = maestroTypeReg; break; } CSRange range = new CSRange (0, Card.CC_LEN_FOR_TYPE); var matches = reg.Matches (proposedNumber.Substring (range.Location, range.Length)); if (matches != null) { if (matches.Count == 1) { return (CardType)idx; } } } return CardType.UNKNOWN; }
public override void Draw (RectangleF rect) { RectangleF r = Offset; string clearText = Text.Substring (0, ShowTextOffset); string grayText = Text.Substring (ShowTextOffset, Text.Length - ShowTextOffset); CGContext context = UIGraphics.GetCurrentContext (); CGColor clearColor = UIColor.Clear.CGColor; context.SetStrokeColor(clearColor); context.SetFillColor(clearColor); context.FillRect(rect); if (clearText.Length !=0) { r.Location = new PointF(r.Location.X+ clearText.DrawString (Offset.Location, Font).Width,r.Location.Y); } CSRange charsToDraw = new CSRange(0, grayText.Length); if (charsToDraw.Length !=0) { CGColor grayColor = UIColor.LightGray.CGColor; context.SetStrokeColor (grayColor); context.SetFillColor (grayColor); var chars = grayText.ToCharArray(); int i; for (i = 0; i < chars.Length; i++) { char character = chars[i]; if (character == ' ') { r.Location= new PointF(r.Location.X+ Offset.Size.Width, r.Location.Y); continue; } if (character == 'X') { #if LED_FONT RectangleF box = rect.Inset(2, 1); #else CGRect box = rect.Inset (3, 3); #endif nfloat radius = 3; context.BeginPath (); context.MoveTo (box.GetMinX () + radius, box.GetMinY ()); var mask = "0"; UIFont drawFont = JudoSDKManager.FIXED_WIDTH_FONT_SIZE_20; mask.DrawString(box, drawFont); r.Location= new PointF(r.Location.X+ Offset.Size.Width, r.Location.Y); continue; } break; } charsToDraw.Location += i; charsToDraw.Length -= i; if (charsToDraw.Length != 0) { grayText.Substring((int)charsToDraw.Location, (int)charsToDraw.Length).DrawString (r.Location, JudoSDKManager.FIXED_WIDTH_FONT_SIZE_20); } } }