mirror of
https://github.com/jlengrand/adyen-web.git
synced 2026-03-10 08:01:22 +00:00
Add support for Ratepay Direct Debit (#1552)
* wip: ratepay * clean up ratepay direct debit * fix unit tests for IbanInput * small test code review changes * fixed types * fix scss removed * skip unit test
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ coverage
|
||||
|
||||
*.log*
|
||||
.env
|
||||
.env*
|
||||
stats.json
|
||||
stats.html
|
||||
.DS_Store
|
||||
|
||||
41
packages/e2e/tests/openInvoices/afterpay/ratepay.test.js
Normal file
41
packages/e2e/tests/openInvoices/afterpay/ratepay.test.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { ClientFunction, Selector } from 'testcafe';
|
||||
import { OPENINVOICES_URL } from '../../pages';
|
||||
|
||||
fixture`Testing RatePay (OpenInvoices)`.page(`${OPENINVOICES_URL}?countryCode=NL`);
|
||||
|
||||
const getComponentData = ClientFunction(() => {
|
||||
return window.afterpay.data;
|
||||
});
|
||||
|
||||
const mockAddressGermany = {
|
||||
city: 'City',
|
||||
country: 'DE',
|
||||
houseNumberOrName: '123',
|
||||
postalCode: '12345',
|
||||
stateOrProvince: 'N/A',
|
||||
street: 'Street'
|
||||
};
|
||||
|
||||
test.skip('should make an RatePay Direct Debit payment', async t => {
|
||||
const checkboxLabelGender = Selector('.ratepay-direct-field .adyen-checkout__field--gender .adyen-checkout__radio_group__label');
|
||||
const payButton = Selector('.ratepay-direct-field adyen-checkout__button--pay');
|
||||
|
||||
// Opens dropdown
|
||||
await t
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--firstName', 'First')
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--lastName', 'Last')
|
||||
// Click checkbox (in reality click its label - for some reason clicking the actual checkboxes takes ages)
|
||||
.click(checkboxLabelGender.nth(0))
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--dateOfBirth', '01011990', { caretPos: 1 })
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--shopperEmail', 'test@test.com')
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--telephoneNumber', '612345678')
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__iban-input__owner-name', 'A. Schneider')
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__iban-input__iban-number', 'DE87123456781234567890')
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--street', mockAddressGermany.street)
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--houseNumberOrName', mockAddressGermany.houseNumberOrName)
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--city', mockAddressGermany.city)
|
||||
.typeText('.ratepay-direct-field .adyen-checkout__input--postalCode', mockAddressGermany.postalCode)
|
||||
// Can't use the checkboxLabelGender trick to speed up the click 'cos this label contains a link - so use a Selector with a timeout
|
||||
.click(payButton)
|
||||
.wait(5000);
|
||||
});
|
||||
@@ -2,11 +2,12 @@ import { h } from 'preact';
|
||||
import OpenInvoiceContainer from '../helpers/OpenInvoiceContainer';
|
||||
import ConsentCheckboxLabel from './components/ConsentCheckboxLabel';
|
||||
import { AFTERPAY_B2B_CONSENT_URL, ALLOWED_COUNTRIES } from './config';
|
||||
import {OpenInvoiceContainerProps} from "../helpers/OpenInvoiceContainer/OpenInvoiceContainer";
|
||||
|
||||
export default class AfterPayB2B extends OpenInvoiceContainer {
|
||||
public static type = 'afterpay_b2b';
|
||||
|
||||
protected static defaultProps = {
|
||||
protected static defaultProps: OpenInvoiceContainerProps = {
|
||||
onChange: () => {},
|
||||
data: { companyDetails: {}, personalDetails: {}, billingAddress: {}, deliveryAddress: {} },
|
||||
visibility: {
|
||||
|
||||
13
packages/lib/src/components/RatePay/RatePayDirectDebit.ts
Normal file
13
packages/lib/src/components/RatePay/RatePayDirectDebit.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import OpenInvoiceContainer from '../helpers/OpenInvoiceContainer';
|
||||
import { ALLOWED_COUNTRIES } from './config';
|
||||
|
||||
export default class RatePayDirectDebit extends OpenInvoiceContainer {
|
||||
public static type = 'ratepay_directdebit';
|
||||
|
||||
formatProps(props) {
|
||||
return {
|
||||
...super.formatProps({ ...props, ...{ visibility: { bankAccount: 'editable' } } }),
|
||||
allowedCountries: props.countryCode ? [props.countryCode] : ALLOWED_COUNTRIES
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ describe('Sepa', () => {
|
||||
const mockStateChange = sepa => {
|
||||
sepa.setState({
|
||||
data: {
|
||||
'sepa.ownerName': 'A. Klaassen',
|
||||
'sepa.ibanNumber': 'NL13TEST0123456789'
|
||||
'ownerName': 'A. Klaassen',
|
||||
'ibanNumber': 'NL13TEST0123456789'
|
||||
},
|
||||
isValid: true
|
||||
});
|
||||
@@ -15,8 +15,8 @@ describe('Sepa', () => {
|
||||
const mockInvalidStateChange = sepa => {
|
||||
sepa.setState({
|
||||
data: {
|
||||
'sepa.ownerName': 'A. Klaassen',
|
||||
'sepa.ibanNumber': 'NOTANIBAN'
|
||||
'ownerName': 'A. Klaassen',
|
||||
'ibanNumber': 'NOTANIBAN'
|
||||
},
|
||||
isValid: false
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { h } from 'preact';
|
||||
import UIElement from '../UIElement';
|
||||
import IbanInput from './components/IbanInput';
|
||||
import IbanInput from '../internal/IbanInput';
|
||||
import CoreProvider from '../../core/Context/CoreProvider';
|
||||
import { SepaElementData } from './types';
|
||||
|
||||
@@ -27,8 +27,8 @@ class SepaElement extends UIElement {
|
||||
return {
|
||||
paymentMethod: {
|
||||
type: SepaElement.type,
|
||||
iban: this.state.data['sepa.ibanNumber'],
|
||||
ownerName: this.state.data['sepa.ownerName']
|
||||
iban: this.state.data['ibanNumber'],
|
||||
ownerName: this.state.data['ownerName']
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.adyen-checkout__iban-input__number {
|
||||
text-transform: uppercase;
|
||||
padding: 5px 36px 5px 8px;
|
||||
}
|
||||
@@ -2,27 +2,25 @@ import { h } from 'preact';
|
||||
import UIElement from '../../UIElement';
|
||||
import OpenInvoice from '../../internal/OpenInvoice';
|
||||
import CoreProvider from '../../../core/Context/CoreProvider';
|
||||
import { UIElementProps } from '../../types';
|
||||
import { OpenInvoiceProps } from '../../internal/OpenInvoice/types';
|
||||
import { AddressSpecifications } from '../../internal/Address/types';
|
||||
|
||||
interface OpenInvoiceElementProps extends UIElementProps {
|
||||
export interface OpenInvoiceContainerProps extends Partial<OpenInvoiceProps>{
|
||||
consentCheckboxLabel?: h.JSX.Element;
|
||||
billingAddressRequiredFields?: string[];
|
||||
billingAddressSpecification?: AddressSpecifications;
|
||||
|
||||
// TODO: add other props for OpenInvoiceElement
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export default class OpenInvoiceContainer extends UIElement<OpenInvoiceElementProps> {
|
||||
protected static defaultProps = {
|
||||
export default class OpenInvoiceContainer extends UIElement<OpenInvoiceContainerProps> {
|
||||
protected static defaultProps: OpenInvoiceContainerProps = {
|
||||
onChange: () => {},
|
||||
data: { companyDetails: {}, personalDetails: {}, billingAddress: {}, deliveryAddress: {} },
|
||||
data: { companyDetails: {}, personalDetails: {}, billingAddress: {}, deliveryAddress: {}, bankAccount: {} },
|
||||
visibility: {
|
||||
companyDetails: 'hidden',
|
||||
personalDetails: 'editable',
|
||||
billingAddress: 'editable',
|
||||
deliveryAddress: 'editable'
|
||||
deliveryAddress: 'editable',
|
||||
bankAccount: 'hidden'
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,7 +63,7 @@ export default class OpenInvoiceContainer extends UIElement<OpenInvoiceElementPr
|
||||
*/
|
||||
formatData() {
|
||||
const { data = {} } = this.state;
|
||||
const { companyDetails = {}, personalDetails = {}, billingAddress, deliveryAddress } = data;
|
||||
const { companyDetails = {}, personalDetails = {}, billingAddress, deliveryAddress, bankAccount } = data;
|
||||
|
||||
return {
|
||||
paymentMethod: {
|
||||
@@ -73,6 +71,13 @@ export default class OpenInvoiceContainer extends UIElement<OpenInvoiceElementPr
|
||||
},
|
||||
...personalDetails,
|
||||
...companyDetails,
|
||||
...(bankAccount && {
|
||||
bankAccount: {
|
||||
iban: bankAccount.ibanNumber,
|
||||
ownerName: bankAccount.ownerName,
|
||||
countryCode: bankAccount.countryCode
|
||||
}
|
||||
}),
|
||||
...(billingAddress && { billingAddress }),
|
||||
...((deliveryAddress || billingAddress) && { deliveryAddress: deliveryAddress || billingAddress })
|
||||
};
|
||||
|
||||
@@ -49,6 +49,7 @@ import Klarna from './Klarna';
|
||||
import Twint from './Twint';
|
||||
import MealVoucherFR from './MealVoucherFR';
|
||||
import OnlineBankingINElement from './OnlineBankingIN';
|
||||
import RatePayDirectDebit from "./RatePay/RatePayDirectDebit";
|
||||
|
||||
/**
|
||||
* Maps each component with a Component element.
|
||||
@@ -137,6 +138,7 @@ const componentsMap = {
|
||||
pix: Pix,
|
||||
qiwiwallet: QiwiWallet,
|
||||
ratepay: RatePay,
|
||||
ratepay_directdebit: RatePayDirectDebit,
|
||||
redirect: Redirect,
|
||||
securedfields: SecuredFields,
|
||||
sepadirectdebit: Sepa,
|
||||
|
||||
@@ -9,8 +9,8 @@ const createWrapper = (props?) => mount(<IbanInput i18n={i18n} {...props} />);
|
||||
describe('IbanInput', () => {
|
||||
test('Renders two fields', () => {
|
||||
const wrapper = createWrapper();
|
||||
expect(wrapper.find('input[name="sepa.ownerName"]')).toHaveLength(1);
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]')).toHaveLength(1);
|
||||
expect(wrapper.find('input[name="ownerName"]')).toHaveLength(1);
|
||||
expect(wrapper.find('input[name="ibanNumber"]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
describe('Validation Errors', () => {
|
||||
@@ -19,12 +19,12 @@ describe('IbanInput', () => {
|
||||
wrapper.instance().setError('iban', true);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.adyen-checkout__field--error')).toHaveLength(1);
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').prop('aria-invalid')).toBe(true);
|
||||
expect(wrapper.find('input[name="ibanNumber"]').prop('aria-invalid')).toBe(true);
|
||||
|
||||
wrapper.instance().setError('iban', false);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('.adyen-checkout__field--error')).toHaveLength(0);
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').prop('aria-invalid')).toBe(false);
|
||||
expect(wrapper.find('input[name="ibanNumber"]').prop('aria-invalid')).toBe(false);
|
||||
});
|
||||
|
||||
test('Set holderName errors', () => {
|
||||
@@ -55,42 +55,42 @@ describe('IbanInput', () => {
|
||||
describe('Placeholders', () => {
|
||||
test('Set iban placeholder', () => {
|
||||
const wrapper = createWrapper({ placeholders: { ibanNumber: 'test' } });
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').prop('placeholder')).toBe('test');
|
||||
expect(wrapper.find('input[name="ibanNumber"]').prop('placeholder')).toBe('test');
|
||||
});
|
||||
|
||||
test('Set holderName placeholder', () => {
|
||||
const wrapper = createWrapper({ placeholders: { ownerName: 'test' } });
|
||||
expect(wrapper.find('input[name="sepa.ownerName"]').prop('placeholder')).toBe('test');
|
||||
expect(wrapper.find('input[name="ownerName"]').prop('placeholder')).toBe('test');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Send values from outside', () => {
|
||||
test('Set ibanNumber', () => {
|
||||
const wrapper = createWrapper({ data: { 'sepa.ibanNumber': 'NL13TEST0123456789' } });
|
||||
const wrapper = createWrapper({ data: { 'ibanNumber': 'NL13TEST0123456789' } });
|
||||
setTimeout(() => {
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
expect(wrapper.find('input[name="ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
});
|
||||
});
|
||||
|
||||
test('Set ibanNumber formatted', () => {
|
||||
const wrapper = createWrapper({ data: { 'sepa.ibanNumber': 'NL13 TEST 0123 4567 89' } });
|
||||
const wrapper = createWrapper({ data: { 'ibanNumber': 'NL13 TEST 0123 4567 89' } });
|
||||
setTimeout(() => {
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
expect(wrapper.find('input[name="ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
});
|
||||
});
|
||||
|
||||
test('Set ownerName', () => {
|
||||
const wrapper = createWrapper({ data: { 'sepa.ownerName': 'Hello World' } });
|
||||
const wrapper = createWrapper({ data: { 'ownerName': 'Hello World' } });
|
||||
setTimeout(() => {
|
||||
expect(wrapper.find('input[name="sepa.ownerName"]').text()).toBe('Hello World');
|
||||
expect(wrapper.find('input[name="ownerName"]').text()).toBe('Hello World');
|
||||
});
|
||||
});
|
||||
|
||||
test('Set ibanNumber and ownerName', () => {
|
||||
const wrapper = createWrapper({ data: { 'sepa.ibanNumber': 'NL13TEST0123456789', 'sepa.ownerName': 'Hello World' } });
|
||||
const wrapper = createWrapper({ data: { 'ibanNumber': 'NL13TEST0123456789', 'ownerName': 'Hello World' } });
|
||||
setTimeout(() => {
|
||||
expect(wrapper.find('input[name="sepa.ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
expect(wrapper.find('input[name="sepa.ownerName"]').text()).toBe('Hello World');
|
||||
expect(wrapper.find('input[name="ibanNumber"]').text()).toBe('NL13 TEST 0123 4567 89');
|
||||
expect(wrapper.find('input[name="ownerName"]').text()).toBe('Hello World');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,18 +1,26 @@
|
||||
import { Component, h, RefObject } from 'preact';
|
||||
import useCoreContext from '../../../../core/Context/useCoreContext';
|
||||
import { renderFormField } from '../../../internal/FormFields';
|
||||
import Field from '../../../internal/FormFields/Field';
|
||||
import useCoreContext from '../../../core/Context/useCoreContext';
|
||||
import { renderFormField } from '../FormFields';
|
||||
import Field from '../FormFields/Field';
|
||||
import { checkIbanStatus, isValidHolder } from './validate';
|
||||
import { electronicFormat, formatIban, getIbanPlaceHolder, getNextCursorPosition } from './utils';
|
||||
import './IbanInput.scss';
|
||||
import { electronicFormat, formatIban, getCountryCode, getIbanPlaceHolder, getNextCursorPosition } from './utils';
|
||||
import Fieldset from '../FormFields/Fieldset';
|
||||
|
||||
interface IbanInputProps {
|
||||
holderName?: string;
|
||||
holderName?: boolean;
|
||||
placeholders?: any;
|
||||
countryCode?: string;
|
||||
showPayButton?: any;
|
||||
payButton?: any;
|
||||
onChange: (data) => void;
|
||||
label: string;
|
||||
data: IbanData;
|
||||
}
|
||||
|
||||
interface IbanData {
|
||||
ownerName?: string;
|
||||
ibanNumber?: string;
|
||||
countryCode?: string;
|
||||
}
|
||||
|
||||
interface IbanInputState {
|
||||
@@ -23,6 +31,7 @@ interface IbanInputState {
|
||||
isValid: boolean;
|
||||
cursor: number;
|
||||
}
|
||||
|
||||
class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
private ibanNumber: RefObject<any>;
|
||||
|
||||
@@ -32,8 +41,9 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
this.state = {
|
||||
status: 'ready',
|
||||
data: {
|
||||
'sepa.ownerName': props?.data?.ownerName || '',
|
||||
'sepa.ibanNumber': props?.data?.ibanNumber || ''
|
||||
ownerName: props?.data?.ownerName || '',
|
||||
ibanNumber: props?.data?.ibanNumber || '',
|
||||
countryCode: props?.data?.countryCode || ''
|
||||
},
|
||||
isValid: false,
|
||||
cursor: 0,
|
||||
@@ -41,14 +51,14 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
valid: {}
|
||||
};
|
||||
|
||||
if (this.state.data['sepa.ibanNumber']) {
|
||||
const electronicFormatIban = electronicFormat(this.state.data['sepa.ibanNumber']); // example: NL13TEST0123456789
|
||||
this.state.data['sepa.ibanNumber'] = formatIban(electronicFormatIban); // example: NL13 TEST 0123 4567 89
|
||||
if (this.state.data['ibanNumber']) {
|
||||
const electronicFormatIban = electronicFormat(this.state.data['ibanNumber']); // example: NL13TEST0123456789
|
||||
this.state.data['ibanNumber'] = formatIban(electronicFormatIban); // example: NL13 TEST 0123 4567 89
|
||||
}
|
||||
|
||||
if (this.state.data['sepa.ibanNumber'] || this.state.data['sepa.ownerName']) {
|
||||
const holderNameValid = this.props.holderName ? isValidHolder(this.state.data['sepa.ownerName']) : '';
|
||||
const ibanValid = this.state.data['sepa.ibanNumber'] ? checkIbanStatus(this.state.data['sepa.ibanNumber']).status === 'valid' : '';
|
||||
if (this.state.data['ibanNumber'] || this.state.data['ownerName']) {
|
||||
const holderNameValid = this.props.holderName ? isValidHolder(this.state.data['ownerName']) : '';
|
||||
const ibanValid = this.state.data['ibanNumber'] ? checkIbanStatus(this.state.data['ibanNumber']).status === 'valid' : '';
|
||||
const isValid = ibanValid && holderNameValid;
|
||||
const data = { data: this.state.data, isValid };
|
||||
|
||||
@@ -60,7 +70,8 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
onChange: () => {},
|
||||
countryCode: null,
|
||||
holderName: true,
|
||||
placeholders: {}
|
||||
placeholders: {},
|
||||
label: null
|
||||
};
|
||||
|
||||
setStatus(status) {
|
||||
@@ -68,8 +79,8 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
}
|
||||
|
||||
onChange() {
|
||||
const holderNameValid = this.props.holderName ? isValidHolder(this.state.data['sepa.ownerName']) : '';
|
||||
const ibanValid = checkIbanStatus(this.state.data['sepa.ibanNumber']).status === 'valid';
|
||||
const holderNameValid = this.props.holderName ? isValidHolder(this.state.data['ownerName']) : true;
|
||||
const ibanValid = checkIbanStatus(this.state.data['ibanNumber']).status === 'valid';
|
||||
const isValid = ibanValid && holderNameValid;
|
||||
const data = { data: this.state.data, isValid };
|
||||
|
||||
@@ -90,9 +101,9 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
|
||||
public handleHolderInput = holder => {
|
||||
this.setState(
|
||||
prevState => ({ data: { ...prevState.data, 'sepa.ownerName': holder } }),
|
||||
prevState => ({ data: { ...prevState.data, ownerName: holder } }),
|
||||
() => {
|
||||
this.setError('holder', !isValidHolder(this.state.data['sepa.ownerName']));
|
||||
this.setError('holder', !isValidHolder(this.state.data['ownerName']));
|
||||
this.onChange(); // propagate state
|
||||
}
|
||||
);
|
||||
@@ -104,15 +115,20 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
const iban = formatIban(electronicFormatIban); // example: NL13 TEST 0123 4567 89
|
||||
const validationStatus = checkIbanStatus(iban).status;
|
||||
|
||||
const countryCode = getCountryCode(electronicFormatIban);
|
||||
|
||||
// calculate cursor's new position
|
||||
const cursor = e.target.selectionStart;
|
||||
const previousIban = this.state.data['sepa.ibanNumber'];
|
||||
const previousIban = this.state.data['ibanNumber'];
|
||||
const newCursorPosition = getNextCursorPosition(cursor, iban, previousIban);
|
||||
|
||||
this.setState(
|
||||
prevState => ({
|
||||
data: { ...prevState.data, 'sepa.ibanNumber': iban },
|
||||
errors: { ...prevState.errors, iban: validationStatus === 'invalid' ? 'sepaDirectDebit.ibanField.invalid' : null },
|
||||
data: { ...prevState.data, ibanNumber: iban, countryCode: countryCode },
|
||||
errors: {
|
||||
...prevState.errors,
|
||||
iban: validationStatus === 'invalid' ? 'sepaDirectDebit.ibanField.invalid' : null
|
||||
},
|
||||
valid: { ...prevState.valid, iban: validationStatus === 'valid' }
|
||||
}),
|
||||
() => {
|
||||
@@ -132,8 +148,8 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
};
|
||||
|
||||
showValidation() {
|
||||
const validationStatus = checkIbanStatus(this.state.data['sepa.ibanNumber']).status;
|
||||
const holderStatus = isValidHolder(this.state.data['sepa.ownerName']);
|
||||
const validationStatus = checkIbanStatus(this.state.data['ibanNumber']).status;
|
||||
const holderStatus = isValidHolder(this.state.data['ownerName']);
|
||||
this.setError('iban', validationStatus !== 'valid' ? 'sepaDirectDebit.ibanField.invalid' : null);
|
||||
this.setError('holder', !holderStatus ? true : null);
|
||||
}
|
||||
@@ -141,22 +157,22 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
render({ placeholders, countryCode }: IbanInputProps, { data, errors, valid }) {
|
||||
const { i18n } = useCoreContext();
|
||||
return (
|
||||
<div className="adyen-checkout__iban-input">
|
||||
<Fieldset classNameModifiers={['iban-input']} label={this.props.label}>
|
||||
{this.props.holderName && (
|
||||
<Field
|
||||
className={'adyen-checkout__field--owner-name'}
|
||||
label={i18n.get('sepa.ownerName')}
|
||||
filled={data['sepa.ownerName'] && data['sepa.ownerName'].length}
|
||||
label={i18n.get('ownerName')}
|
||||
filled={data['ownerName'] && data['ownerName'].length}
|
||||
errorMessage={errors.holder ? i18n.get('creditCard.holderName.invalid') : false}
|
||||
dir={'ltr'}
|
||||
>
|
||||
{renderFormField('text', {
|
||||
name: 'sepa.ownerName',
|
||||
name: 'ownerName',
|
||||
className: 'adyen-checkout__iban-input__owner-name',
|
||||
placeholder: 'ownerName' in placeholders ? placeholders.ownerName : i18n.get('sepaDirectDebit.nameField.placeholder'),
|
||||
value: data['sepa.ownerName'],
|
||||
value: data['ownerName'],
|
||||
'aria-invalid': !!this.state.errors.holder,
|
||||
'aria-label': i18n.get('sepa.ownerName'),
|
||||
'aria-label': i18n.get('ownerName'),
|
||||
onInput: e => this.handleHolderInput(e.target.value)
|
||||
})}
|
||||
</Field>
|
||||
@@ -164,9 +180,9 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
|
||||
<Field
|
||||
className={'adyen-checkout__field--iban-number'}
|
||||
label={i18n.get('sepa.ibanNumber')}
|
||||
label={i18n.get('ibanNumber')}
|
||||
errorMessage={errors.iban ? i18n.get(errors.iban) : false}
|
||||
filled={data['sepa.ibanNumber'] && data['sepa.ibanNumber'].length}
|
||||
filled={data['ibanNumber'] && data['ibanNumber'].length}
|
||||
isValid={valid.iban}
|
||||
onBlur={this.handleIbanBlur}
|
||||
dir={'ltr'}
|
||||
@@ -175,21 +191,21 @@ class IbanInput extends Component<IbanInputProps, IbanInputState> {
|
||||
ref: ref => {
|
||||
this.ibanNumber = ref;
|
||||
},
|
||||
name: 'sepa.ibanNumber',
|
||||
name: 'ibanNumber',
|
||||
className: 'adyen-checkout__iban-input__iban-number',
|
||||
classNameModifiers: ['large'],
|
||||
placeholder: 'ibanNumber' in placeholders ? placeholders.ibanNumber : getIbanPlaceHolder(countryCode),
|
||||
value: data['sepa.ibanNumber'],
|
||||
value: data['ibanNumber'],
|
||||
onInput: this.handleIbanInput,
|
||||
'aria-invalid': !!this.state.errors.iban,
|
||||
'aria-label': i18n.get('sepa.ibanNumber'),
|
||||
'aria-label': i18n.get('ibanNumber'),
|
||||
autocorrect: 'off',
|
||||
spellcheck: false
|
||||
})}
|
||||
</Field>
|
||||
|
||||
{this.props.showPayButton && this.props.payButton({ status: this.state.status })}
|
||||
</div>
|
||||
</Fieldset>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -66,12 +66,13 @@ export const formatIban = iban =>
|
||||
.replace(/(.{4})(?!$)/g, '$1 ')
|
||||
.trim();
|
||||
|
||||
export type ElectronicFormat = string;
|
||||
/**
|
||||
* Returns any non alphanumeric characters and uppercases them
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export const electronicFormat = iban => {
|
||||
export const electronicFormat = (iban: string): ElectronicFormat => {
|
||||
const NON_ALPHANUM = /[^a-zA-Z0-9]/g;
|
||||
return iban.replace(NON_ALPHANUM, '').toUpperCase();
|
||||
};
|
||||
@@ -183,3 +184,9 @@ export const getNextCursorPosition = (cursor, iban, previousIban) => {
|
||||
|
||||
return cursor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param electronicFormatIban -
|
||||
* @returns countryCode string
|
||||
*/
|
||||
export const getCountryCode = (electronicFormatIban: ElectronicFormat) => electronicFormatIban.slice(0, 2);
|
||||
@@ -1,4 +1,11 @@
|
||||
import { iso13616Prepare, iso7064Mod97_10, electronicFormat, regex, getIbanCountrySpecification } from './utils';
|
||||
import {
|
||||
iso13616Prepare,
|
||||
iso7064Mod97_10,
|
||||
electronicFormat,
|
||||
regex,
|
||||
getIbanCountrySpecification,
|
||||
getCountryCode
|
||||
} from './utils';
|
||||
|
||||
/**
|
||||
* Contains a validation status
|
||||
@@ -46,7 +53,7 @@ export const checkIbanStatus = iban => {
|
||||
return new ValidationStatus('no-validate', 'TOO_SHORT'); // A
|
||||
}
|
||||
|
||||
const countryCode = electronicFormatIban.slice(0, 2);
|
||||
const countryCode = getCountryCode(electronicFormatIban);
|
||||
const countrySpecification = getIbanCountrySpecification(countryCode);
|
||||
|
||||
if (!countrySpecification) {
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
OpenInvoiceStateValid
|
||||
} from './types';
|
||||
import './OpenInvoice.scss';
|
||||
import IbanInput from '../IbanInput';
|
||||
|
||||
export default function OpenInvoice(props: OpenInvoiceProps) {
|
||||
const { countryCode, visibility } = props;
|
||||
@@ -58,7 +59,10 @@ export default function OpenInvoice(props: OpenInvoiceProps) {
|
||||
};
|
||||
|
||||
const handleSeparateDeliveryAddress = () => {
|
||||
setActiveFieldsets(prevActiveFields => ({ ...prevActiveFields, deliveryAddress: !activeFieldsets.deliveryAddress }));
|
||||
setActiveFieldsets(prevActiveFields => ({
|
||||
...prevActiveFields,
|
||||
deliveryAddress: !activeFieldsets.deliveryAddress
|
||||
}));
|
||||
};
|
||||
|
||||
const handleConsentCheckbox = e => {
|
||||
@@ -101,6 +105,16 @@ export default function OpenInvoice(props: OpenInvoiceProps) {
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeFieldsets.bankAccount && (
|
||||
<IbanInput
|
||||
holderName={true}
|
||||
label="bankAccount"
|
||||
data={data.bankAccount}
|
||||
onChange={handleFieldset('bankAccount')}
|
||||
ref={fieldsetsRefs.bankAccount}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeFieldsets.billingAddress && (
|
||||
<Address
|
||||
allowedCountries={props.allowedCountries}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
import { AddressData, FieldsetVisibility, PersonalDetailsSchema } from '../../../types';
|
||||
import { CompanyDetailsSchema } from '../CompanyDetails/types';
|
||||
import { AddressSpecifications } from '../Address/types';
|
||||
import {UIElementProps} from "../../types";
|
||||
import UIElement from "../../UIElement";
|
||||
|
||||
export interface OpenInvoiceVisibility {
|
||||
companyDetails?: FieldsetVisibility;
|
||||
personalDetails?: FieldsetVisibility;
|
||||
billingAddress?: FieldsetVisibility;
|
||||
deliveryAddress?: FieldsetVisibility;
|
||||
bankAccount?: FieldsetVisibility;
|
||||
}
|
||||
|
||||
export interface OpenInvoiceProps {
|
||||
export interface BankDetailsSchema {
|
||||
countryCode?: string,
|
||||
ibanNumber?: any,
|
||||
ownerName?: string
|
||||
}
|
||||
|
||||
export interface OpenInvoiceProps extends UIElementProps{
|
||||
allowedCountries?: string[];
|
||||
consentCheckboxLabel: any;
|
||||
countryCode?: string;
|
||||
@@ -18,8 +27,9 @@ export interface OpenInvoiceProps {
|
||||
personalDetails?: PersonalDetailsSchema;
|
||||
billingAddress?: AddressData;
|
||||
deliveryAddress?: AddressData;
|
||||
bankAccount?: BankDetailsSchema
|
||||
};
|
||||
onChange: Function;
|
||||
onChange: (state: any, element?: UIElement) => void;
|
||||
payButton: any;
|
||||
showPayButton?: boolean;
|
||||
visibility?: OpenInvoiceVisibility;
|
||||
@@ -33,6 +43,7 @@ export interface OpenInvoiceStateData {
|
||||
personalDetails?: PersonalDetailsSchema;
|
||||
billingAddress?: AddressData;
|
||||
deliveryAddress?: AddressData;
|
||||
bankAccount?: BankDetailsSchema
|
||||
consentCheckbox?: boolean;
|
||||
}
|
||||
|
||||
@@ -42,6 +53,7 @@ export interface OpenInvoiceStateError {
|
||||
billingAddress?: boolean;
|
||||
deliveryAddress?: boolean;
|
||||
personalDetails?: boolean;
|
||||
bankAccount?: boolean;
|
||||
}
|
||||
|
||||
export interface OpenInvoiceStateValid {
|
||||
@@ -50,6 +62,7 @@ export interface OpenInvoiceStateValid {
|
||||
billingAddress?: boolean;
|
||||
deliveryAddress?: boolean;
|
||||
personalDetails?: boolean;
|
||||
bankAccount?: boolean;
|
||||
}
|
||||
|
||||
export interface OpenInvoiceActiveFieldsets {
|
||||
@@ -57,6 +70,7 @@ export interface OpenInvoiceActiveFieldsets {
|
||||
personalDetails: boolean;
|
||||
billingAddress: boolean;
|
||||
deliveryAddress: boolean;
|
||||
bankAccount: boolean;
|
||||
}
|
||||
|
||||
export interface OpenInvoiceFieldsetsRefs {
|
||||
@@ -64,4 +78,5 @@ export interface OpenInvoiceFieldsetsRefs {
|
||||
personalDetails?;
|
||||
billingAddress?;
|
||||
deliveryAddress?;
|
||||
bankAccount?;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { OpenInvoiceActiveFieldsets, OpenInvoiceStateData, OpenInvoiceVisibility } from './types';
|
||||
|
||||
export const fieldsetsSchema: Array<keyof OpenInvoiceStateData> = ['companyDetails', 'personalDetails', 'billingAddress', 'deliveryAddress'];
|
||||
export const fieldsetsSchema: Array<keyof OpenInvoiceStateData> = [
|
||||
'companyDetails',
|
||||
'personalDetails',
|
||||
'billingAddress',
|
||||
'deliveryAddress',
|
||||
'bankAccount'
|
||||
];
|
||||
|
||||
const isPrefilled = (fieldsetData: object = {}): boolean => Object.keys(fieldsetData).length > 1;
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "الدفع الدوري",
|
||||
"sepaDirectDebit.ibanField.invalid": "رقم حساب غير صحيح",
|
||||
"sepaDirectDebit.nameField.placeholder": "جميل سعيد",
|
||||
"sepa.ownerName": "صاحب الحساب",
|
||||
"sepa.ibanNumber": "رقم الحساب (IBAN)",
|
||||
"ownerName": "صاحب الحساب",
|
||||
"ibanNumber": "رقم الحساب (IBAN)",
|
||||
"error.title": "خطأ",
|
||||
"error.subtitle.redirect": "فشل إعادة التوجيه",
|
||||
"error.subtitle.payment": "فشل الدفع",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Opakující se platba",
|
||||
"sepaDirectDebit.ibanField.invalid": "Neplatné číslo účtu",
|
||||
"sepaDirectDebit.nameField.placeholder": "Jan Novák",
|
||||
"sepa.ownerName": "Jméno držitele účtu",
|
||||
"sepa.ibanNumber": "Číslo účtu (IBAN)",
|
||||
"ownerName": "Jméno držitele účtu",
|
||||
"ibanNumber": "Číslo účtu (IBAN)",
|
||||
"error.title": "Chyba",
|
||||
"error.subtitle.redirect": "Přesměrování selhalo",
|
||||
"error.subtitle.payment": "Platba selhala",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Løbende betaling",
|
||||
"sepaDirectDebit.ibanField.invalid": "Ugyldigt kontonummer",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Kontohavernavn",
|
||||
"sepa.ibanNumber": "Kontonummer (IBAN)",
|
||||
"ownerName": "Kontohavernavn",
|
||||
"ibanNumber": "Kontonummer (IBAN)",
|
||||
"error.title": "Fejl",
|
||||
"error.subtitle.redirect": "Omdirigering fejlede",
|
||||
"error.subtitle.payment": "Betaling fejlede",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Ratenzahlung",
|
||||
"sepaDirectDebit.ibanField.invalid": "Ungültige Kontonummer",
|
||||
"sepaDirectDebit.nameField.placeholder": "A. Müller",
|
||||
"sepa.ownerName": "Name des Kontoinhabers",
|
||||
"sepa.ibanNumber": "Kontonummer (IBAN)",
|
||||
"ownerName": "Name des Kontoinhabers",
|
||||
"ibanNumber": "Kontonummer (IBAN)",
|
||||
"error.title": "Fehler",
|
||||
"error.subtitle.redirect": "Weiterleitung fehlgeschlagen",
|
||||
"error.subtitle.payment": "Zahlung fehlgeschlagen",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Ανακυκλούμενη πληρωμή",
|
||||
"sepaDirectDebit.ibanField.invalid": "Μη έγκυρος αριθμός λογαριασμού",
|
||||
"sepaDirectDebit.nameField.placeholder": "Γ. Παπαδάκης",
|
||||
"sepa.ownerName": "Όνομα κατόχου",
|
||||
"sepa.ibanNumber": "Αριθμός λογαριασμού (IBAN)",
|
||||
"ownerName": "Όνομα κατόχου",
|
||||
"ibanNumber": "Αριθμός λογαριασμού (IBAN)",
|
||||
"error.title": "Σφάλμα",
|
||||
"error.subtitle.redirect": "Η ανακατεύθυνση απέτυχε",
|
||||
"error.subtitle.payment": "Η πληρωμή απέτυχε",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Revolving payment",
|
||||
"sepaDirectDebit.ibanField.invalid": "Invalid account number",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Holder Name",
|
||||
"sepa.ibanNumber": "Account Number (IBAN)",
|
||||
"ownerName": "Holder Name",
|
||||
"ibanNumber": "Account Number (IBAN)",
|
||||
"error.title": "Error",
|
||||
"error.subtitle.redirect": "Redirect failed",
|
||||
"error.subtitle.payment": "Payment failed",
|
||||
@@ -214,5 +214,8 @@
|
||||
"pix.instructions": "Open the app with the PIX registered key, choose Pay with PIX and scan the QR Code or copy and paste the code",
|
||||
"twint.saved": "saved",
|
||||
"orPayWith": "or pay with",
|
||||
"invalidFormatExpects": "Invalid format. Expected format: %{format}"
|
||||
"invalidFormatExpects": "Invalid format. Expected format: %{format}",
|
||||
"ownerName": "Holder Name",
|
||||
"ibanNumber": "Account Number (IBAN)",
|
||||
"bankAccount": "Bank Details"
|
||||
}
|
||||
@@ -25,8 +25,8 @@
|
||||
"installments.revolving": "Pago rotativo",
|
||||
"sepaDirectDebit.ibanField.invalid": "Número de cuenta no válido",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Nombre del titular de cuenta",
|
||||
"sepa.ibanNumber": "Número de cuenta (IBAN)",
|
||||
"ownerName": "Nombre del titular de cuenta",
|
||||
"ibanNumber": "Número de cuenta (IBAN)",
|
||||
"error.title": "Error",
|
||||
"error.subtitle.redirect": "Redirección fallida",
|
||||
"error.subtitle.payment": "Pago fallido",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Toistuva maksu",
|
||||
"sepaDirectDebit.ibanField.invalid": "Väärä tilin numero",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Haltijan nimi",
|
||||
"sepa.ibanNumber": "Tilinumero (IBAN)",
|
||||
"ownerName": "Haltijan nimi",
|
||||
"ibanNumber": "Tilinumero (IBAN)",
|
||||
"error.title": "Virhe",
|
||||
"error.subtitle.redirect": "Uuteen kohteeseen siirto epäonnistui",
|
||||
"error.subtitle.payment": "Maksu epännistui",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Paiement en plusieurs fois",
|
||||
"sepaDirectDebit.ibanField.invalid": "Numéro de compte non valide",
|
||||
"sepaDirectDebit.nameField.placeholder": "N. Bernard",
|
||||
"sepa.ownerName": "Au nom de",
|
||||
"sepa.ibanNumber": "Numéro de compte (IBAN)",
|
||||
"ownerName": "Au nom de",
|
||||
"ibanNumber": "Numéro de compte (IBAN)",
|
||||
"error.title": "Erreur",
|
||||
"error.subtitle.redirect": "Échec de la redirection",
|
||||
"error.subtitle.payment": "Échec du paiement",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Obnovljivo plaćanje",
|
||||
"sepaDirectDebit.ibanField.invalid": "Nevažeći broj računa",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Ime vlasnika",
|
||||
"sepa.ibanNumber": "Broj računa (IBAN)",
|
||||
"ownerName": "Ime vlasnika",
|
||||
"ibanNumber": "Broj računa (IBAN)",
|
||||
"error.title": "Greška",
|
||||
"error.subtitle.redirect": "Preusmjeravanje nije uspjelo",
|
||||
"error.subtitle.payment": "Plaćanje nije uspjelo",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Többösszegű fizetés",
|
||||
"sepaDirectDebit.ibanField.invalid": "Érvénytelen számlaszám",
|
||||
"sepaDirectDebit.nameField.placeholder": "Gipsz Jakab",
|
||||
"sepa.ownerName": "Számlatulajdonos neve",
|
||||
"sepa.ibanNumber": "Számlaszám (IBAN)",
|
||||
"ownerName": "Számlatulajdonos neve",
|
||||
"ibanNumber": "Számlaszám (IBAN)",
|
||||
"error.title": "Hiba",
|
||||
"error.subtitle.redirect": "Sikertelen átirányítás",
|
||||
"error.subtitle.payment": "Sikertelen fizetés",
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
"installments.revolving": "Pagamento ricorrente",
|
||||
"sepaDirectDebit.ibanField.invalid": "Numero di conto non valido",
|
||||
"sepaDirectDebit.nameField.placeholder": "A. Bianchi",
|
||||
"sepa.ownerName": "Nome Intestatario Conto",
|
||||
"sepa.ibanNumber": "Numero di conto (IBAN)",
|
||||
"ownerName": "Nome Intestatario Conto",
|
||||
"ibanNumber": "Numero di conto (IBAN)",
|
||||
"error.title": "Errore",
|
||||
"error.subtitle.redirect": "Reindirizzamento non riuscito",
|
||||
"error.subtitle.payment": "Pagamento non riuscito",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "リボ払い",
|
||||
"sepaDirectDebit.ibanField.invalid": "口座番号の入力間違い",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "名義",
|
||||
"sepa.ibanNumber": "口座番号 (IBAN)",
|
||||
"ownerName": "名義",
|
||||
"ibanNumber": "口座番号 (IBAN)",
|
||||
"error.title": "エラー",
|
||||
"error.subtitle.redirect": "画面の切り替え失敗にしました",
|
||||
"error.subtitle.payment": "支払できませんでした",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "리볼빙 결제",
|
||||
"sepaDirectDebit.ibanField.invalid": "유효하지 않은 계좌 번호",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "소유자 이름",
|
||||
"sepa.ibanNumber": "계좌 번호(IBAN)",
|
||||
"ownerName": "소유자 이름",
|
||||
"ibanNumber": "계좌 번호(IBAN)",
|
||||
"error.title": "오류",
|
||||
"error.subtitle.redirect": "리디렉션 실패",
|
||||
"error.subtitle.payment": "결제 실패",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Terugkerende betaling",
|
||||
"sepaDirectDebit.ibanField.invalid": "Ongeldig rekeningnummer",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Janssen",
|
||||
"sepa.ownerName": "Ten name van",
|
||||
"sepa.ibanNumber": "Rekeningnummer (IBAN)",
|
||||
"ownerName": "Ten name van",
|
||||
"ibanNumber": "Rekeningnummer (IBAN)",
|
||||
"error.title": "Fout",
|
||||
"error.subtitle.redirect": "Doorsturen niet gelukt",
|
||||
"error.subtitle.payment": "Betaling is niet geslaagd",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Gjentakende betaling",
|
||||
"sepaDirectDebit.ibanField.invalid": "Ugyldig kontonummer",
|
||||
"sepaDirectDebit.nameField.placeholder": "O. Nordmann",
|
||||
"sepa.ownerName": "Kortholders navn",
|
||||
"sepa.ibanNumber": "Kontonummer (IBAN)",
|
||||
"ownerName": "Kortholders navn",
|
||||
"ibanNumber": "Kontonummer (IBAN)",
|
||||
"error.title": "Feil",
|
||||
"error.subtitle.redirect": "Videresending feilet",
|
||||
"error.subtitle.payment": "Betaling feilet",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Płatność odnawialna",
|
||||
"sepaDirectDebit.ibanField.invalid": "Nieprawidłowy numer rachunku",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Kowalski",
|
||||
"sepa.ownerName": "Imię i nazwisko posiadacza karty",
|
||||
"sepa.ibanNumber": "Numer rachunku (IBAN)",
|
||||
"ownerName": "Imię i nazwisko posiadacza karty",
|
||||
"ibanNumber": "Numer rachunku (IBAN)",
|
||||
"error.title": "Błąd",
|
||||
"error.subtitle.redirect": "Przekierowanie nie powiodło się",
|
||||
"error.subtitle.payment": "Płatność nie powiodła się",
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
"installments.revolving": "Pagamento rotativo",
|
||||
"sepaDirectDebit.ibanField.invalid": "Número de conta inválido",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Silva",
|
||||
"sepa.ownerName": "Nome do titular da conta bancária",
|
||||
"sepa.ibanNumber": "Número de conta (NIB)",
|
||||
"ownerName": "Nome do titular da conta bancária",
|
||||
"ibanNumber": "Número de conta (NIB)",
|
||||
"error.title": "Erro",
|
||||
"error.subtitle.redirect": "Falha no redirecionamento",
|
||||
"error.subtitle.payment": "Falha no pagamento",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Plată recurentă",
|
||||
"sepaDirectDebit.ibanField.invalid": "Numărul de cont este incorect",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "Nume posesor",
|
||||
"sepa.ibanNumber": "Număr cont (IBAN)",
|
||||
"ownerName": "Nume posesor",
|
||||
"ibanNumber": "Număr cont (IBAN)",
|
||||
"error.title": "Eroare",
|
||||
"error.subtitle.redirect": "Redirecționare eșuată",
|
||||
"error.subtitle.payment": "Plată eșuată",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Повторяющаяся оплата",
|
||||
"sepaDirectDebit.ibanField.invalid": "Недействительный номер счета",
|
||||
"sepaDirectDebit.nameField.placeholder": "И. Петров",
|
||||
"sepa.ownerName": "Имя владельца",
|
||||
"sepa.ibanNumber": "Номер счета (IBAN)",
|
||||
"ownerName": "Имя владельца",
|
||||
"ibanNumber": "Номер счета (IBAN)",
|
||||
"error.title": "Ошибка",
|
||||
"error.subtitle.redirect": "Сбой перенаправления",
|
||||
"error.subtitle.payment": "Сбой оплаты",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Revolvingová platba",
|
||||
"sepaDirectDebit.ibanField.invalid": "Neplatné číslo účtu",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Novák",
|
||||
"sepa.ownerName": "Meno držiteľa",
|
||||
"sepa.ibanNumber": "Číslo účtu (IBAN)",
|
||||
"ownerName": "Meno držiteľa",
|
||||
"ibanNumber": "Číslo účtu (IBAN)",
|
||||
"error.title": "Chyba",
|
||||
"error.subtitle.redirect": "Nepodarilo sa presmerovať",
|
||||
"error.subtitle.payment": "Platba zlyhala",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Revolving plačilo",
|
||||
"sepaDirectDebit.ibanField.invalid": "Neveljavna številka računa",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Novak",
|
||||
"sepa.ownerName": "Ime imetnika",
|
||||
"sepa.ibanNumber": "Številka računa (IBAN)",
|
||||
"ownerName": "Ime imetnika",
|
||||
"ibanNumber": "Številka računa (IBAN)",
|
||||
"error.title": "Napaka",
|
||||
"error.subtitle.redirect": "Preusmeritev ni uspela",
|
||||
"error.subtitle.payment": "Plačilo ni uspelo",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "Uppdelad betalning",
|
||||
"sepaDirectDebit.ibanField.invalid": "Ogiltigt kontonummer",
|
||||
"sepaDirectDebit.nameField.placeholder": "A. Andersson",
|
||||
"sepa.ownerName": "Känt av kontoinnehavaren",
|
||||
"sepa.ibanNumber": "Kontonummer (IBAN)",
|
||||
"ownerName": "Känt av kontoinnehavaren",
|
||||
"ibanNumber": "Kontonummer (IBAN)",
|
||||
"error.title": "Fel",
|
||||
"error.subtitle.redirect": "Omdirigering misslyckades",
|
||||
"error.subtitle.payment": "Betalning misslyckades",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "循环支付",
|
||||
"sepaDirectDebit.ibanField.invalid": "无效的账号",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "持卡人姓名",
|
||||
"sepa.ibanNumber": "账号 (IBAN)",
|
||||
"ownerName": "持卡人姓名",
|
||||
"ibanNumber": "账号 (IBAN)",
|
||||
"error.title": "错误",
|
||||
"error.subtitle.redirect": "重定向失败",
|
||||
"error.subtitle.payment": "支付失败",
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"installments.revolving": "延期付款",
|
||||
"sepaDirectDebit.ibanField.invalid": "帳戶號碼無效",
|
||||
"sepaDirectDebit.nameField.placeholder": "J. Smith",
|
||||
"sepa.ownerName": "持有人名稱",
|
||||
"sepa.ibanNumber": "帳戶號碼 (IBAN)",
|
||||
"ownerName": "持有人名稱",
|
||||
"ibanNumber": "帳戶號碼 (IBAN)",
|
||||
"error.title": "錯誤",
|
||||
"error.subtitle.redirect": "無法重新導向",
|
||||
"error.subtitle.payment": "付款失敗",
|
||||
|
||||
@@ -31,6 +31,15 @@ export async function initSession() {
|
||||
paymentMethodsConfiguration: {
|
||||
paywithgoogle: {
|
||||
buttonType: 'plain'
|
||||
},
|
||||
card: {
|
||||
hasHolderName: true,
|
||||
holderNameRequired: true,
|
||||
holderName: 'J. Smith',
|
||||
positionHolderNameOnTop: true,
|
||||
|
||||
// billingAddress config:
|
||||
billingAddressRequired: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,6 +12,15 @@
|
||||
<header></header>
|
||||
<main>
|
||||
<form class="merchant-checkout__form" method="post">
|
||||
<div class="merchant-checkout__payment-method">
|
||||
<div class="merchant-checkout__payment-method__header">
|
||||
<h2>RatePay Direct Debit</h2>
|
||||
</div>
|
||||
<div class="merchant-checkout__payment-method__details">
|
||||
<div class="ratepay-direct-field"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="merchant-checkout__payment-method">
|
||||
<div class="merchant-checkout__payment-method__header">
|
||||
<h2>AfterPay</h2>
|
||||
|
||||
@@ -104,6 +104,18 @@ getPaymentMethods({ amount, shopperLocale }).then(async paymentMethodsData => {
|
||||
})
|
||||
.mount('.ratepay-field');
|
||||
|
||||
// RATEPAY
|
||||
window.ratepay = checkout
|
||||
.create('ratepay_directdebit', {
|
||||
//countryCode: 'DE', // 'DE' / 'AT' / 'CH'
|
||||
visibility: {
|
||||
personalDetails: 'editable', // editable [default] / readOnly / hidden
|
||||
billingAddress: 'editable',
|
||||
deliveryAddress: 'editable'
|
||||
}
|
||||
})
|
||||
.mount('.ratepay-direct-field');
|
||||
|
||||
// ATOME
|
||||
window.atome = checkout
|
||||
.create('atome', {
|
||||
|
||||
Reference in New Issue
Block a user