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 ] diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 570b76f3b510..7b9167a19d2d 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 { @@ -5406,6 +5407,7 @@ pub struct PaymentLinkDetails { pub merchant_description: Option, pub sdk_layout: String, pub display_sdk_only: bool, + pub locale: Option, } #[derive(Debug, serde::Serialize, Clone)] @@ -5430,6 +5432,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 ef39a34a11e6..2fc57f62f49e 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::get_header_value_by_key}, types::{ api::payment_link::PaymentLinkResponseExt, domain, @@ -64,6 +65,7 @@ pub async fn form_payment_link_data( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, + locale: Option, ) -> RouterResult<(PaymentLink, PaymentLinkData, PaymentLinkConfig)> { let db = &*state.store; let payment_intent = db @@ -214,6 +216,7 @@ pub async fn form_payment_link_data( redirect: false, theme: payment_link_config.theme.clone(), return_url: return_url.clone(), + locale: locale.clone(), }; return Ok(( @@ -240,6 +243,7 @@ pub async fn form_payment_link_data( merchant_description: payment_intent.description, sdk_layout: payment_link_config.sdk_layout.clone(), display_sdk_only: payment_link_config.display_sdk_only, + locale, }); Ok((payment_link, payment_link_details, payment_link_config)) @@ -253,9 +257,17 @@ pub async fn initiate_secure_payment_link_flow( payment_id: String, request_headers: &header::HeaderMap, ) -> RouterResponse { - let (payment_link, payment_link_details, payment_link_config) = - form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id) - .await?; + 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, + key_store, + merchant_id, + payment_id, + locale, + ) + .await?; validator::validate_secure_payment_link_render_request( request_headers, @@ -341,10 +353,19 @@ pub async fn initiate_payment_link_flow( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, + request_headers: &header::HeaderMap, ) -> RouterResponse { - let (_, payment_details, payment_link_config) = - form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id) - .await?; + 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, + 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)?; @@ -577,7 +598,6 @@ pub fn get_payment_link_config_based_on_priority( DEFAULT_ENABLE_SAVED_PAYMENT_METHOD ) ); - let payment_link_config = PaymentLinkConfig { theme, logo, @@ -617,7 +637,10 @@ pub async fn get_payment_link_status( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: String, + request_headers: &header::HeaderMap, ) -> RouterResponse { + 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( @@ -726,6 +749,7 @@ pub async fn get_payment_link_status( redirect: true, theme: payment_link_config.theme.clone(), return_url, + locale, }; let js_script = get_js_script(&PaymentLinkData::PaymentLinkStatusDetails(payment_details))?; let payment_link_status_data = services::PaymentLinkStatusData { 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..ce727c40c761 --- /dev/null +++ b/crates/router/src/core/payment_link/locale.js @@ -0,0 +1,557 @@ +/* +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: ", + 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.", + notAllowed: "You are not allowed to view this content.", + errorCode: "Error code", + errorMessage: "Error Message" + }, + 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: "אירעה שגיאה בלתי צפויה.", + notAllowed: "אינך מורשה לצפות בתוכן זה.", + errorCode: "קוד שגיאה", + errorMessage: "הודעת שגיאה" + }, + 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.", + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu.", + errorCode: "Code d'erreur", + errorMessage: "Message d'erreur" + }, + 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.", + notAllowed: "You are not allowed to view this content.", + errorCode: "Error code", + errorMessage: "Error Message" + + }, + 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: "حدث خطأ غير متوقع.", + notAllowed: "أنت غير مسموح لك بعرض هذا المحتوى.", + errorCode: "رمز الخطأ", + errorMessage: "رسالة الخطأ" + }, + 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: "予期しないエラーが発生しました。", + notAllowed: "このコンテンツを表示する権限がありません。", + errorCode: "エラーコード", + errorMessage: "エラーメッセージ" + }, + 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.", + notAllowed: "Sie dürfen diesen Inhalt nicht ansehen.", + errorCode: "Fehlercode", + errorMessage: "Fehlermeldung" + }, + 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.", + notAllowed: "Vous n'êtes pas autorisé à voir ce contenu.", + errorCode: "Code d'erreur", + errorMessage: "Message d'erreur" + + }, + 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.", + notAllowed: "No tienes permiso para ver este contenido.", + errorCode: "Código de error", + errorMessage: "Mensaje de error" + }, + 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.", + notAllowed: "No tens permís per veure aquest contingut.", + errorCode: "Codi d'error", + errorMessage: "Missatge d'error" + }, + 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, 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.", + 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.", + 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: ", + 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.", + notAllowed: "Non sei autorizzato a vedere questo contenuto.", + errorCode: "Codice di errore", + errorMessage: "Messaggio di errore" + }, + 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.", + notAllowed: "Nie masz uprawnień do przeglądania tej zawartości.", + errorCode: "Kod błędu", + errorMessage: "Komunikat o błędzie" + }, + 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.", + notAllowed: "Je mag deze inhoud niet bekijken.", + errorCode: "Foutcode", + errorMessage: "Foutmelding" + }, + 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.", + notAllowed: "Du har inte behörighet att se detta innehåll.", + errorCode: "Felkod", + errorMessage: "Felmeddelande" + }, + 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: "Произошла неожиданная ошибка.", + notAllowed: "Вам не разрешено просматривать этот контент.", + errorCode: "Код ошибки", + errorMessage: "Сообщение об ошибке" + }, + 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: "发生意外错误。", + notAllowed: "您没有权限查看此内容。", + errorCode: "错误代码", + errorMessage: "错误信息" + } + }; + + 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.html b/crates/router/src/core/payment_link/payment_link_initiate/payment_link.html index 5e165ac171a7..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 @@ -249,7 +249,7 @@ height="16" > - Your Cart + - Pay now + @@ -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 c0c5fd78e17f..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 @@ -71,6 +71,7 @@ function invert(color, bw) { ); } + /** * UTIL FUNCTIONS END HERE */ @@ -85,6 +86,7 @@ window.state = { isMobileView: window.innerWidth <= 1400, }; +const translations = getTranslations(window.__PAYMENT_DETAILS.locale); /** * Trigger - init function invoked once the script tag is loaded * Use @@ -135,7 +137,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 +145,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 +160,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 +178,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 +276,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 8d7266c499e8..6b91d5d285f8 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -158,7 +158,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 94eddff25d4e..fa22a2f5aeef 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; @@ -261,6 +261,7 @@ impl GetTracker, api::PaymentsRequest> for Pa profile_id.clone(), domain_name, session_expiry, + header_payload.locale.clone(), ) .await? } @@ -1232,22 +1233,26 @@ 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 open_payment_link = format!( - "{}/payment_link/{}/{}", + "{}/payment_link/{}/{}?locale={}", domain_name, merchant_id.get_string_repr(), - payment_id.clone() + payment_id.clone(), + 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/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 35cdafe0021f..c8da548916fc 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 f061fc2f07b8..1e968f0dc70b 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 06b1037cb383..7e25156c9a64 100644 --- a/crates/router/src/routes/payment_link.rs +++ b/crates/router/src/routes/payment_link.rs @@ -58,10 +58,12 @@ pub async fn initiate_payment_link( ) -> impl Responder { let flow = Flow::PaymentLinkInitiate; let (merchant_id, payment_id) = path.into_inner(); + let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), }; + let headers = req.headers(); Box::pin(api::server_wrap( flow, state, @@ -74,6 +76,7 @@ pub async fn initiate_payment_link( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), + headers, ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), @@ -165,10 +168,12 @@ pub async fn payment_link_status( ) -> impl Responder { let flow = Flow::PaymentLinkStatus; let (merchant_id, payment_id) = path.into_inner(); + let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), }; + let headers = req.headers(); Box::pin(api::server_wrap( flow, state, @@ -181,6 +186,7 @@ pub async fn payment_link_status( auth.key_store, payload.merchant_id.clone(), payload.payment_id.clone(), + headers, ) }, &crate::services::authentication::MerchantIdAuth(merchant_id), diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index a4db90f28b61..d2f0cfeb7759 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 @@ -132,7 +139,7 @@ pub async fn payments_create( auth.merchant_account, auth.profile_id, auth.key_store, - HeaderPayload::default(), + header_payload.clone(), req, api::AuthFlow::Merchant, ) diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs index 99393e6cd1b9..3049a49c601d 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); diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 467867ef8406..b23b2755260d 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::{ @@ -1284,6 +1284,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); @@ -1324,6 +1326,7 @@ impl ForeignTryFrom<&HeaderMap> for payments::HeaderPayload { browser_name, x_client_platform, x_merchant_domain, + locale, }) } }