Click to Pay - 3rd party cookies (#2409)

* feat: storing cookies

* feat: tests

* feat: timeout adjust

* fix: removed log

* fix: checking checkbox + styles

* fix: using input email

* feat: ui changes

* feat: removing truncating text feature

* feat: changeset

* fix: code review points

* fix: margins

* feat: translations

* feat: truncating text feature back

* feat: email

* fix: update drop shadow
This commit is contained in:
Guilherme Ribeiro
2023-12-04 09:38:04 +01:00
committed by GitHub
parent d7b5dd7bb3
commit fcf40a1f71
48 changed files with 417 additions and 56 deletions

View File

@@ -0,0 +1,5 @@
---
'@adyen/adyen-web': minor
---
Click to Pay - Enabling MC/Visa to drop cookies if the shopper gives consent

View File

@@ -4,7 +4,7 @@ import { loginValidationRules } from './validate';
import useCoreContext from '../../../../../core/Context/useCoreContext';
import useForm from '../../../../../utils/useForm';
import Field from '../../../FormFields/Field';
import InputText from '../../../FormFields/InputText';
import InputEmail from '../../../FormFields/InputEmail';
type OnChangeProps = { data: CtPLoginInputDataState; valid; errors; isValid: boolean };
@@ -73,7 +73,7 @@ const CtPLoginInput = (props: CtPLoginInputProps): h.JSX.Element => {
errorMessage={isLoginInputDirty ? props.errorMessage || !!errors.shopperLogin : null}
classNameModifiers={['shopperLogin']}
>
<InputText
<InputEmail
name={'shopperLogin'}
autocorrect={'off'}
spellcheck={false}

View File

@@ -0,0 +1,71 @@
import { h } from 'preact';
import { render, screen } from '@testing-library/preact';
import CoreProvider from '../../../../../core/Context/CoreProvider';
import ClickToPayProvider from '../../context/ClickToPayProvider';
import { IClickToPayService } from '../../services/types';
import { mock } from 'jest-mock-extended';
import { Resources } from '../../../../../core/Context/Resources';
import Language from '../../../../../language';
import userEvent from '@testing-library/user-event';
import CtPOneTimePassword from './CtPOneTimePassword';
const customRender = (ui, { clickToPayService = mock<IClickToPayService>(), configuration = {} } = {}) => {
return render(
<CoreProvider i18n={new Language()} loadingContext="test" resources={new Resources()}>
<ClickToPayProvider
clickToPayService={clickToPayService}
isStandaloneComponent={true}
amount={{ value: 5000, currency: 'USD' }}
onSetStatus={jest.fn()}
configuration={configuration}
onError={jest.fn()}
onSubmit={jest.fn()}
setClickToPayRef={jest.fn()}
>
{ui}
</ClickToPayProvider>
</CoreProvider>
);
};
describe('Click to Pay - CtPOneTimePassword', () => {
test('should set to store the cookie if shopper ticks the checkbox', async () => {
const user = userEvent.setup();
const ctpServiceMock = mock<IClickToPayService>();
ctpServiceMock.schemes = ['visa', 'mc'];
// const onResendCodeMock = jest.fn();
customRender(<CtPOneTimePassword />, { clickToPayService: ctpServiceMock });
// Default false
const checkbox = (await screen.findByLabelText('Skip verification next time')) as HTMLInputElement;
expect(checkbox.checked).toBe(false);
// Checked
await user.click(checkbox);
expect(checkbox.checked).toBe(true);
expect(ctpServiceMock.updateStoreCookiesConsent).toHaveBeenCalledWith(true);
expect(ctpServiceMock.updateStoreCookiesConsent).toHaveBeenCalledTimes(1);
// Unchecked
await user.click(checkbox);
expect(checkbox.checked).toBe(false);
expect(ctpServiceMock.updateStoreCookiesConsent).toHaveBeenCalledWith(false);
expect(ctpServiceMock.updateStoreCookiesConsent).toHaveBeenCalledTimes(2);
});
test('should pass OTP to ClickToPay service', async () => {
const user = userEvent.setup({ delay: 100 });
const ctpServiceMock = mock<IClickToPayService>();
ctpServiceMock.schemes = ['visa', 'mc'];
customRender(<CtPOneTimePassword />, { clickToPayService: ctpServiceMock });
await screen.findByLabelText('One time code', { exact: false });
await user.keyboard('654321');
await user.keyboard('[Enter]');
expect(ctpServiceMock.finishIdentityValidation).toHaveBeenCalledWith('654321');
});
});

View File

@@ -8,6 +8,7 @@ import { CtPInfo } from '../CtPInfo';
import CtPSection from '../CtPSection';
import useCoreContext from '../../../../../core/Context/useCoreContext';
import './CtPOneTimePassword.scss';
import CtPSaveCookiesCheckbox from './CtPSaveCookiesCheckbox';
type CtPOneTimePasswordProps = {
onDisplayCardComponent?(): void;
@@ -80,6 +81,9 @@ const CtPOneTimePassword = ({ onDisplayCardComponent }: CtPOneTimePasswordProps)
onResendCode={onResendCode}
isValidatingOtp={isValidatingOtp}
/>
<CtPSaveCookiesCheckbox />
<Button
disabled={isAccountLocked}
label={i18n.get('continue')}

View File

@@ -38,5 +38,5 @@
}
.adyen-checkout-ctp__section > .adyen-checkout__field.adyen-checkout__field--otp {
margin-bottom: 20px;
margin-bottom: 12px;
}

View File

@@ -0,0 +1,35 @@
@import "../../../../../../style/index";
.adyen-checkout-ctp__otp-checkbox-container {
padding: 12px;
background-color: $color-gray-lighter;
border-radius: $border-radius-medium;
margin-bottom: 16px;
}
.adyen-checkout-ctp__otp-checkbox-container--checked {
background-color: #F2F8FF;
}
.adyen-checkout-ctp__otp-checkbox-container label {
cursor: pointer;
}
.adyen-checkout-ctp__section .adyen-checkout__field.adyen-checkout-ctp__otp-checkbox-container {
margin-bottom: 4px;
}
.adyen-checkout-ctp__otp-checkbox-info {
color: $color-new-gray-darker;
font-size: 13px;
line-height: 19px;
font-weight: 400;
margin: 4px 0 0;
}
.adyen-checkout-ctp__otp-readmore-button {
all: unset;
text-transform: lowercase;
cursor: pointer;
color: $color-blue;
}

View File

@@ -0,0 +1,55 @@
import { h, Fragment } from 'preact';
import classnames from 'classnames';
import Field from '../../../../FormFields/Field';
import Checkbox from '../../../../FormFields/Checkbox';
import useCoreContext from '../../../../../../core/Context/useCoreContext';
import { useState, useCallback } from 'preact/hooks';
import useClickToPayContext from '../../../context/useClickToPayContext';
import isScreenSmall from '../../../../../../utils/isScreenSmall';
import './CtPSaveCookiesCheckbox.scss';
function CtPSaveCookiesCheckbox() {
const { i18n } = useCoreContext();
const { updateStoreCookiesConsent, isStoringCookies } = useClickToPayContext();
const [checked, setIsChecked] = useState(isStoringCookies);
const [isTextTruncated, setIsTextTruncated] = useState<boolean>(isScreenSmall());
const handleOnChange = useCallback(() => {
const newChecked = !checked;
setIsChecked(newChecked);
updateStoreCookiesConsent(newChecked);
}, [updateStoreCookiesConsent, setIsChecked, checked]);
return (
<div
className={classnames('adyen-checkout-ctp__otp-checkbox-container', {
'adyen-checkout-ctp__otp-checkbox-container--checked': checked
})}
>
<Field name={'clickToPayCookiesCheckbox'} addContextualElement={false} useLabelElement={false} i18n={i18n}>
<Checkbox
name={'clickToPayCookiesCheckbox'}
onInput={handleOnChange}
label={i18n.get('ctp.otp.saveCookiesCheckbox.label')}
checked={checked}
aria-describedby={'adyen-ctp-cookies-info'}
/>
</Field>
<p className="adyen-checkout-ctp__otp-checkbox-info">
{isTextTruncated ? (
<Fragment>
<span id="adyen-ctp-cookies-info">{i18n.get('ctp.otp.saveCookiesCheckbox.shorterInfo')} </span>
<button className="adyen-checkout-ctp__otp-readmore-button" onClick={() => setIsTextTruncated(false)}>
{i18n.get('readMore')}..
</button>
</Fragment>
) : (
<span id="adyen-ctp-cookies-info">{i18n.get('ctp.otp.saveCookiesCheckbox.information')}</span>
)}
</p>
</div>
);
}
export default CtPSaveCookiesCheckbox;

View File

@@ -0,0 +1 @@
export { default } from './CtPSaveCookiesCheckbox';

View File

@@ -3,7 +3,7 @@
.adyen-checkout-ctp__section {
position: relative;
background-color: white;
box-shadow: 0 8px 24px rgb(0 0 0 / 15%);
box-shadow: 0 6px 12px rgb(0 17 44 / 8%), 0 2px 4px rgb(0 17 44 / 4%);
border-radius: 12px;
padding: 16px;
@@ -11,7 +11,7 @@
display: flex;
align-items: center;
height: 18px;
margin-bottom: 14px;
margin-bottom: 16px;
}
&--standalone {
@@ -31,8 +31,8 @@
font-size: 17px;
font-weight: 600;
line-height: 22px;
margin: 0 0 4px;
padding: 0;
margin: 0;
width: auto;
@media screen and (max-width: 400px) {
@@ -49,7 +49,7 @@
font-size: 13px;
font-weight: 400;
line-height: 19px;
color: $color-gray-darker;
color: $color-new-gray-darker;
margin: 0 0 16px;
}

View File

@@ -11,8 +11,10 @@ export interface IClickToPayContext
extends Pick<IClickToPayService, 'checkout' | 'startIdentityValidation' | 'finishIdentityValidation' | 'verifyIfShopperIsEnrolled'> {
isStandaloneComponent: boolean;
isCtpPrimaryPaymentMethod: boolean;
isStoringCookies: boolean;
setIsCtpPrimaryPaymentMethod(isPrimary: boolean): void;
logoutShopper(): Promise<void>;
updateStoreCookiesConsent(shouldStore: boolean): void;
ctpState: CtpState;
cards: ShopperCard[];
schemes: string[];
@@ -37,8 +39,10 @@ const ClickToPayContext = createContext<IClickToPayContext>({
configuration: null,
isStandaloneComponent: null,
isCtpPrimaryPaymentMethod: null,
isStoringCookies: false,
setIsCtpPrimaryPaymentMethod: null,
logoutShopper: null,
updateStoreCookiesConsent: null,
ctpState: null,
cards: [],
schemes: [],

View File

@@ -90,6 +90,13 @@ const ClickToPayProvider = ({
await ctpService?.logout();
}, [ctpService]);
const updateStoreCookiesConsent = useCallback(
(shouldStore: boolean) => {
ctpService.updateStoreCookiesConsent(shouldStore);
},
[ctpService]
);
return (
<ClickToPayContext.Provider
value={{
@@ -99,6 +106,7 @@ const ClickToPayProvider = ({
onSetStatus,
amount,
configuration,
isStoringCookies: ctpService?.storeCookies,
isStandaloneComponent,
isCtpPrimaryPaymentMethod,
setIsCtpPrimaryPaymentMethod,
@@ -112,6 +120,7 @@ const ClickToPayProvider = ({
logoutShopper,
startIdentityValidation,
finishIdentityValidation,
updateStoreCookiesConsent,
onReady
}}
>

View File

@@ -4,8 +4,94 @@ import { ISrcSdkLoader } from './sdks/SrcSdkLoader';
import VisaSdk from './sdks/VisaSdk';
import MastercardSdk from './sdks/MastercardSdk';
import { IdentityLookupParams, SchemesConfiguration } from './types';
import { SrciIdentityLookupResponse, SrcProfile } from './sdks/types';
import { SrciCheckoutResponse, SrciIdentityLookupResponse, SrcProfile } from './sdks/types';
import SrciError from './sdks/SrciError';
import ShopperCard from '../models/ShopperCard';
test('should be able to tweak the configuration to store the cookie', () => {
const visa = mock<VisaSdk>();
const schemesConfig = mock<SchemesConfiguration>();
const sdkLoader = mock<ISrcSdkLoader>();
sdkLoader.load.mockResolvedValue([visa]);
const service = new ClickToPayService(schemesConfig, sdkLoader, 'test');
expect(service.storeCookies).toBe(false);
service.updateStoreCookiesConsent(true);
expect(service.storeCookies).toBe(true);
service.updateStoreCookiesConsent(false);
expect(service.storeCookies).toBe(false);
});
test('should pass the complianceSettings if the cookie is set to be stored', async () => {
const checkoutResponseMock = mock<SrciCheckoutResponse>();
checkoutResponseMock.dcfActionCode = 'COMPLETE';
const profileFromVisaSrcSystem: SrcProfile = {
srcCorrelationId: '123456',
profiles: [
{
maskedCards: [
{
srcDigitalCardId: 'xxxx',
panLastFour: '8902',
dateOfCardLastUsed: '2019-09-28T08:10:02.312Z',
paymentCardDescriptor: 'visa',
panExpirationMonth: '12',
panExpirationYear: '2020',
digitalCardData: {
descriptorName: 'Visa',
artUri: 'https://image.com/visa'
},
tokenId: '9w8e8e'
}
]
}
]
};
const visa = mock<VisaSdk>();
// @ts-ignore Mocking readonly property
visa.schemeName = 'visa';
visa.checkout.mockResolvedValue(checkoutResponseMock);
visa.init.mockResolvedValue();
visa.isRecognized.mockResolvedValue({ recognized: true, idTokens: ['id-token'] });
visa.getSrcProfile.mockResolvedValue(profileFromVisaSrcSystem);
const sdkLoader = mock<ISrcSdkLoader>();
const schemesConfig = mock<SchemesConfiguration>();
const shopperCard = mock<ShopperCard>();
shopperCard.srcDigitalCardId = 'xxxx';
shopperCard.srcCorrelationId = 'zzzz';
shopperCard.scheme = 'visa';
Object.defineProperty(shopperCard, 'isDcfPopupEmbedded', {
get: jest.fn(() => false)
});
sdkLoader.load.mockResolvedValue([visa]);
const service = new ClickToPayService(schemesConfig, sdkLoader, 'test');
service.updateStoreCookiesConsent(true);
await service.initialize();
await service.checkout(shopperCard);
expect(visa.checkout).toHaveBeenCalledTimes(1);
expect(visa.checkout).toHaveBeenCalledWith({
complianceSettings: {
complianceResources: [
{
complianceType: 'REMEMBER_ME',
uri: ''
}
]
},
srcCorrelationId: 'zzzz',
srcDigitalCardId: 'xxxx'
});
});
test('should pass the correct configuration to the respective scheme SDKs', async () => {
const visa = mock<VisaSdk>();

View File

@@ -55,6 +55,11 @@ class ClickToPayService implements IClickToPayService {
public shopperCards: ShopperCard[] = null;
public identityValidationData: IdentityValidationData = null;
/**
* Indicates if the shopper opted for saving cookies during the transaction
*/
public storeCookies = false;
constructor(
schemesConfig: SchemesConfiguration,
sdkLoader: ISrcSdkLoader,
@@ -77,12 +82,17 @@ class ClickToPayService implements IClickToPayService {
return this.sdkLoader.schemes;
}
public updateStoreCookiesConsent(shouldStore: boolean) {
this.storeCookies = shouldStore;
}
public async initialize(): Promise<void> {
this.setState(CtpState.Loading);
try {
this.sdks = await this.sdkLoader.load(this.environment);
await this.initiateSdks();
const { recognized = false, idTokens = null } = await this.verifyIfShopperIsRecognized();
if (recognized) {
@@ -104,10 +114,14 @@ class ClickToPayService implements IClickToPayService {
this.setState(CtpState.NotAvailable);
} catch (error) {
if (error instanceof SrciError) console.warn(`Error at ClickToPayService # init: ${error.toString()}`);
if (error instanceof TimeoutError) {
if (error instanceof SrciError && error?.reason === 'REQUEST_TIMEOUT') {
const timeoutError = new TimeoutError(`ClickToPayService - Timeout during ${error.source}() of the scheme '${error.scheme}'`);
this.onTimeout?.(timeoutError);
} else if (error instanceof TimeoutError) {
console.warn(error.toString());
this.onTimeout?.(error);
} else if (error instanceof SrciError) {
console.warn(`Error at ClickToPayService # init: ${error.toString()}`);
} else {
console.warn(error);
}
@@ -168,7 +182,8 @@ class ClickToPayService implements IClickToPayService {
const checkoutResponse = await checkoutSdk.checkout({
srcDigitalCardId: card.srcDigitalCardId,
srcCorrelationId: card.srcCorrelationId,
...(card.isDcfPopupEmbedded && { windowRef: window.frames[CTP_IFRAME_NAME] })
...(card.isDcfPopupEmbedded && { windowRef: window.frames[CTP_IFRAME_NAME] }),
...(this.storeCookies && { complianceSettings: { complianceResources: [{ complianceType: 'REMEMBER_ME', uri: '' }] } })
});
if (checkoutResponse.dcfActionCode !== 'COMPLETE') {

View File

@@ -33,12 +33,17 @@ class MastercardSdk extends AbstractSrcInitiator {
}
public async init(params: SrcInitParams, srciTransactionId: string): Promise<void> {
const sdkProps = {
...params,
...getMastercardSettings(this.customSdkConfiguration),
srciTransactionId
};
await this.schemeSdk.init(sdkProps);
try {
const sdkProps = {
...params,
...getMastercardSettings(this.customSdkConfiguration),
srciTransactionId
};
await this.schemeSdk.init(sdkProps);
} catch (err) {
const srciError = new SrciError(err, 'init', this.schemeName);
throw srciError;
}
}
public async identityLookup({ identityValue, type }: SrcIdentityLookupParams): Promise<SrciIdentityLookupResponse> {

View File

@@ -33,13 +33,18 @@ class VisaSdk extends AbstractSrcInitiator {
}
public async init(params: SrcInitParams, srciTransactionId: string): Promise<void> {
const sdkProps = {
...params,
...getVisaSetttings(this.customSdkConfiguration),
srciTransactionId
};
try {
const sdkProps = {
...params,
...getVisaSetttings(this.customSdkConfiguration),
srciTransactionId
};
await this.schemeSdk.init(sdkProps);
await this.schemeSdk.init(sdkProps);
} catch (err) {
const srciError = new SrciError(err, 'init', this.schemeName);
throw srciError;
}
}
public async identityLookup({ identityValue, type }: SrcIdentityLookupParams): Promise<SrciIdentityLookupResponse> {

View File

@@ -59,6 +59,16 @@ export type SrcCard = {
export type SrcCheckoutParams = {
srcCorrelationId: string;
srcDigitalCardId: string;
complianceSettings?: {
complianceResources: [
{
complianceType: 'REMEMBER_ME';
uri: string;
version?: string;
dataPublished?: string;
}
];
};
windowRef?: Window;
};

View File

@@ -9,6 +9,8 @@ export interface IClickToPayService {
identityValidationData: IdentityValidationData;
schemes: string[];
shopperAccountFound: boolean;
storeCookies: boolean;
updateStoreCookiesConsent(shouldStore: boolean): void;
initialize(): Promise<void>;
checkout(card: ShopperCard): Promise<ClickToPayCheckoutPayload>;
logout(): Promise<void>;

View File

@@ -7,7 +7,6 @@
position: relative;
padding-left: 24px;
cursor: pointer;
display: inline-block;
line-height: 19px;
color: $color-black;
font-size: $font-size-small;

View File

@@ -1,6 +1,6 @@
import { h } from 'preact';
import InputBase from './InputBase';
import InputBase, { InputBaseProps } from './InputBase';
export default function InputEmail(props) {
export default function InputEmail(props: InputBaseProps) {
return <InputBase {...props} type="email" autoCapitalize="off" />;
}

View File

@@ -1,7 +1,7 @@
@import "../../../style/index";
.adyen-checkout__open-invoice .adyen-checkout__fieldset--billingAddress {
padding-bottom: 8px;
margin-bottom: 16px;
}
.adyen-checkout__open-invoice .adyen-checkout__fieldset--deliveryAddress {
@@ -14,7 +14,7 @@
}
.adyen-checkout__open-invoice .adyen-checkout__field--consentCheckbox {
margin-top: 22px;
margin-top: 16px;
}
.adyen-checkout__input--separateDeliveryAddress + .adyen-checkout__checkbox__label {

View File

@@ -4,6 +4,7 @@
"payButton.with": "ادفع %{value} باستخدام %{maskedData}",
"close": "إغلاق",
"storeDetails": "حفظ لمدفوعاتي القادمة",
"readMore": "اقرأ المزيد",
"creditCard.holderName": "الاسم على البطاقة",
"creditCard.holderName.placeholder": "جميل سعيد",
"creditCard.holderName.invalid": "أدخل الاسم كما هو موضح على البطاقة",
@@ -22,7 +23,7 @@
"creditCard.cvcField.placeholder.3digits": "3 أرقام",
"creditCard.taxNumber.placeholder": "يوم شهر سنة / 0123456789",
"installments": "عدد الأقساط",
"installmentOption": "%{times} x %{partialValue}",
"installmentOption": "%{times} × %{partialValue}",
"installmentOptionMonths": "%{times} أشهر",
"installments.oneTime": "الدفع مرة واحدة",
"installments.installments": "الدفع على أقساط",
@@ -260,6 +261,7 @@
"ctp.otp.subtitle": "أدخل الرمز %@ الذي أرسلناه إلى ٪@ للتحقق من هويتك.",
"ctp.otp.saveCookiesCheckbox.label": "تخطي التحقق في المرة القادمة",
"ctp.otp.saveCookiesCheckbox.information": "حدد حفظ البيانات على جهازك ومتصفحك في المتاجر المشاركة لإتمام عملية الدفع بشكل أسرع. لا يوصى به للأجهزة المشتركة.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "حدد تذكرني على جهازك ومتصفحك.",
"ctp.emptyProfile.message": "لا توجد بطاقات مسجلة في هذا الملف التعريفي على Click to Pay",
"ctp.separatorText": "أو استخدم",
"ctp.cards.title": "أكمل الدفع باستخدام بطاقة Click to Pay",
@@ -300,4 +302,4 @@
"ancv.confirmPayment": "استخدم تطبيق ANCV الخاص بك لتأكيد الدفع.",
"ancv.form.instruction": "يعد تطبيق Cheque-Vacances ضروريًا للمصادقة على هذه المدفوعات.",
"ancv.beneficiaryId.invalid": "أدخل عنوان بريد إلكتروني صحيحًا أو معرف ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Zaplatit %{value} pomocí %{maskedData}",
"close": "Zavřít",
"storeDetails": "Uložit pro příští platby",
"readMore": "Přečtěte si více",
"creditCard.holderName": "Jméno na kartě",
"creditCard.holderName.placeholder": "Jan Novák",
"creditCard.holderName.invalid": "Zadejte jméno, jak je uvedeno na kartě",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Zadejte kód %@, který jsme vám odeslali na %@ a ověřte sami sebe.",
"ctp.otp.saveCookiesCheckbox.label": "Příště přeskočte ověřování",
"ctp.otp.saveCookiesCheckbox.information": "Zvolte, že si je chcete zapamatovat ve svém zařízení a prohlížeči v zúčastněných obchodech, abyste se rychleji odhlásili. Nedoporučuje se pro sdílená zařízení.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Vyberte, abyste si je zapamatovali ve svém zařízení a prohlížeči",
"ctp.emptyProfile.message": "V tomto profilu Click to Pay nejsou zaregistrovány žádné karty",
"ctp.separatorText": "nebo použijte",
"ctp.cards.title": "Dokončete platbu pomocí Click to Pay",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Pro potvrzení platby použijte aplikaci ANCV.",
"ancv.form.instruction": "K potvrzení této platby je nutná aplikace Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Zadejte platnou e-mailovou adresu nebo ID ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Betal %{value} med %{maskedData}",
"close": "Luk",
"storeDetails": "Gem til min næste betaling",
"readMore": "Læs mere",
"creditCard.holderName": "Navn på kort",
"creditCard.holderName.placeholder": "J. Hansen",
"creditCard.holderName.invalid": "Indtast navn som vist på kortet",
@@ -260,6 +261,7 @@
"ctp.otp.subtitle": "Indtast den kode, vi har sendt til %@ for at bekræfte, at det er dig.",
"ctp.otp.saveCookiesCheckbox.label": "Spring bekræftelse over næste gang",
"ctp.otp.saveCookiesCheckbox.information": "Vælg dette for at blive husket på din enhed og browser i deltagende butikker for hurtigere betaling. Anbefales ikke på delte enheder.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Vælg dette for at blive husket på din enhed og browser",
"ctp.emptyProfile.message": "Ingen kort registreret i denne Click to Pay-profil",
"ctp.separatorText": "eller brug",
"ctp.cards.title": "Gennemfør betaling med Click to Pay",
@@ -297,4 +299,4 @@
"ancv.confirmPayment": "Brug din ANCV-applikation til at bekræfte betalingen.",
"ancv.form.instruction": "Cheque-Vacances-applikationen er nødvendig for at validere denne betaling.",
"ancv.beneficiaryId.invalid": "Indtast en gyldig e-mailadresse eller ANCV-id"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "%{value} mit %{maskedData} zahlen",
"close": "Schließen",
"storeDetails": "Für zukünftige Zahlvorgänge speichern",
"readMore": "Mehr lesen",
"creditCard.holderName": "Name auf der Karte",
"creditCard.holderName.placeholder": "A. Müller",
"creditCard.holderName.invalid": "Geben Sie den Namen wie auf der Karte gezeigt ein",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Geben Sie den Code ein, der von %@ an %@ gesendet wurde, um Ihre Identität zu bestätigen.",
"ctp.otp.saveCookiesCheckbox.label": "Verifizierung beim nächsten Mal überspringen",
"ctp.otp.saveCookiesCheckbox.information": "Wählen Sie diese Option, um bei teilnehmenden Geschäften auf Ihrem Gerät und Browser gespeichert zu werden, um den Bestellvorgang zu beschleunigen. Nicht für gemeinsam genutzte Geräte empfohlen.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Wählen Sie diese Option aus, um auf Ihrem Gerät und Browser gespeichert zu werden",
"ctp.emptyProfile.message": "In diesem Click-to-Pay-Profil sind keine Karten registriert",
"ctp.separatorText": "oder verwenden",
"ctp.cards.title": "Zahlung mit Click to Pay abschließen",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Bestätigen Sie die Zahlung mit Ihrem ANCV-Antrag.",
"ancv.form.instruction": "Zur Validierung dieser Zahlung ist der Antrag „Cheque-Vacances“ erforderlich.",
"ancv.beneficiaryId.invalid": "Geben Sie eine gültige E-Mail-Adresse oder ANCV-ID ein"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Πληρωμή %{value} με %{maskedData}",
"close": "Κλείσιμο",
"storeDetails": "Αποθήκευση για την επόμενη πληρωμή μου",
"readMore": "Ανάγνωση περισσότερων",
"creditCard.holderName": "Όνομα στην κάρτα",
"creditCard.holderName.placeholder": "Γ. Παπαδάκης",
"creditCard.holderName.invalid": "Εισαγάγετε το όνομα όπως αναγράφεται στην κάρτα",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Εισαγάγετε τον κωδικό %@ που στάλθηκε στο %@ για να επαληθεύσετε ότι είστε εσείς.",
"ctp.otp.saveCookiesCheckbox.label": "Παράβλεψη επαλήθευσης την επόμενη φορά",
"ctp.otp.saveCookiesCheckbox.information": "Επιλέξτε να απομνημονεύεται στη συσκευή και στο πρόγραμμα περιήγησής σας στα συμμετέχοντα καταστήματα για ταχύτερη ολοκλήρωση της πληρωμής. Δεν συνιστάται για κοινόχρηστες συσκευές.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Επιλέξτε να απομνημονεύεται στη συσκευή και στο πρόγραμμα περιήγησής σας",
"ctp.emptyProfile.message": "Δεν υπάρχουν καταχωρισμένες κάρτες σε αυτό το προφίλ Click to Pay",
"ctp.separatorText": "ή χρησιμοποιήστε το",
"ctp.cards.title": "Ολοκληρώστε την πληρωμή με το Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Χρησιμοποιήστε την εφαρμογή ANCV για επιβεβαίωση της πληρωμής.",
"ancv.form.instruction": "Η εφαρμογή Cheque-Vacances είναι απαραίτητη για επικύρωση της πληρωμής αυτής.",
"ancv.beneficiaryId.invalid": "Εισαγάγετε έγκυρη διεύθυνση email ή αναγνωριστικό ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Pay %{value} with %{maskedData}",
"close": "Close",
"storeDetails": "Save for my next payment",
"readMore": "Read more",
"creditCard.holderName": "Name on card",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Enter name as shown on card",
@@ -261,6 +262,7 @@
"ctp.otp.subtitle": "Enter the code %@ sent to %@ to verify its you.",
"ctp.otp.saveCookiesCheckbox.label": "Skip verification next time",
"ctp.otp.saveCookiesCheckbox.information": "Select to be remembered on your device and browser at participating stores for faster checkout. Not recommended for shared devices.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Select to be remembered on your device and browser",
"ctp.emptyProfile.message": "No cards registered in this Click to Pay profile",
"ctp.separatorText": "or use",
"ctp.cards.title": "Complete payment with Click to Pay",
@@ -301,4 +303,4 @@
"ancv.confirmPayment": "Use your ANCV application to confirm the payment.",
"ancv.form.instruction": "The Cheque-Vacances application is necessary to validate this payment.",
"ancv.beneficiaryId.invalid": "Enter a valid email address or ANCV ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Pague %{value} con %{maskedData}",
"close": "Cerrar",
"storeDetails": "Recordar para mi próximo pago",
"readMore": "Leer más",
"creditCard.holderName": "Nombre en la tarjeta",
"creditCard.holderName.placeholder": "Juan Pérez",
"creditCard.holderName.invalid": "Introduzca el nombre como se muestra en la tarjeta",
@@ -254,6 +255,7 @@
"ctp.otp.subtitle": "Introduzca el código %@ que le hemos enviado a %@ para verificar que es usted.",
"ctp.otp.saveCookiesCheckbox.label": "Omitir verificación la próxima vez",
"ctp.otp.saveCookiesCheckbox.information": "Seleccione esta opción para recordarle en su dispositivo y navegador en las tiendas participantes para agilizar el proceso de pago. No lo recomendamos para dispositivos compartidos.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Seleccione esta opción para recordarle en su dispositivo y navegador",
"ctp.emptyProfile.message": "No hay tarjetas registradas en este perfil de Click to Pay",
"ctp.separatorText": "o utilice",
"ctp.cards.title": "Completar el pago con Click to Pay",
@@ -291,4 +293,4 @@
"ancv.confirmPayment": "Utilice su solicitud de la ANCV para confirmar el pago.",
"ancv.form.instruction": "La aplicación de Cheque-Vacances es necesaria para validar este pago.",
"ancv.beneficiaryId.invalid": "Introduzca una dirección de correo electrónico válida o un documento de identidad de la ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Maksa %{value} käyttäen maksutapaa %{maskedData}",
"close": "Sulje",
"storeDetails": "Tallenna seuraavaa maksuani varten",
"readMore": "Lue lisää",
"creditCard.holderName": "Nimi kortilla",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Syötä nimi sellaisena kuin se on kortissa",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Syötä koodi, jonka %@ lähetti osoitteeseen %@ vahvistaaksesi, että kyseessä olet sinä.",
"ctp.otp.saveCookiesCheckbox.label": "Ohita vahvistus seuraavalla kerralla",
"ctp.otp.saveCookiesCheckbox.information": "Valitse, että sinut muistetaan laitteellasi ja selaimessa osallistuvissa myymälöissä, jotta voit maksaa nopeammin. Ei suositella jaetuilla laitteilla.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Valitse, jotta sinut muistetaan laitteellasi ja selaimessa",
"ctp.emptyProfile.message": "Tähän Click to Pay -profiiliin ei ole rekisteröity kortteja",
"ctp.separatorText": "tai käytä",
"ctp.cards.title": "Suorita maksu Click to Paylla",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Vahvista maksusi ANCV-sovelluksella.",
"ancv.form.instruction": "Tämän maksun vahvistaminen edellyttää Cheque-Vacances -sovelluksen.",
"ancv.beneficiaryId.invalid": "Anna kelvollinen sähköpostiosoite tai ANCV-tunnus"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Payer %{value} avec %{maskedData}",
"close": "Fermer",
"storeDetails": "Sauvegarder pour mon prochain paiement",
"readMore": "Lire la suite",
"creditCard.holderName": "Nom sur la carte",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Entrez le nom tel qu'il apparaît sur la carte",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Saisissez le code %@ envoyé à %@ pour vérifier votre identité.",
"ctp.otp.saveCookiesCheckbox.label": "Ignorer la vérification la prochaine fois",
"ctp.otp.saveCookiesCheckbox.information": "Sélectionnez cette option pour mémoriser les informations sur votre appareil et votre navigateur afin d'accélérer le paiement dans les magasins participants. Non recommandé pour les appareils partagés.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Sélectionner cette option pour mémoriser les informations sur votre appareil et votre navigateur",
"ctp.emptyProfile.message": "Aucune carte enregistrée dans ce profil Click to Pay",
"ctp.separatorText": "ou utilisez",
"ctp.cards.title": "Terminez le paiement avec Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Utilisez votre application ANCV pour confirmer le paiement.",
"ancv.form.instruction": "L'application Chèque-Vacances est nécessaire pour valider ce paiement.",
"ancv.beneficiaryId.invalid": "Saisissez une adresse e-mail ou un identifiant ANCV valide"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Platite iznos od %{value} uporabom stavke %{maskedData}",
"close": "Zatvori",
"storeDetails": "Pohrani za moje sljedeće plaćanje",
"readMore": "Opširnije",
"creditCard.holderName": "Ime na kartici",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Unesite ime kako je prikazano na kartici",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Upišite kôd %@ koji smo poslali na %@ da bismo potvrdili da ste to vi.",
"ctp.otp.saveCookiesCheckbox.label": "Sljedeći puta preskoči provjeru",
"ctp.otp.saveCookiesCheckbox.information": "Odaberite kako biste bili zapamćeni na svom uređaju i pregledniku u uključenim trgovinama za bržu naplatu. Ne preporučuje se za zajedničke uređaje.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Odaberite ako želite da vas se zapamti na vašem uređaju i pregledniku",
"ctp.emptyProfile.message": "Nema kartica registriranih u sklopu ovog profila usluge Click to Pay",
"ctp.separatorText": "ili upotrijebite",
"ctp.cards.title": "Dovrši plaćanje uslugom Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Koristite svoju ANCV aplikaciju za potvrdu plaćanja.",
"ancv.form.instruction": "Za potvrdu ove uplate neophodna je aplikacija Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Unesite valjanu adresu e-pošte ili ANCV ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "%{value} fizetése a következővel: %{maskedData}",
"close": "Bezárás",
"storeDetails": "Mentés a következő fizetéshez",
"readMore": "Bővebben",
"creditCard.holderName": "A kártyán szereplő név",
"creditCard.holderName.placeholder": "Gipsz Jakab",
"creditCard.holderName.invalid": "Adja meg a kártyán szereplő nevet",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Írja be a kódot, amit a(z) %@ küldött %@ részére ellenőrzés céljából.",
"ctp.otp.saveCookiesCheckbox.label": "Ellenőrzés kihagyása a következő alkalommal",
"ctp.otp.saveCookiesCheckbox.information": "Jelölje be, hogy a résztvevő üzletek a gyorsabb fizetés érdekében emlékezzenek az eszközre és a böngészőre. Megosztott eszközök esetén nem ajánlott.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Jelölje be, hogy a rendszer emlékezzen az eszközre és a böngészőre",
"ctp.emptyProfile.message": "Ebben a Click to Pay-profilban nincs regisztrált kártya",
"ctp.separatorText": "vagy használja a következőt",
"ctp.cards.title": "Fizetés Click to Pay használatával",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "A fizetés megerősítéséhez használja az ANCV alkalmazást.",
"ancv.form.instruction": "A fizetés érvényesítéséhez a Cheque-Vacances alkalmazás szükséges.",
"ancv.beneficiaryId.invalid": "Adjon meg egy érvényes e-mail-címet vagy ANCV-azonosítót"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Paga %{value} con %{maskedData}",
"close": "Chiudi",
"storeDetails": "Salva per il prossimo pagamento",
"readMore": "Leggi di più",
"creditCard.holderName": "Titolare carta",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Immetti il nome riportato sulla carta",
@@ -257,6 +258,7 @@
"ctp.otp.subtitle": "Inserisci il codice che %@ ha inviato a %@ per verificare la tua identità.",
"ctp.otp.saveCookiesCheckbox.label": "Salta la verifica la prossima volta",
"ctp.otp.saveCookiesCheckbox.information": "Scegli di essere ricordato sul dispositivo e il browser che utilizzi per velocizzare il pagamento nei negozi partecipanti. Non consigliato per dispositivi condivisi.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Seleziona per essere ricordato sul tuo dispositivo e sul browser",
"ctp.emptyProfile.message": "Non esistono carte registrate in questo profilo Click to Pay",
"ctp.separatorText": "o utilizza",
"ctp.cards.title": "Completa il pagamento con Click to Pay",
@@ -297,4 +299,4 @@
"ancv.confirmPayment": "Utilizza la tua richiesta ANCV per confermare il pagamento.",
"ancv.form.instruction": "Per confermare il pagamento è necessario utilizzare la richiesta Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Inserisci un indirizzo e-mail o un identificativo ANCV valido"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "%{value}を%{maskedData}で支払う",
"close": "終了",
"storeDetails": "次回のお支払いのため詳細を保存",
"readMore": "詳細を確認",
"creditCard.holderName": "カード上の名前",
"creditCard.holderName.placeholder": "Taro Yamada",
"creditCard.holderName.invalid": "カードに記載されている名前を入力してください",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "%@から%@に送信されたコードを入力して、ご本人であることを確認してください。",
"ctp.otp.saveCookiesCheckbox.label": "次回は検証をスキップする",
"ctp.otp.saveCookiesCheckbox.information": "対象店舗で、お使いのデバイスとブラウザで記憶させるように選択すると、より迅速なチェックアウトが可能になります。共有デバイスでは推奨されません。",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "選択すると、お使いのデバイスとブラウザに記憶されます",
"ctp.emptyProfile.message": "このClick to Payプロフィールに登録されているカードはありません。",
"ctp.separatorText": "または以下を使用",
"ctp.cards.title": "Click to Payで支払いを完了する",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "ANCVアプリケーションを使用して、支払を確認してください。",
"ancv.form.instruction": "この支払を検証するには、Cheque-Vacancesアプリケーションが必要です。",
"ancv.beneficiaryId.invalid": "有効なメールアドレスまたはANCV IDを入力してください"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "%{maskedData}(으)로 %{value} 결제",
"close": "닫기",
"storeDetails": "다음 결제를 위해 이 수단 저장",
"readMore": "자세히 보기",
"creditCard.holderName": "카드상의 이름",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "카드에 표시된 대로 이름을 입력합니다.",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "%@로 전송된 %@ 코드를 입력하여 본인 인증을 진행합니다.",
"ctp.otp.saveCookiesCheckbox.label": "다음 번에는 인증 건너뛰기",
"ctp.otp.saveCookiesCheckbox.information": "더 빠른 결제를 위해 사용자 기기와 참여 매장의 브라우저에서 정보를 기억하도록 선택하세요. 공유 기기에는 권장하지 않습니다.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "장치와 브라우저에서 기억되도록 선택하기",
"ctp.emptyProfile.message": "해당 Click to Pay 프로필에 등록된 카드가 없습니다",
"ctp.separatorText": "또는 사용",
"ctp.cards.title": "Click to Pay로 결제 완료",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "ANCV 애플리케이션을 사용해 결제를 확인하세요.",
"ancv.form.instruction": "이 결제를 인증하려면 Cheque-Vacances 애플리케이션이 필요합니다.",
"ancv.beneficiaryId.invalid": "유효한 이메일 주소나 ANCV ID를 입력하세요."
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Betaal %{value} met %{maskedData}",
"close": "Sluiten",
"storeDetails": "Bewaar voor mijn volgende betaling",
"readMore": "Verder lezen",
"creditCard.holderName": "Naam op kaart",
"creditCard.holderName.placeholder": "J. Janssen",
"creditCard.holderName.invalid": "Voer naam in zoals weergegeven op kaart",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Voer de code %@ in die naar %@ is gestuurd, zodat we kunnen verifiëren dat u het bent.",
"ctp.otp.saveCookiesCheckbox.label": "Verificatie de volgende keer overslaan",
"ctp.otp.saveCookiesCheckbox.information": "Selecteer om te worden onthouden op uw apparaat en in uw browser bij deelnemende winkels, zodat u sneller kunt afrekenen. Niet aanbevolen voor gedeelde apparaten.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Selecteer om onthouden te worden op uw apparaat en browser",
"ctp.emptyProfile.message": "Geen kaarten geregistreerd voor dit Click to Pay-profiel",
"ctp.separatorText": "of gebruik",
"ctp.cards.title": "Voltooi de betaling met Click to Pay",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Gebruik uw ANCV-toepassing om de betaling te bevestigen.",
"ancv.form.instruction": "De Cheque-Vacances applicatie is nodig om deze betaling te valideren.",
"ancv.beneficiaryId.invalid": "Voer een geldig e-mailadres of ANCV-id in"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Betal %{value} med %{maskedData}",
"close": "Lukk",
"storeDetails": "Lagre til min neste betaling",
"readMore": "Les mer",
"creditCard.holderName": "Navn på kortet",
"creditCard.holderName.placeholder": "O. Nordmann",
"creditCard.holderName.invalid": "Skriv inn navnet som vist på kortet",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Tast inn koden vi sendte til %@, for å verifisere at det er deg.",
"ctp.otp.saveCookiesCheckbox.label": "Hopp over verifisering neste gang",
"ctp.otp.saveCookiesCheckbox.information": "Velg for å bli husket på enheten og i nettleseren din i deltakende butikker for raskere betaling. Anbefales ikke for delte enheter.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Velg for å bli husket på enheten og i nettleseren din",
"ctp.emptyProfile.message": "Ingen kort er registrert i denne Click to Pay-profilen",
"ctp.separatorText": "eller bruk",
"ctp.cards.title": "Fullfør betalingen med Click to Pay",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Bruk ANCV-appen for å bekrefte betalingen.",
"ancv.form.instruction": "Cheque-Vacances-appen er nødvendig for å validere denne betalingen.",
"ancv.beneficiaryId.invalid": "Oppgi en gyldig e-postadresse eller ANCV-ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Zapłać %{value} za pomocą %{maskedData}",
"close": "Zamknij",
"storeDetails": "Zapisz na potrzeby następnej płatności",
"readMore": "Czytaj więcej",
"creditCard.holderName": "Imię i nazwisko na karcie",
"creditCard.holderName.placeholder": "J. Kowalski",
"creditCard.holderName.invalid": "Wpisz imię i nazwisko w takim formacie, jak na karcie",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Wprowadź kod %@ wysłany na adres %@, aby potwierdzić swoją tożsamość.",
"ctp.otp.saveCookiesCheckbox.label": "Następnym razem pomiń weryfikację",
"ctp.otp.saveCookiesCheckbox.information": "Wybierz opcję zapamiętywania na urządzeniu i w przeglądarce w sklepach uczestniczących w programie, aby przyspieszyć realizację transakcji. Niezalecane dla współużytkowanych urządzeń.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Wybierz, aby zapamiętać dane logowania na Twoim urządzeniu i przeglądarce",
"ctp.emptyProfile.message": "W tym profilu Click to Pay nie zarejestrowano żadnych kart",
"ctp.separatorText": "lub przypadków jej użycia",
"ctp.cards.title": "Dokończ płatność za pomocą funkcji Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Użyj aplikacji ANCV, aby potwierdzić płatność.",
"ancv.form.instruction": "Do zatwierdzenia tej płatności konieczna jest aplikacja Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Wprowadź poprawny adres e-mail lub identyfikator ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Pague %{value} com %{maskedData}",
"close": "Fechar",
"storeDetails": "Salvar para meu próximo pagamento",
"readMore": "Leia mais",
"creditCard.holderName": "Nome no cartão",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Digite o nome conforme mostrado no cartão",
@@ -257,6 +258,7 @@
"ctp.otp.subtitle": "Digite o código %@ enviado para %@ para confirmar que é você.",
"ctp.otp.saveCookiesCheckbox.label": "Ignorar verificação da próxima vez",
"ctp.otp.saveCookiesCheckbox.information": "Selecione esta opção para ser lembrado no seu dispositivo e navegador, agilizando o pagamento nas lojas participantes. Não recomendado para dispositivos compartilhados.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Selecione para ser lembrado em seu dispositivo e navegador",
"ctp.emptyProfile.message": "Não há nenhum cartão cadastrado neste perfil do Click to Pay",
"ctp.separatorText": "ou use",
"ctp.cards.title": "Concluir o pagamento com o Click to Pay",
@@ -297,4 +299,4 @@
"ancv.confirmPayment": "Use o aplicativo da ANCV para confirmar o pagamento.",
"ancv.form.instruction": "É necessário ter o aplicativo da Cheque-Vacances para validar este pagamento.",
"ancv.beneficiaryId.invalid": "Insira um endereço de e-mail válido ou uma ID da ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Pagar %{value} com %{maskedData}",
"close": "Fechar",
"storeDetails": "Guardar para o meu próximo pagamento",
"readMore": "Ler mais",
"creditCard.holderName": "Nome no cartão",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Introduzir o nome como mostrado no cartão",
@@ -261,6 +262,7 @@
"ctp.otp.subtitle": "Introduza o código %@ enviado para %@ para verificar se é você.",
"ctp.otp.saveCookiesCheckbox.label": "Saltar verificação da próxima vez",
"ctp.otp.saveCookiesCheckbox.information": "Selecione para ser memorizado no seu dispositivo e navegador nas lojas participantes, para uma finalização de compra mais rápida. Não recomendado para dispositivos partilhados.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Selecione para ser memorizado no seu dispositivo e navegador",
"ctp.emptyProfile.message": "Nenhum cartão registado neste perfil Click to Pay",
"ctp.separatorText": "ou utilize",
"ctp.cards.title": "Pagamento completo com Click to Pay",
@@ -301,4 +303,4 @@
"ancv.confirmPayment": "Use a sua aplicação ANCV para confirmar o pagamento.",
"ancv.form.instruction": "A app Cheque-Vacances é necessária para validar este pagamento.",
"ancv.beneficiaryId.invalid": "Insira um endereço de e-mail ou ID válido de ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Plătiți %{value} cu %{maskedData}",
"close": "Închidere",
"storeDetails": "Salvează pentru următoarea mea plată",
"readMore": "Citiți mai mult",
"creditCard.holderName": "Numele de pe card",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "Completați numele după cum figurează pe card",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Introduceți codul %@ pe care l-am trimis la %@ pentru a confirma că sunteți dvs.",
"ctp.otp.saveCookiesCheckbox.label": "Omiteți verificarea data viitoare",
"ctp.otp.saveCookiesCheckbox.information": "Selectați pentru a fi reținut pe dispozitiv și în browserul dvs. la magazinele participante pentru o plată mai rapidă. Nerecomandat pentru dispozitivele partajate.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Selectați pentru a fi memorat pe dispozitiv și browser",
"ctp.emptyProfile.message": "Niciun card înregistrat în acest profil Click to Pay",
"ctp.separatorText": "sau folosiți",
"ctp.cards.title": "Finalizați plata cu Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Utilizați aplicația ANCV pentru a confirma plata.",
"ancv.form.instruction": "Aplicația Cheque-Vacances este necesară pentru a valida această plată.",
"ancv.beneficiaryId.invalid": "Completați o adresă de e-mail sau un ID ANCV valabil"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Оплатить %{value} %{maskedData}",
"close": "Закрыть",
"storeDetails": "Сохранить для следующего платежа",
"readMore": "Подробнее",
"creditCard.holderName": "Имя на карте",
"creditCard.holderName.placeholder": "И. Петров",
"creditCard.holderName.invalid": "Введите имя, как оно указано на карте",
@@ -256,6 +257,7 @@
"ctp.otp.subtitle": "Для подтверждения своей личности введите код %@, отправленный %@.",
"ctp.otp.saveCookiesCheckbox.label": "Пропустить подтверждение в следующий раз",
"ctp.otp.saveCookiesCheckbox.information": "Чтобы в соответствующих магазинах запомнили ваше устройство и браузер, выберите эту опцию. Это позволит быстрее оформлять заказы. Не рекомендуется на устройствах совместного использования.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Выберите, чтобы запомнили ваше устройство и браузер",
"ctp.emptyProfile.message": "В данном профиле Click to Pay нет зарегистрированных карт",
"ctp.separatorText": "или используйте",
"ctp.cards.title": "Оформите оплату с помощью Click to Pay",
@@ -296,4 +298,4 @@
"ancv.confirmPayment": "Используйте приложение ANCV для подтверждения платежа.",
"ancv.form.instruction": "Для подтверждения этого платежа необходимо приложение Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Введите действительный адрес электронной почты или идентификатор ANCV"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Zaplatiť %{value} pomocou %{maskedData}",
"close": "Zavrieť",
"storeDetails": "Uložiť pre moju ďalšiu platbu",
"readMore": "Prečítajte si viac",
"creditCard.holderName": "Meno na karte",
"creditCard.holderName.placeholder": "J. Novák",
"creditCard.holderName.invalid": "Zadajte meno tak, ako je uvedené na karte",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Zadajte kód %@, ktorý sme poslali na adresu %@, aby sme overili, že ste to vy.",
"ctp.otp.saveCookiesCheckbox.label": "Nabudúce preskočiť overovanie",
"ctp.otp.saveCookiesCheckbox.information": "Vyberte túto možnosť na zapamätanie v zariadení a prehliadači v zúčastnených obchodoch, čím urýchlite platbu. Neodporúča sa pre zdieľané zariadenia.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Vyberte túto možnosť na zapamätanie v zariadení a prehliadači",
"ctp.emptyProfile.message": "V tomto profile Click to Pay nie sú registrované žiadne karty",
"ctp.separatorText": "alebo použite",
"ctp.cards.title": "Dokončite platbu v službe Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Na potvrdenie platby použite svoju aplikáciu ANCV.",
"ancv.form.instruction": "Na potvrdenie tejto platby je potrebná aplikácia Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Zadajte platnú e-mailovú adresu alebo ANCV ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Plačajte %{value} z %{maskedData}",
"close": "Zapri",
"storeDetails": "Shrani za moje naslednje plačilo",
"readMore": "Preberi več",
"creditCard.holderName": "Ime na kartici",
"creditCard.holderName.placeholder": "J. Novak",
"creditCard.holderName.invalid": "Vnesite ime, kot je prikazano na kartici",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Vnesite kodo %@, ki smo jo poslali na %@, da potrdite, da ste to res vi.",
"ctp.otp.saveCookiesCheckbox.label": "Naslednjič preskoči preverjanje",
"ctp.otp.saveCookiesCheckbox.information": "Izberite če želite, da se v vaši napravi in brskalniku v sodelujočih trgovinah vaši podatki shranijo za hitrejši zaključek zakupa. Ni priporočljivo za naprave v skupni rabi.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Izberite, če želite, da se v vaši napravi in brskalniku shranijo vaši podatki",
"ctp.emptyProfile.message": "V tem profilu Click to Pay ni registriranih nobenih kartic",
"ctp.separatorText": "ali uporabite",
"ctp.cards.title": "Dokončajte plačilo s storitvijo Click to Pay",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "Za potrditev plačila uporabite aplikacijo ANCV.",
"ancv.form.instruction": "Za potrditev tega plačila je potrebna aplikacija Cheque-Vacances.",
"ancv.beneficiaryId.invalid": "Vnesite veljaven e-poštni naslov ali ANCV ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "Betala %{value} med %{maskedData}",
"close": "Stäng",
"storeDetails": "Spara till min nästa betalning",
"readMore": "Läs mer",
"creditCard.holderName": "Namn på kort",
"creditCard.holderName.placeholder": "A. Andersson",
"creditCard.holderName.invalid": "Ange namnet som det står på kortet",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "Ange koden som %@ skickade till %@ för att verifiera att det är du.",
"ctp.otp.saveCookiesCheckbox.label": "Hoppa över verifieringen nästa gång",
"ctp.otp.saveCookiesCheckbox.information": "Välj att bli ihågkommen på din enhet och webbläsare i deltagande butiker för snabbare utcheckning. Rekommenderas inte för delade enheter.",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "Välj att bli ihågkommen på din enhet och i din webbläsare",
"ctp.emptyProfile.message": "Inga kort registrerade i denna Click to Pay-profil",
"ctp.separatorText": "eller använd",
"ctp.cards.title": "Slutför betalningen med Click to Pay",
@@ -297,4 +299,4 @@
"ancv.confirmPayment": "Bekräfta betalningen i din ANCV-app.",
"ancv.form.instruction": "Appen Cheque-Vacances krävs för att validera denna betalning.",
"ancv.beneficiaryId.invalid": "Ange en giltig e-postadress eller ANCV-ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "使用 %{maskedData} 支付 %{value}",
"close": "关闭",
"storeDetails": "保存以便下次支付使用",
"readMore": "阅读更多",
"creditCard.holderName": "卡片上的姓名",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "输入卡片上显示的姓名",
@@ -258,6 +259,7 @@
"ctp.otp.subtitle": "请输入我们发送至 %@ 的代码 (%@),以验证是您本人。",
"ctp.otp.saveCookiesCheckbox.label": "下次跳过验证",
"ctp.otp.saveCookiesCheckbox.information": "在您的设备和浏览器上,在参与活动的店铺中选择记住该选项,以便更快地结账。不建议用于共享设备。",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "选择在您的设备和浏览器上记住",
"ctp.emptyProfile.message": "此 Click to Pay 个人资料中尚未注册任何卡片",
"ctp.separatorText": "或使用",
"ctp.cards.title": "借助 Click to Pay 完成付款",
@@ -298,4 +300,4 @@
"ancv.confirmPayment": "使用您的 ANCV 应用以确认付款。",
"ancv.form.instruction": "要验证这笔付款,必须使用 Checke-Vacances 应用。",
"ancv.beneficiaryId.invalid": "输入有效的电子邮件地址或 ANCV ID"
}
}

View File

@@ -4,6 +4,7 @@
"payButton.with": "用 %{maskedData} 支付 %{value}",
"close": "關閉",
"storeDetails": "儲存以供下次付款使用",
"readMore": "閱讀全文",
"creditCard.holderName": "信用卡上的姓名",
"creditCard.holderName.placeholder": "J. Smith",
"creditCard.holderName.invalid": "輸入卡上所示的姓名",
@@ -259,6 +260,7 @@
"ctp.otp.subtitle": "請輸入我們傳送至 %@ 的驗證碼 %@,以驗證是您本人。",
"ctp.otp.saveCookiesCheckbox.label": "下次略過驗證",
"ctp.otp.saveCookiesCheckbox.information": "選擇在裝置和瀏覽器中記住參與商店的驗證資訊,以加快結帳速度。不建議在共享裝置上選取該設定。",
"ctp.otp.saveCookiesCheckbox.shorterInfo": "選擇在裝置和瀏覽器中記住",
"ctp.emptyProfile.message": "此 Click to Pay 個人資料中未註冊任何卡",
"ctp.separatorText": "或使用",
"ctp.cards.title": "使用 Click to Pay 完成付款",
@@ -299,4 +301,4 @@
"ancv.confirmPayment": "使用您的 ANCV 應用程式確認付款。",
"ancv.form.instruction": "必須申請 Cheque-Vacances 才能驗證此付款。",
"ancv.beneficiaryId.invalid": "輸入有效的電子郵件地址或 ANCV ID"
}
}

View File

@@ -0,0 +1,3 @@
const isScreenSmall = (): boolean => window.matchMedia('(max-width: 480px)').matches;
export default isScreenSmall;

View File

@@ -188,7 +188,7 @@ getPaymentMethods({ amount, shopperLocale }).then(async paymentMethodsResponse =
mcSrcClientId: '6d41d4d6-45b1-42c3-a5d0-a28c0e69d4b1'
},
clickToPayConfiguration: {
shopperEmail: 'shopper@example.com',
shopperEmail: 'shopper@adyen.com',
merchantDisplayName: 'Adyen Merchant Name',
onReady: () => {
console.log('Component is ready to be used');