diff --git a/examples/dynamic-checkout/index.html b/examples/dynamic-checkout/index.html
index 4e53cfa2..bea7306f 100644
--- a/examples/dynamic-checkout/index.html
+++ b/examples/dynamic-checkout/index.html
@@ -11,7 +11,7 @@
document.addEventListener("DOMContentLoaded", function () {
// You need to replace these values with your own
const projectId = "test-proj_qEi1u5BwoYcZb6mOMKDWIm4mpqKCq6bN"
- const invoiceId = "iv_39bZyCq6bNxAWSl9DA6PXGt63mEi952M"
+ const invoiceId = "iv_39vI9Cq6bN1LV3k0Xh7bSIxV0ICdFwHu"
const clientSecret = ""
const client = new ProcessOut.ProcessOut(projectId)
diff --git a/package.json b/package.json
index e352790f..0c748a34 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "processout.js",
- "version": "1.7.3",
+ "version": "1.7.4",
"description": "ProcessOut.js is a JavaScript library for ProcessOut's payment processing API.",
"scripts": {
"build:processout": "tsc -p src/processout && uglifyjs --compress --keep-fnames --ie8 dist/processout.js -o dist/processout.js",
diff --git a/src/dynamic-checkout/config/billing-address.ts b/src/dynamic-checkout/config/billing-address.ts
index 92f4d3b5..ab978bf6 100644
--- a/src/dynamic-checkout/config/billing-address.ts
+++ b/src/dynamic-checkout/config/billing-address.ts
@@ -978,7 +978,7 @@ module ProcessOut {
name: "United States",
postcodeUnit: "zip",
stateUnit: "state",
- units: ["state"],
+ units: ["street1", "street2", "city", "state", "postcode"],
states: [
{
abbreviation: "AL",
diff --git a/src/dynamic-checkout/config/payment-config.ts b/src/dynamic-checkout/config/payment-config.ts
index d43e6cbf..8aa9a217 100644
--- a/src/dynamic-checkout/config/payment-config.ts
+++ b/src/dynamic-checkout/config/payment-config.ts
@@ -9,6 +9,7 @@ module ProcessOut {
capturePayments?: boolean
allowFallbackToSale?: boolean
showStatusMessage?: boolean
+ payButtonText?: string
}
export type DynamicCheckoutInternalConfigType = {
@@ -26,6 +27,7 @@ module ProcessOut {
capturePayments: DynamicCheckoutPublicConfigType["capturePayments"] = false
allowFallbackToSale: DynamicCheckoutPublicConfigType["allowFallbackToSale"] = false
showStatusMessage: DynamicCheckoutPublicConfigType["showStatusMessage"] = true
+ payButtonText: DynamicCheckoutPublicConfigType["payButtonText"] = ""
invoiceDetails: DynamicCheckoutInternalConfigType["invoiceDetails"]
constructor(config: DynamicCheckoutPublicConfigType) {
@@ -61,6 +63,7 @@ module ProcessOut {
this.locale = config.locale || "en"
this.capturePayments = config.capturePayments || false
this.allowFallbackToSale = config.allowFallbackToSale || false
+ this.payButtonText = config.payButtonText || ""
if (config.showStatusMessage !== undefined && config.showStatusMessage !== null) {
this.showStatusMessage = config.showStatusMessage
diff --git a/src/dynamic-checkout/dynamic-checkout.ts b/src/dynamic-checkout/dynamic-checkout.ts
index 0a2169a9..273c9338 100644
--- a/src/dynamic-checkout/dynamic-checkout.ts
+++ b/src/dynamic-checkout/dynamic-checkout.ts
@@ -71,7 +71,7 @@ module ProcessOut {
}
private onGetInvoiceLoading() {
- this.loadView(new DynamicCheckoutInvoiceLoadingView().element)
+ this.loadView(new DynamicCheckoutInvoiceLoadingView(this.paymentConfig.locale).element)
DynamicCheckoutEventsUtils.dispatchWidgetLoadingEvent()
}
diff --git a/src/dynamic-checkout/elements/payment-method-button.ts b/src/dynamic-checkout/elements/payment-method-button.ts
index fb4073ec..e2fa210a 100644
--- a/src/dynamic-checkout/elements/payment-method-button.ts
+++ b/src/dynamic-checkout/elements/payment-method-button.ts
@@ -14,6 +14,7 @@ module ProcessOut {
deleteMode: boolean = false,
deletingAllowed: boolean = false,
handleDeletePaymentMethod?: () => void,
+ locale: string = "en",
) {
this.processOutInstance = processOutInstance
@@ -25,6 +26,7 @@ module ProcessOut {
deletingAllowed,
rightContent,
handleDeletePaymentMethod,
+ locale,
)
}
@@ -36,6 +38,7 @@ module ProcessOut {
deletingAllowed: boolean,
rightContent?: HTMLElement,
handleDeletePaymentMethod?: () => void,
+ locale: string = "en",
) {
const [
element,
@@ -56,6 +59,7 @@ module ProcessOut {
],
attributes: {
"data-id": id,
+ for: `payment-method-${id}`,
},
},
{
@@ -88,17 +92,23 @@ module ProcessOut {
attributes: {
type: "radio",
name: "payment-method",
+ id: `payment-method-${id}`,
+ value: id,
},
},
{
tagName: "button",
classNames: ["dco-delete-payment-method-button"],
+ attributes: {
+ "aria-label": Translations.getText("delete-payment-method-label", locale),
+ },
},
{
tagName: "img",
classNames: ["dco-delete-payment-method-icon"],
attributes: {
src: this.processOutInstance.endpoint("js", TRASH_ICON),
+ alt: "",
},
},
])
diff --git a/src/dynamic-checkout/elements/payment-methods-manager.ts b/src/dynamic-checkout/elements/payment-methods-manager.ts
index 0d11bb3e..e815c655 100644
--- a/src/dynamic-checkout/elements/payment-methods-manager.ts
+++ b/src/dynamic-checkout/elements/payment-methods-manager.ts
@@ -25,12 +25,19 @@ module ProcessOut {
{
tagName: "button",
classNames: ["dco-express-checkout-header-settings-button"],
+ attributes: {
+ "aria-label": Translations.getText(
+ "settings-button-label",
+ this.paymentConfig.locale,
+ ),
+ },
},
{
tagName: "img",
classNames: ["dco-express-checkout-cog-icon"],
attributes: {
src: this.processOutInstance.endpoint("js", COG_ICON),
+ alt: "",
},
},
])
@@ -58,6 +65,9 @@ module ProcessOut {
stickyFooter: true,
closeMethods: ["overlay", "button", "escape"],
closeLabel: closeLabel,
+ onClose: () => {
+ this.element.focus()
+ },
})
: null
diff --git a/src/dynamic-checkout/locales/de.ts b/src/dynamic-checkout/locales/de.ts
new file mode 100644
index 00000000..5dac6bf7
--- /dev/null
+++ b/src/dynamic-checkout/locales/de.ts
@@ -0,0 +1,47 @@
+module ProcessOut {
+ export const de = {
+ "apm-redirect-message": "Sie werden zur Zahlungsbestätigung weitergeleitet.",
+ "save-for-future-label": "Für zukünftige Zahlungen speichern",
+ "continue-with-apm-button": "Weiter mit",
+ "pay-button-text": "Bezahlen",
+ "card-details-section-title": "Kartendetails",
+ "cardholder-name-label": "Name des Karteninhabers",
+ "billing-address-section-title": "Rechnungsadresse",
+ "country-label": "Land",
+ "select-country-placeholder": "Land auswählen",
+ "select-state-placeholder": "Bundesland auswählen",
+ "card-number-error-message": "Kartennummer ist ungültig",
+ "expiry-date-error-message": "Ablaufdatum ist ungültig",
+ "cvc-error-message": "CVC ist ungültig",
+ "cardholder-name-error-message": "Name des Karteninhabers ist ungültig",
+ "payment-error-message": "Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.",
+ "payment-cancelled-message": "Die Zahlung wurde storniert.",
+ "express-checkout-header": "Express-Checkout",
+ "other-payment-methods-header": "Weitere Zahlungsmethoden",
+ "select-payment-method-label": "Zahlungsmethode auswählen",
+ "payment-success-message": "Diese Zahlung wurde abgeschlossen.",
+ "payment-info-message":
+ "Wir verarbeiten Ihre Zahlung. Sie können dieses Fenster jetzt schließen.",
+ "payment-error-generic-message": "Wir konnten Ihre Zahlung nicht verarbeiten.",
+ "street1-label": "Adresszeile 1",
+ "street2-label": "Adresszeile 2",
+ "city-label": "Stadt",
+ "postcode-label": "Postleitzahl",
+ "state-label": "Bundesland",
+ "payments-manager-header": "Gespeicherte Zahlungsmethoden verwalten",
+ "payments-manager-close-button": "Schließen",
+ "no-saved-payment-methods-header": "Keine gespeicherten Zahlungsmethoden",
+ "no-saved-payment-methods-message":
+ "Wenn Sie das nächste Mal eine Zahlungsmethode speichern, wird sie hier angezeigt.",
+ "card-number-label": "Kartennummer",
+ "expiry-date-label": "Ablaufdatum",
+ "cvc-label": "CVC",
+ "card-not-supported-error-message": "Diese Karte wird nicht unterstützt",
+ "card-label": "Karte",
+ "delete-payment-method-label": "Zahlungsmethode löschen",
+ "settings-button-label": "Gespeicherte Zahlungsmethoden verwalten",
+ "loading-label": "Laden",
+ "processing-payment-label": "Zahlung wird verarbeitet",
+ "card-form-label": "Kartenzahlungsformular",
+ }
+}
diff --git a/src/dynamic-checkout/locales/en.ts b/src/dynamic-checkout/locales/en.ts
index 569c4b67..a9ca100e 100644
--- a/src/dynamic-checkout/locales/en.ts
+++ b/src/dynamic-checkout/locales/en.ts
@@ -32,7 +32,15 @@ module ProcessOut {
"no-saved-payment-methods-header": "No saved payment methods",
"no-saved-payment-methods-message":
"The next time you save a payment method, it will appear here.",
+ "card-number-label": "Card number",
+ "expiry-date-label": "Expiry date",
+ "cvc-label": "CVC",
"card-not-supported-error-message": "This card is not supported",
"card-label": "Card",
+ "delete-payment-method-label": "Delete payment method",
+ "settings-button-label": "Manage saved payment methods",
+ "loading-label": "Loading",
+ "processing-payment-label": "Processing payment",
+ "card-form-label": "Card payment form",
}
}
diff --git a/src/dynamic-checkout/locales/es.ts b/src/dynamic-checkout/locales/es.ts
index 58cfe3a6..022f2b75 100644
--- a/src/dynamic-checkout/locales/es.ts
+++ b/src/dynamic-checkout/locales/es.ts
@@ -32,7 +32,15 @@ module ProcessOut {
"no-saved-payment-methods-header": "No hay métodos de pago guardados",
"no-saved-payment-methods-message":
"La próxima vez que guardes un método de pago, aparecerá aquí.",
+ "card-number-label": "Número de tarjeta",
+ "expiry-date-label": "Fecha de vencimiento",
+ "cvc-label": "CVC",
"card-not-supported-error-message": "Esta tarjeta no es compatible",
"card-label": "Tarjeta bancaria",
+ "delete-payment-method-label": "Eliminar método de pago",
+ "settings-button-label": "Administrar métodos de pago guardados",
+ "loading-label": "Cargando",
+ "processing-payment-label": "Procesando pago",
+ "card-form-label": "Formulario de pago con tarjeta",
}
}
diff --git a/src/dynamic-checkout/locales/fr.ts b/src/dynamic-checkout/locales/fr.ts
index b3945dcc..c303ebd0 100644
--- a/src/dynamic-checkout/locales/fr.ts
+++ b/src/dynamic-checkout/locales/fr.ts
@@ -33,7 +33,15 @@ module ProcessOut {
"no-saved-payment-methods-header": "Aucune méthode de paiement enregistrée",
"no-saved-payment-methods-message":
"La prochaine fois que vous enregistrez une méthode de paiement, elle apparaîtra ici.",
+ "card-number-label": "Numéro de carte",
+ "expiry-date-label": "Date d'expiration",
+ "cvc-label": "CVC",
"card-not-supported-error-message": "Cette carte n'est pas acceptée",
"card-label": "Carte",
+ "delete-payment-method-label": "Supprimer le moyen de paiement",
+ "settings-button-label": "Gérer les moyens de paiement enregistrés",
+ "loading-label": "Chargement",
+ "processing-payment-label": "Traitement du paiement",
+ "card-form-label": "Formulaire de paiement par carte",
}
}
diff --git a/src/dynamic-checkout/locales/it.ts b/src/dynamic-checkout/locales/it.ts
new file mode 100644
index 00000000..6cc82a9d
--- /dev/null
+++ b/src/dynamic-checkout/locales/it.ts
@@ -0,0 +1,47 @@
+module ProcessOut {
+ export const it = {
+ "apm-redirect-message": "Verrai reindirizzato per completare il pagamento.",
+ "save-for-future-label": "Salva per pagamenti futuri",
+ "continue-with-apm-button": "Continua con",
+ "pay-button-text": "Paga",
+ "card-details-section-title": "Dettagli della carta",
+ "cardholder-name-label": "Nome del titolare della carta",
+ "billing-address-section-title": "Indirizzo di fatturazione",
+ "country-label": "Paese",
+ "select-country-placeholder": "Seleziona paese",
+ "select-state-placeholder": "Seleziona provincia",
+ "card-number-error-message": "Il numero della carta non è valido",
+ "expiry-date-error-message": "La data di scadenza non è valida",
+ "cvc-error-message": "Il CVC non è valido",
+ "cardholder-name-error-message": "Il nome del titolare della carta non è valido",
+ "payment-error-message": "Si è verificato un errore. Riprova.",
+ "payment-cancelled-message": "Il pagamento è stato annullato.",
+ "express-checkout-header": "Checkout rapido",
+ "other-payment-methods-header": "Altri metodi di pagamento",
+ "select-payment-method-label": "Seleziona metodo di pagamento",
+ "payment-success-message": "Il pagamento è stato completato.",
+ "payment-info-message":
+ "Stiamo elaborando il tuo pagamento. Ora puoi chiudere questa finestra.",
+ "payment-error-generic-message": "Non è stato possibile elaborare il pagamento.",
+ "street1-label": "Indirizzo riga 1",
+ "street2-label": "Indirizzo riga 2",
+ "city-label": "Città",
+ "postcode-label": "Codice postale",
+ "state-label": "Provincia",
+ "payments-manager-header": "Gestisci metodi di pagamento salvati",
+ "payments-manager-close-button": "Chiudi",
+ "no-saved-payment-methods-header": "Nessun metodo di pagamento salvato",
+ "no-saved-payment-methods-message":
+ "La prossima volta che salvi un metodo di pagamento, apparirà qui.",
+ "card-number-label": "Numero della carta",
+ "expiry-date-label": "Data di scadenza",
+ "cvc-label": "CVC",
+ "card-not-supported-error-message": "Questa carta non è supportata",
+ "card-label": "Carta",
+ "delete-payment-method-label": "Elimina metodo di pagamento",
+ "settings-button-label": "Gestisci metodi di pagamento salvati",
+ "loading-label": "Caricamento",
+ "processing-payment-label": "Elaborazione del pagamento",
+ "card-form-label": "Modulo di pagamento con carta",
+ }
+}
diff --git a/src/dynamic-checkout/locales/ja.ts b/src/dynamic-checkout/locales/ja.ts
new file mode 100644
index 00000000..8a13753c
--- /dev/null
+++ b/src/dynamic-checkout/locales/ja.ts
@@ -0,0 +1,47 @@
+module ProcessOut {
+ export const ja = {
+ "apm-redirect-message": "お支払いを完了するためにリダイレクトされます。",
+ "save-for-future-label": "今後の支払いのために保存",
+ "continue-with-apm-button": "で続行",
+ "pay-button-text": "支払う",
+ "card-details-section-title": "カード情報",
+ "cardholder-name-label": "カード名義人",
+ "billing-address-section-title": "請求先住所",
+ "country-label": "国",
+ "select-country-placeholder": "国を選択",
+ "select-state-placeholder": "都道府県を選択",
+ "card-number-error-message": "カード番号が無効です",
+ "expiry-date-error-message": "有効期限が無効です",
+ "cvc-error-message": "CVCが無効です",
+ "cardholder-name-error-message": "カード名義人が無効です",
+ "payment-error-message": "エラーが発生しました。もう一度お試しください。",
+ "payment-cancelled-message": "お支払いがキャンセルされました。",
+ "express-checkout-header": "エクスプレスチェックアウト",
+ "other-payment-methods-header": "その他の支払い方法",
+ "select-payment-method-label": "支払い方法を選択",
+ "payment-success-message": "お支払いが完了しました。",
+ "payment-info-message":
+ "お支払いを処理しています。このウィンドウを閉じていただいて構いません。",
+ "payment-error-generic-message": "お支払いを処理できませんでした。",
+ "street1-label": "住所1",
+ "street2-label": "住所2",
+ "city-label": "市区町村",
+ "postcode-label": "郵便番号",
+ "state-label": "都道府県",
+ "payments-manager-header": "保存済みの支払い方法を管理",
+ "payments-manager-close-button": "閉じる",
+ "no-saved-payment-methods-header": "保存済みの支払い方法はありません",
+ "no-saved-payment-methods-message":
+ "次回支払い方法を保存すると、ここに表示されます。",
+ "card-number-label": "カード番号",
+ "expiry-date-label": "有効期限",
+ "cvc-label": "CVC",
+ "card-not-supported-error-message": "このカードはサポートされていません",
+ "card-label": "カード",
+ "delete-payment-method-label": "支払い方法を削除",
+ "settings-button-label": "保存済みの支払い方法を管理",
+ "loading-label": "読み込み中",
+ "processing-payment-label": "支払いを処理中",
+ "card-form-label": "カード決済フォーム",
+ }
+}
diff --git a/src/dynamic-checkout/locales/ko.ts b/src/dynamic-checkout/locales/ko.ts
new file mode 100644
index 00000000..064f220e
--- /dev/null
+++ b/src/dynamic-checkout/locales/ko.ts
@@ -0,0 +1,47 @@
+module ProcessOut {
+ export const ko = {
+ "apm-redirect-message": "결제를 완료하기 위해 리디렉션됩니다.",
+ "save-for-future-label": "향후 결제를 위해 저장",
+ "continue-with-apm-button": "계속하기",
+ "pay-button-text": "결제",
+ "card-details-section-title": "카드 정보",
+ "cardholder-name-label": "카드 소유자 이름",
+ "billing-address-section-title": "청구지 주소",
+ "country-label": "국가",
+ "select-country-placeholder": "국가 선택",
+ "select-state-placeholder": "시/도 선택",
+ "card-number-error-message": "카드 번호가 유효하지 않습니다",
+ "expiry-date-error-message": "만료일이 유효하지 않습니다",
+ "cvc-error-message": "CVC가 유효하지 않습니다",
+ "cardholder-name-error-message": "카드 소유자 이름이 유효하지 않습니다",
+ "payment-error-message": "오류가 발생했습니다. 다시 시도해 주세요.",
+ "payment-cancelled-message": "결제가 취소되었습니다.",
+ "express-checkout-header": "빠른 결제",
+ "other-payment-methods-header": "기타 결제 수단",
+ "select-payment-method-label": "결제 수단 선택",
+ "payment-success-message": "결제가 완료되었습니다.",
+ "payment-info-message":
+ "결제를 처리하고 있습니다. 이 창을 닫으셔도 됩니다.",
+ "payment-error-generic-message": "결제를 처리할 수 없습니다.",
+ "street1-label": "주소 1",
+ "street2-label": "주소 2",
+ "city-label": "시/군/구",
+ "postcode-label": "우편번호",
+ "state-label": "시/도",
+ "payments-manager-header": "저장된 결제 수단 관리",
+ "payments-manager-close-button": "닫기",
+ "no-saved-payment-methods-header": "저장된 결제 수단 없음",
+ "no-saved-payment-methods-message":
+ "다음에 결제 수단을 저장하면 여기에 표시됩니다.",
+ "card-number-label": "카드 번호",
+ "expiry-date-label": "만료일",
+ "cvc-label": "CVC",
+ "card-not-supported-error-message": "이 카드는 지원되지 않습니다",
+ "card-label": "카드",
+ "delete-payment-method-label": "결제 수단 삭제",
+ "settings-button-label": "저장된 결제 수단 관리",
+ "loading-label": "로딩 중",
+ "processing-payment-label": "결제 처리 중",
+ "card-form-label": "카드 결제 양식",
+ }
+}
diff --git a/src/dynamic-checkout/locales/pl.ts b/src/dynamic-checkout/locales/pl.ts
index 7d0329e9..abfed255 100644
--- a/src/dynamic-checkout/locales/pl.ts
+++ b/src/dynamic-checkout/locales/pl.ts
@@ -32,7 +32,15 @@ module ProcessOut {
"no-saved-payment-methods-header": "Brak zapisanych metod płatności",
"no-saved-payment-methods-message":
"Gdy następnym razem zapiszesz metodę płatności, pojawi się tutaj.",
+ "card-number-label": "Numer karty",
+ "expiry-date-label": "Data ważności",
+ "cvc-label": "CVC",
"card-not-supported-error-message": "Ta karta nie jest obsługiwana",
"card-label": "Karta płatnicza",
+ "delete-payment-method-label": "Usuń metodę płatności",
+ "settings-button-label": "Zarządzaj zapisanymi metodami płatności",
+ "loading-label": "Ładowanie",
+ "processing-payment-label": "Przetwarzanie płatności",
+ "card-form-label": "Formularz płatności kartą",
}
}
diff --git a/src/dynamic-checkout/locales/pt.ts b/src/dynamic-checkout/locales/pt.ts
index 3c6c8c77..e581918c 100644
--- a/src/dynamic-checkout/locales/pt.ts
+++ b/src/dynamic-checkout/locales/pt.ts
@@ -33,7 +33,15 @@ module ProcessOut {
"no-saved-payment-methods-header": "Nenhum método de pagamento salvo",
"no-saved-payment-methods-message":
"Depois de guardar uma forma de pagamento, ela aparecerá aqui. ",
+ "card-number-label": "Número do cartão",
+ "expiry-date-label": "Data de validade",
+ "cvc-label": "CVC",
"card-not-supported-error-message": "Este cartão não é suportado",
"card-label": "Cartão",
+ "delete-payment-method-label": "Excluir método de pagamento",
+ "settings-button-label": "Gerenciar métodos de pagamento salvos",
+ "loading-label": "Carregando",
+ "processing-payment-label": "Processando pagamento",
+ "card-form-label": "Formulário de pagamento com cartão",
}
}
diff --git a/src/dynamic-checkout/payment-methods/apm.ts b/src/dynamic-checkout/payment-methods/apm.ts
index f85ee139..feb3e57f 100644
--- a/src/dynamic-checkout/payment-methods/apm.ts
+++ b/src/dynamic-checkout/payment-methods/apm.ts
@@ -94,7 +94,7 @@ module ProcessOut {
this.processOutInstance.handleAction(
apm.redirect_url,
paymentToken => {
- this.resetContainerHtml().appendChild(new DynamicCheckoutInvoiceLoadingView().element)
+ this.resetContainerHtml().appendChild(new DynamicCheckoutInvoiceLoadingView(this.paymentConfig.locale).element)
DynamicCheckoutEventsUtils.dispatchPaymentPendingEvent(paymentToken, {
payment_method_name: apm.gateway_name,
@@ -177,7 +177,7 @@ module ProcessOut {
this.processOutInstance.handleAction(
data.customer_action.value,
paymentToken => {
- this.resetContainerHtml().appendChild(new DynamicCheckoutInvoiceLoadingView().element)
+ this.resetContainerHtml().appendChild(new DynamicCheckoutInvoiceLoadingView(this.paymentConfig.locale).element)
this.processOutInstance.makeCardPayment(
this.paymentConfig.invoiceId,
@@ -302,6 +302,7 @@ module ProcessOut {
"js",
"/images/dynamic-checkout-assets/apm-redirect-arrow.svg",
),
+ alt: "",
},
},
{
@@ -325,7 +326,7 @@ module ProcessOut {
tagName: "label",
classNames: ["dco-payment-method-button-save-for-future-label"],
attributes: {
- for: `save-apm-for-future-${this.paymentMethod.display.name}`,
+ for: `save-apm-for-future-${this.paymentMethod.apm.gateway_name}`,
},
textContent: Translations.getText("save-for-future-label", this.paymentConfig.locale),
},
diff --git a/src/dynamic-checkout/payment-methods/apple-pay.ts b/src/dynamic-checkout/payment-methods/apple-pay.ts
index 5c4e3107..66953aed 100644
--- a/src/dynamic-checkout/payment-methods/apple-pay.ts
+++ b/src/dynamic-checkout/payment-methods/apple-pay.ts
@@ -21,7 +21,7 @@ module ProcessOut {
tagName: "div",
classNames: ["dco-wallet-checkout-button"],
attributes: {
- id: "google-pay-button-container",
+ id: "apple-pay-button-container",
},
})
diff --git a/src/dynamic-checkout/payment-methods/card.ts b/src/dynamic-checkout/payment-methods/card.ts
index a2d9b42b..5e40ced1 100644
--- a/src/dynamic-checkout/payment-methods/card.ts
+++ b/src/dynamic-checkout/payment-methods/card.ts
@@ -224,10 +224,11 @@ module ProcessOut {
}
private getChildrenElement() {
- const payButtonText = `${Translations.getText(
- "pay-button-text",
- this.paymentConfig.locale,
- )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
+ const payButtonText = this.paymentConfig.payButtonText
+ || `${Translations.getText(
+ "pay-button-text",
+ this.paymentConfig.locale,
+ )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
const [
cardFormWrapper,
@@ -242,6 +243,7 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-wrapper"],
attributes: {
id: "card-form",
+ "aria-label": Translations.getText("card-form-label", this.paymentConfig.locale),
},
},
{
@@ -313,16 +315,20 @@ module ProcessOut {
cardDetailsSectionTitle,
cardDetailsSectionInputsWrapper,
cardNumberInputWrapper,
+ cardNumberLabel,
cardNumberInput,
cardNumberInputErrorMessage,
splitCardInputRow,
expiryDateInputWrapper,
+ expiryDateLabel,
expiryDateInput,
expiryDateInputErrorMessage,
cvcInputWrapper,
+ cvcLabel,
cvcInput,
cvcInputErrorMessage,
cardHolderNameInputWrapper,
+ cardHolderNameLabel,
cardHolderNameInput,
cardHolderNameInputErrorMessage,
cardSchemeLogo,
@@ -347,6 +353,11 @@ module ProcessOut {
tagName: "div",
classNames: ["dco-payment-method-card-form-input-wrapper"],
},
+ {
+ tagName: "label",
+ classNames: ["dco-input-label"],
+ textContent: Translations.getText("card-number-label", this.paymentConfig.locale),
+ },
{
tagName: "div",
classNames: ["dco-payment-method-card-form-input"],
@@ -360,6 +371,7 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-input-error-message"],
attributes: {
id: "card-number-error-message",
+ role: "alert",
},
},
{
@@ -370,6 +382,11 @@ module ProcessOut {
tagName: "div",
classNames: ["dco-payment-method-card-form-input-wrapper"],
},
+ {
+ tagName: "label",
+ classNames: ["dco-input-label"],
+ textContent: Translations.getText("expiry-date-label", this.paymentConfig.locale),
+ },
{
tagName: "div",
classNames: ["dco-payment-method-card-form-input"],
@@ -383,12 +400,18 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-input-error-message"],
attributes: {
id: "expiry-date-error-message",
+ role: "alert",
},
},
{
tagName: "div",
classNames: ["dco-payment-method-card-form-input-wrapper"],
},
+ {
+ tagName: "label",
+ classNames: ["dco-input-label"],
+ textContent: Translations.getText("cvc-label", this.paymentConfig.locale),
+ },
{
tagName: "div",
classNames: [
@@ -405,12 +428,21 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-input-error-message"],
attributes: {
id: "cvc-error-message",
+ role: "alert",
},
},
{
tagName: "div",
classNames: ["dco-payment-method-card-form-input-wrapper"],
},
+ {
+ tagName: "label",
+ classNames: ["dco-input-label"],
+ attributes: {
+ for: "cardholder-name-input",
+ },
+ textContent: Translations.getText("cardholder-name-label", this.paymentConfig.locale),
+ },
{
tagName: "input",
classNames: [
@@ -418,8 +450,10 @@ module ProcessOut {
"dco-payment-method-card-form-input-cardholder-name",
],
attributes: {
+ id: "cardholder-name-input",
name: "cardholder-name",
placeholder: Translations.getText("cardholder-name-label", this.paymentConfig.locale),
+ autocomplete: "cc-name",
},
},
{
@@ -427,6 +461,7 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-input-error-message"],
attributes: {
id: "cardholder-name-error-message",
+ role: "alert",
},
},
{
@@ -444,6 +479,7 @@ module ProcessOut {
}
HTMLElements.appendChildren(cardNumberInputWrapper, [
+ cardNumberLabel,
cardNumberInput,
cardNumberInputErrorMessage,
])
@@ -454,15 +490,17 @@ module ProcessOut {
])
HTMLElements.appendChildren(expiryDateInputWrapper, [
+ expiryDateLabel,
expiryDateInput,
expiryDateInputErrorMessage,
])
- HTMLElements.appendChildren(cvcInputWrapper, [cvcInput, cvcInputErrorMessage])
+ HTMLElements.appendChildren(cvcInputWrapper, [cvcLabel, cvcInput, cvcInputErrorMessage])
HTMLElements.appendChildren(splitCardInputRow, [expiryDateInputWrapper, cvcInputWrapper])
HTMLElements.appendChildren(cardHolderNameInputWrapper, [
+ cardHolderNameLabel,
cardHolderNameInput,
cardHolderNameInputErrorMessage,
])
@@ -555,10 +593,17 @@ module ProcessOut {
payButton.disabled = true
payButton.textContent = ""
+ payButton.setAttribute(
+ "aria-label",
+ Translations.getText("processing-payment-label", this.paymentConfig.locale),
+ )
const spinner = HTMLElements.createElement({
tagName: "span",
classNames: ["dco-payment-method-button-pay-button-spinner"],
+ attributes: {
+ "aria-hidden": "true",
+ },
})
HTMLElements.appendChildren(payButton, [spinner])
@@ -569,8 +614,10 @@ module ProcessOut {
tagName: "select",
classNames: ["dco-payment-method-card-form-input"],
attributes: {
+ id: "country-select",
name: "country",
placeholder: Translations.getText("country-label", this.paymentConfig.locale),
+ "aria-label": Translations.getText("country-label", this.paymentConfig.locale),
},
})
@@ -634,13 +681,16 @@ module ProcessOut {
}
if (automaticMode && shouldShowPostcodeForAutomaticMode) {
+ const postcodeLabel = billingAddressUnitsData(this.paymentConfig).postcode.placeholder
+
return [
HTMLElements.createElement({
tagName: "input",
classNames: ["dco-payment-method-card-form-input"],
attributes: {
name: "postcode",
- placeholder: billingAddressUnitsData(this.paymentConfig).postcode.placeholder,
+ placeholder: postcodeLabel,
+ "aria-label": postcodeLabel,
},
}),
]
@@ -657,6 +707,7 @@ module ProcessOut {
classNames: ["dco-payment-method-card-form-input"],
attributes: {
name: unit,
+ "aria-label": Translations.getText("state-label", this.paymentConfig.locale),
},
})
@@ -678,12 +729,15 @@ module ProcessOut {
HTMLElements.appendChildren(input, [stateOption])
})
} else {
+ const unitLabel = billingAddressUnitsData(this.paymentConfig)[unit].placeholder
+
input = HTMLElements.createElement({
tagName: "input",
classNames: ["dco-payment-method-card-form-input"],
attributes: {
name: unit,
- placeholder: billingAddressUnitsData(this.paymentConfig)[unit].placeholder,
+ placeholder: unitLabel,
+ "aria-label": unitLabel,
},
})
}
diff --git a/src/dynamic-checkout/payment-methods/saved-apm.ts b/src/dynamic-checkout/payment-methods/saved-apm.ts
index 29c0f26f..86df63ca 100644
--- a/src/dynamic-checkout/payment-methods/saved-apm.ts
+++ b/src/dynamic-checkout/payment-methods/saved-apm.ts
@@ -32,6 +32,7 @@ module ProcessOut {
deleteMode,
paymentMethod.apm_customer_token.deleting_allowed,
handleDeletePaymentMethod,
+ paymentConfig.locale,
)
this.processOutInstance = processOutInstance
@@ -44,10 +45,11 @@ module ProcessOut {
}
private getChildrenElement(deleteMode?: boolean) {
- const payButtonText = `${Translations.getText(
- "pay-button-text",
- this.paymentConfig.locale,
- )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
+ const payButtonText = this.paymentConfig.payButtonText
+ || `${Translations.getText(
+ "pay-button-text",
+ this.paymentConfig.locale,
+ )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
const [wrapper, payButton] = HTMLElements.createMultipleElements([
{
@@ -214,10 +216,17 @@ module ProcessOut {
payButton.disabled = true
payButton.textContent = ""
+ payButton.setAttribute(
+ "aria-label",
+ Translations.getText("processing-payment-label", this.paymentConfig.locale),
+ )
const spinner = HTMLElements.createElement({
tagName: "span",
classNames: ["dco-payment-method-button-pay-button-spinner"],
+ attributes: {
+ "aria-hidden": "true",
+ },
})
HTMLElements.appendChildren(payButton, [spinner])
diff --git a/src/dynamic-checkout/payment-methods/saved-card.ts b/src/dynamic-checkout/payment-methods/saved-card.ts
index f98751ad..f4dd9409 100644
--- a/src/dynamic-checkout/payment-methods/saved-card.ts
+++ b/src/dynamic-checkout/payment-methods/saved-card.ts
@@ -33,6 +33,7 @@ module ProcessOut {
deleteMode,
paymentMethod.card_customer_token.deleting_allowed,
handleDeletePaymentMethod,
+ paymentConfig.locale,
)
this.processOutInstance = processOutInstance
@@ -45,12 +46,11 @@ module ProcessOut {
}
private getChildrenElement(deleteMode?: boolean) {
- const payButtonText = `${Translations.getText(
- "pay-button-text",
- this.paymentConfig.locale,
- )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
-
- console.log(this.paymentMethod)
+ const payButtonText = this.paymentConfig.payButtonText
+ || `${Translations.getText(
+ "pay-button-text",
+ this.paymentConfig.locale,
+ )} ${this.paymentConfig.invoiceDetails.amount} ${this.paymentConfig.invoiceDetails.currency}`
const [wrapper, payButton] = HTMLElements.createMultipleElements([
{
@@ -148,10 +148,17 @@ module ProcessOut {
payButton.disabled = true
payButton.textContent = ""
+ payButton.setAttribute(
+ "aria-label",
+ Translations.getText("processing-payment-label", this.paymentConfig.locale),
+ )
const spinner = HTMLElements.createElement({
tagName: "span",
classNames: ["dco-payment-method-button-pay-button-spinner"],
+ attributes: {
+ "aria-hidden": "true",
+ },
})
HTMLElements.appendChildren(payButton, [spinner])
diff --git a/src/dynamic-checkout/references.ts b/src/dynamic-checkout/references.ts
index 7c7db413..5eeef502 100644
--- a/src/dynamic-checkout/references.ts
+++ b/src/dynamic-checkout/references.ts
@@ -22,10 +22,14 @@
///
///
///
-///
+///
///
///
///
+///
+///
+///
+///
///
///
///
diff --git a/src/dynamic-checkout/styles/default.ts b/src/dynamic-checkout/styles/default.ts
index e78c01ad..280d4f89 100644
--- a/src/dynamic-checkout/styles/default.ts
+++ b/src/dynamic-checkout/styles/default.ts
@@ -500,8 +500,8 @@ const defaultStyles = `
}
.dco-express-checkout-header-settings-button {
- width: 32px;
- height: 32px;
+ min-width: 44px;
+ min-height: 44px;
padding: 0;
display: flex;
justify-content: center;
@@ -509,14 +509,13 @@ const defaultStyles = `
background-color: transparent;
border: none;
cursor: pointer;
- padding: 0;
transition: all .4s;
border-radius: 4px;
}
.dco-delete-payment-method-button {
- width: 32px;
- height: 32px;
+ min-width: 44px;
+ min-height: 44px;
display: flex;
justify-content: center;
align-items: center;
@@ -811,4 +810,58 @@ const defaultStyles = `
padding: 12px;
background-color: #1213140a;
}
+
+.dco-input-label {
+ display: block;
+ font-size: 12px;
+ font-weight: 500;
+ color: #696F79;
+ margin-bottom: 4px;
+}
+
+ .dco-payment-method-button-radio-button:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: 2px;
+ }
+
+ .dco-payment-method-button-pay-button:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: 2px;
+ }
+
+ .dco-delete-payment-method-button:focus-visible,
+ .dco-express-checkout-header-settings-button:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: 2px;
+ }
+
+ .dco-payment-method-card-form-input:focus-visible,
+ .dco-payment-method-card-form-input-cardholder-name:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: -1px;
+ border-color: #242C38;
+ }
+
+ select.dco-payment-method-card-form-input:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: -1px;
+ border-color: #242C38;
+ }
+
+ .close-modal-btn:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: 2px;
+ }
+
+ .dco-payment-method-button-save-for-future-checkbox:focus-visible {
+ outline: 2px solid #242C38;
+ outline-offset: 2px;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ .dco-invoice-loading,
+ .dco-payment-method-button-pay-button-spinner {
+ animation: none;
+ }
+ }
`
diff --git a/src/dynamic-checkout/utils/translations.ts b/src/dynamic-checkout/utils/translations.ts
index e1a3e6f1..9fc101dc 100644
--- a/src/dynamic-checkout/utils/translations.ts
+++ b/src/dynamic-checkout/utils/translations.ts
@@ -3,9 +3,13 @@
module ProcessOut {
export class Translations {
static localeTranslationsMap = {
+ de: de,
en: en,
es: es,
fr: fr,
+ it: it,
+ ja: ja,
+ ko: ko,
pl: pl,
pt: pt,
}
diff --git a/src/dynamic-checkout/views/invoice-loading.ts b/src/dynamic-checkout/views/invoice-loading.ts
index dbb9e494..fc4bab97 100644
--- a/src/dynamic-checkout/views/invoice-loading.ts
+++ b/src/dynamic-checkout/views/invoice-loading.ts
@@ -4,15 +4,22 @@ module ProcessOut {
export class DynamicCheckoutInvoiceLoadingView {
public element: Element
- constructor() {
+ constructor(locale: string = "en") {
const [element, spinner] = HTMLElements.createMultipleElements([
{
tagName: "div",
classNames: ["dco-invoice-loading-container"],
+ attributes: {
+ role: "status",
+ "aria-label": Translations.getText("loading-label", locale),
+ },
},
{
tagName: "div",
classNames: ["dco-invoice-loading"],
+ attributes: {
+ "aria-hidden": "true",
+ },
},
])
diff --git a/src/dynamic-checkout/views/payment-cancelled.ts b/src/dynamic-checkout/views/payment-cancelled.ts
index 946f7390..66547ec9 100644
--- a/src/dynamic-checkout/views/payment-cancelled.ts
+++ b/src/dynamic-checkout/views/payment-cancelled.ts
@@ -9,12 +9,16 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-card-payment-success"],
+ attributes: {
+ role: "alert",
+ },
},
{
tagName: "img",
classNames: ["dco-card-payment-success-image"],
attributes: {
src: processOutInstance.endpoint("js", PAYMENT_ERROR_IMAGE_ASSET),
+ alt: "",
},
},
{
diff --git a/src/dynamic-checkout/views/payment-error.ts b/src/dynamic-checkout/views/payment-error.ts
index 244c590e..ef7b4ae8 100644
--- a/src/dynamic-checkout/views/payment-error.ts
+++ b/src/dynamic-checkout/views/payment-error.ts
@@ -13,12 +13,16 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-card-payment-success"],
+ attributes: {
+ role: "alert",
+ },
},
{
tagName: "img",
classNames: ["dco-card-payment-success-image"],
attributes: {
src: processOutInstance.endpoint("js", PAYMENT_ERROR_IMAGE_ASSET),
+ alt: "",
},
},
{
diff --git a/src/dynamic-checkout/views/payment-info.ts b/src/dynamic-checkout/views/payment-info.ts
index fd48b3ac..2b64abad 100644
--- a/src/dynamic-checkout/views/payment-info.ts
+++ b/src/dynamic-checkout/views/payment-info.ts
@@ -9,6 +9,9 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-card-payment-success"],
+ attributes: {
+ role: "status",
+ },
},
{
tagName: "p",
diff --git a/src/dynamic-checkout/views/payment-methods.ts b/src/dynamic-checkout/views/payment-methods.ts
index 813b8bad..8c07191c 100644
--- a/src/dynamic-checkout/views/payment-methods.ts
+++ b/src/dynamic-checkout/views/payment-methods.ts
@@ -68,6 +68,30 @@ module ProcessOut {
wrapper.appendChild(regularPaymentMethodsSectionWrapper)
}
+ const hasExpressPaymentMethods =
+ walletPaymentMethods.length > 0 || expressPaymentMethods.length > 0
+
+ if (regularPaymentMethods.length === 1) {
+ const radioButton = regularPaymentMethods[0].element.querySelector(
+ ".dco-payment-method-button-radio-button",
+ ) as HTMLInputElement
+
+ if (radioButton) {
+ radioButton.checked = true
+ radioButton.style.display = "none"
+ }
+
+ if (!hasExpressPaymentMethods) {
+ const header = regularPaymentMethodsSectionWrapper.querySelector(
+ ".dco-regular-payment-methods-section-header",
+ ) as HTMLElement
+
+ if (header) {
+ header.style.display = "none"
+ }
+ }
+ }
+
return wrapper
}
@@ -127,6 +151,10 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-express-checkout-payment-methods-wrapper"],
+ attributes: {
+ role: "radiogroup",
+ "aria-label": Translations.getText("express-checkout-header", this.paymentConfig.locale),
+ },
},
])
@@ -189,6 +217,15 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-regular-payment-methods-list-wrapper"],
+ attributes: {
+ role: "radiogroup",
+ "aria-label": Translations.getText(
+ expressPaymentMethods.length > 0
+ ? "other-payment-methods-header"
+ : "select-payment-method-label",
+ this.paymentConfig.locale,
+ ),
+ },
},
])
@@ -387,6 +424,14 @@ module ProcessOut {
}
this.createPaymentMethodsManager(expressCheckoutHeader)
+
+ const nextFocusTarget =
+ (paymentManagerMethodsList.querySelector(".dco-delete-payment-method-button") as HTMLElement) ||
+ (document.querySelector(".close-modal-btn") as HTMLElement)
+
+ if (nextFocusTarget) {
+ nextFocusTarget.focus()
+ }
}
private createPaymentsManagerEmptyState(paymentsManagerMethodsList: Element) {
diff --git a/src/dynamic-checkout/views/payment-success.ts b/src/dynamic-checkout/views/payment-success.ts
index b7ac206d..8318cc40 100644
--- a/src/dynamic-checkout/views/payment-success.ts
+++ b/src/dynamic-checkout/views/payment-success.ts
@@ -9,12 +9,16 @@ module ProcessOut {
{
tagName: "div",
classNames: ["dco-card-payment-success"],
+ attributes: {
+ role: "status",
+ },
},
{
tagName: "img",
classNames: ["dco-card-payment-success-image"],
attributes: {
src: processOutInstance.endpoint("js", PAYMENT_SUCCESS_IMAGE_ASSET),
+ alt: "",
},
},
{