ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

wp-calypso 结账表单校验与输入掩码:getCreditCardType 与 maskField 实战解析

wp-calypso 结账表单校验与输入掩码:getCreditCardType 与 maskField 实战解析 前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载本指南以 client/lib/checkout/README.md 为核心深入讲解 WordPress.com 前端项目 wp-calypso 中负责**信用卡信息校验与表单字段掩码masking**的 checkout 工具模块。通过阅读本文你将掌握两个核心 API——getCreditCardType()识别卡品牌与maskField()格式化/掩码输入值——的实现原理、各字段的格式化规则、真实调用场景与测试用例并能在自己的支付表单中直接复用这套方案。模块定位与目录结构client/lib/checkout是一个轻量的纯工具模块职责非常单一校验并掩码结账表单字段如信用卡卡号、有效期、CVV、巴西 CPF/CNPJ 证件号。它不依赖任何 UI 框架导出的是两个无副作用的纯函数因此既可以在 React 组件中使用也可以嵌入到wordpress/data的 reducer 中等非渲染场景。模块的完整结构如下client/lib/checkout/index.js —— 公共入口统一导出两个 APIclient/lib/checkout/validation.ts —— 卡品牌识别逻辑getCreditCardTypeclient/lib/checkout/masking.js —— 字段掩码/格式化逻辑maskField及各字段掩码规则client/lib/checkout/test/validation.js —— 卡品牌识别测试client/lib/checkout/test/masking.js —— 掩码行为测试。入口文件 index.js 的全部内容就是两行转发对外暴露的 API 面极其稳定export { getCreditCardType } from ./validation; export { maskField } from ./masking;这意味着项目内其他模块统一通过calypso/lib/checkout这个路径引用而不关心内部实现细节后续若替换底层库例如换掉creditcards也无需改动调用方。卡品牌识别getCreditCardType( number )签名与返回值getCreditCardType( number?: string ): string | null传入一个卡号字符串可为空返回该卡对应的品牌标识。返回值是小写字符串例如visa、mastercard、amex、discover、jcb、diners、unionpay无法识别时返回null。实现原理完整实现在 validation.ts核心逻辑如下import creditcards from creditcards; export function getCreditCardType( number?: string ): string | null { if ( number ) { number number.replace( / /g, ); let cardType creditcards.card.type( number, true ); if ( typeof cardType undefined ) { return null; } // We already use amex for American Express everywhere else if ( cardType American Express ) { cardType amex; } // Normalize Diners as well if ( cardType Diners Club ) { cardType diners; } return cardType.toLowerCase(); } return null; }几个值得注意的细节先剥离空格再识别number.replace( / /g, )保证带格式如4242 4242 4242 4242的输入也能正确识别与掩码逻辑无缝配合。底层依赖creditcards库品牌判定交由 npm 包creditcards当前仓库锁定版本为creditcardsnpm:^3.1.0见 yarn.lock。creditcards.card.type( number, true )的第二个参数true表示按银行识别号IIN/BIN即卡号前若干位进行品牌归属判断。品牌归一化creditcards返回的原始名称为American Express、Diners Club而项目其余代码统一使用amex、diners简写因此这里做了显式映射后再统一toLowerCase()保证全项目命名一致。各品牌识别范围来自测试用例test/validation.js 用真实测试号锁定了识别边界这些范围可以直接作为业务判断依据品牌识别范围 / 前缀测试示例visa以 4 开头4242424242424242、4000000400000008mastercard范围 2221–2720 与 51–552221000000000000、2720990000000000、5100000000000000、5599000000000000amex37/34 开头15 位370000000000002、378282246310005discover6011、64、65 开头6011000990139424、6445644564456445jcb35 开头3530111333300000diners30/36/38/39 开头30569309025904、38520000023237unionpay62 开头6240008631401148测试中还覆盖了边界防误判例如509999999999999950 开头不被识别为mastercard560000000000000056 开头不是mastercard622125不被识别为discover——说明底层库按完整的 BIN 范围表而非简单的首位数前缀判断。在真实组件中的调用方式getCreditCardType最典型的调用方是卡号输入框组件 client/components/upgrades/credit-card-number-input/index.jsximport { getCreditCardType } from calypso/lib/checkout; class CreditCardNumberInput extends Component { render() { return ( div classNamecredit-card-number-input Input { ...this.props } classes{ getCreditCardType( this.props.value ) } / /div ); } }这里把识别的品牌名直接作为 CSS 类名传给输入框如classesvisa、classesamexUI 层据此渲染对应的卡组织图标与样式无需在组件内重复实现品牌判断逻辑。字段掩码maskField( fieldName, previousValue, nextValue )签名与行为契约maskField( fieldName, previousValue, nextValue ) // stringfieldName字段名对应内部掩码表的一个键previousValue字段变更前的当前值nextValue用户输入产生的新值返回值经过格式化/清洗后的值。其实现masking.js非常直接先在fieldMasks表中按字段名查掩码规则查不到就原样返回nextValue白名单策略未知字段不做任何处理export function maskField( fieldName, previousValue, nextValue ) { const fieldMask fieldMasks[ fieldName ]; if ( ! fieldMask ) { return nextValue; } return fieldMask.mask( previousValue, nextValue ); }fieldMasks表masking.js目前注册了四个字段number、expiration-date、cvv、document。卡号字段number卡号掩码委托给formatCreditCard( cardNumber )masking.js其格式化规则为先通过getCreditCardType判断品牌American Express 走专用格式其余卡统一清洗掉非数字字符、截断到最多 19 位再按4-4-4-7分组。以 test/masking.js 中的用例为准各品牌的分组差异一目了然输入输出分组3782822463100053782 822463 10005Amex4-6-515 位305693090259043056 9309 0259 04Diners4-4-4-214 位22230031220032222223 0031 2200 3222普通卡4-4-4-416 位60114962336089739386011 4962 3360 897393819 位卡4-4-4-7同时测试验证了容错与截断能力输入带任意空白如 3782 8224 6310 005 会被规整为3782 822463 10005超过最大位数的输入如 20 余位会被裁剪到品牌允许的最大长度Amex 15 位、其他 19 位。Amex 专用格式formatAmexCreditCardmasking.js将 15 位数字按4-6-5分三组即3782 822463 10005的形态。有效期字段expiration-date掩码规则masking.js按“可删除性优先、格式化次之”的顺序处理模拟了真实的输入体验mask: function ( previousValue, nextValue ) { // 用户在删除字符时不干预原样返回 if ( previousValue previousValue.length nextValue.length ) { return nextValue; } // 用户刚键入分隔符 / 时不干预 if ( previousValue previousValue.length 2 nextValue.length 3 nextValue[ 2 ] / ) { return nextValue; } // 清洗掉非数字字符 nextValue nextValue.replace( /[^\d]/g, ); if ( nextValue.length 2 ) { return nextValue; } // 自动插入斜杠形如 MM/YY return nextValue.substring( 0, 2 ) / nextValue.substring( 2, 4 ); },行为要点删除保护02/33状态下删除到12会原样返回12不会自动补成12/之类的干扰性格式自动补斜杠输入超过 2 位数字后自动插入/如输入2222得到22/22清洗非法字符10/ee被清洗为1010/2#清洗为10/2w$%直接变为空字符串长度保护最多保留 4 位数字MM/YY超出部分被丢弃。测试 test/masking.js 还覆盖了previousValue与新值长度比较的各种场景确保格式化只在“新增字符”时触发。CVV 字段cvv规则最简单masking.js只保留数字并截断到 4 位兼容 Amex 的 4 位 CVVmask: function ( previousValue, nextValue ) { return nextValue.replace( /[^\d]/g, ).substring( 0, 4 ); },测试用例maskField( cvv, null, 5$5.5w6 6_666 )返回5556maskField( cvv, null, 333111222000 )返回3331直观展示了清洗与截断效果。证件字段document巴西 CPF/CNPJdocument是EBANX巴西本地支付网关使用的字段用于收集巴西纳税人的 CPF个人11 位或 CNPJ企业14 位证件号。掩码规则masking.js会先按数字位数自动判断类型再格式化数字位数 11按 CNPJ 格式XX.XXX.XXX/XXXX-XX否则按 CPF 格式XXX.XXX.XXX-XX最后用replace( /^[\s.-]|[\s.-]$/g, )去掉首尾残留的分隔符。源码注释还提到该字段对应的isValidCPF()/isValidCNPJ()校验函数位于ebanx.jsmasking.js 注释说明掩码只是展示层真正的有效性校验由 EBANX 侧负责前端只保证格式可读、可提交。在结账流程中的真实集成wpcom-credit-cardstoremaskField最核心的生产环境用法位于信用卡支付方式的状态仓库 client/my-sites/checkout/src/payment-methods/credit-card/store.ts。该文件用wordpress/data注册了wpcom-credit-cardstore并在FIELD_VALUE_SETaction 的 reducer 中统一对每个字段的输入做掩码store.tscase FIELD_VALUE_SET: return { ...state, [ action.payload.key ]: { value: maskField( action.payload.key, state[ action.payload.key ]?.value, action.payload.value ), isTouched: true, errors: [], }, };这段代码展示了maskField的典型接入模式把previousValue与nextValue都交给掩码函数由它决定是格式化、清洗还是原样放行。UI 层如 credit-card-expiry-field.tsx 中nameexpiration-date的输入框在onChange时调用setFieldValue( expiration-date, event.target.value )最终呈现给用户的永远是掩码后的整洁格式。也正是这种“reducer 内统一掩码”的架构使得卡号、有效期、CVV 的输入体验自动分组、自动插斜杠、非法字符清洗、删除保护与结账状态机解耦——无论输入来自键盘、粘贴还是浏览器自动填充都经过同一套规则收敛。测试保障与行为边界模块附带两组 Jest 测试把关键行为固化为可回归的契约test/validation.js覆盖 7 种卡品牌的识别、BIN 边界如 2221–2720、51–55、6011/64/65与误判排除test/masking.js覆盖卡号四种分组4-6-5 / 4-4-4-2 / 4-4-4-4 / 4-4-4-7、Amex 截断、CVV 清洗与 4 位上限、有效期删除保护与自动插斜杠。两个测试文件头部都声明了jest-environment jsdom说明这些测试虽然本质上是纯函数断言但在 jsdom 环境下运行以兼容更宽的 DOM 依赖场景。小结client/lib/checkout模块以两个纯函数撑起了 wp-calypso 结账表单的两大刚需getCreditCardType—— 基于creditcards库 品牌归一化为卡号输入框提供品牌识别能力驱动 CSS 类、卡组织图标识别结果全项目统一为小写短名amex/diners等maskField—— 通过可扩展的fieldMasks白名单表为number、expiration-date、cvv、document四个字段提供一致的掩码体验未知字段原样放行且删除操作永远不被“帮倒忙”。对任何需要处理支付表单的开发者这套“识别 掩码 reducer 统一接入 测试锁定”的组合拳都值得直接借鉴把格式逻辑收敛为纯函数、通过字段表扩展新格式、在状态层统一应用即可在保持代码极简的同时获得稳定可回归的输入体验。赞分享前端CMS【免费下载链接】wp-calypsoThe JavaScript and API powered WordPress.com项目地址https://gitcode.com/gh_mirrors/wp/wp-calypso点击查看免费下载相关推荐wp-calypso 表单输入组件 FormTextInput 完全指南样式、状态与校验指示器的实现剖析wp calypso 表单输入组件 FormTextInput 完全指南样式、状态与校验指示器的实现剖析 导读 FormTextInput / 是 wp c前端CMSwp-calypso AccountPassword 组件解析WordPress.com 密码修改表单的实时校验、强密码生成与保存闭环wp calypso AccountPassword 组件解析WordPress.com 密码修改表单的实时校验、强密码生成与保存闭环 在 wp calyps前端CMSwp-calypso 域名注册人附加信息表单模块解析TLD 专属表单设计、JSON Schema 验证与结账集成wp calypso 域名注册人附加信息表单模块解析TLD 专属表单设计、JSON Schema 验证与结账集成 导读 .uk 、 .ca 、 .fr 、 .前端CMS上一篇MiniMind快速实战2小时3元从零训出64M小模型下一篇AgentScope 2.0构建生产级智能体系统的架构实践与技术解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表