@paybyrd/card-collect
Version:
Paybyrd's tool to aid in the creation of credit card info collect forms
236 lines (205 loc) • 5.54 kB
text/typescript
import { CardCollectProps, CardCollectResponse } from '../types/types';
import { generateField } from '../utils/init';
import { validateFields, clearValidations, generateError } from '../utils/validations';
import { getBrandByCardNumber } from '../utils/utils';
import CreditCardPlaceholder from '../icons/CreditCardPlaceholder.svg';
import CreditCardPlaceholderCVV from '../icons/CreditCardPlaceholderCVV.svg';
import CreditCardPlaceholderExpDate from '../icons/CreditCardPlaceholderExpDate.svg';
const handleCardCollectV1 = ({
displayErrors,
onFieldChange = () => {},
validateOnChange,
displayHelpIcons,
onCardCollectFrameLoaded,
i18nMessages
}: CardCollectProps = {}): CardCollectResponse => {
const cHolder = document.getElementById('cc-holder');
const cNumber = document.getElementById('cc-number');
const cExpDate = document.getElementById('cc-expiration-date');
const cCVV = document.getElementById('cc-cvc');
const allFields = [cHolder, cNumber, cExpDate, cCVV];
let isDirty = false;
// Generate fields in DOM
if (cHolder) {
generateField({
wrapper: cHolder,
id: 'pb-cc-holder',
validationType: 'holderName',
customHandleChange: (holderName: string) => {
const { isValid, errors } = validateFields({
holderValue: holderName,
i18nMessages
});
onFieldChange({
fieldId: 'pb-cc-holder',
element: cHolder,
error: errors['cc-holder'],
value: holderName,
isValid
});
if (validateOnChange || isDirty) {
clearValidations([cHolder]);
if (!isValid) {
generateError({
field: cHolder,
displayErrors,
errorData: errors['cc-holder']
});
}
}
}
});
}
if (cNumber) {
generateField({
wrapper: cNumber,
maxLength: 22,
type: 'tel',
id: 'pb-cc-number',
validationType: 'cardNumber',
customHandleChange: (cardNumber: string) => {
const wrapper = cNumber && cNumber.querySelector('.form-field-addornment');
if (wrapper) {
wrapper.innerHTML = getBrandByCardNumber(
(cardNumber || '').replace(/\s+/g, '')
);
}
const { isValid, errors } = validateFields({
cardValue: cardNumber,
i18nMessages
});
onFieldChange({
fieldId: 'pb-cc-number',
element: cNumber,
error: errors['cc-number'],
value: cardNumber,
isValid
});
if (validateOnChange || isDirty) {
clearValidations([cNumber]);
if (!isValid) {
generateError({
field: cNumber,
displayErrors,
errorData: errors['cc-number']
});
}
}
},
inputAddornment: CreditCardPlaceholder
});
}
if (cExpDate) {
generateField({
wrapper: cExpDate,
maxLength: 5,
type: 'tel',
id: 'pb-cc-exp-date',
validationType: 'expirationDate',
eventType: 'keyup',
customHandleChange: (expDate: string) => {
const { isValid, errors } = validateFields({
dateValue: expDate,
i18nMessages
});
onFieldChange({
fieldId: 'pb-cc-exp-date',
element: cExpDate,
error: errors['cc-expiration-date'],
value: expDate,
isValid
});
if (validateOnChange || isDirty) {
clearValidations([cExpDate]);
if (!isValid) {
generateError({
field: cExpDate,
displayErrors,
errorData: errors['cc-expiration-date']
});
}
}
},
inputAddornment: displayHelpIcons ? CreditCardPlaceholderExpDate : undefined
});
}
if (cCVV) {
generateField({
wrapper: cCVV,
maxLength: 4,
type: 'tel',
id: 'pb-cc-cvv',
validationType: 'cvv',
customHandleChange: (cvv: string) => {
const { isValid, errors } = validateFields({
cvvValue: cvv,
i18nMessages
});
onFieldChange({
fieldId: 'pb-cc-cvv',
element: cCVV,
error: errors['cc-cvc'],
value: cvv,
isValid
});
if (validateOnChange || isDirty) {
clearValidations([cCVV]);
if (!isValid) {
generateError({
field: cCVV,
displayErrors,
errorData: errors['cc-cvc']
});
}
}
},
inputAddornment: displayHelpIcons ? CreditCardPlaceholderCVV : undefined
});
}
const submit = () => {
clearValidations(allFields);
const holderValue = cHolder?.getElementsByTagName('input')[0]?.value;
const cardValue = cNumber?.getElementsByTagName('input')[0]?.value.replace(/ /g, '');
let dateValue = cExpDate?.getElementsByTagName('input')[0]?.value.replace('/', '');
const cvvValue = cCVV?.getElementsByTagName('input')[0]?.value;
if (dateValue && /^\d{3,4}$/.test(dateValue)) {
const normalizedDate = dateValue.padStart(4, '0');
dateValue = `${normalizedDate.slice(0, 2)}/${normalizedDate.slice(2)}`;
}
const { isValid, errors } = validateFields({
holderValue,
cardValue,
dateValue,
cvvValue,
i18nMessages
});
if (!isValid) {
isDirty = true;
Object.entries(errors).map((error) => {
const field = document.getElementById(error[0]);
const errorData = error[1];
if (field) {
generateError({
field,
displayErrors,
errorData
});
}
});
return Promise.reject(errors);
}
// Returns all card data so it can be used by the client to finish the payment
return Promise.resolve({
status: 200,
data: {
holderValue: holderValue || '',
cardValue: cardValue || '',
dateValue: dateValue || '',
cvvValue: cvvValue || ''
}
});
};
onCardCollectFrameLoaded?.();
return { cardCollect_submit: submit };
};
export default handleCardCollectV1;