简体   繁体   English

使用 Yup 验证信用卡详细信息

[英]Using Yup to validate credit card details

I'm using Yup to validate a signup form but I'm struggling to validate the credit card fields due to needing methods from both Yup's string and number schema.我正在使用Yup来验证注册表单,但由于需要来自 Yup 的stringnumber架构的方法,我正在努力验证信用卡字段。

Card number for example should not exceed 16 characters.例如,卡号不应超过 16 个字符。 This is easily achievable using the max method from the string schema.使用string模式中的max方法可以轻松实现这一点。 However, if the user typed in 16 letters rather than numbers this would currently pass validation.但是,如果用户输入 16 个字母而不是数字,这当前将通过验证。 If I change the schema from string to number then max doesn't behave in the same way and instead adds up all the numbers in the field and checks to see if it equates to less than the max number.如果我将模式从string更改为numbermax不会以相同的方式运行,而是将字段中的所有数字相加并检查它是否等于小于最大数字。

An example of a field where I would need to use the min and max methods of the number schema is the expiry month where the min would be 1 and the max would be 12. However, I still need to check to make sure that the number of characters is in this field is 2 as a leading 0 should be used for the months January to September.我需要使用number架构的minmax方法的字段示例是到期月份,其中最小值为 1,最大值为 12。但是,我仍然需要检查以确保数字此字段中的字符数为 2,因为 1 月至 9 月应使用前导 0。

const validationSchema = {
  cardNumber: Yup.string()
    .label('Card number')
    .max(16)
    .required(),
  cvc: Yup.string()
    .label('CVC')
    .min(3)
    .max(4)
    .required(),
  nameOnCard: Yup.string()
    .label('Name on card')
    .required(),
  expiryMonth: Yup.string()
    .label('Expiry month')
    .min(2)
    .max(2)
    .required(),
  expiryYear: Yup.string()
    .label('Expiry year')
    .min(4)
    .max(4)
    .required(),
};

Instead of doing validation like this, you can use Yup's test method and return true or false given by third-party validators.您可以使用 Yup 的测试方法并返回第三方验证器给出的truefalse ,而不是像这样进行验证。 For example: braintree/card-validator .例如: braintree/card-validator So, it would look something like this:所以,它看起来像这样:

import valid from 'card-validator'; //import statement

CreditCardNumber: 
Yup
    .string()
    .test('test-number', // this is used internally by yup
    'Credit Card number is invalid', //validation message
     value => valid.number(value).isValid) // return true false based on validation
    .required()

There are also valid.expirationDate(value).isValid , valid.cvv(value).isValid and valid.postalCode(value).isValid还有valid.expirationDate(value).isValid , valid.cvv(value).isValidvalid.postalCode(value).isValid

https://github.com/braintree/card-validator https://github.com/braintree/card-validator

https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function-schema https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function-schema

Hope it helps!希望能帮助到你!

Here's how I used Yup's .test() method for validating a credit card's expiration in the past.这是我过去如何使用Yup 的.test()方法来验证信用卡的过期时间。

1) I had to use a mask, and by using a mask the DOM element I had to use was a single input field. 1) 我必须使用掩码,并且通过使用掩码,我必须使用的 DOM 元素是单个输入字段。 The mask looks like this __/__ (two underscores separated by a forward slash)掩码看起来像这样__/__ (两个下划线由正斜杠分隔)

At first, the validation started off as:起初,验证开始于:

export const expirationDate = Yup.string()
  .typeError('Not a valid expiration date. Example: MM/YY')
  .max(5, 'Not a valid expiration date. Example: MM/YY')
  .matches(
    /([0-9]{2})\/([0-9]{2})/,
    'Not a valid expiration date. Example: MM/YY'
  )
  .required('Expiration date is required')

Even though there was server-side validation, I should still do the work to prevent bad inputs such as: 13/19 or 99/99 .即使有服务器端验证,我仍然应该做一些工作来防止错误的输入,例如: 13/1999/99 Why waste a roundtrip network call.为什么要浪费往返网络电话。 So, in between the .matches() and .required() method calls I added:因此,在.matches().required()方法调用之间,我添加了:

.test(
    'test-credit-card-expiration-date',
    'Invalid Expiration Date has past',
    expirationDate => {
      if (!expirationDate) {
        return false
      }

      const today = new Date()
      const monthToday = today.getMonth() + 1
      const yearToday = today
        .getFullYear()
        .toString()
        .substr(-2)

      const [expMonth, expYear] = expirationDate.split('/')

      if (Number(expYear) < Number(yearToday)) {
        return false
      } else if (
        Number(expMonth) < monthToday &&
        Number(expYear) <= Number(yearToday)
      ) {
        return false
      }

      return true
    }
  )
  .test(
    'test-credit-card-expiration-date',
    'Invalid Expiration Month',
    expirationDate => {
      if (!expirationDate) {
        return false
      }
      const today = new Date()
        .getFullYear()
        .toString()
        .substr(-2)

      const [expMonth] = expirationDate.split('/')

      if (Number(expMonth) > 12) {
        return false
      }

      return true
    }
  )

references:参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM