0

I have an angular application that takes credit card payment. I also have a credit card swiper that works as a card reader. Although I am able to read the credit card data, when the credit card is swiped, it fills the credit card input field with the first 16 numbers, which are not necessarily the credit card numbers, and discards the rest. If I try to use keyup or change, I am only able to get the numbers that are filled in the input field and not the whole swipe data. Is there any way I can process the data before it is saved and validated from the payment form?

My payment form is:

 this.paymentForm = this._fb.group({
        email: ['', [Validators.required, Validators.pattern('(?:[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])')]],
        expirationMonth: ['01', [CreditCardValidators.validateExpDate]],
        expirationYear: ['2024', [CreditCardValidators.validateExpDate]],
        cvv: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(4)]],
        creditCard: ['', [CreditCardValidators.validateCCNumber]],
    });

The HTML for the cc input is:

  <div>
    <label for="cc-number">Card Number</label>
    <input matInput id="cc-number" (input)="processCard($event)" formControlName="creditCard" class="input-cart-number"
    type="num" autocomplete="cc-number" ccNumber name='cardNumber' autofocus placeholder="XXXX XXXX XXXX XXXX" length="16" style="width: 280px; font-size: 15px;"/>
    <br>
    <mat-error *ngIf="f.creditCard.errors && f.creditCard.touched">Card number is <strong>required</strong>
    </mat-error>
  </div>

and the processCard event is:

 processCard(event){
  console.log('cc ' +JSON.stringify(event));
 }

From thus event, i want to get the full swiped text value. I can use event.target.value but that will return the form control value which has a validator and only reads the first 16 numbers and chops off the rest.

The card data on swipe is returned as:

%B6011361000006668^DISCOVER TESTCARD/DEVKIT^251210123456789?;**6011361000006668=2512**10123456789?

from the above, The card number is 6011361000006668 and the expiration date is 12/25.

z123
  • 193
  • 1
  • 15

1 Answers1

0

The solutions was changing the html and ts code to:

<div>
   <label for="cc-number">Card Number</label>
   <input matInput id="cc-number" (change)="processCard($event)" formControlName="creditCard" class="input-cart-number" type="num" autocomplete="cc-number"  name='cardNumber' autofocus placeholder="XXXX XXXX XXXX XXXX" style="width: 280px; font-size: 15px;"/>
   <br>
   <mat-error *ngIf="f.creditCard.errors && f.creditCard.touched">
                            Card number is <strong>required</strong>
   </mat-error>
</div>


 processCard(event){
  if(event.target.value.length > 16 && event.target.value.includes('%')) {
    let ccNumber = Number(event.target.value.split('=')[0].substring(event.target.value.split('=')[0].length - 16));
    let expMonth = event.target.value.split('=')[1].substring(2,4);
    let expYear = event.target.value.split('=')[1].substring(0,2);
    this.f.creditCard.setValue(ccNumber);
    this.f.expirationMonth.setValue(expMonth);
    this.f.expirationYear.setValue(20 +expYear);
    document.getElementById('cc-cvc').focus();
  } else if(event.target.value.length === 16 && event.key !== 'Backspace') {
    event.preventDefault();
  }

}

z123
  • 193
  • 1
  • 15