mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
Add ID number field with validators to US and HK
This commit is contained in:
parent
a137773b82
commit
0cc6cf9663
4 changed files with 108 additions and 18 deletions
|
|
@ -412,6 +412,9 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
|
|||
state: hasProvince ? province : state,
|
||||
};
|
||||
|
||||
const idNumber =
|
||||
country === 'US' ? { ssn_last_4: personalIdNumber } : { personal_id_number: personalIdNumber };
|
||||
|
||||
// Params for Stripe SDK
|
||||
const params = {
|
||||
legal_entity: {
|
||||
|
|
@ -420,7 +423,7 @@ export const createStripeAccount = payoutDetails => (dispatch, getState, sdk) =>
|
|||
address: omitBy(address, isUndefined),
|
||||
dob: birthDate,
|
||||
type: 'individual',
|
||||
personal_id_number: personalIdNumber,
|
||||
...idNumber,
|
||||
},
|
||||
tos_shown_and_accepted: true,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -116,25 +116,47 @@ const PayoutDetailsFormComponent = props => (
|
|||
const bankAccountRequired = validators.required(' ');
|
||||
|
||||
const showPersonalIdNumber =
|
||||
country && stripeCountryConfigs(country).personalIdNumberRequired;
|
||||
(country && stripeCountryConfigs(country).personalIdNumberRequired) ||
|
||||
(country && stripeCountryConfigs(country).ssnLast4Required);
|
||||
|
||||
const personalIdNumberLabel = showPersonalIdNumber
|
||||
? intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberLabel.${country}`,
|
||||
const personalIdNumberRequired = validators.required(
|
||||
intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberRequired`,
|
||||
})
|
||||
);
|
||||
|
||||
let personalIdNumberLabel = null;
|
||||
let personalIdNumberPlaceholder = null;
|
||||
let personalIdNumberValid = personalIdNumberRequired;
|
||||
|
||||
if (country === 'US') {
|
||||
personalIdNumberLabel = intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberLabel.US`,
|
||||
});
|
||||
personalIdNumberPlaceholder = intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberPlaceholder.US`,
|
||||
});
|
||||
|
||||
const validSSN = validators.validSsnLast4(
|
||||
intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberValid`,
|
||||
})
|
||||
: null;
|
||||
const personalIdNumberPlaceholder = showPersonalIdNumber
|
||||
? intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberPlaceholder.${country}`,
|
||||
);
|
||||
personalIdNumberValid = validators.composeValidators(personalIdNumberRequired, validSSN);
|
||||
} else if (country === 'HK') {
|
||||
personalIdNumberLabel = intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberLabel.HK`,
|
||||
});
|
||||
personalIdNumberPlaceholder = intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberPlaceholder.HK`,
|
||||
});
|
||||
const validHKID = validators.validHKID(
|
||||
intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberValid`,
|
||||
})
|
||||
: null;
|
||||
const personalIdNumberRequired = showPersonalIdNumber
|
||||
? validators.required(
|
||||
intl.formatMessage({
|
||||
id: `PayoutDetailsForm.personalIdNumberRequired`,
|
||||
})
|
||||
)
|
||||
: null;
|
||||
);
|
||||
personalIdNumberValid = validators.composeValidators(personalIdNumberRequired, validHKID);
|
||||
}
|
||||
|
||||
const classes = classNames(css.root, className, {
|
||||
[css.disabled]: disabled,
|
||||
|
|
@ -261,7 +283,7 @@ const PayoutDetailsFormComponent = props => (
|
|||
type="text"
|
||||
label={personalIdNumberLabel}
|
||||
placeholder={personalIdNumberPlaceholder}
|
||||
validate={personalIdNumberRequired}
|
||||
validate={personalIdNumberValid}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -503,6 +503,7 @@
|
|||
"PayoutDetailsForm.personalIdNumberLabel.US": "Last 4 digits of social security number (SSN)",
|
||||
"PayoutDetailsForm.personalIdNumberPlaceholder.HK": "XY123456",
|
||||
"PayoutDetailsForm.personalIdNumberRequired": "This field is required",
|
||||
"PayoutDetailsForm.personalIdNumberValid": "Invalid value",
|
||||
"PayoutDetailsForm.postalCodeLabel": "Postal code",
|
||||
"PayoutDetailsForm.postalCodePlaceholder": "00100",
|
||||
"PayoutDetailsForm.postalCodeRequired": "This field is required",
|
||||
|
|
|
|||
|
|
@ -136,5 +136,69 @@ export const ageAtLeast = (message, minYears) => value => {
|
|||
return message;
|
||||
};
|
||||
|
||||
export const validSsnLast4 = message => value => {
|
||||
return value.length === 4 ? VALID : message;
|
||||
};
|
||||
|
||||
export const validHKID = message => value => {
|
||||
// Accept value 000000000 for testing Stripe
|
||||
if (value.length === 9 && value.match(/([0]{9})/)) {
|
||||
return VALID;
|
||||
}
|
||||
|
||||
// HKID format example: AB364912(5)
|
||||
// ID can start with one or two letters and the check digit in the end can be in brackets or not
|
||||
if (value.length < 8) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Handle possible brackets in value
|
||||
if (value.charAt(value.length - 3) === '(' && value.charAt(value.length - 1) === ')') {
|
||||
value = value.substring(0, value.length - 3) + value.charAt(value.length - 2);
|
||||
}
|
||||
value = value.toUpperCase();
|
||||
|
||||
// Check that pattern is correct and split value to array
|
||||
const hkidPattern = /^([A-Z]{1,2})([0-9]{6})([A0-9])$/;
|
||||
const matchArray = value.match(hkidPattern);
|
||||
|
||||
if (!matchArray) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const charPart = matchArray[1];
|
||||
const numPart = matchArray[2];
|
||||
const checkDigit = matchArray[3];
|
||||
|
||||
// Calculate the checksum for character part.
|
||||
// Transfer letters to numbers so that A=10, B=11, C=12 etc.
|
||||
// If there is only one letter in the ID use 36 as the first value
|
||||
// Total calculation is weighted so that 1st digit is x9, 2nd digit x8, 3rd digit x7 etc.
|
||||
|
||||
const strValidChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
let checkSum = 0;
|
||||
|
||||
if (charPart.length === 2) {
|
||||
checkSum += 9 * (10 + strValidChars.indexOf(charPart.charAt(0)));
|
||||
checkSum += 8 * (10 + strValidChars.indexOf(charPart.charAt(1)));
|
||||
} else {
|
||||
checkSum += 9 * 36;
|
||||
checkSum += 8 * (10 + strValidChars.indexOf(charPart));
|
||||
}
|
||||
|
||||
// Calculate the checksum for numeric part
|
||||
|
||||
for (let i = 0, j = 7; i < numPart.length; i++, j--) {
|
||||
checkSum += j * numPart.charAt(i);
|
||||
}
|
||||
|
||||
// Verify the check digit
|
||||
const remaining = checkSum % 11;
|
||||
const verify = remaining === 0 ? 0 : 11 - remaining;
|
||||
const isValid = verify === checkDigit || (verify === 10 && checkDigit === 'A');
|
||||
|
||||
return isValid ? VALID : message;
|
||||
};
|
||||
|
||||
export const composeValidators = (...validators) => value =>
|
||||
validators.reduce((error, validator) => error || validator(value), VALID);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue