sbycrosz / react-native-credit-card-input

Easy, cross-platform credit-card input for your React Native Project! Start accepting payment 💰 in your app today!
MIT License
1.47k stars 706 forks source link

Credit card input allow me to add 19 numbers instead of just 16 #148

Closed edoantonioco closed 5 years ago

edoantonioco commented 5 years ago

The credit card input allow me to add 19 characters, instead of the 16 characters that credit cards have.

This on latest version, 0.4.1 And I dont see a way to control that in the library settings

Screenshot_20190712_102858

edoantonioco commented 5 years ago

I cant repro this issue anymore, which is great. No idea why it happened, and I hope it wont happen again.

sailykeepitonthelow commented 3 years ago

@edoantonioco I am still facing this issue when you enter the wrong number then you will be able to get this issue. Can you help me resolve this issue?

IhorReactNative commented 2 years ago

Maybe for someone will be helpful.

To fix it use lib "patch-package", install to your project. (don't miss to add postinstall script)

Then going to YOUR_PROJECT_DIR/node_modules/react-native-credit-card-input/src/CCFieldValidator.js

Above function "toStatus" add new function. And from now it will mark card as valid when validation.isPotentiallyValid and card have 16 digits.

const cardNumberToStatus = (validation, cardNumbersFilled) => {
  return validation.isValid || (validation.isPotentiallyValid && cardNumbersFilled)
  ? 'valid'
  : validation.isPotentiallyValid
    ? 'incomplete'
    : 'invalid';
};

After going to edit class CCFieldValidator, method "validateValues". Looking for fields validations and below will add next code part

let cardNumberFilled = false;
if(formValues.number){
  const cardNumberBlocks = formValues.number.split(' ');
  cardNumberFilled = cardNumberBlocks.length === 4 && cardNumberBlocks[3].length === 4;
}

and in "const validationStatuses = ..." changing object key/value from number: toStatus(numberValidation), to number: cardNumberToStatus(numberValidation, cardNumberFilled),

Summary file will look like

import valid from "card-validator";
import pick from "lodash.pick";
import values from "lodash.values";
import every from "lodash.every";

const cardNumberToStatus = (validation, cardNumbersFilled) => {
  return validation.isValid || (validation.isPotentiallyValid && cardNumbersFilled)
  ? 'valid'
  : validation.isPotentiallyValid
    ? 'incomplete'
    : 'invalid';
};

const toStatus = validation => {
  return validation.isValid ? "valid" :
  validation.isPotentiallyValid ? "incomplete" :
  "invalid";
};

const FALLBACK_CARD = { gaps: [4, 8, 12], lengths: [16], code: { size: 3 } };

export default class CCFieldValidator {
  constructor(displayedFields, validatePostalCode) {
    this._displayedFields = displayedFields;
    this._validatePostalCode = validatePostalCode;
  }

  validateValues = (formValues) => {
    const numberValidation = valid.number(formValues.number);
    const expiryValidation = valid.expirationDate(formValues.expiry);
    const maxCVCLength = (numberValidation.card || FALLBACK_CARD).code.size;
    const cvcValidation = valid.cvv(formValues.cvc, maxCVCLength);

    let cardNumberFilled = false;
    if(formValues.number){
      const cardNumberBlocks = formValues.number.split(' ');
      cardNumberFilled = cardNumberBlocks.length === 4 && cardNumberBlocks[3].length === 4;
    }

    const validationStatuses = pick({
      number: cardNumberToStatus(numberValidation, cardNumberFilled),
      expiry: toStatus(expiryValidation),
      cvc: toStatus(cvcValidation),
      name: !!formValues.name ? "valid" : "incomplete",
      postalCode: this._validatePostalCode(formValues.postalCode),
    }, this._displayedFields);

    return {
      valid: every(values(validationStatuses), status => status === "valid"),
      status: validationStatuses,
    };
  };
}

In the end creating patch file using command yarn patch-package react-native-credit-card-input or npx patch-package react-native-credit-card-input.

UPD: added change to file YOUR_PROJECT_DIR/node_modules/react-native-credit-card-input/src/CCFieldFormatter.js

_formatNumber = (number, card) => {
    const numberSanitized = removeNonNumber(number);
    const maxLength = card.lengths[0];
    const lengthSanitized = limitLength(numberSanitized, maxLength);
    return lengthSanitized.length > maxLength ? addGaps(lengthSanitized.slice(0, maxLength + 1, card.gaps)) : addGaps(lengthSanitized, card.gaps);
};