diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c2607f2..223960a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ way to update this template, but currently, we follow a pattern: ## Upcoming version 2019-XX-XX +- [add] Add support for Singapore as the payout country of a provider. Also fix a bug in passing the + personal ID number to Stripe. [#1122](https://github.com/sharetribe/flex-template-web/pull/1122) - [add] Add events.mapbox.com to `connect-src` in `csp.js` file. [#1123](https://github.com/sharetribe/flex-template-web/pull/1123) - [change] Verify email automatically once the verification link is clicked. Redirect the user to diff --git a/src/components/StripeBankAccountTokenInputField/StripeBankAccountTokenInputField.util.js b/src/components/StripeBankAccountTokenInputField/StripeBankAccountTokenInputField.util.js index c095265f..7b479d95 100644 --- a/src/components/StripeBankAccountTokenInputField/StripeBankAccountTokenInputField.util.js +++ b/src/components/StripeBankAccountTokenInputField/StripeBankAccountTokenInputField.util.js @@ -12,8 +12,10 @@ export const INSTITUTION_NUMBER = 'institutionNumber'; export const TRANSIT_NUMBER = 'transitNumber'; // Needed for creating full routing number in Hong Kong export const CLEARING_CODE = 'clearingCode'; -// Needed for creating full routing number in Hong Kong +// Needed for creating full routing number in Hong Kong and Singapore export const BRANCH_CODE = 'branchCode'; +// Needed for creating full routing number in Singapore +export const BANK_CODE = 'bankCode'; // International bank account number (e.g. EU countries use this) export const IBAN = 'iban'; // Routing number to separate bank account in different areas @@ -29,6 +31,7 @@ export const BANK_ACCOUNT_INPUTS = [ INSTITUTION_NUMBER, CLEARING_CODE, BRANCH_CODE, + BANK_CODE, SORT_CODE, ROUTING_NUMBER, ACCOUNT_NUMBER, @@ -190,6 +193,14 @@ export const mapInputsToStripeAccountKeys = (country, values) => { routing_number: cleanedString(values[ROUTING_NUMBER]), account_number: cleanedString(values[ACCOUNT_NUMBER]), }; + case 'SG': + return { + routing_number: cleanedString(values[BANK_CODE]).concat( + '-', + cleanedString(values[BRANCH_CODE]) + ), + account_number: cleanedString(values[ACCOUNT_NUMBER]), + }; case 'HK': return { routing_number: cleanedString(values[CLEARING_CODE]).concat( diff --git a/src/ducks/stripe.duck.js b/src/ducks/stripe.duck.js index ba6833ed..f80923f1 100644 --- a/src/ducks/stripe.duck.js +++ b/src/ducks/stripe.duck.js @@ -278,7 +278,7 @@ const personTokenParams = (personData, country) => { country === 'US' ? { ssn_last_4: personalIdNumber } : personalIdNumber - ? { personal_id_number: personalIdNumber } + ? { id_number: personalIdNumber } : {}; const accountOpenerMaybe = isAccountOpener ? { account_opener: true } : {}; @@ -476,7 +476,7 @@ const accountTokenParamsForIndividual = (individual, country) => { country === 'US' ? { ssn_last_4: personalIdNumber } : personalIdNumber - ? { personal_id_number: personalIdNumber } + ? { id_number: personalIdNumber } : {}; return { diff --git a/src/forms/PayoutDetailsForm/PayoutDetailsPersonalDetails.js b/src/forms/PayoutDetailsForm/PayoutDetailsPersonalDetails.js index b050cc1d..54af048f 100644 --- a/src/forms/PayoutDetailsForm/PayoutDetailsPersonalDetails.js +++ b/src/forms/PayoutDetailsForm/PayoutDetailsPersonalDetails.js @@ -115,6 +115,19 @@ const PayoutDetailsPersonalDetails = props => { }) ); personalIdNumberValid = validators.composeValidators(personalIdNumberRequired, validHKID); + } else if (country === 'SG') { + personalIdNumberLabel = intl.formatMessage({ + id: `PayoutDetailsForm.personalIdNumberLabel.SG`, + }); + personalIdNumberPlaceholder = intl.formatMessage({ + id: `PayoutDetailsForm.personalIdNumberPlaceholder.SG`, + }); + const validSGID = validators.validSGID( + intl.formatMessage({ + id: `PayoutDetailsForm.personalIdNumberValid`, + }) + ); + personalIdNumberValid = validators.composeValidators(personalIdNumberRequired, validSGID); } const phoneLabel = intl.formatMessage({ id: 'PayoutDetailsForm.personalPhoneLabel' }); diff --git a/src/stripe-config.js b/src/stripe-config.js index 34632a06..dd8113d4 100644 --- a/src/stripe-config.js +++ b/src/stripe-config.js @@ -284,6 +284,28 @@ export const stripeSupportedCountries = [ owners: true, }, }, + { + // Singapore + code: 'SG', + currency: 'SGD', + addressConfig: { + addressLine: true, + postalCode: true, + }, + accountConfig: { + bankCode: true, + branchCode: true, + accountNumber: true, + }, + companyConfig: { + personalAddress: true, + owners: true, + personalIdNumberRequired: true, + }, + individualConfig: { + personalIdNumberRequired: true, + }, + }, { // Spain code: 'ES', diff --git a/src/translations/en.json b/src/translations/en.json index c637033b..26c0d8ec 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -533,6 +533,7 @@ "PayoutDetailsForm.companyTaxIdLabel.NZ": "NZBN", "PayoutDetailsForm.companyTaxIdLabel.PT": "N.º Contribuinte", "PayoutDetailsForm.companyTaxIdLabel.SE": "Organisationsnummer", + "PayoutDetailsForm.companyTaxIdLabel.SG": "Unique Entity Number (UEN)", "PayoutDetailsForm.companyTaxIdLabel.US": "Tax ID", "PayoutDetailsForm.companyTaxIdPlaceholder": "Enter {idName}…", "PayoutDetailsForm.companyTaxIdRequired": "{idName} is required", @@ -557,6 +558,7 @@ "PayoutDetailsForm.countryNames.NZ": "New Zealand", "PayoutDetailsForm.countryNames.PT": "Portugal", "PayoutDetailsForm.countryNames.SE": "Sweden", + "PayoutDetailsForm.countryNames.SG": "Singapore", "PayoutDetailsForm.countryNames.US": "United States", "PayoutDetailsForm.countryPlaceholder": "Select your country…", "PayoutDetailsForm.countryRequired": "This field is required", @@ -583,8 +585,10 @@ "PayoutDetailsForm.personalEmailPlaceholder": "Email address", "PayoutDetailsForm.personalEmailRequired": "This field is required", "PayoutDetailsForm.personalIdNumberLabel.HK": "Hong Kong Identity Card Number (HKID)", + "PayoutDetailsForm.personalIdNumberLabel.SG": "National Registration Identity Card (NRIC) or Foreign Identification Number (FIN)", "PayoutDetailsForm.personalIdNumberLabel.US": "Last 4 digits of social security number (SSN)", "PayoutDetailsForm.personalIdNumberPlaceholder.HK": "XY123456", + "PayoutDetailsForm.personalIdNumberPlaceholder.SG": "S8888888A", "PayoutDetailsForm.personalIdNumberPlaceholder.US": "1234", "PayoutDetailsForm.personalIdNumberRequired": "This field is required", "PayoutDetailsForm.personalIdNumberTitle": "Personal id number", @@ -743,6 +747,10 @@ "StripeBankAccountTokenInputField.accountNumber.placeholder": "Type in bank account number…", "StripeBankAccountTokenInputField.accountNumber.required": "Bank account number is required", "StripeBankAccountTokenInputField.andBeforeLastItemInAList": " and", + "StripeBankAccountTokenInputField.bankCode.inline": "bank code", + "StripeBankAccountTokenInputField.bankCode.label": "Bank code", + "StripeBankAccountTokenInputField.bankCode.placeholder": "Type in bank code…", + "StripeBankAccountTokenInputField.bankCode.required": "Bank code is required", "StripeBankAccountTokenInputField.branchCode.inline": "branch code", "StripeBankAccountTokenInputField.branchCode.label": "Branch code", "StripeBankAccountTokenInputField.branchCode.placeholder": "Type in branch code…", diff --git a/src/util/validators.js b/src/util/validators.js index 56e51d00..704f136f 100644 --- a/src/util/validators.js +++ b/src/util/validators.js @@ -219,5 +219,9 @@ export const validHKID = message => value => { return isValid ? VALID : message; }; +export const validSGID = message => value => { + return value.length === 9 ? VALID : message; +}; + export const composeValidators = (...validators) => value => validators.reduce((error, validator) => error || validator(value), VALID);