From 900bb4fbc4089e9320fd31a73f66e629ea592098 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Thu, 1 Aug 2024 12:34:47 +0530 Subject: [PATCH 01/16] add middleware for adding accept language header --- crates/router/src/lib.rs | 1 + crates/router/src/middleware.rs | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index 6581436c2511..9691a5366263 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -341,6 +341,7 @@ pub fn get_application_builder( .wrap(cors::cors(cors)) // this middleware works only for Http1.1 requests .wrap(middleware::Http400RequestDetailsLogger) + .wrap(middleware::AddAcceptLanguageHeader) .wrap(middleware::LogSpanInitializer) .wrap(router_env::tracing_actix_web::TracingLogger::default()) } diff --git a/crates/router/src/middleware.rs b/crates/router/src/middleware.rs index 7b9919d3afaf..5962114b0ac6 100644 --- a/crates/router/src/middleware.rs +++ b/crates/router/src/middleware.rs @@ -315,3 +315,85 @@ where }) } } + +/// Middleware for Adding Accept-Language header based on query params +pub struct AddAcceptLanguageHeader; + +impl actix_web::dev::Transform + for AddAcceptLanguageHeader +where + S: actix_web::dev::Service< + actix_web::dev::ServiceRequest, + Response = actix_web::dev::ServiceResponse, + Error = actix_web::Error, + >, + S::Future: 'static, + B: 'static, +{ + type Response = actix_web::dev::ServiceResponse; + type Error = actix_web::Error; + type Transform = AddAcceptLanguageHeaderMiddleware; + type InitError = (); + type Future = std::future::Ready>; + + fn new_transform(&self, service: S) -> Self::Future { + std::future::ready(Ok(AddAcceptLanguageHeaderMiddleware { + service: std::rc::Rc::new(service), + })) + } +} + +pub struct AddAcceptLanguageHeaderMiddleware { + service: std::rc::Rc, +} + +impl actix_web::dev::Service + for AddAcceptLanguageHeaderMiddleware +where + S: actix_web::dev::Service< + actix_web::dev::ServiceRequest, + Response = actix_web::dev::ServiceResponse, + Error = actix_web::Error, + > + 'static, + S::Future: 'static, + B: 'static, +{ + type Response = actix_web::dev::ServiceResponse; + type Error = actix_web::Error; + type Future = futures::future::LocalBoxFuture<'static, Result>; + + actix_web::dev::forward_ready!(service); + fn call(&self, mut req: actix_web::dev::ServiceRequest) -> Self::Future { + let svc = self.service.clone(); + Box::pin(async move { + let query_params = req.query_string(); + let locale_param = query_params + .split('&') + .find_map(|param| { + let mut split = param.split('='); + if let (Some(key), Some(value)) = (split.next(), split.next()) { + if key == "locale" { + return Some(value.to_string()); + } + } + None + }); + let accept_language_header = req.headers().get(actix_web::http::header::ACCEPT_LANGUAGE); + if let Some(locale) = locale_param { + req.headers_mut().insert( + http::header::HeaderName::from_static("accept-language"), + http::HeaderValue::from_str(&locale)?, + ); + } else if accept_language_header.is_none() { + req.headers_mut().insert( + http::header::HeaderName::from_static("accept-language"), + http::HeaderValue::from_static("en"), + ); + } + let response_fut = svc.call(req); + let response = response_fut.await?; + Ok(response) + }) + } + +} \ No newline at end of file From fcbe2b7f329b9deb7740372382fad580fdcab790 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 07:14:37 +0000 Subject: [PATCH 02/16] chore: run formatter --- crates/router/src/middleware.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/router/src/middleware.rs b/crates/router/src/middleware.rs index 5962114b0ac6..7457290ac360 100644 --- a/crates/router/src/middleware.rs +++ b/crates/router/src/middleware.rs @@ -367,9 +367,7 @@ where let svc = self.service.clone(); Box::pin(async move { let query_params = req.query_string(); - let locale_param = query_params - .split('&') - .find_map(|param| { + let locale_param = query_params.split('&').find_map(|param| { let mut split = param.split('='); if let (Some(key), Some(value)) = (split.next(), split.next()) { if key == "locale" { @@ -378,7 +376,8 @@ where } None }); - let accept_language_header = req.headers().get(actix_web::http::header::ACCEPT_LANGUAGE); + let accept_language_header = + req.headers().get(actix_web::http::header::ACCEPT_LANGUAGE); if let Some(locale) = locale_param { req.headers_mut().insert( http::header::HeaderName::from_static("accept-language"), @@ -395,5 +394,4 @@ where Ok(response) }) } - -} \ No newline at end of file +} From 90b6e9358368dbead5f1b752bb548321c31c34b4 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Fri, 2 Aug 2024 12:56:04 +0530 Subject: [PATCH 03/16] resolve comments --- crates/router/src/middleware.rs | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/crates/router/src/middleware.rs b/crates/router/src/middleware.rs index 7457290ac360..a4a9d1baa5ed 100644 --- a/crates/router/src/middleware.rs +++ b/crates/router/src/middleware.rs @@ -367,21 +367,19 @@ where let svc = self.service.clone(); Box::pin(async move { let query_params = req.query_string(); - let locale_param = query_params.split('&').find_map(|param| { - let mut split = param.split('='); - if let (Some(key), Some(value)) = (split.next(), split.next()) { - if key == "locale" { - return Some(value.to_string()); - } - } - None - }); + let locale_param = + serde_qs::from_str::(query_params).map_err(|error| { + actix_web::error::ErrorBadRequest(format!( + "Could not convert query params to locale query parmas: {:?}", + error + )) + })?; let accept_language_header = req.headers().get(actix_web::http::header::ACCEPT_LANGUAGE); - if let Some(locale) = locale_param { + if let Some(locale) = locale_param.locale { req.headers_mut().insert( http::header::HeaderName::from_static("accept-language"), - http::HeaderValue::from_str(&locale)?, + http::HeaderValue::from_str(&locale.to_string())?, ); } else if accept_language_header.is_none() { req.headers_mut().insert( @@ -395,3 +393,8 @@ where }) } } + +#[derive(serde::Deserialize)] +pub struct LocaleQueryParam { + locale: Option, +} From 8d10fdbaa1c3d42b2c9f017b2955b58c8a4e7167 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Tue, 6 Aug 2024 01:20:13 +0530 Subject: [PATCH 04/16] add localization support for payment links --- crates/api_models/src/payments.rs | 6 +- crates/router/src/core/payment_link.rs | 9 +- .../payment_link_initiate/payment_link.html | 4 +- .../payment_link_initiate/payment_link.js | 218 ++++++++++++++++- .../payment_link_status/status.js | 230 ++++++++++++++++-- crates/router/src/core/payments.rs | 2 +- crates/router/src/core/payments/operations.rs | 2 +- .../payments/operations/payment_approve.rs | 2 +- .../payments/operations/payment_cancel.rs | 2 +- .../payments/operations/payment_capture.rs | 2 +- .../operations/payment_complete_authorize.rs | 2 +- .../payments/operations/payment_confirm.rs | 4 +- .../payments/operations/payment_create.rs | 10 +- .../payments/operations/payment_reject.rs | 2 +- .../payments/operations/payment_session.rs | 2 +- .../core/payments/operations/payment_start.rs | 2 +- .../payments/operations/payment_status.rs | 2 +- .../payments/operations/payment_update.rs | 2 +- .../payments_incremental_authorization.rs | 2 +- crates/router/src/routes/payment_link.rs | 14 ++ crates/router/src/routes/payments.rs | 9 +- crates/router/src/types/transformers.rs | 7 +- 22 files changed, 475 insertions(+), 60 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index eb04fe8300e8..77283cb7a7ee 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -750,6 +750,7 @@ pub struct HeaderPayload { pub browser_name: Option, pub x_client_platform: Option, pub x_merchant_domain: Option, + pub locale: Option, } impl HeaderPayload { @@ -5372,13 +5373,14 @@ pub struct PaymentLinkInitiateRequest { #[schema(value_type = String)] pub merchant_id: id_type::MerchantId, pub payment_id: String, + pub locale: Option, } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum PaymentLinkData<'a> { PaymentLinkDetails(&'a PaymentLinkDetails), - PaymentLinkStatusDetails(PaymentLinkStatusDetails), + PaymentLinkStatusDetails(Box), } #[derive(Debug, serde::Serialize, Clone)] @@ -5400,6 +5402,7 @@ pub struct PaymentLinkDetails { pub sdk_layout: String, pub display_sdk_only: bool, pub enabled_saved_payment_method: bool, + pub locale: Option, } #[derive(Debug, serde::Serialize)] @@ -5417,6 +5420,7 @@ pub struct PaymentLinkStatusDetails { pub redirect: bool, pub theme: String, pub return_url: String, + pub locale: Option, } #[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)] diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index a6d50fe61562..a7fdaa58e744 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -55,6 +55,7 @@ pub async fn initiate_payment_link_flow( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, + locale: Option, ) -> RouterResponse { let db = &*state.store; let payment_intent = db @@ -203,6 +204,7 @@ pub async fn initiate_payment_link_flow( redirect: false, theme: payment_link_config.theme.clone(), return_url: return_url.clone(), + locale: locale.clone(), }; logger::info!( @@ -210,7 +212,7 @@ pub async fn initiate_payment_link_flow( payment_details ); let js_script = get_js_script( - &api_models::payments::PaymentLinkData::PaymentLinkStatusDetails(payment_details), + &api_models::payments::PaymentLinkData::PaymentLinkStatusDetails(Box::new(payment_details)), )?; let payment_link_error_data = services::PaymentLinkStatusData { js_script, @@ -238,6 +240,7 @@ pub async fn initiate_payment_link_flow( sdk_layout: payment_link_config.sdk_layout.clone(), display_sdk_only: payment_link_config.display_sdk_only, enabled_saved_payment_method: payment_link_config.enabled_saved_payment_method, + locale, }; let js_script = get_js_script(&api_models::payments::PaymentLinkData::PaymentLinkDetails( @@ -494,6 +497,7 @@ pub async fn get_payment_link_status( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, + locale: Option, ) -> RouterResponse { let db = &*state.store; let payment_intent = db @@ -602,9 +606,10 @@ pub async fn get_payment_link_status( redirect: true, theme: payment_link_config.theme.clone(), return_url, + locale, }; let js_script = get_js_script( - &api_models::payments::PaymentLinkData::PaymentLinkStatusDetails(payment_details), + &api_models::payments::PaymentLinkData::PaymentLinkStatusDetails(Box::new(payment_details)), )?; let payment_link_status_data = services::PaymentLinkStatusData { js_script, diff --git a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html index 1e6723201c90..1093271727c1 100644 --- a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html +++ b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html @@ -249,7 +249,7 @@ height="16" > - Your Cart + - Pay now + diff --git a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js index 1a28b6ecf826..8528f9b6f1ed 100644 --- a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js +++ b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js @@ -179,6 +179,185 @@ var unifiedCheckout = null; var pub_key = window.__PAYMENT_DETAILS.pub_key; var hyper = null; +const locales = { + en: { + expiresOn: "Link expires on: ", + refId: "Ref Id: ", + requestedBy: "Requested by ", + payNow: "Pay now", + yourCart: "Your Cart", + quantity: "Quantity", + showLess: "Show Less", + showMore: "Show More", + miscellaneousCharges: "Miscellaneous charges", + miscellaneousChargesDetail: "(includes taxes, shipping, discounts, offers etc.)", + paymentTakingLonger: "Sorry! Your payment is taking longer than expected. Please check back again in sometime.", + paymentLinkExpired: "Payment Link Expired", + paymentReceived: "We have successfully received your payment", + paymentLinkExpiredMessage: "Sorry, this payment link has expired. Please use below reference for further investigation.", + paidSuccessfully: "Paid successfully", + paymentPending: "Payment Pending", + paymentFailed: "Payment Failed!", + paymentCancelled: "Payment Cancelled", + paymentUnderReview: "Payment under review", + paymentSuccess: "Payment Success", + partialPaymentCaptured: "Partial payment was captured.", + somethingWentWrong: "Something went wrong", + redirecting: "Redirecting ...", + redirectingIn: "Redirecting in ", + seconds: " seconds ...", + unexpectedError: "An unexpected error occurred." + }, + de: { + expiresOn: "Link läuft ab am: ", + refId: "Referenz-ID: ", + requestedBy: "Angefordert von ", + payNow: "Jetzt bezahlen", + yourCart: "Ihr Warenkorb", + quantity: "Menge", + showLess: "Weniger anzeigen", + showMore: "Mehr anzeigen", + miscellaneousCharges: "Sonstige Gebühren", + miscellaneousChargesDetail: "(einschließlich Steuern, Versand, Rabatte, Angebote usw.)", + paymentTakingLonger: "Entschuldigung! Ihre Zahlung dauert länger als erwartet. Bitte prüfen Sie später erneut.", + paymentLinkExpired: "Zahlungslink abgelaufen", + paymentReceived: "Wir haben Ihre Zahlung erfolgreich erhalten", + paymentLinkExpiredMessage: "Entschuldigung, dieser Zahlungslink ist abgelaufen. Bitte verwenden Sie die folgende Referenz für weitere Untersuchungen.", + paidSuccessfully: "Erfolgreich bezahlt", + paymentPending: "Zahlung ausstehend", + paymentFailed: "Zahlung fehlgeschlagen!", + paymentCancelled: "Zahlung storniert", + paymentUnderReview: "Zahlung wird überprüft", + paymentSuccess: "Zahlung erfolgreich", + partialPaymentCaptured: "Teilzahlung wurde erfasst.", + somethingWentWrong: "Etwas ist schiefgelaufen", + redirecting: "Weiterleiten ...", + redirectingIn: "Weiterleiten in ", + seconds: " Sekunden ...", + unexpectedError: "Ein unerwarteter Fehler ist aufgetreten." + }, + pt: { + expiresOn: "Link expira em: ", + refId: "ID de referência: ", + requestedBy: "Solicitado por ", + payNow: "Pagar agora", + yourCart: "Seu Carrinho", + quantity: "Quantidade", + showLess: "Mostrar menos", + showMore: "Mostrar mais", + miscellaneousCharges: "Encargos diversos", + miscellaneousChargesDetail: "(inclui impostos, frete, descontos, ofertas, etc.)", + paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, verifique novamente em algum tempo.", + paymentLinkExpired: "Link de Pagamento Expirado", + paymentReceived: "Recebemos seu pagamento com sucesso", + paymentLinkExpiredMessage: "Desculpe, este link de pagamento expirou. Por favor, use a referência abaixo para investigação adicional.", + paidSuccessfully: "Pago com sucesso", + paymentPending: "Pagamento Pendente", + paymentFailed: "Pagamento Falhou!", + paymentCancelled: "Pagamento Cancelado", + paymentUnderReview: "Pagamento em análise", + paymentSuccess: "Sucesso no pagamento", + partialPaymentCaptured: "Pagamento parcial capturado.", + somethingWentWrong: "Algo deu errado", + redirecting: "Redirecionando ...", + redirectingIn: "Redirecionando em ", + seconds: " segundos ...", + unexpectedError: "Ocorreu um erro inesperado." + }, + it: { + expiresOn: "Link scade il: ", + refId: "ID di riferimento: ", + requestedBy: "Richiesto da ", + payNow: "Paga ora", + yourCart: "Il tuo carrello", + quantity: "Quantità", + showLess: "Mostra meno", + showMore: "Mostra di più", + miscellaneousCharges: "Spese varie", + miscellaneousChargesDetail: "(inclusi tasse, spedizione, sconti, offerte, ecc.)", + paymentTakingLonger: "Spiacenti! Il tuo pagamento sta impiegando più tempo del previsto. Controlla di nuovo tra un po'.", + paymentLinkExpired: "Link di pagamento scaduto", + paymentReceived: "Abbiamo ricevuto il tuo pagamento con successo", + paymentLinkExpiredMessage: "Spiacenti, questo link di pagamento è scaduto. Utilizza il riferimento sottostante per ulteriori indagini.", + paidSuccessfully: "Pagato con successo", + paymentPending: "Pagamento in sospeso", + paymentFailed: "Pagamento fallito!", + paymentCancelled: "Pagamento annullato", + paymentUnderReview: "Pagamento in revisione", + paymentSuccess: "Pagamento riuscito", + partialPaymentCaptured: "Pagamento parziale catturato.", + somethingWentWrong: "Qualcosa è andato storto", + redirecting: "Reindirizzando ...", + redirectingIn: "Reindirizzando in ", + seconds: " secondi ...", + unexpectedError: "Si è verificato un errore imprevisto." + }, + zh: { + expiresOn: "链接到期日期:", + refId: "参考编号:", + requestedBy: "请求者:", + payNow: "立即支付", + yourCart: "你的购物车", + quantity: "数量", + showLess: "显示更少", + showMore: "显示更多", + miscellaneousCharges: "其他费用", + miscellaneousChargesDetail: "(包括税费、运费、折扣、优惠等)", + paymentTakingLonger: "对不起!您的付款花费的时间比预期的要长。请稍后再检查。", + paymentLinkExpired: "支付链接已过期", + paymentReceived: "我们已经成功收到您的付款", + paymentLinkExpiredMessage: "对不起,这个支付链接已经过期。请使用下面的参考信息进行进一步调查。", + paidSuccessfully: "支付成功", + paymentPending: "付款待处理", + paymentFailed: "支付失败!", + paymentCancelled: "支付已取消", + paymentUnderReview: "支付正在审查", + paymentSuccess: "支付成功", + partialPaymentCaptured: "部分付款已捕获。", + somethingWentWrong: "出了点问题", + redirecting: "正在重定向 ...", + redirectingIn: "在 ", + seconds: " 秒内重定向 ...", + unexpectedError: "发生了意外错误。" + }, + es: { + expiresOn: "El enlace expira el: ", + refId: "ID de referencia: ", + requestedBy: "Solicitado por ", + payNow: "Pagar ahora", + yourCart: "Tu carrito", + quantity: "Cantidad", + showLess: "Mostrar menos", + showMore: "Mostrar más", + miscellaneousCharges: "Cargos varios", + miscellaneousChargesDetail: "(incluye impuestos, envío, descuentos, ofertas, etc.)", + paymentTakingLonger: "¡Lo siento! Tu pago está tardando más de lo esperado. Por favor, vuelve a verificarlo más tarde.", + paymentLinkExpired: "Enlace de pago expirado", + paymentReceived: "Hemos recibido tu pago con éxito", + paymentLinkExpiredMessage: "Lo siento, este enlace de pago ha expirado. Por favor, usa la referencia a continuación para una investigación adicional.", + paidSuccessfully: "Pagado exitosamente", + paymentPending: "Pago Pendiente", + paymentFailed: "¡Pago Fallido!", + paymentCancelled: "Pago Cancelado", + paymentUnderReview: "Pago en revisión", + paymentSuccess: "Éxito en el pago", + partialPaymentCaptured: "Pago parcial capturado.", + somethingWentWrong: "Algo salió mal", + redirecting: "Redirigiendo ...", + redirectingIn: "Redirigiendo en ", + seconds: " segundos ...", + unexpectedError: "Ocurrió un error inesperado." + } +}; + + +function getTranslations() { + var locale = window.__PAYMENT_DETAILS.locale || 'en'; // defaults if locale is not present in payment details. + return locales[locale] || locales['en']; // defaults if locale is not implemented in locales. +} + +const translations = getTranslations(); + /** * Trigger - init function invoked once the script tag is loaded * Use @@ -211,8 +390,8 @@ function boot() { orderDetails.push({ "amount": (paymentDetails.amount - charges).toFixed(2), "product_img_link": "https://live.hyperswitch.io/payment-link-assets/cart_placeholder.png", - "product_name": "Miscellaneous charges\n" + - "(includes taxes, shipping, discounts, offers etc.)", + "product_name": translations.miscellaneousCharges+"\n" + + translations.miscellaneousChargesDetail, "quantity": null }); } @@ -292,6 +471,13 @@ function initializeEventListeners(paymentDetails) { submitButtonLoaderNode.style.borderBottomColor = contrastingTone; } + // Get locale for pay now + var payNowButtonText = document.createElement("div"); + var payNowButtonText = document.getElementById('submit-button-text'); + if (payNowButtonText) { + payNowButtonText.textContent = translations.payNow; + } + if (submitButtonNode instanceof HTMLButtonElement) { submitButtonNode.style.color = contrastBWColor; } @@ -390,6 +576,7 @@ function initializeSDK() { // @ts-ignore var paymentDetails = window.__PAYMENT_DETAILS; var client_secret = paymentDetails.client_secret; + var locale = paymentDetails.locale; var appearance = { variables: { colorPrimary: paymentDetails.theme || "rgb(0, 109, 249)", @@ -401,7 +588,7 @@ function initializeSDK() { colorTextPlaceholder: "#33415550", borderColor: "#33415550", colorBackground: "rgb(255, 255, 255)", - }, + } }; // @ts-ignore hyper = window.Hyper(pub_key, { @@ -410,6 +597,7 @@ function initializeSDK() { widgets = hyper.widgets({ appearance: appearance, clientSecret: client_secret, + locale: locale, }); var type = paymentDetails.sdk_layout === "spaced_accordion" || @@ -494,7 +682,7 @@ function handleSubmit(e) { if (error.type === "validation_error") { showMessage(error.message); } else { - showMessage("An unexpected error occurred."); + showMessage(translations.unexpectedError); } } else { redirectToStatus(); @@ -529,11 +717,12 @@ function showMessage(msg) { * Use - redirect to /payment_link/status */ function redirectToStatus() { + var locale = window.__PAYMENT_DETAILS.locale || "en"; var arr = window.location.pathname.split("/"); arr.splice(0, 2); arr.unshift("status"); arr.unshift("payment_link"); - window.location.href = window.location.origin + "/" + arr.join("/"); + window.location.href = window.location.origin + "/" + arr.join("/") + "?locale=" + locale; } function addText(id, msg) { @@ -630,12 +819,12 @@ function renderPaymentDetails(paymentDetails) { // Create merchant name's node var merchantNameNode = document.createElement("div"); merchantNameNode.className = "hyper-checkout-payment-merchant-name"; - merchantNameNode.innerText = "Requested by " + paymentDetails.merchant_name; + merchantNameNode.innerText = translations.requestedBy + paymentDetails.merchant_name; // Create payment ID node var paymentIdNode = document.createElement("div"); paymentIdNode.className = "hyper-checkout-payment-ref"; - paymentIdNode.innerText = "Ref Id: " + paymentDetails.payment_id; + paymentIdNode.innerText = translations.refId + paymentDetails.payment_id; // Create merchant logo's node var merchantLogoNode = document.createElement("img"); @@ -648,7 +837,7 @@ function renderPaymentDetails(paymentDetails) { paymentExpiryNode.className = "hyper-checkout-payment-footer-expiry"; var expiryDate = new Date(paymentDetails.session_expiry); var formattedDate = formatDate(expiryDate); - paymentExpiryNode.innerText = "Link expires on: " + formattedDate; + paymentExpiryNode.innerText = translations.expiresOn + formattedDate; // Append information to DOM var paymentContextNode = document.getElementById( @@ -692,6 +881,11 @@ function renderCart(paymentDetails) { var cartItemsNode = document.getElementById("hyper-checkout-cart-items"); var MAX_ITEMS_VISIBLE_AFTER_COLLAPSE = paymentDetails.max_items_visible_after_collapse; + var yourCartText = document.createElement("span"); + var yourCartText = document.getElementById('your-cart-text'); + if (yourCartText) { + yourCartText.textContent = translations.yourCart; + } orderDetails.map(function (item, index) { if (index >= MAX_ITEMS_VISIBLE_AFTER_COLLAPSE) { @@ -723,7 +917,7 @@ function renderCart(paymentDetails) { buttonTextNode.id = "hyper-checkout-cart-button-text"; var hiddenItemsCount = orderDetails.length - MAX_ITEMS_VISIBLE_AFTER_COLLAPSE; - buttonTextNode.innerText = "Show More (" + hiddenItemsCount + ")"; + buttonTextNode.innerText = translations.showMore+" (" + hiddenItemsCount + ")"; expandButtonNode.append(buttonTextNode, buttonImageNode); if (cartNode instanceof HTMLDivElement) { cartNode.insertBefore(expandButtonNode, cartNode.lastElementChild); @@ -787,7 +981,7 @@ function renderCartItem( if (item.quantity !== null) { var quantityNode = document.createElement("div"); quantityNode.className = "hyper-checkout-card-item-quantity"; - quantityNode.innerText = "Qty: " + item.quantity; + quantityNode.innerText = translations.quantity+": " + item.quantity; } // Product price var priceNode = document.createElement("div"); @@ -862,7 +1056,7 @@ function handleCartView(paymentDetails) { } if (cartButtonTextNode instanceof HTMLSpanElement) { - cartButtonTextNode.innerText = "Show Less"; + cartButtonTextNode.innerText = translations.showLess; } var arrowUpImage = document.getElementById("arrow-up"); @@ -900,7 +1094,7 @@ function handleCartView(paymentDetails) { var hiddenItemsCount = orderDetails.length - MAX_ITEMS_VISIBLE_AFTER_COLLAPSE; if (cartButtonTextNode instanceof HTMLSpanElement) { - cartButtonTextNode.innerText = "Show More (" + hiddenItemsCount + ")"; + cartButtonTextNode.innerText = translations.showMore+" (" + hiddenItemsCount + ")"; } var arrowDownImage = document.getElementById("arrow-down"); if ( diff --git a/crates/router/src/core/payment_link/payment_link_status/status.js b/crates/router/src/core/payment_link/payment_link_status/status.js index c0c5fd78e17f..eec06fad184d 100644 --- a/crates/router/src/core/payment_link/payment_link_status/status.js +++ b/crates/router/src/core/payment_link/payment_link_status/status.js @@ -71,6 +71,183 @@ function invert(color, bw) { ); } +const locales = { + en: { + expiresOn: "Link expires on: ", + refId: "Ref Id: ", + requestedBy: "Requested by ", + payNow: "Pay now", + yourCart: "Your Cart", + quantity: "Quantity", + showLess: "Show Less", + showMore: "Show More", + miscellaneousCharges: "Miscellaneous charges", + miscellaneousChargesDetail: "(includes taxes, shipping, discounts, offers etc.)", + paymentTakingLonger: "Sorry! Your payment is taking longer than expected. Please check back again in sometime.", + paymentLinkExpired: "Payment Link Expired", + paymentReceived: "We have successfully received your payment", + paymentLinkExpiredMessage: "Sorry, this payment link has expired. Please use below reference for further investigation.", + paidSuccessfully: "Paid successfully", + paymentPending: "Payment Pending", + paymentFailed: "Payment Failed!", + paymentCancelled: "Payment Cancelled", + paymentUnderReview: "Payment under review", + paymentSuccess: "Payment Success", + partialPaymentCaptured: "Partial payment was captured.", + somethingWentWrong: "Something went wrong", + redirecting: "Redirecting ...", + redirectingIn: "Redirecting in ", + seconds: " seconds ...", + errorCode: "Error code", + errorMessage: "Error message" + }, + de: { + expiresOn: "Link läuft ab am: ", + refId: "Referenz-ID: ", + requestedBy: "Angefordert von ", + payNow: "Jetzt bezahlen", + yourCart: "Ihr Warenkorb", + quantity: "Menge", + showLess: "Weniger anzeigen", + showMore: "Mehr anzeigen", + miscellaneousCharges: "Sonstige Gebühren", + miscellaneousChargesDetail: "(einschließlich Steuern, Versand, Rabatte, Angebote usw.)", + paymentTakingLonger: "Entschuldigung! Ihre Zahlung dauert länger als erwartet. Bitte prüfen Sie später erneut.", + paymentLinkExpired: "Zahlungslink abgelaufen", + paymentReceived: "Wir haben Ihre Zahlung erfolgreich erhalten", + paymentLinkExpiredMessage: "Entschuldigung, dieser Zahlungslink ist abgelaufen. Bitte verwenden Sie die folgende Referenz für weitere Untersuchungen.", + paidSuccessfully: "Erfolgreich bezahlt", + paymentPending: "Zahlung ausstehend", + paymentFailed: "Zahlung fehlgeschlagen!", + paymentCancelled: "Zahlung storniert", + paymentUnderReview: "Zahlung wird überprüft", + paymentSuccess: "Zahlung erfolgreich", + partialPaymentCaptured: "Teilzahlung wurde erfasst.", + somethingWentWrong: "Etwas ist schiefgelaufen", + redirecting: "Weiterleiten ...", + redirectingIn: "Weiterleiten in ", + seconds: " Sekunden ...", + errorCode: "Fehlercode", + errorMessage: "Fehlermeldung" + }, + pt: { + expiresOn: "Link expira em: ", + refId: "ID de referência: ", + requestedBy: "Solicitado por ", + payNow: "Pagar agora", + yourCart: "Seu Carrinho", + quantity: "Quantidade", + showLess: "Mostrar menos", + showMore: "Mostrar mais", + miscellaneousCharges: "Encargos diversos", + miscellaneousChargesDetail: "(inclui impostos, frete, descontos, ofertas, etc.)", + paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, verifique novamente em algum tempo.", + paymentLinkExpired: "Link de Pagamento Expirado", + paymentReceived: "Recebemos seu pagamento com sucesso", + paymentLinkExpiredMessage: "Desculpe, este link de pagamento expirou. Por favor, use a referência abaixo para investigação adicional.", + paidSuccessfully: "Pago com sucesso", + paymentPending: "Pagamento Pendente", + paymentFailed: "Pagamento Falhou!", + paymentCancelled: "Pagamento Cancelado", + paymentUnderReview: "Pagamento em análise", + paymentSuccess: "Sucesso no pagamento", + partialPaymentCaptured: "Pagamento parcial capturado.", + somethingWentWrong: "Algo deu errado", + redirecting: "Redirecionando ...", + redirectingIn: "Redirecionando em ", + seconds: " segundos ...", + errorCode: "Código de erro", + errorMessage: "Mensagem de erro" + }, + it: { + expiresOn: "Link scade il: ", + refId: "ID di riferimento: ", + requestedBy: "Richiesto da ", + payNow: "Paga ora", + yourCart: "Il tuo carrello", + quantity: "Quantità", + showLess: "Mostra meno", + showMore: "Mostra di più", + miscellaneousCharges: "Spese varie", + miscellaneousChargesDetail: "(inclusi tasse, spedizione, sconti, offerte, ecc.)", + paymentTakingLonger: "Spiacenti! Il tuo pagamento sta impiegando più tempo del previsto. Controlla di nuovo tra un po'.", + paymentLinkExpired: "Link di pagamento scaduto", + paymentReceived: "Abbiamo ricevuto il tuo pagamento con successo", + paymentLinkExpiredMessage: "Spiacenti, questo link di pagamento è scaduto. Utilizza il riferimento sottostante per ulteriori indagini.", + paidSuccessfully: "Pagato con successo", + paymentPending: "Pagamento in sospeso", + paymentFailed: "Pagamento fallito!", + paymentCancelled: "Pagamento annullato", + paymentUnderReview: "Pagamento in revisione", + paymentSuccess: "Pagamento riuscito", + partialPaymentCaptured: "Pagamento parziale catturato.", + somethingWentWrong: "Qualcosa è andato storto", + redirecting: "Reindirizzando ...", + redirectingIn: "Reindirizzando in ", + seconds: " secondi ...", + errorCode: "Codice di errore", + errorMessage: "Messaggio di errore" + }, + zh: { + expiresOn: "链接到期日期:", + refId: "参考编号:", + requestedBy: "请求者:", + payNow: "立即支付", + yourCart: "你的购物车", + quantity: "数量", + showLess: "显示更少", + showMore: "显示更多", + miscellaneousCharges: "其他费用", + miscellaneousChargesDetail: "(包括税费、运费、折扣、优惠等)", + paymentTakingLonger: "对不起!您的付款花费的时间比预期的要长。请稍后再检查。", + paymentLinkExpired: "支付链接已过期", + paymentReceived: "我们已经成功收到您的付款", + paymentLinkExpiredMessage: "对不起,这个支付链接已经过期。请使用下面的参考信息进行进一步调查。", + paidSuccessfully: "支付成功", + paymentPending: "付款待处理", + paymentFailed: "支付失败!", + paymentCancelled: "支付已取消", + paymentUnderReview: "支付正在审查", + paymentSuccess: "支付成功", + partialPaymentCaptured: "部分付款已捕获。", + somethingWentWrong: "出了点问题", + redirecting: "正在重定向 ...", + redirectingIn: "在 ", + seconds: " 秒内重定向 ...", + errorCode: "错误代码", + errorMessage: "错误信息" + }, + es: { + expiresOn: "El enlace expira el: ", + refId: "ID de referencia: ", + requestedBy: "Solicitado por ", + payNow: "Pagar ahora", + yourCart: "Tu carrito", + quantity: "Cantidad", + showLess: "Mostrar menos", + showMore: "Mostrar más", + miscellaneousCharges: "Cargos varios", + miscellaneousChargesDetail: "(incluye impuestos, envío, descuentos, ofertas, etc.)", + paymentTakingLonger: "¡Lo siento! Tu pago está tardando más de lo esperado. Por favor, vuelve a verificarlo más tarde.", + paymentLinkExpired: "Enlace de pago expirado", + paymentReceived: "Hemos recibido tu pago con éxito", + paymentLinkExpiredMessage: "Lo siento, este enlace de pago ha expirado. Por favor, usa la referencia a continuación para una investigación adicional.", + paidSuccessfully: "Pagado exitosamente", + paymentPending: "Pago Pendiente", + paymentFailed: "¡Pago Fallido!", + paymentCancelled: "Pago Cancelado", + paymentUnderReview: "Pago en revisión", + paymentSuccess: "Éxito en el pago", + partialPaymentCaptured: "Pago parcial capturado.", + somethingWentWrong: "Algo salió mal", + redirecting: "Redirigiendo ...", + redirectingIn: "Redirigiendo en ", + seconds: " segundos ...", + errorCode: "Código de error", + errorMessage: "Mensaje de error" + } +}; + /** * UTIL FUNCTIONS END HERE */ @@ -85,6 +262,15 @@ window.state = { isMobileView: window.innerWidth <= 1400, }; + +function getTranslations() { + var paymentDetails = window.__PAYMENT_DETAILS; + console.log(paymentDetails); + var locale = paymentDetails.locale || 'en'; // defaults if locale is not present in payment details. + return locales[locale] || locales['en']; // defaults if locale is not implemented in locales. +} + +const translations = getTranslations(); /** * Trigger - init function invoked once the script tag is loaded * Use @@ -135,7 +321,7 @@ function renderStatusDetails(paymentDetails) { }; // Payment details - var paymentId = createItem("Ref Id", paymentDetails.payment_id); + var paymentId = createItem(translations.refId, paymentDetails.payment_id); // @ts-ignore statusDetails.items.push(paymentId); @@ -143,15 +329,14 @@ function renderStatusDetails(paymentDetails) { switch (status) { case "expired": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/failed.png"; - statusDetails.status = "Payment Link Expired"; - statusDetails.message = - "Sorry, this payment link has expired. Please use below reference for further investigation."; + statusDetails.status = translations.paymentLinkExpired; + statusDetails.message = translations.paymentLinkExpiredMessage; break; case "succeeded": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/success.png"; - statusDetails.message = "We have successfully received your payment"; - statusDetails.status = "Paid successfully"; + statusDetails.message = translations.paymentReceived; + statusDetails.status = translations.paidSuccessfully; statusDetails.amountText = new Date( paymentDetails.created ).toTimeString(); @@ -159,17 +344,16 @@ function renderStatusDetails(paymentDetails) { case "processing": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/pending.png"; - statusDetails.message = - "Sorry! Your payment is taking longer than expected. Please check back again in sometime."; - statusDetails.status = "Payment Pending"; + statusDetails.message = translations.paymentTakingLonger; + statusDetails.status = translations.paymentPending; break; case "failed": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/failed.png"; - statusDetails.status = "Payment Failed!"; - var errorCodeNode = createItem("Error code", paymentDetails.error_code); + statusDetails.status = translations.paymentFailed; + var errorCodeNode = createItem(translations.errorCode, paymentDetails.error_code); var errorMessageNode = createItem( - "Error message", + translations.errorMessage, paymentDetails.error_message ); // @ts-ignore @@ -178,34 +362,34 @@ function renderStatusDetails(paymentDetails) { case "cancelled": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/failed.png"; - statusDetails.status = "Payment Cancelled"; + statusDetails.status = translations.paymentCancelled; break; case "requires_merchant_action": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/pending.png"; - statusDetails.status = "Payment under review"; + statusDetails.status = translations.paymentUnderReview; break; case "requires_capture": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/success.png"; - statusDetails.message = "We have successfully received your payment"; - statusDetails.status = "Payment Success"; + statusDetails.message = translations.paymentReceived; + statusDetails.status = translations.paymentSuccess; break; case "partially_captured": statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/success.png"; - statusDetails.message = "Partial payment was captured."; - statusDetails.status = "Payment Success"; + statusDetails.message = translations.partialPaymentCaptured; + statusDetails.status = translations.paymentSuccess; break; default: statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/failed.png"; - statusDetails.status = "Something went wrong"; + statusDetails.status = translations.somethingWentWrong; // Error details if (typeof paymentDetails.error === "object") { - var errorCodeNode = createItem("Error Code", paymentDetails.error.code); + var errorCodeNode = createItem(translations.errorCode, paymentDetails.error.code); var errorMessageNode = createItem( - "Error Message", + translations.errorMessage, paymentDetails.error.message ); // @ts-ignore @@ -276,8 +460,8 @@ function renderStatusDetails(paymentDetails) { var secondsLeft = timeout - j++; var innerText = secondsLeft === 0 - ? "Redirecting ..." - : "Redirecting in " + secondsLeft + " seconds ..."; + ? translations.redirecting + : translations.redirectingIn + secondsLeft + " "+translations.seconds; // @ts-ignore statusRedirectTextNode.innerText = innerText; if (secondsLeft === 0) { diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 003c95610945..746697e5659c 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -157,7 +157,7 @@ where &merchant_account, &key_store, auth_flow, - header_payload.payment_confirm_source, + &header_payload, ) .await?; diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 336755c6e3da..fc2ab1c11083 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -107,7 +107,7 @@ pub trait GetTracker: Send { merchant_account: &domain::MerchantAccount, mechant_key_store: &domain::MerchantKeyStore, auth_flow: services::AuthFlow, - payment_confirm_source: Option, + header_payload: &api::HeaderPayload, ) -> RouterResult>; } diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 3cbcc0bb8313..15560b2d6f38 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -40,7 +40,7 @@ impl GetTracker, api::PaymentsCaptureRequest> merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let merchant_id = merchant_account.get_id(); diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 4e771659a8a6..2e9f070140b3 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -40,7 +40,7 @@ impl GetTracker, api::PaymentsCancelRequest> merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let merchant_id = merchant_account.get_id(); diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index cc942016225a..d0e8e0605c47 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -41,7 +41,7 @@ impl GetTracker, api::PaymentsCaptu merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let merchant_id = merchant_account.get_id(); diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs index 664a7c9bb032..5e2b9e7552cf 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -42,7 +42,7 @@ impl GetTracker, api::PaymentsRequest> for Co merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let merchant_id = merchant_account.get_id(); diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 52d76289d883..4e02ddc7e51d 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -59,7 +59,7 @@ impl GetTracker, api::PaymentsRequest> for Pa merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, auth_flow: services::AuthFlow, - payment_confirm_source: Option, + header_payload: &api::HeaderPayload, ) -> RouterResult> { let merchant_id = merchant_account.get_id(); let storage_scheme = merchant_account.storage_scheme; @@ -99,7 +99,7 @@ impl GetTracker, api::PaymentsRequest> for Pa Some(common_enums::PaymentSource::Webhook), Some(common_enums::PaymentSource::ExternalAuthenticator), ] - .contains(&payment_confirm_source) + .contains(&header_payload.payment_confirm_source) { helpers::validate_payment_status_against_not_allowed_statuses( &payment_intent.status, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index b7f86b6838a7..662c81b08aba 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -66,7 +66,7 @@ impl GetTracker, api::PaymentsRequest> for Pa merchant_account: &domain::MerchantAccount, merchant_key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let ephemeral_key = Self::get_ephemeral_key(request, state, merchant_account).await; @@ -244,6 +244,7 @@ impl GetTracker, api::PaymentsRequest> for Pa profile_id.clone(), domain_name, session_expiry, + header_payload.locale.clone(), ) .await? } @@ -1215,14 +1216,17 @@ async fn create_payment_link( profile_id: String, domain_name: String, session_expiry: PrimitiveDateTime, + locale: Option, ) -> RouterResult> { let created_at @ last_modified_at = Some(common_utils::date_time::now()); let payment_link_id = utils::generate_id(consts::ID_LENGTH, "plink"); + let locale_str = locale.unwrap_or("en".to_owned()); let payment_link = format!( - "{}/payment_link/{}/{}", + "{}/payment_link/{}/{}?locale={}", domain_name, merchant_id.get_string_repr(), - payment_id.clone() + payment_id.clone(), + locale_str ); let payment_link_config_encoded_value = payment_link_config.encode_to_value().change_context( diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 4e46791c8e1c..c1ea9589ff7c 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -37,7 +37,7 @@ impl GetTracker, PaymentsCancelRequest> for P merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; let merchant_id = merchant_account.get_id(); diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index e65fcbc390b8..3932b69752a3 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -40,7 +40,7 @@ impl GetTracker, api::PaymentsSessionRequest> merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let payment_id = payment_id .get_payment_intent_id() diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index 0172b5f26443..728b7b538a52 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -37,7 +37,7 @@ impl GetTracker, api::PaymentsStartRequest> f merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let (mut payment_intent, payment_attempt, currency, amount); let db = &*state.store; diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index a7ba54a377d4..44a08e916373 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -190,7 +190,7 @@ impl GetTracker, api::PaymentsRetrieveRequest merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { get_tracker_for_sync( payment_id, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 3a5cd00b9c3b..be0f25d88dff 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -50,7 +50,7 @@ impl GetTracker, api::PaymentsRequest> for Pa merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let (mut payment_intent, mut payment_attempt, currency): (_, _, storage_enums::Currency); diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs index c7311059ba2d..996e30e31f78 100644 --- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs +++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs @@ -44,7 +44,7 @@ impl merchant_account: &domain::MerchantAccount, key_store: &domain::MerchantKeyStore, _auth_flow: services::AuthFlow, - _payment_confirm_source: Option, + _header_payload: &api::HeaderPayload, ) -> RouterResult> { let db = &*state.store; diff --git a/crates/router/src/routes/payment_link.rs b/crates/router/src/routes/payment_link.rs index 33d3c21ef9f7..412a5463a9be 100644 --- a/crates/router/src/routes/payment_link.rs +++ b/crates/router/src/routes/payment_link.rs @@ -58,9 +58,15 @@ pub async fn initiate_payment_link( ) -> impl Responder { let flow = Flow::PaymentLinkInitiate; let (merchant_id, payment_id) = path.into_inner(); + let locale = req + .headers() + .get(actix_web::http::header::ACCEPT_LANGUAGE) + .and_then(|header_value| header_value.to_str().ok()) + .map(|str| str.to_owned()); let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), + locale, }; Box::pin(api::server_wrap( flow, @@ -74,6 +80,7 @@ pub async fn initiate_payment_link( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), + payload.locale.clone(), ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), @@ -132,9 +139,15 @@ pub async fn payment_link_status( ) -> impl Responder { let flow = Flow::PaymentLinkStatus; let (merchant_id, payment_id) = path.into_inner(); + let locale = req + .headers() + .get(actix_web::http::header::ACCEPT_LANGUAGE) + .and_then(|header_value| header_value.to_str().ok()) + .map(|str| str.to_owned()); let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), + locale, }; Box::pin(api::server_wrap( flow, @@ -148,6 +161,7 @@ pub async fn payment_link_status( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), + payload.locale.clone(), ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index 956909f9e5a5..3d0e99ae7be7 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -106,6 +106,13 @@ pub async fn payments_create( return api::log_and_return_error_response(err); } + let header_payload = match HeaderPayload::foreign_try_from(req.headers()) { + Ok(headers) => headers, + Err(err) => { + return api::log_and_return_error_response(err); + } + }; + tracing::Span::current().record( "payment_id", payload @@ -131,7 +138,7 @@ pub async fn payments_create( req_state, auth.merchant_account, auth.key_store, - HeaderPayload::default(), + header_payload.clone(), req, api::AuthFlow::Merchant, ) diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 11aebf5b98d6..1a8b3c62b372 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -21,8 +21,8 @@ use super::domain; use crate::{ core::errors, headers::{ - BROWSER_NAME, X_CLIENT_PLATFORM, X_CLIENT_SOURCE, X_CLIENT_VERSION, X_MERCHANT_DOMAIN, - X_PAYMENT_CONFIRM_SOURCE, + ACCEPT_LANGUAGE, BROWSER_NAME, X_CLIENT_PLATFORM, X_CLIENT_SOURCE, X_CLIENT_VERSION, + X_MERCHANT_DOMAIN, X_PAYMENT_CONFIRM_SOURCE, }, services::authentication::get_header_value_by_key, types::{ @@ -1237,6 +1237,8 @@ impl ForeignTryFrom<&HeaderMap> for payments::HeaderPayload { })) }, )?; + let locale = + get_header_value_by_key(ACCEPT_LANGUAGE.into(), headers)?.map(|val| val.to_string()); let x_hs_latency = get_header_value_by_key(X_HS_LATENCY.into(), headers) .map(|value| value == Some("true")) .unwrap_or(false); @@ -1277,6 +1279,7 @@ impl ForeignTryFrom<&HeaderMap> for payments::HeaderPayload { browser_name, x_client_platform, x_merchant_domain, + locale, }) } } From 9b97f09cd0c2cd3acc19505eaaae9f147e3798be Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:23:23 +0000 Subject: [PATCH 05/16] chore: run formatter --- crates/router/src/core/payment_link.rs | 30 +++++++++++++++++--------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index e620fe6ab771..bbe0deebb99b 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -261,9 +261,15 @@ pub async fn initiate_secure_payment_link_flow( .and_then(|header_value| header_value.to_str().ok()) .map(|str| str.to_owned()); - let (payment_link, payment_link_details, payment_link_config) = - form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id, locale) - .await?; + let (payment_link, payment_link_details, payment_link_config) = form_payment_link_data( + &state, + merchant_account, + key_store, + merchant_id, + payment_id, + locale, + ) + .await?; validator::validate_secure_payment_link_render_request( request_headers, @@ -349,11 +355,17 @@ pub async fn initiate_payment_link_flow( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, - locale: Option + locale: Option, ) -> RouterResponse { - let (_, payment_details, payment_link_config) = - form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id,locale) - .await?; + let (_, payment_details, payment_link_config) = form_payment_link_data( + &state, + merchant_account, + key_store, + merchant_id, + payment_id, + locale, + ) + .await?; let css_script = get_color_scheme_css(&payment_link_config); let js_script = get_js_script(&payment_details)?; @@ -738,9 +750,7 @@ pub async fn get_payment_link_status( return_url, locale, }; - let js_script = get_js_script( - &PaymentLinkData::PaymentLinkStatusDetails(payment_details), - )?; + let js_script = get_js_script(&PaymentLinkData::PaymentLinkStatusDetails(payment_details))?; let payment_link_status_data = services::PaymentLinkStatusData { js_script, css_script, From ee4b88913c873978423da6c0eeeb649d19e139fc Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 07:25:49 +0000 Subject: [PATCH 06/16] docs(openapi): re-generate OpenAPI specification --- api-reference/openapi_spec.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 040df7d84f04..77370fbf9020 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -14034,6 +14034,10 @@ }, "payment_id": { "type": "string" + }, + "locale": { + "type": "string", + "nullable": true } } }, From 03df1d6269390fc6c9c100d706896357b0974ab7 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Tue, 6 Aug 2024 13:44:59 +0530 Subject: [PATCH 07/16] move locales to different file --- crates/router/src/core/payment_link/locale.js | 478 ++++++++++++++++++ .../payment_link_initiate/payment_link.html | 1 + .../payment_link_initiate/payment_link.js | 170 ------- .../payment_link_status/status.html | 1 + .../payment_link_status/status.js | 176 ------- crates/router/src/services/api.rs | 7 + 6 files changed, 487 insertions(+), 346 deletions(-) create mode 100644 crates/router/src/core/payment_link/locale.js diff --git a/crates/router/src/core/payment_link/locale.js b/crates/router/src/core/payment_link/locale.js new file mode 100644 index 000000000000..c079d2b7fd6f --- /dev/null +++ b/crates/router/src/core/payment_link/locale.js @@ -0,0 +1,478 @@ +const locales = { + en: { + expiresOn: "Link expires on: ", + refId: "Ref Id: ", + requestedBy: "Requested by ", + payNow: "Pay now", + yourCart: "Your Cart", + quantity: "Quantity", + showLess: "Show Less", + showMore: "Show More", + miscellaneousCharges: "Miscellaneous charges", + miscellaneousChargesDetail: "(includes taxes, shipping, discounts, offers etc.)", + paymentTakingLonger: "Sorry! Your payment is taking longer than expected. Please check back again in sometime.", + paymentLinkExpired: "Payment Link Expired", + paymentReceived: "We have successfully received your payment", + paymentLinkExpiredMessage: "Sorry, this payment link has expired. Please use below reference for further investigation.", + paidSuccessfully: "Paid successfully", + paymentPending: "Payment Pending", + paymentFailed: "Payment Failed!", + paymentCancelled: "Payment Cancelled", + paymentUnderReview: "Payment under review", + paymentSuccess: "Payment Success", + partialPaymentCaptured: "Partial payment was captured.", + somethingWentWrong: "Something went wrong", + redirecting: "Redirecting ...", + redirectingIn: "Redirecting in ", + seconds: " seconds ...", + unexpectedError: "An unexpected error occurred." + }, + he: { + expiresOn: "הקישור יפוג ב: ", + refId: "מזהה הפניה: ", + requestedBy: "ביקש על ידי ", + payNow: "שלם עכשיו", + yourCart: "העגלה שלך", + quantity: "כמות", + showLess: "הצג פחות", + showMore: "הצג עוד", + miscellaneousCharges: "חיובים נוספים", + miscellaneousChargesDetail: "(כולל מיסים, משלוח, הנחות, הצעות וכו')", + paymentTakingLonger: "מצטערים! התשלום שלך לוקח יותר זמן מהצפוי. אנא בדוק שוב בעוד זמן מה.", + paymentLinkExpired: "הקישור לתשלום פג", + paymentReceived: "קיבלנו את התשלום שלך בהצלחה", + paymentLinkExpiredMessage: "מצטערים, הקישור הזה לתשלום פג. השתמש בהפניה למטה להמשך החקירה.", + paidSuccessfully: "שולם בהצלחה", + paymentPending: "התשלום ממתין", + paymentFailed: "התשלום נכשל!", + paymentCancelled: "התשלום בוטל", + paymentUnderReview: "התשלום בבדיקה", + paymentSuccess: "התשלום הצליח", + partialPaymentCaptured: "תשלום חלקי נלכד.", + somethingWentWrong: "משהו השתבש", + redirecting: "מעביר...", + redirectingIn: "מעביר בעוד ", + seconds: " שניות ...", + unexpectedError: "אירעה שגיאה בלתי צפויה." + }, + fr: { + expiresOn: "Le lien expire le: ", + refId: "ID de référence: ", + requestedBy: "Demandé par ", + payNow: "Payer maintenant", + yourCart: "Votre panier", + quantity: "Quantité", + showLess: "Afficher moins", + showMore: "Afficher plus", + miscellaneousCharges: "Frais divers", + miscellaneousChargesDetail: "(comprend les taxes, les frais d'expédition, les remises, les offres, etc.)", + paymentTakingLonger: "Désolé! Votre paiement prend plus de temps que prévu. Veuillez réessayer plus tard.", + paymentLinkExpired: "Lien de paiement expiré", + paymentReceived: "Nous avons bien reçu votre paiement", + paymentLinkExpiredMessage: "Désolé, ce lien de paiement a expiré. Veuillez utiliser la référence ci-dessous pour une enquête plus approfondie.", + paidSuccessfully: "Payé avec succès", + paymentPending: "Paiement en attente", + paymentFailed: "Échec du paiement!", + paymentCancelled: "Paiement annulé", + paymentUnderReview: "Paiement en cours de révision", + paymentSuccess: "Paiement réussi", + partialPaymentCaptured: "Paiement partiel capturé.", + somethingWentWrong: "Quelque chose a mal tourné", + redirecting: "Redirection...", + redirectingIn: "Redirection dans ", + seconds: " secondes...", + unexpectedError: "Une erreur inattendue est survenue." + }, + en_GB: { + expiresOn: "Link expires on: ", + refId: "Ref Id: ", + requestedBy: "Requested by ", + payNow: "Pay now", + yourCart: "Your Basket", + quantity: "Quantity", + showLess: "Show Less", + showMore: "Show More", + miscellaneousCharges: "Miscellaneous charges", + miscellaneousChargesDetail: "(includes taxes, shipping, discounts, offers etc.)", + paymentTakingLonger: "Sorry! Your payment is taking longer than expected. Please check back again in sometime.", + paymentLinkExpired: "Payment Link Expired", + paymentReceived: "We have successfully received your payment", + paymentLinkExpiredMessage: "Sorry, this payment link has expired. Please use below reference for further investigation.", + paidSuccessfully: "Paid successfully", + paymentPending: "Payment Pending", + paymentFailed: "Payment Failed!", + paymentCancelled: "Payment Cancelled", + paymentUnderReview: "Payment under review", + paymentSuccess: "Payment Success", + partialPaymentCaptured: "Partial payment was captured.", + somethingWentWrong: "Something went wrong", + redirecting: "Redirecting ...", + redirectingIn: "Redirecting in ", + seconds: " seconds ...", + unexpectedError: "An unexpected error occurred." + }, + ar: { + expiresOn: "الرابط ينتهي في: ", + refId: "معرف المرجع: ", + requestedBy: "طلب بواسطة ", + payNow: "ادفع الآن", + yourCart: "سلة التسوق الخاصة بك", + quantity: "الكمية", + showLess: "عرض أقل", + showMore: "عرض المزيد", + miscellaneousCharges: "رسوم متنوعة", + miscellaneousChargesDetail: "(يشمل الضرائب والشحن والخصومات والعروض وما إلى ذلك)", + paymentTakingLonger: "عذرًا! يستغرق الدفع الخاص بك وقتًا أطول من المتوقع. يرجى التحقق مرة أخرى بعد فترة.", + paymentLinkExpired: "انتهاء صلاحية رابط الدفع", + paymentReceived: "لقد تلقينا دفعتك بنجاح", + paymentLinkExpiredMessage: "عذرًا، انتهت صلاحية رابط الدفع هذا. يرجى استخدام المرجع أدناه لمزيد من التحقيق.", + paidSuccessfully: "تم الدفع بنجاح", + paymentPending: "الدفع معلق", + paymentFailed: "فشل الدفع!", + paymentCancelled: "تم إلغاء الدفع", + paymentUnderReview: "الدفع قيد المراجعة", + paymentSuccess: "نجاح الدفع", + partialPaymentCaptured: "تم تحصيل دفعة جزئية.", + somethingWentWrong: "حدث خطأ ما", + redirecting: "إعادة توجيه ...", + redirectingIn: "إعادة توجيه في ", + seconds: " ثوانٍ ...", + unexpectedError: "حدث خطأ غير متوقع." + }, + ja: { + expiresOn: "リンクの有効期限は: ", + refId: "参照 ID: ", + requestedBy: "リクエスト者 ", + payNow: "今すぐ支払う", + yourCart: "あなたのカート", + quantity: "数量", + showLess: "表示を減らす", + showMore: "もっと見る", + miscellaneousCharges: "その他の料金", + miscellaneousChargesDetail: "(税金、送料、割引、特典などが含まれます)", + paymentTakingLonger: "申し訳ありません! お支払いに予想以上の時間がかかっています。 しばらくしてから再度確認してください。", + paymentLinkExpired: "支払いリンクの有効期限が切れました", + paymentReceived: "お支払いが正常に完了しました", + paymentLinkExpiredMessage: "申し訳ありませんが、この支払いリンクの有効期限が切れています。 詳細な調査については、以下の参照をご利用ください。", + paidSuccessfully: "支払い完了", + paymentPending: "保留中の支払い", + paymentFailed: "支払い失敗!", + paymentCancelled: "支払いがキャンセルされました", + paymentUnderReview: "支払いの審査中", + paymentSuccess: "支払い成功", + partialPaymentCaptured: "部分的な支払いが取得されました。", + somethingWentWrong: "何かがうまくいかなかった", + redirecting: "リダイレクト中...", + redirectingIn: "リダイレクト中 ", + seconds: " 秒 ...", + unexpectedError: "予期しないエラーが発生しました。" + }, + de: { + expiresOn: "Link läuft ab am: ", + refId: "Referenz-ID: ", + requestedBy: "Angefordert von ", + payNow: "Jetzt bezahlen", + yourCart: "Ihr Warenkorb", + quantity: "Menge", + showLess: "Weniger anzeigen", + showMore: "Mehr anzeigen", + miscellaneousCharges: "Sonstige Gebühren", + miscellaneousChargesDetail: "(einschließlich Steuern, Versand, Rabatte, Angebote usw.)", + paymentTakingLonger: "Entschuldigung! Ihre Zahlung dauert länger als erwartet. Bitte prüfen Sie später erneut.", + paymentLinkExpired: "Zahlungslink abgelaufen", + paymentReceived: "Wir haben Ihre Zahlung erfolgreich erhalten", + paymentLinkExpiredMessage: "Entschuldigung, dieser Zahlungslink ist abgelaufen. Bitte verwenden Sie die folgende Referenz für weitere Untersuchungen.", + paidSuccessfully: "Erfolgreich bezahlt", + paymentPending: "Zahlung ausstehend", + paymentFailed: "Zahlung fehlgeschlagen!", + paymentCancelled: "Zahlung storniert", + paymentUnderReview: "Zahlung wird überprüft", + paymentSuccess: "Zahlung erfolgreich", + partialPaymentCaptured: "Teilzahlung wurde erfasst.", + somethingWentWrong: "Etwas ist schiefgelaufen", + redirecting: "Weiterleiten ...", + redirectingIn: "Weiterleiten in ", + seconds: " Sekunden ...", + unexpectedError: "Ein unerwarteter Fehler ist aufgetreten." + }, + fr_BE: { + expiresOn: "Le lien expire le: ", + refId: "ID de référence: ", + requestedBy: "Demandé par ", + payNow: "Payer maintenant", + yourCart: "Votre panier", + quantity: "Quantité", + showLess: "Afficher moins", + showMore: "Afficher plus", + miscellaneousCharges: "Frais divers", + miscellaneousChargesDetail: "(comprend les taxes, les frais d'expédition, les remises, les offres, etc.)", + paymentTakingLonger: "Désolé! Votre paiement prend plus de temps que prévu. Veuillez réessayer plus tard.", + paymentLinkExpired: "Lien de paiement expiré", + paymentReceived: "Nous avons bien reçu votre paiement", + paymentLinkExpiredMessage: "Désolé, ce lien de paiement a expiré. Veuillez utiliser la référence ci-dessous pour une enquête plus approfondie.", + paidSuccessfully: "Payé avec succès", + paymentPending: "Paiement en attente", + paymentFailed: "Échec du paiement!", + paymentCancelled: "Paiement annulé", + paymentUnderReview: "Paiement en cours de révision", + paymentSuccess: "Paiement réussi", + partialPaymentCaptured: "Paiement partiel capturé.", + somethingWentWrong: "Quelque chose a mal tourné", + redirecting: "Redirection...", + redirectingIn: "Redirection dans ", + seconds: " secondes...", + unexpectedError: "Une erreur inattendue est survenue." + }, + es: { + expiresOn: "El enlace expira el: ", + refId: "ID de referencia: ", + requestedBy: "Solicitado por ", + payNow: "Pagar ahora", + yourCart: "Tu carrito", + quantity: "Cantidad", + showLess: "Mostrar menos", + showMore: "Mostrar más", + miscellaneousCharges: "Cargos varios", + miscellaneousChargesDetail: "(incluye impuestos, envío, descuentos, ofertas, etc.)", + paymentTakingLonger: "¡Lo siento! Tu pago está tardando más de lo esperado. Por favor, vuelve a verificarlo más tarde.", + paymentLinkExpired: "Enlace de pago expirado", + paymentReceived: "Hemos recibido tu pago con éxito", + paymentLinkExpiredMessage: "Lo siento, este enlace de pago ha expirado. Por favor, usa la referencia a continuación para una investigación adicional.", + paidSuccessfully: "Pagado exitosamente", + paymentPending: "Pago Pendiente", + paymentFailed: "¡Pago Fallido!", + paymentCancelled: "Pago Cancelado", + paymentUnderReview: "Pago en revisión", + paymentSuccess: "Éxito en el pago", + partialPaymentCaptured: "Pago parcial capturado.", + somethingWentWrong: "Algo salió mal", + redirecting: "Redirigiendo ...", + redirectingIn: "Redirigiendo en ", + seconds: " segundos ...", + unexpectedError: "Ocurrió un error inesperado." + }, + ca: { + expiresOn: "L'enllaç caduca el: ", + refId: "ID de referència: ", + requestedBy: "Sol·licitat per ", + payNow: "Paga ara", + yourCart: "El teu carret", + quantity: "Quantitat", + showLess: "Mostrar menys", + showMore: "Mostrar més", + miscellaneousCharges: "Càrrecs diversos", + miscellaneousChargesDetail: "(inclou impostos, enviaments, descomptes, ofertes, etc.)", + paymentTakingLonger: "Ho sentim! El teu pagament està trigant més del que s'esperava. Si us plau, torna-ho a comprovar d'aquí a una estona.", + paymentLinkExpired: "Enllaç de pagament caducat", + paymentReceived: "Hem rebut el teu pagament amb èxit", + paymentLinkExpiredMessage: "Ho sentim, aquest enllaç de pagament ha caducat. Si us plau, utilitza la referència següent per a més investigació.", + paidSuccessfully: "Pagat amb èxit", + paymentPending: "Pagament pendent", + paymentFailed: "Pagament fallit!", + paymentCancelled: "Pagament cancel·lat", + paymentUnderReview: "Pagament en revisió", + paymentSuccess: "Pagament amb èxit", + partialPaymentCaptured: "Pagament parcial capturat.", + somethingWentWrong: "Alguna cosa ha anat malament", + redirecting: "Redirigint ...", + redirectingIn: "Redirigint en ", + seconds: " segons ...", + unexpectedError: "S'ha produït un error inesperat." + }, + pt: { + expiresOn: "Link expira em: ", + refId: "ID de referência: ", + requestedBy: "Solicitado por ", + payNow: "Pagar agora", + yourCart: "Seu Carrinho", + quantity: "Quantidade", + showLess: "Mostrar menos", + showMore: "Mostrar mais", + miscellaneousCharges: "Encargos diversos", + miscellaneousChargesDetail: "(inclui impostos, frete, descontos, ofertas, etc.)", + paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, verifique novamente em algum tempo.", + paymentLinkExpired: "Link de Pagamento Expirado", + paymentReceived: "Recebemos seu pagamento com sucesso", + paymentLinkExpiredMessage: "Desculpe, este link de pagamento expirou. Por favor, use a referência abaixo para investigação adicional.", + paidSuccessfully: "Pago com sucesso", + paymentPending: "Pagamento Pendente", + paymentFailed: "Pagamento Falhou!", + paymentCancelled: "Pagamento Cancelado", + paymentUnderReview: "Pagamento em análise", + paymentSuccess: "Sucesso no pagamento", + partialPaymentCaptured: "Pagamento parcial capturado.", + somethingWentWrong: "Algo deu errado", + redirecting: "Redirecionando ...", + redirectingIn: "Redirecionando em ", + seconds: " segundos ...", + unexpectedError: "Ocorreu um erro inesperado." + }, + it: { + expiresOn: "Link scade il: ", + refId: "ID di riferimento: ", + requestedBy: "Richiesto da ", + payNow: "Paga ora", + yourCart: "Il tuo carrello", + quantity: "Quantità", + showLess: "Mostra meno", + showMore: "Mostra di più", + miscellaneousCharges: "Spese varie", + miscellaneousChargesDetail: "(inclusi tasse, spedizione, sconti, offerte, ecc.)", + paymentTakingLonger: "Spiacenti! Il tuo pagamento sta impiegando più tempo del previsto. Controlla di nuovo tra un po'.", + paymentLinkExpired: "Link di pagamento scaduto", + paymentReceived: "Abbiamo ricevuto il tuo pagamento con successo", + paymentLinkExpiredMessage: "Spiacenti, questo link di pagamento è scaduto. Utilizza il riferimento sottostante per ulteriori indagini.", + paidSuccessfully: "Pagato con successo", + paymentPending: "Pagamento in sospeso", + paymentFailed: "Pagamento fallito!", + paymentCancelled: "Pagamento annullato", + paymentUnderReview: "Pagamento in revisione", + paymentSuccess: "Pagamento riuscito", + partialPaymentCaptured: "Pagamento parziale catturato.", + somethingWentWrong: "Qualcosa è andato storto", + redirecting: "Reindirizzando ...", + redirectingIn: "Reindirizzando in ", + seconds: " secondi ...", + unexpectedError: "Si è verificato un errore imprevisto." + }, + pl: { + expiresOn: "Link wygasa w dniu: ", + refId: "Identyfikator referencyjny: ", + requestedBy: "Zażądane przez ", + payNow: "Zapłać teraz", + yourCart: "Twój koszyk", + quantity: "Ilość", + showLess: "Pokaż mniej", + showMore: "Pokaż więcej", + miscellaneousCharges: "Różne opłaty", + miscellaneousChargesDetail: "(obejmuje podatki, wysyłkę, rabaty, oferty itp.)", + paymentTakingLonger: "Przepraszamy! Twoja płatność trwa dłużej niż oczekiwano. Sprawdź ponownie później.", + paymentLinkExpired: "Link do płatności wygasł", + paymentReceived: "Otrzymaliśmy twoją płatność pomyślnie", + paymentLinkExpiredMessage: "Przepraszamy, ten link do płatności wygasł. Skorzystaj z poniższego odniesienia do dalszego dochodzenia.", + paidSuccessfully: "Zapłacono pomyślnie", + paymentPending: "Oczekująca płatność", + paymentFailed: "Płatność nie powiodła się!", + paymentCancelled: "Płatność anulowana", + paymentUnderReview: "Płatność w trakcie przeglądu", + paymentSuccess: "Sukces płatności", + partialPaymentCaptured: "Częściowa płatność została przechwycona.", + somethingWentWrong: "Coś poszło nie tak", + redirecting: "Przekierowanie ...", + redirectingIn: "Przekierowanie w ", + seconds: " sekund ...", + unexpectedError: "Wystąpił nieoczekiwany błąd." + }, + nl: { + expiresOn: "Link verloopt op: ", + refId: "Ref Id: ", + requestedBy: "Aangevraagd door ", + payNow: "Nu betalen", + yourCart: "Je winkelwagen", + quantity: "Hoeveelheid", + showLess: "Toon minder", + showMore: "Toon meer", + miscellaneousCharges: "Diverse kosten", + miscellaneousChargesDetail: "(inclusief belastingen, verzending, kortingen, aanbiedingen, enz.)", + paymentTakingLonger: "Sorry! Je betaling duurt langer dan verwacht. Controleer het later opnieuw.", + paymentLinkExpired: "Betaallink verlopen", + paymentReceived: "We hebben je betaling succesvol ontvangen", + paymentLinkExpiredMessage: "Sorry, deze betaallink is verlopen. Gebruik de onderstaande referentie voor verder onderzoek.", + paidSuccessfully: "Succesvol betaald", + paymentPending: "Betaling in behandeling", + paymentFailed: "Betaling mislukt!", + paymentCancelled: "Betaling geannuleerd", + paymentUnderReview: "Betaling in behandeling", + paymentSuccess: "Betaling geslaagd", + partialPaymentCaptured: "Deelbetaling is vastgelegd.", + somethingWentWrong: "Er is iets misgegaan", + redirecting: "Doorverwijzen ...", + redirectingIn: "Doorverwijzen in ", + seconds: " seconden ...", + unexpectedError: "Er is een onverwachte fout opgetreden." + }, + sv: { + expiresOn: "Länken upphör att gälla den: ", + refId: "Referens-ID: ", + requestedBy: "Begärd av ", + payNow: "Betala nu", + yourCart: "Din varukorg", + quantity: "Antal", + showLess: "Visa mindre", + showMore: "Visa mer", + miscellaneousCharges: "Diverse avgifter", + miscellaneousChargesDetail: "(inklusive skatter, frakt, rabatter, erbjudanden osv.)", + paymentTakingLonger: "Ledsen! Din betalning tar längre tid än väntat. Vänligen kontrollera igen senare.", + paymentLinkExpired: "Betalningslänk har upphört att gälla", + paymentReceived: "Vi har mottagit din betalning", + paymentLinkExpiredMessage: "Tyvärr, denna betalningslänk har upphört att gälla. Använd nedanstående referens för ytterligare utredning.", + paidSuccessfully: "Betalad framgångsrikt", + paymentPending: "Betalning väntar", + paymentFailed: "Betalning misslyckades!", + paymentCancelled: "Betalning avbruten", + paymentUnderReview: "Betalning under granskning", + paymentSuccess: "Betalning lyckades", + partialPaymentCaptured: "Delbetalning har fångats.", + somethingWentWrong: "Något gick fel", + redirecting: "Omdirigerar ...", + redirectingIn: "Omdirigerar om ", + seconds: " sekunder ...", + unexpectedError: "Ett oväntat fel inträffade." + }, + ru: { + expiresOn: "Ссылка истекает: ", + refId: "ID ссылки: ", + requestedBy: "Запрошено ", + payNow: "Оплатить сейчас", + yourCart: "Ваша корзина", + quantity: "Количество", + showLess: "Показать меньше", + showMore: "Показать больше", + miscellaneousCharges: "Прочие сборы", + miscellaneousChargesDetail: "(включает налоги, доставку, скидки, предложения и т. д.)", + paymentTakingLonger: "Извините! Ваш платеж занимает больше времени, чем ожидалось. Пожалуйста, проверьте позже.", + paymentLinkExpired: "Срок действия ссылки оплаты истек", + paymentReceived: "Мы успешно получили ваш платеж", + paymentLinkExpiredMessage: "Извините, срок действия этой ссылки на оплату истек. Пожалуйста, используйте ссылку ниже для дальнейшего расследования.", + paidSuccessfully: "Оплачено успешно", + paymentPending: "Ожидание оплаты", + paymentFailed: "Платеж не прошел!", + paymentCancelled: "Платеж отменен", + paymentUnderReview: "Платеж на рассмотрении", + paymentSuccess: "Платеж успешен", + partialPaymentCaptured: "Частичный платеж захвачен.", + somethingWentWrong: "Что-то пошло не так", + redirecting: "Перенаправление...", + redirectingIn: "Перенаправление через ", + seconds: " секунд ...", + unexpectedError: "Произошла неожиданная ошибка." + }, + zh: { + expiresOn: "链接将于以下时间过期: ", + refId: "参考编号: ", + requestedBy: "请求者: ", + payNow: "立即付款", + yourCart: "您的购物车", + quantity: "数量", + showLess: "显示较少", + showMore: "显示更多", + miscellaneousCharges: "其他费用", + miscellaneousChargesDetail: "(包括税费、运费、折扣、优惠等)", + paymentTakingLonger: "抱歉! 您的付款比预期的时间更长。 请稍后再回来查看。", + paymentLinkExpired: "支付链接已过期", + paymentReceived: "我们已成功收到您的付款", + paymentLinkExpiredMessage: "抱歉,此支付链接已过期。 请使用以下参考进行进一步调查。", + paidSuccessfully: "支付成功", + paymentPending: "付款待定", + paymentFailed: "付款失败!", + paymentCancelled: "付款取消", + paymentUnderReview: "付款审查中", + paymentSuccess: "付款成功", + partialPaymentCaptured: "已捕获部分付款。", + somethingWentWrong: "发生了一些错误", + redirecting: "重定向中...", + redirectingIn: "将在 ", + seconds: " 秒内重定向...", + unexpectedError: "发生意外错误。" + } + }; \ No newline at end of file diff --git a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html index 05af4100e50c..3513de1bb666 100644 --- a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html +++ b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html @@ -323,6 +323,7 @@ diff --git a/crates/router/src/core/payment_link/payment_link_status/status.js b/crates/router/src/core/payment_link/payment_link_status/status.js index eec06fad184d..2fa6c76d1ece 100644 --- a/crates/router/src/core/payment_link/payment_link_status/status.js +++ b/crates/router/src/core/payment_link/payment_link_status/status.js @@ -71,182 +71,6 @@ function invert(color, bw) { ); } -const locales = { - en: { - expiresOn: "Link expires on: ", - refId: "Ref Id: ", - requestedBy: "Requested by ", - payNow: "Pay now", - yourCart: "Your Cart", - quantity: "Quantity", - showLess: "Show Less", - showMore: "Show More", - miscellaneousCharges: "Miscellaneous charges", - miscellaneousChargesDetail: "(includes taxes, shipping, discounts, offers etc.)", - paymentTakingLonger: "Sorry! Your payment is taking longer than expected. Please check back again in sometime.", - paymentLinkExpired: "Payment Link Expired", - paymentReceived: "We have successfully received your payment", - paymentLinkExpiredMessage: "Sorry, this payment link has expired. Please use below reference for further investigation.", - paidSuccessfully: "Paid successfully", - paymentPending: "Payment Pending", - paymentFailed: "Payment Failed!", - paymentCancelled: "Payment Cancelled", - paymentUnderReview: "Payment under review", - paymentSuccess: "Payment Success", - partialPaymentCaptured: "Partial payment was captured.", - somethingWentWrong: "Something went wrong", - redirecting: "Redirecting ...", - redirectingIn: "Redirecting in ", - seconds: " seconds ...", - errorCode: "Error code", - errorMessage: "Error message" - }, - de: { - expiresOn: "Link läuft ab am: ", - refId: "Referenz-ID: ", - requestedBy: "Angefordert von ", - payNow: "Jetzt bezahlen", - yourCart: "Ihr Warenkorb", - quantity: "Menge", - showLess: "Weniger anzeigen", - showMore: "Mehr anzeigen", - miscellaneousCharges: "Sonstige Gebühren", - miscellaneousChargesDetail: "(einschließlich Steuern, Versand, Rabatte, Angebote usw.)", - paymentTakingLonger: "Entschuldigung! Ihre Zahlung dauert länger als erwartet. Bitte prüfen Sie später erneut.", - paymentLinkExpired: "Zahlungslink abgelaufen", - paymentReceived: "Wir haben Ihre Zahlung erfolgreich erhalten", - paymentLinkExpiredMessage: "Entschuldigung, dieser Zahlungslink ist abgelaufen. Bitte verwenden Sie die folgende Referenz für weitere Untersuchungen.", - paidSuccessfully: "Erfolgreich bezahlt", - paymentPending: "Zahlung ausstehend", - paymentFailed: "Zahlung fehlgeschlagen!", - paymentCancelled: "Zahlung storniert", - paymentUnderReview: "Zahlung wird überprüft", - paymentSuccess: "Zahlung erfolgreich", - partialPaymentCaptured: "Teilzahlung wurde erfasst.", - somethingWentWrong: "Etwas ist schiefgelaufen", - redirecting: "Weiterleiten ...", - redirectingIn: "Weiterleiten in ", - seconds: " Sekunden ...", - errorCode: "Fehlercode", - errorMessage: "Fehlermeldung" - }, - pt: { - expiresOn: "Link expira em: ", - refId: "ID de referência: ", - requestedBy: "Solicitado por ", - payNow: "Pagar agora", - yourCart: "Seu Carrinho", - quantity: "Quantidade", - showLess: "Mostrar menos", - showMore: "Mostrar mais", - miscellaneousCharges: "Encargos diversos", - miscellaneousChargesDetail: "(inclui impostos, frete, descontos, ofertas, etc.)", - paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, verifique novamente em algum tempo.", - paymentLinkExpired: "Link de Pagamento Expirado", - paymentReceived: "Recebemos seu pagamento com sucesso", - paymentLinkExpiredMessage: "Desculpe, este link de pagamento expirou. Por favor, use a referência abaixo para investigação adicional.", - paidSuccessfully: "Pago com sucesso", - paymentPending: "Pagamento Pendente", - paymentFailed: "Pagamento Falhou!", - paymentCancelled: "Pagamento Cancelado", - paymentUnderReview: "Pagamento em análise", - paymentSuccess: "Sucesso no pagamento", - partialPaymentCaptured: "Pagamento parcial capturado.", - somethingWentWrong: "Algo deu errado", - redirecting: "Redirecionando ...", - redirectingIn: "Redirecionando em ", - seconds: " segundos ...", - errorCode: "Código de erro", - errorMessage: "Mensagem de erro" - }, - it: { - expiresOn: "Link scade il: ", - refId: "ID di riferimento: ", - requestedBy: "Richiesto da ", - payNow: "Paga ora", - yourCart: "Il tuo carrello", - quantity: "Quantità", - showLess: "Mostra meno", - showMore: "Mostra di più", - miscellaneousCharges: "Spese varie", - miscellaneousChargesDetail: "(inclusi tasse, spedizione, sconti, offerte, ecc.)", - paymentTakingLonger: "Spiacenti! Il tuo pagamento sta impiegando più tempo del previsto. Controlla di nuovo tra un po'.", - paymentLinkExpired: "Link di pagamento scaduto", - paymentReceived: "Abbiamo ricevuto il tuo pagamento con successo", - paymentLinkExpiredMessage: "Spiacenti, questo link di pagamento è scaduto. Utilizza il riferimento sottostante per ulteriori indagini.", - paidSuccessfully: "Pagato con successo", - paymentPending: "Pagamento in sospeso", - paymentFailed: "Pagamento fallito!", - paymentCancelled: "Pagamento annullato", - paymentUnderReview: "Pagamento in revisione", - paymentSuccess: "Pagamento riuscito", - partialPaymentCaptured: "Pagamento parziale catturato.", - somethingWentWrong: "Qualcosa è andato storto", - redirecting: "Reindirizzando ...", - redirectingIn: "Reindirizzando in ", - seconds: " secondi ...", - errorCode: "Codice di errore", - errorMessage: "Messaggio di errore" - }, - zh: { - expiresOn: "链接到期日期:", - refId: "参考编号:", - requestedBy: "请求者:", - payNow: "立即支付", - yourCart: "你的购物车", - quantity: "数量", - showLess: "显示更少", - showMore: "显示更多", - miscellaneousCharges: "其他费用", - miscellaneousChargesDetail: "(包括税费、运费、折扣、优惠等)", - paymentTakingLonger: "对不起!您的付款花费的时间比预期的要长。请稍后再检查。", - paymentLinkExpired: "支付链接已过期", - paymentReceived: "我们已经成功收到您的付款", - paymentLinkExpiredMessage: "对不起,这个支付链接已经过期。请使用下面的参考信息进行进一步调查。", - paidSuccessfully: "支付成功", - paymentPending: "付款待处理", - paymentFailed: "支付失败!", - paymentCancelled: "支付已取消", - paymentUnderReview: "支付正在审查", - paymentSuccess: "支付成功", - partialPaymentCaptured: "部分付款已捕获。", - somethingWentWrong: "出了点问题", - redirecting: "正在重定向 ...", - redirectingIn: "在 ", - seconds: " 秒内重定向 ...", - errorCode: "错误代码", - errorMessage: "错误信息" - }, - es: { - expiresOn: "El enlace expira el: ", - refId: "ID de referencia: ", - requestedBy: "Solicitado por ", - payNow: "Pagar ahora", - yourCart: "Tu carrito", - quantity: "Cantidad", - showLess: "Mostrar menos", - showMore: "Mostrar más", - miscellaneousCharges: "Cargos varios", - miscellaneousChargesDetail: "(incluye impuestos, envío, descuentos, ofertas, etc.)", - paymentTakingLonger: "¡Lo siento! Tu pago está tardando más de lo esperado. Por favor, vuelve a verificarlo más tarde.", - paymentLinkExpired: "Enlace de pago expirado", - paymentReceived: "Hemos recibido tu pago con éxito", - paymentLinkExpiredMessage: "Lo siento, este enlace de pago ha expirado. Por favor, usa la referencia a continuación para una investigación adicional.", - paidSuccessfully: "Pagado exitosamente", - paymentPending: "Pago Pendiente", - paymentFailed: "¡Pago Fallido!", - paymentCancelled: "Pago Cancelado", - paymentUnderReview: "Pago en revisión", - paymentSuccess: "Éxito en el pago", - partialPaymentCaptured: "Pago parcial capturado.", - somethingWentWrong: "Algo salió mal", - redirecting: "Redirigiendo ...", - redirectingIn: "Redirigiendo en ", - seconds: " segundos ...", - errorCode: "Código de error", - errorMessage: "Mensaje de error" - } -}; /** * UTIL FUNCTIONS END HERE diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 99393e6cd1b9..e1f838b8f70d 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1820,6 +1820,8 @@ fn build_payment_link_template( // Logging template let logging_template = include_str!("redirection/assets/redirect_error_logs_push.js").to_string(); + //Locale template + let locale_template = include_str!("../core/payment_link/locale.js").to_string(); // Modify Html template with rendered js and rendered css files let html_template = @@ -1838,6 +1840,7 @@ fn build_payment_link_template( "hyperloader_sdk_link", &get_hyper_loader_sdk(&payment_link_data.sdk_url), ); + context.insert("locale_template", &locale_template); context.insert("rendered_css", &rendered_css); context.insert("rendered_js", &rendered_js); @@ -1914,6 +1917,9 @@ pub fn get_payment_link_status( } }; + //Locale template + let locale_template = include_str!("../core/payment_link/locale.js"); + // Logging template let logging_template = include_str!("redirection/assets/redirect_error_logs_push.js").to_string(); @@ -1938,6 +1944,7 @@ pub fn get_payment_link_status( let _ = tera.add_raw_template("payment_link_status", &html_template); context.insert("rendered_css", &rendered_css); + context.insert("locale_template",&locale_template); context.insert("rendered_js", &rendered_js); context.insert("logging_template", &logging_template); From e9b72ad886a9e3dd0bd94c01a852f93d1ef1bb10 Mon Sep 17 00:00:00 2001 From: "hyperswitch-bot[bot]" <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 08:21:18 +0000 Subject: [PATCH 08/16] chore: run formatter --- crates/router/src/services/api.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index e1f838b8f70d..3049a49c601d 100644 --- a/crates/router/src/services/api.rs +++ b/crates/router/src/services/api.rs @@ -1820,7 +1820,7 @@ fn build_payment_link_template( // Logging template let logging_template = include_str!("redirection/assets/redirect_error_logs_push.js").to_string(); - //Locale template + //Locale template let locale_template = include_str!("../core/payment_link/locale.js").to_string(); // Modify Html template with rendered js and rendered css files @@ -1944,7 +1944,7 @@ pub fn get_payment_link_status( let _ = tera.add_raw_template("payment_link_status", &html_template); context.insert("rendered_css", &rendered_css); - context.insert("locale_template",&locale_template); + context.insert("locale_template", &locale_template); context.insert("rendered_js", &rendered_js); context.insert("logging_template", &logging_template); From 5f507a5c069ee6cf61b67a7d0bfb70ce02c95209 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Tue, 6 Aug 2024 13:52:49 +0530 Subject: [PATCH 09/16] exclued typos for locale.js --- .typos.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/.typos.toml b/.typos.toml index 3223e799cc39..82fb84ecf389 100644 --- a/.typos.toml +++ b/.typos.toml @@ -62,4 +62,5 @@ extend-exclude = [ "openapi/open_api_spec.yaml", # no longer updated "crates/router/src/utils/user/blocker_emails.txt", # this file contains various email domains "CHANGELOG.md", # This file contains all the commits + "crates/router/src/core/payment_link/locale.js" # this file contains converision of static strings in various languages ] From b7a4a940b816e80650c99607410086491679b33b Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Tue, 6 Aug 2024 15:39:12 +0530 Subject: [PATCH 10/16] add locale --- crates/router/src/core/payment_link/locale.js | 75 ++++++++++++++----- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/crates/router/src/core/payment_link/locale.js b/crates/router/src/core/payment_link/locale.js index c079d2b7fd6f..4e1ca64e1f03 100644 --- a/crates/router/src/core/payment_link/locale.js +++ b/crates/router/src/core/payment_link/locale.js @@ -1,3 +1,23 @@ +/* +The languages supported by locale.js are: + 1) English (en) + 2) Hebrew (he) + 3) French (fr) + 4) British English (en_GB) + 5) Arabic (ar) + 6) Japanese (ja) + 7) German (de) + 8) Belgian French (fr_BE) + 9) Spanish (es) + 10) Catalan (ca) + 11) Portuguese (pt) + 12) Italian (it) + 13) Polish (pl) + 14) Dutch (nl) + 15) Swedish (sv) + 16) Russian (ru) + 17) Chinese (zh) +*/ const locales = { en: { expiresOn: "Link expires on: ", @@ -25,7 +45,8 @@ const locales = { redirecting: "Redirecting ...", redirectingIn: "Redirecting in ", seconds: " seconds ...", - unexpectedError: "An unexpected error occurred." + unexpectedError: "An unexpected error occurred.", + notAllowed: "You are not allowed to view this content." }, he: { expiresOn: "הקישור יפוג ב: ", @@ -53,7 +74,8 @@ const locales = { redirecting: "מעביר...", redirectingIn: "מעביר בעוד ", seconds: " שניות ...", - unexpectedError: "אירעה שגיאה בלתי צפויה." + unexpectedError: "אירעה שגיאה בלתי צפויה.", + notAllowed: "אינך מורשה לצפות בתוכן זה." }, fr: { expiresOn: "Le lien expire le: ", @@ -81,7 +103,8 @@ const locales = { redirecting: "Redirection...", redirectingIn: "Redirection dans ", seconds: " secondes...", - unexpectedError: "Une erreur inattendue est survenue." + unexpectedError: "Une erreur inattendue est survenue.", + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu." }, en_GB: { expiresOn: "Link expires on: ", @@ -109,7 +132,9 @@ const locales = { redirecting: "Redirecting ...", redirectingIn: "Redirecting in ", seconds: " seconds ...", - unexpectedError: "An unexpected error occurred." + unexpectedError: "An unexpected error occurred.", + notAllowed: "You are not allowed to view this content." + }, ar: { expiresOn: "الرابط ينتهي في: ", @@ -137,7 +162,8 @@ const locales = { redirecting: "إعادة توجيه ...", redirectingIn: "إعادة توجيه في ", seconds: " ثوانٍ ...", - unexpectedError: "حدث خطأ غير متوقع." + unexpectedError: "حدث خطأ غير متوقع.", + notAllowed: "أنت غير مسموح لك بعرض هذا المحتوى." }, ja: { expiresOn: "リンクの有効期限は: ", @@ -165,7 +191,8 @@ const locales = { redirecting: "リダイレクト中...", redirectingIn: "リダイレクト中 ", seconds: " 秒 ...", - unexpectedError: "予期しないエラーが発生しました。" + unexpectedError: "予期しないエラーが発生しました。", + notAllowed: "このコンテンツを表示する権限がありません。" }, de: { expiresOn: "Link läuft ab am: ", @@ -193,7 +220,8 @@ const locales = { redirecting: "Weiterleiten ...", redirectingIn: "Weiterleiten in ", seconds: " Sekunden ...", - unexpectedError: "Ein unerwarteter Fehler ist aufgetreten." + unexpectedError: "Ein unerwarteter Fehler ist aufgetreten.", + notAllowed: "Sie dürfen diesen Inhalt nicht ansehen." }, fr_BE: { expiresOn: "Le lien expire le: ", @@ -221,7 +249,9 @@ const locales = { redirecting: "Redirection...", redirectingIn: "Redirection dans ", seconds: " secondes...", - unexpectedError: "Une erreur inattendue est survenue." + unexpectedError: "Une erreur inattendue est survenue.", + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu." + }, es: { expiresOn: "El enlace expira el: ", @@ -249,7 +279,8 @@ const locales = { redirecting: "Redirigiendo ...", redirectingIn: "Redirigiendo en ", seconds: " segundos ...", - unexpectedError: "Ocurrió un error inesperado." + unexpectedError: "Ocurrió un error inesperado.", + notAllowed: "No tienes permiso para ver este contenido." }, ca: { expiresOn: "L'enllaç caduca el: ", @@ -277,7 +308,8 @@ const locales = { redirecting: "Redirigint ...", redirectingIn: "Redirigint en ", seconds: " segons ...", - unexpectedError: "S'ha produït un error inesperat." + unexpectedError: "S'ha produït un error inesperat.", + notAllowed: "No tens permís per veure aquest contingut." }, pt: { expiresOn: "Link expira em: ", @@ -290,7 +322,7 @@ const locales = { showMore: "Mostrar mais", miscellaneousCharges: "Encargos diversos", miscellaneousChargesDetail: "(inclui impostos, frete, descontos, ofertas, etc.)", - paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, verifique novamente em algum tempo.", + paymentTakingLonger: "Desculpe! Seu pagamento está demorando mais do que o esperado. Por favor, volte novamente em algum momento.", paymentLinkExpired: "Link de Pagamento Expirado", paymentReceived: "Recebemos seu pagamento com sucesso", paymentLinkExpiredMessage: "Desculpe, este link de pagamento expirou. Por favor, use a referência abaixo para investigação adicional.", @@ -305,7 +337,8 @@ const locales = { redirecting: "Redirecionando ...", redirectingIn: "Redirecionando em ", seconds: " segundos ...", - unexpectedError: "Ocorreu um erro inesperado." + unexpectedError: "Ocorreu um erro inesperado.", + notAllowed: "Você não tem permissão para ver este conteúdo." }, it: { expiresOn: "Link scade il: ", @@ -333,7 +366,8 @@ const locales = { redirecting: "Reindirizzando ...", redirectingIn: "Reindirizzando in ", seconds: " secondi ...", - unexpectedError: "Si è verificato un errore imprevisto." + unexpectedError: "Si è verificato un errore imprevisto.", + notAllowed: "Non sei autorizzato a vedere questo contenuto." }, pl: { expiresOn: "Link wygasa w dniu: ", @@ -361,7 +395,8 @@ const locales = { redirecting: "Przekierowanie ...", redirectingIn: "Przekierowanie w ", seconds: " sekund ...", - unexpectedError: "Wystąpił nieoczekiwany błąd." + unexpectedError: "Wystąpił nieoczekiwany błąd.", + notAllowed: "Nie masz uprawnień do przeglądania tej zawartości." }, nl: { expiresOn: "Link verloopt op: ", @@ -389,7 +424,8 @@ const locales = { redirecting: "Doorverwijzen ...", redirectingIn: "Doorverwijzen in ", seconds: " seconden ...", - unexpectedError: "Er is een onverwachte fout opgetreden." + unexpectedError: "Er is een onverwachte fout opgetreden.", + notAllowed: "Je mag deze inhoud niet bekijken." }, sv: { expiresOn: "Länken upphör att gälla den: ", @@ -417,7 +453,8 @@ const locales = { redirecting: "Omdirigerar ...", redirectingIn: "Omdirigerar om ", seconds: " sekunder ...", - unexpectedError: "Ett oväntat fel inträffade." + unexpectedError: "Ett oväntat fel inträffade.", + notAllowed: "Du har inte behörighet att se detta innehåll." }, ru: { expiresOn: "Ссылка истекает: ", @@ -445,7 +482,8 @@ const locales = { redirecting: "Перенаправление...", redirectingIn: "Перенаправление через ", seconds: " секунд ...", - unexpectedError: "Произошла неожиданная ошибка." + unexpectedError: "Произошла неожиданная ошибка.", + notAllowed: "Вам не разрешено просматривать этот контент." }, zh: { expiresOn: "链接将于以下时间过期: ", @@ -473,6 +511,7 @@ const locales = { redirecting: "重定向中...", redirectingIn: "将在 ", seconds: " 秒内重定向...", - unexpectedError: "发生意外错误。" + unexpectedError: "发生意外错误。", + notAllowed: "您没有权限查看此内容。" } }; \ No newline at end of file From 4625b7e8524e9fb491f4b6d5354bc04d773c1ea8 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Tue, 6 Aug 2024 17:22:32 +0530 Subject: [PATCH 11/16] move get_translation function to locale.js --- crates/router/src/core/payment_link/locale.js | 76 ++++++++++++++----- .../payment_link_initiate/payment_link.js | 9 +-- .../secure_payment_link_initiator.js | 5 +- .../payment_link_status/status.js | 10 +-- 4 files changed, 62 insertions(+), 38 deletions(-) diff --git a/crates/router/src/core/payment_link/locale.js b/crates/router/src/core/payment_link/locale.js index 4e1ca64e1f03..ce727c40c761 100644 --- a/crates/router/src/core/payment_link/locale.js +++ b/crates/router/src/core/payment_link/locale.js @@ -46,7 +46,9 @@ const locales = { redirectingIn: "Redirecting in ", seconds: " seconds ...", unexpectedError: "An unexpected error occurred.", - notAllowed: "You are not allowed to view this content." + notAllowed: "You are not allowed to view this content.", + errorCode: "Error code", + errorMessage: "Error Message" }, he: { expiresOn: "הקישור יפוג ב: ", @@ -75,7 +77,9 @@ const locales = { redirectingIn: "מעביר בעוד ", seconds: " שניות ...", unexpectedError: "אירעה שגיאה בלתי צפויה.", - notAllowed: "אינך מורשה לצפות בתוכן זה." + notAllowed: "אינך מורשה לצפות בתוכן זה.", + errorCode: "קוד שגיאה", + errorMessage: "הודעת שגיאה" }, fr: { expiresOn: "Le lien expire le: ", @@ -104,7 +108,9 @@ const locales = { redirectingIn: "Redirection dans ", seconds: " secondes...", unexpectedError: "Une erreur inattendue est survenue.", - notAllowed: "Vous n'êtes pas autorisé à voir ce contenu." + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu.", + errorCode: "Code d'erreur", + errorMessage: "Message d'erreur" }, en_GB: { expiresOn: "Link expires on: ", @@ -133,7 +139,9 @@ const locales = { redirectingIn: "Redirecting in ", seconds: " seconds ...", unexpectedError: "An unexpected error occurred.", - notAllowed: "You are not allowed to view this content." + notAllowed: "You are not allowed to view this content.", + errorCode: "Error code", + errorMessage: "Error Message" }, ar: { @@ -163,7 +171,9 @@ const locales = { redirectingIn: "إعادة توجيه في ", seconds: " ثوانٍ ...", unexpectedError: "حدث خطأ غير متوقع.", - notAllowed: "أنت غير مسموح لك بعرض هذا المحتوى." + notAllowed: "أنت غير مسموح لك بعرض هذا المحتوى.", + errorCode: "رمز الخطأ", + errorMessage: "رسالة الخطأ" }, ja: { expiresOn: "リンクの有効期限は: ", @@ -192,7 +202,9 @@ const locales = { redirectingIn: "リダイレクト中 ", seconds: " 秒 ...", unexpectedError: "予期しないエラーが発生しました。", - notAllowed: "このコンテンツを表示する権限がありません。" + notAllowed: "このコンテンツを表示する権限がありません。", + errorCode: "エラーコード", + errorMessage: "エラーメッセージ" }, de: { expiresOn: "Link läuft ab am: ", @@ -221,7 +233,9 @@ const locales = { redirectingIn: "Weiterleiten in ", seconds: " Sekunden ...", unexpectedError: "Ein unerwarteter Fehler ist aufgetreten.", - notAllowed: "Sie dürfen diesen Inhalt nicht ansehen." + notAllowed: "Sie dürfen diesen Inhalt nicht ansehen.", + errorCode: "Fehlercode", + errorMessage: "Fehlermeldung" }, fr_BE: { expiresOn: "Le lien expire le: ", @@ -250,7 +264,9 @@ const locales = { redirectingIn: "Redirection dans ", seconds: " secondes...", unexpectedError: "Une erreur inattendue est survenue.", - notAllowed: "Vous n'êtes pas autorisé à voir ce contenu." + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu.", + errorCode: "Code d'erreur", + errorMessage: "Message d'erreur" }, es: { @@ -280,7 +296,9 @@ const locales = { redirectingIn: "Redirigiendo en ", seconds: " segundos ...", unexpectedError: "Ocurrió un error inesperado.", - notAllowed: "No tienes permiso para ver este contenido." + notAllowed: "No tienes permiso para ver este contenido.", + errorCode: "Código de error", + errorMessage: "Mensaje de error" }, ca: { expiresOn: "L'enllaç caduca el: ", @@ -309,7 +327,9 @@ const locales = { redirectingIn: "Redirigint en ", seconds: " segons ...", unexpectedError: "S'ha produït un error inesperat.", - notAllowed: "No tens permís per veure aquest contingut." + notAllowed: "No tens permís per veure aquest contingut.", + errorCode: "Codi d'error", + errorMessage: "Missatge d'error" }, pt: { expiresOn: "Link expira em: ", @@ -338,7 +358,10 @@ const locales = { redirectingIn: "Redirecionando em ", seconds: " segundos ...", unexpectedError: "Ocorreu um erro inesperado.", - notAllowed: "Você não tem permissão para ver este conteúdo." + notAllowed: "Você não tem permissão para ver este conteúdo.", + errorCode: "Código de erro", + errorMessage: "Mensagem de erro" + }, it: { expiresOn: "Link scade il: ", @@ -367,7 +390,9 @@ const locales = { redirectingIn: "Reindirizzando in ", seconds: " secondi ...", unexpectedError: "Si è verificato un errore imprevisto.", - notAllowed: "Non sei autorizzato a vedere questo contenuto." + notAllowed: "Non sei autorizzato a vedere questo contenuto.", + errorCode: "Codice di errore", + errorMessage: "Messaggio di errore" }, pl: { expiresOn: "Link wygasa w dniu: ", @@ -396,7 +421,9 @@ const locales = { redirectingIn: "Przekierowanie w ", seconds: " sekund ...", unexpectedError: "Wystąpił nieoczekiwany błąd.", - notAllowed: "Nie masz uprawnień do przeglądania tej zawartości." + notAllowed: "Nie masz uprawnień do przeglądania tej zawartości.", + errorCode: "Kod błędu", + errorMessage: "Komunikat o błędzie" }, nl: { expiresOn: "Link verloopt op: ", @@ -425,7 +452,9 @@ const locales = { redirectingIn: "Doorverwijzen in ", seconds: " seconden ...", unexpectedError: "Er is een onverwachte fout opgetreden.", - notAllowed: "Je mag deze inhoud niet bekijken." + notAllowed: "Je mag deze inhoud niet bekijken.", + errorCode: "Foutcode", + errorMessage: "Foutmelding" }, sv: { expiresOn: "Länken upphör att gälla den: ", @@ -454,7 +483,9 @@ const locales = { redirectingIn: "Omdirigerar om ", seconds: " sekunder ...", unexpectedError: "Ett oväntat fel inträffade.", - notAllowed: "Du har inte behörighet att se detta innehåll." + notAllowed: "Du har inte behörighet att se detta innehåll.", + errorCode: "Felkod", + errorMessage: "Felmeddelande" }, ru: { expiresOn: "Ссылка истекает: ", @@ -483,7 +514,9 @@ const locales = { redirectingIn: "Перенаправление через ", seconds: " секунд ...", unexpectedError: "Произошла неожиданная ошибка.", - notAllowed: "Вам не разрешено просматривать этот контент." + notAllowed: "Вам не разрешено просматривать этот контент.", + errorCode: "Код ошибки", + errorMessage: "Сообщение об ошибке" }, zh: { expiresOn: "链接将于以下时间过期: ", @@ -512,6 +545,13 @@ const locales = { redirectingIn: "将在 ", seconds: " 秒内重定向...", unexpectedError: "发生意外错误。", - notAllowed: "您没有权限查看此内容。" + notAllowed: "您没有权限查看此内容。", + errorCode: "错误代码", + errorMessage: "错误信息" } - }; \ No newline at end of file + }; + + function getTranslations(locale_str) { + var locale = locale_str || 'en'; // defaults if locale is not present in payment details. + return locales[locale] || locales['en']; // defaults if locale is not implemented in locales. + } \ No newline at end of file diff --git a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js index ca14551b7497..18b90a91171b 100644 --- a/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js +++ b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.js @@ -179,14 +179,7 @@ var unifiedCheckout = null; var pub_key = window.__PAYMENT_DETAILS.pub_key; var hyper = null; - - -function getTranslations() { - var locale = window.__PAYMENT_DETAILS.locale || 'en'; // defaults if locale is not present in payment details. - return locales[locale] || locales['en']; // defaults if locale is not implemented in locales. -} - -const translations = getTranslations(); +const translations = getTranslations(window.__PAYMENT_DETAILS.locale); /** * Trigger - init function invoked once the script tag is loaded diff --git a/crates/router/src/core/payment_link/payment_link_initiate/secure_payment_link_initiator.js b/crates/router/src/core/payment_link/payment_link_initiate/secure_payment_link_initiator.js index 58e9c20e0a07..777cfd8cadd8 100644 --- a/crates/router/src/core/payment_link/payment_link_initiate/secure_payment_link_initiator.js +++ b/crates/router/src/core/payment_link/payment_link_initiate/secure_payment_link_initiator.js @@ -13,12 +13,11 @@ try { if (!isFramed) { function initializeSDK() { - var errMsg = "You are not allowed to view this content."; var contentElement = document.getElementById("payment-link"); if (contentElement instanceof HTMLDivElement) { - contentElement.innerHTML = errMsg; + contentElement.innerHTML = translations.notAllowed; } else { - document.body.innerHTML = errMsg; + document.body.innerHTML = translations.notAllowed; } } } else { diff --git a/crates/router/src/core/payment_link/payment_link_status/status.js b/crates/router/src/core/payment_link/payment_link_status/status.js index 2fa6c76d1ece..ee0e639863e3 100644 --- a/crates/router/src/core/payment_link/payment_link_status/status.js +++ b/crates/router/src/core/payment_link/payment_link_status/status.js @@ -86,15 +86,7 @@ window.state = { isMobileView: window.innerWidth <= 1400, }; - -function getTranslations() { - var paymentDetails = window.__PAYMENT_DETAILS; - console.log(paymentDetails); - var locale = paymentDetails.locale || 'en'; // defaults if locale is not present in payment details. - return locales[locale] || locales['en']; // defaults if locale is not implemented in locales. -} - -const translations = getTranslations(); +const translations = getTranslations(window.__PAYMENT_DETAILS.locale); /** * Trigger - init function invoked once the script tag is loaded * Use From 698ccfbe00365ddfffd2de063562af8b7f3e916d Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Wed, 7 Aug 2024 00:21:15 +0530 Subject: [PATCH 12/16] resolve comments --- crates/router/src/core/payment_link.rs | 14 +++++++-- crates/router/src/routes/payment_link.rs | 36 +++++++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index bbe0deebb99b..6c00a1d59a7a 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -258,8 +258,18 @@ pub async fn initiate_secure_payment_link_flow( ) -> RouterResponse { let locale = request_headers .get(header::ACCEPT_LANGUAGE) - .and_then(|header_value| header_value.to_str().ok()) - .map(|str| str.to_owned()); + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + logger::warn!( + "Could not convert accept-language header to string: {}", + err + ); + err + }) + }) + .transpose() + .ok() + .flatten(); let (payment_link, payment_link_details, payment_link_config) = form_payment_link_data( &state, diff --git a/crates/router/src/routes/payment_link.rs b/crates/router/src/routes/payment_link.rs index 35cbd03a32e1..794366b91d54 100644 --- a/crates/router/src/routes/payment_link.rs +++ b/crates/router/src/routes/payment_link.rs @@ -1,4 +1,4 @@ -use actix_web::{web, Responder}; +use actix_web::{http::header::ACCEPT_LANGUAGE, web, Responder}; use router_env::{instrument, tracing, Flow}; use crate::{ @@ -60,9 +60,20 @@ pub async fn initiate_payment_link( let (merchant_id, payment_id) = path.into_inner(); let locale = req .headers() - .get(actix_web::http::header::ACCEPT_LANGUAGE) - .and_then(|header_value| header_value.to_str().ok()) - .map(|str| str.to_owned()); + .get(ACCEPT_LANGUAGE) + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + router_env::logger::warn!( + "Could not convert accept-language header to string: {}", + err + ); + err + }) + }) + .transpose() + .ok() + .flatten(); + let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), @@ -175,9 +186,20 @@ pub async fn payment_link_status( let (merchant_id, payment_id) = path.into_inner(); let locale = req .headers() - .get(actix_web::http::header::ACCEPT_LANGUAGE) - .and_then(|header_value| header_value.to_str().ok()) - .map(|str| str.to_owned()); + .get(ACCEPT_LANGUAGE) + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + router_env::logger::warn!( + "Could not convert accept-language header to string: {}", + err + ); + err + }) + }) + .transpose() + .ok() + .flatten(); + let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), From 854ef6ae4ddbc010b2c4ba101a1b3bb594e8c373 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Wed, 7 Aug 2024 14:13:36 +0530 Subject: [PATCH 13/16] resolve comments --- api-reference/openapi_spec.json | 4 -- crates/api_models/src/payments.rs | 1 - crates/router/src/core/payment_link.rs | 34 +++++++++++++-- .../payments/operations/payment_create.rs | 7 ++-- crates/router/src/routes/payment_link.rs | 41 +++---------------- 5 files changed, 40 insertions(+), 47 deletions(-) diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index 1161049160dd..64893d291c47 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -14035,10 +14035,6 @@ }, "payment_id": { "type": "string" - }, - "locale": { - "type": "string", - "nullable": true } } }, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index aa117841668c..7b9167a19d2d 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -5380,7 +5380,6 @@ pub struct PaymentLinkInitiateRequest { #[schema(value_type = String)] pub merchant_id: id_type::MerchantId, pub payment_id: String, - pub locale: Option, } #[derive(Debug, serde::Serialize)] diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 6c00a1d59a7a..4298cbd65c4a 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -365,8 +365,22 @@ pub async fn initiate_payment_link_flow( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, - locale: Option, + request_headers: &header::HeaderMap, ) -> RouterResponse { + let locale = request_headers + .get(header::ACCEPT_LANGUAGE) + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + logger::warn!( + "Could not convert accept-language header to string: {}", + err + ); + err + }) + }) + .transpose() + .ok() + .flatten(); let (_, payment_details, payment_link_config) = form_payment_link_data( &state, merchant_account, @@ -608,7 +622,6 @@ pub fn get_payment_link_config_based_on_priority( DEFAULT_ENABLE_SAVED_PAYMENT_METHOD ) ); - let payment_link_config = PaymentLinkConfig { theme, logo, @@ -618,6 +631,7 @@ pub fn get_payment_link_config_based_on_priority( enabled_saved_payment_method, allowed_domains, }; + router_env::logger::debug!("payment_link_config : {:?}", payment_link_config.clone()); Ok((payment_link_config, domain_name)) } @@ -648,8 +662,22 @@ pub async fn get_payment_link_status( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, - locale: Option, + request_headers: &header::HeaderMap, ) -> RouterResponse { + let locale = request_headers + .get(header::ACCEPT_LANGUAGE) + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + logger::warn!( + "Could not convert accept-language header to string: {}", + err + ); + err + }) + }) + .transpose() + .ok() + .flatten(); let db = &*state.store; let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 4aa3b0c65ee1..fa22a2f5aeef 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1243,15 +1243,16 @@ async fn create_payment_link( domain_name, merchant_id.get_string_repr(), payment_id.clone(), - locale_str, + locale_str.clone(), ); let secure_link = payment_link_config.allowed_domains.as_ref().map(|_| { format!( - "{}/payment_link/s/{}/{}", + "{}/payment_link/s/{}/{}?locale={}", domain_name, merchant_id.get_string_repr(), - payment_id.clone() + payment_id.clone(), + locale_str, ) }); diff --git a/crates/router/src/routes/payment_link.rs b/crates/router/src/routes/payment_link.rs index 794366b91d54..7e25156c9a64 100644 --- a/crates/router/src/routes/payment_link.rs +++ b/crates/router/src/routes/payment_link.rs @@ -1,4 +1,4 @@ -use actix_web::{http::header::ACCEPT_LANGUAGE, web, Responder}; +use actix_web::{web, Responder}; use router_env::{instrument, tracing, Flow}; use crate::{ @@ -58,27 +58,12 @@ pub async fn initiate_payment_link( ) -> impl Responder { let flow = Flow::PaymentLinkInitiate; let (merchant_id, payment_id) = path.into_inner(); - let locale = req - .headers() - .get(ACCEPT_LANGUAGE) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - router_env::logger::warn!( - "Could not convert accept-language header to string: {}", - err - ); - err - }) - }) - .transpose() - .ok() - .flatten(); let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), - locale, }; + let headers = req.headers(); Box::pin(api::server_wrap( flow, state, @@ -91,7 +76,7 @@ pub async fn initiate_payment_link( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), - payload.locale.clone(), + headers, ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), @@ -110,7 +95,6 @@ pub async fn initiate_secure_payment_link( let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), - locale: None, }; let headers = req.headers(); Box::pin(api::server_wrap( @@ -184,27 +168,12 @@ pub async fn payment_link_status( ) -> impl Responder { let flow = Flow::PaymentLinkStatus; let (merchant_id, payment_id) = path.into_inner(); - let locale = req - .headers() - .get(ACCEPT_LANGUAGE) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - router_env::logger::warn!( - "Could not convert accept-language header to string: {}", - err - ); - err - }) - }) - .transpose() - .ok() - .flatten(); let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), - locale, }; + let headers = req.headers(); Box::pin(api::server_wrap( flow, state, @@ -217,7 +186,7 @@ pub async fn payment_link_status( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), - payload.locale.clone(), + headers, ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), From ba44e50e43caa856248485a276981a74da093b26 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Wed, 7 Aug 2024 14:56:09 +0530 Subject: [PATCH 14/16] remove log --- crates/router/src/core/payment_link.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 4298cbd65c4a..3c76ab41a11f 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -631,7 +631,6 @@ pub fn get_payment_link_config_based_on_priority( enabled_saved_payment_method, allowed_domains, }; - router_env::logger::debug!("payment_link_config : {:?}", payment_link_config.clone()); Ok((payment_link_config, domain_name)) } From 55c4a0ad41a6a927581fba2bfb853ad22c72f108 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Wed, 7 Aug 2024 16:06:57 +0530 Subject: [PATCH 15/16] resolve comments --- crates/router/src/core/payment_link.rs | 49 ++------------------ crates/router/src/services/authentication.rs | 14 ++++++ 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 3c76ab41a11f..4199a0ae2682 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -24,8 +24,9 @@ use super::errors::{self, RouterResult, StorageErrorExt}; use crate::{ errors::RouterResponse, get_payment_link_config_value, get_payment_link_config_value_based_on_priority, + headers::ACCEPT_LANGUAGE, routes::SessionState, - services, + services::{self, authentication::try_get_header_value_by_key}, types::{ api::payment_link::PaymentLinkResponseExt, domain, @@ -256,21 +257,7 @@ pub async fn initiate_secure_payment_link_flow( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = request_headers - .get(header::ACCEPT_LANGUAGE) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - logger::warn!( - "Could not convert accept-language header to string: {}", - err - ); - err - }) - }) - .transpose() - .ok() - .flatten(); - + let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); let (payment_link, payment_link_details, payment_link_config) = form_payment_link_data( &state, merchant_account, @@ -367,20 +354,7 @@ pub async fn initiate_payment_link_flow( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = request_headers - .get(header::ACCEPT_LANGUAGE) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - logger::warn!( - "Could not convert accept-language header to string: {}", - err - ); - err - }) - }) - .transpose() - .ok() - .flatten(); + let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); let (_, payment_details, payment_link_config) = form_payment_link_data( &state, merchant_account, @@ -663,20 +637,7 @@ pub async fn get_payment_link_status( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = request_headers - .get(header::ACCEPT_LANGUAGE) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - logger::warn!( - "Could not convert accept-language header to string: {}", - err - ); - err - }) - }) - .transpose() - .ok() - .flatten(); + let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); let db = &*state.store; let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index a82306fd1331..ddb0d56db0c1 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -1525,6 +1525,20 @@ pub fn get_header_value_by_key(key: String, headers: &HeaderMap) -> RouterResult .transpose() } +pub fn try_get_header_value_by_key(key: String, headers: &HeaderMap) -> Option { + headers + .get(key.clone()) + .map(|value| { + value.to_str().map(|str| str.to_owned()).map_err(|err| { + logger::warn!("Could not convert {} header to string: {}", key, err); + err + }) + }) + .transpose() + .ok() + .flatten() +} + pub fn get_jwt_from_authorization_header(headers: &HeaderMap) -> RouterResult<&str> { headers .get(crate::headers::AUTHORIZATION) From a61c4072e5a1dc5edddf5299d1523696bb881c90 Mon Sep 17 00:00:00 2001 From: Chikke Srujan Date: Wed, 7 Aug 2024 16:28:54 +0530 Subject: [PATCH 16/16] remove try --- crates/router/src/core/payment_link.rs | 11 +++++++---- crates/router/src/services/authentication.rs | 14 -------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 4199a0ae2682..2fc57f62f49e 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -26,7 +26,7 @@ use crate::{ get_payment_link_config_value, get_payment_link_config_value_based_on_priority, headers::ACCEPT_LANGUAGE, routes::SessionState, - services::{self, authentication::try_get_header_value_by_key}, + services::{self, authentication::get_header_value_by_key}, types::{ api::payment_link::PaymentLinkResponseExt, domain, @@ -257,7 +257,8 @@ pub async fn initiate_secure_payment_link_flow( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); + let locale = get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers)? + .map(|val| val.to_string()); let (payment_link, payment_link_details, payment_link_config) = form_payment_link_data( &state, merchant_account, @@ -354,7 +355,8 @@ pub async fn initiate_payment_link_flow( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); + let locale = get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers)? + .map(|val| val.to_string()); let (_, payment_details, payment_link_config) = form_payment_link_data( &state, merchant_account, @@ -637,7 +639,8 @@ pub async fn get_payment_link_status( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let locale = try_get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers); + let locale = get_header_value_by_key(ACCEPT_LANGUAGE.into(), request_headers)? + .map(|val| val.to_string()); let db = &*state.store; let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index ddb0d56db0c1..a82306fd1331 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -1525,20 +1525,6 @@ pub fn get_header_value_by_key(key: String, headers: &HeaderMap) -> RouterResult .transpose() } -pub fn try_get_header_value_by_key(key: String, headers: &HeaderMap) -> Option { - headers - .get(key.clone()) - .map(|value| { - value.to_str().map(|str| str.to_owned()).map_err(|err| { - logger::warn!("Could not convert {} header to string: {}", key, err); - err - }) - }) - .transpose() - .ok() - .flatten() -} - pub fn get_jwt_from_authorization_header(headers: &HeaderMap) -> RouterResult<&str> { headers .get(crate::headers::AUTHORIZATION)