You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular表单控件中带验证的信用卡刷卡输入处理问题

问题:Angular信用卡刷卡器完整数据获取方案

我有一个支持信用卡支付的Angular应用,搭配了信用卡刷卡器。目前能读取信用卡数据,但刷卡时仅在信用卡输入框填充前16位数字(不一定是完整卡号),其余数据被丢弃。使用keyup或change事件只能获取输入框内的数字,拿不到完整刷卡数据。想知道能不能在表单保存和验证前处理完整的刷卡数据?

现有代码

表单定义

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]],
    });

信用卡输入框HTML

<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>

现有事件处理

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

刷卡返回完整数据示例

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

其中卡号为6011361000006668,有效期为12/25。


解决方案

1. 核心问题分析

当前表单控件的CreditCardValidators.validateCCNumber验证器会实时过滤输入内容,导致刷卡器输出的完整数据被截断。要获取完整数据,必须绕过这个实时验证的干扰。

2. 推荐实现方案:隐藏输入框接收完整数据

新增一个不绑定表单控件、无验证规则的隐藏输入框,让刷卡器的完整输出直接进入这个框,再从这里解析数据并填充表单。

修改HTML代码

<div>
  <label for="cc-number">Card Number</label>
  <!-- 原有输入框保留,用于手动输入或展示格式化卡号 -->
  <input matInput id="cc-number" 
         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;"/>
  <!-- 新增隐藏输入框,专门接收完整刷卡数据 -->
  <input #swipeInput type="text" style="position: absolute; left: -9999px;" (input)="handleSwipe($event)"/>
  <br>
  <mat-error *ngIf="f.creditCard.errors && f.creditCard.touched">Card number is <strong>required</strong>
  </mat-error>
</div>

组件中解析并填充数据

import { ViewChild, ElementRef } from '@angular/core';

// 获取隐藏输入框的DOM引用
@ViewChild('swipeInput') swipeInput!: ElementRef<HTMLInputElement>;

handleSwipe(event: Event) {
  const fullSwipeData = (event.target as HTMLInputElement).value;
  if (!fullSwipeData) return;

  // 解析刷卡数据(匹配示例格式)
  const cardNumberMatch = fullSwipeData.match(/%B(\d+)\^/);
  const expiryMatch = fullSwipeData.match(/\^(\d{4})/);

  if (cardNumberMatch && expiryMatch) {
    const cardNumber = cardNumberMatch[1];
    // 解析有效期:示例中2512对应2025年12月
    const expiryYear = `20${expiryMatch[1].slice(0, 2)}`;
    const expiryMonth = expiryMatch[1].slice(2);

    // 自动填充表单字段
    this.paymentForm.patchValue({
      creditCard: cardNumber,
      expirationYear: expiryYear,
      expirationMonth: expiryMonth
    });

    // 清空隐藏输入框,准备下一次刷卡
    this.swipeInput.nativeElement.value = '';
  }
}

3. 优化焦点处理(可选)

确保刷卡器输出直接进入隐藏输入框,可在组件初始化时设置焦点:

ngAfterViewInit() {
  this.swipeInput.nativeElement.focus();
}

如果需要保留手动输入功能,可在原有输入框的焦点事件中切换:

<input matInput id="cc-number" 
       (focus)="swipeInput.nativeElement.blur()"
       (blur)="swipeInput.nativeElement.focus()"
       formControlName="creditCard" ... />

内容的提问来源于stack exchange,提问作者coder123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:08:29