From b25137295704b82872809665bc697e57ccf7060c Mon Sep 17 00:00:00 2001 From: support Date: Sun, 18 Oct 2026 08:06:47 +0200 Subject: [PATCH 1/2] Show the payment method in the customer's language in order e-mails and PDF IPaymentProvider gets GetFriendlyName(languageId), defaulting to FriendlyName so external plugins keep working; the shipped payment plugins translate it into the given language. The {{Order.PaymentMethod}} token and the PDF invoice pass Order.CustomerLanguageId instead of following the request language. Tax and shipping provider errors are logged with SystemName. --- .../Services/Tax/TaxService.cs | 2 +- .../Services/Shipping/ShippingService.cs | 2 +- .../Checkout/Payments/IPaymentProvider.cs | 7 +++++ .../Messages/GetOrderTokensCommandHandler.cs | 4 ++- .../BrainTreePaymentProvider.cs | 3 ++ .../CashOnDeliveryPaymentProvider.cs | 3 ++ .../StripeCheckoutPaymentProvider.cs | 3 ++ .../GetOrderTokensCommandHandlerTests.cs | 29 +++++++++++++++++-- .../PdfTemplates/OrderPdfTemplate.cshtml | 2 +- 9 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/Business/Grand.Business.Catalog/Services/Tax/TaxService.cs b/src/Business/Grand.Business.Catalog/Services/Tax/TaxService.cs index e3ee25ff42..f3e3a6a434 100644 --- a/src/Business/Grand.Business.Catalog/Services/Tax/TaxService.cs +++ b/src/Business/Grand.Business.Catalog/Services/Tax/TaxService.cs @@ -218,7 +218,7 @@ await IsVatExempt(calculateTaxRequest.Address, calculateTaxRequest.Customer)) else { foreach (var error in calculateTaxResult.Errors) - _logger.LogError("{FriendlyName} - {Error}", activeTaxProvider.FriendlyName, error); + _logger.LogError("{SystemName} - {Error}", activeTaxProvider.SystemName, error); } return (taxRate, isTaxable); diff --git a/src/Business/Grand.Business.Checkout/Services/Shipping/ShippingService.cs b/src/Business/Grand.Business.Checkout/Services/Shipping/ShippingService.cs index 4aeee8ca9b..96962436fd 100644 --- a/src/Business/Grand.Business.Checkout/Services/Shipping/ShippingService.cs +++ b/src/Business/Grand.Business.Checkout/Services/Shipping/ShippingService.cs @@ -200,7 +200,7 @@ public virtual async Task GetShippingOptions(Customer foreach (var error in getShippingOptionResponse.Errors) { result.AddError(error); - _logger.LogWarning("Shipping ({FriendlyName}) {Error}", shippingRateMethod.FriendlyName, error); + _logger.LogWarning("Shipping ({SystemName}) {Error}", shippingRateMethod.SystemName, error); } //clear the shipping options in this case diff --git a/src/Business/Grand.Business.Core/Interfaces/Checkout/Payments/IPaymentProvider.cs b/src/Business/Grand.Business.Core/Interfaces/Checkout/Payments/IPaymentProvider.cs index d248ed523e..b983b92532 100644 --- a/src/Business/Grand.Business.Core/Interfaces/Checkout/Payments/IPaymentProvider.cs +++ b/src/Business/Grand.Business.Core/Interfaces/Checkout/Payments/IPaymentProvider.cs @@ -106,6 +106,13 @@ public interface IPaymentProvider : IProvider /// Task GetControllerRouteName(); + /// + /// Gets a friendly name in the given language, for text that does not follow the current request + /// (e.g. order e-mails). Defaults to . + /// + /// Language identifier + string GetFriendlyName(string languageId) => FriendlyName; + #endregion #region Properties diff --git a/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs b/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs index fefe67d106..a2cb5dcefb 100644 --- a/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs +++ b/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs @@ -130,7 +130,9 @@ public async Task Handle(GetOrderTokensCommand request, Cancellatio var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(request.Order.PaymentMethodSystemName); liquidOrder.PaymentMethod = - paymentMethod != null ? paymentMethod.FriendlyName : request.Order.PaymentMethodSystemName; + paymentMethod != null + ? paymentMethod.GetFriendlyName(request.Order.CustomerLanguageId) + : request.Order.PaymentMethodSystemName; var dict = new Dictionary(); foreach (var item in request.Order.OrderTaxes) diff --git a/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs b/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs index dce6645233..75becec8ab 100644 --- a/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs +++ b/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs @@ -347,6 +347,9 @@ public async Task SupportVoid() public string FriendlyName => _translationService.GetResource(BrainTreeDefaults.FriendlyName); + public string GetFriendlyName(string languageId) => + _translationService.GetResource(BrainTreeDefaults.FriendlyName, languageId); + public int Priority => _brainTreePaymentSettings.DisplayOrder; public IList LimitedToStores => new List(); diff --git a/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs b/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs index 88b07a5c0e..35f2aeee98 100644 --- a/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs +++ b/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs @@ -41,6 +41,9 @@ public CashOnDeliveryPaymentProvider( public string FriendlyName => _translationService.GetResource(CashOnDeliveryPaymentDefaults.FriendlyName); + public string GetFriendlyName(string languageId) => + _translationService.GetResource(CashOnDeliveryPaymentDefaults.FriendlyName, languageId); + public int Priority => _cashOnDeliveryPaymentSettings.DisplayOrder; public IList LimitedToStores => new List(); diff --git a/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs b/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs index 724ec1456d..7c4b37f678 100644 --- a/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs +++ b/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs @@ -41,6 +41,9 @@ public StripeCheckoutPaymentProvider( public string FriendlyName => _translationService.GetResource(StripeCheckoutDefaults.FriendlyName); + public string GetFriendlyName(string languageId) => + _translationService.GetResource(StripeCheckoutDefaults.FriendlyName, languageId); + public int Priority => _stripeCheckoutPaymentSettings.DisplayOrder; public IList LimitedToStores => new List(); diff --git a/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs b/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs index 08816ea40c..39ae660e9d 100644 --- a/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs @@ -1,4 +1,4 @@ -using Grand.Business.Core.Commands.Messages.Tokens; +using Grand.Business.Core.Commands.Messages.Tokens; using Grand.Business.Core.Interfaces.Catalog.Prices; using Grand.Business.Core.Interfaces.Catalog.Products; using Grand.Business.Core.Interfaces.Checkout.GiftVouchers; @@ -24,6 +24,7 @@ public class GetOrderTokensCommandHandlerTests { private readonly Currency _orderCurrency = new() { CurrencyCode = "EUR" }; private GetOrderTokensCommandHandler _handler; + private Mock _paymentServiceMock; private Mock _priceFormatterMock; [TestInitialize] @@ -41,10 +42,12 @@ public void Init() _priceFormatterMock.Setup(x => x.FormatPrice(It.IsAny(), It.IsAny())) .Returns((double price, Currency currency) => $"{currency?.CurrencyCode}{price}"); + _paymentServiceMock = new Mock(); + _handler = new GetOrderTokensCommandHandler(languageService.Object, currencyService.Object, new Mock().Object, new Mock().Object, _priceFormatterMock.Object, new Mock().Object, new Mock().Object, - new Mock().Object, giftVoucherService.Object, new TaxSettings()); + _paymentServiceMock.Object, giftVoucherService.Object, new TaxSettings()); } [TestMethod] @@ -62,4 +65,26 @@ public async Task Handle_FormatsTaxRatesInTheOrderCurrency() //Assert Assert.AreEqual("EUR10", result.TaxRates["23"]); } + + [TestMethod] + public async Task Handle_PaymentMethodNameInTheCustomerLanguage() + { + //Arrange + var paymentProvider = new Mock(); + paymentProvider.Setup(x => x.FriendlyName).Returns("Request language"); + paymentProvider.Setup(x => x.GetFriendlyName("1")).Returns("Customer language"); + _paymentServiceMock.Setup(x => x.LoadPaymentMethodBySystemName("Payments.Test")) + .Returns(paymentProvider.Object); + var order = new Order { + CustomerCurrencyCode = "EUR", CustomerLanguageId = "1", PaymentMethodSystemName = "Payments.Test" + }; + + //Act + var result = await _handler.Handle(new GetOrderTokensCommand { + Order = order, Customer = new Customer(), Store = new Store(), Host = new DomainHost { Url = "https://localhost/" } + }, CancellationToken.None); + + //Assert + Assert.AreEqual("Customer language", result.PaymentMethod); + } } diff --git a/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml b/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml index f6de98c094..8c58f982c7 100644 --- a/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml +++ b/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml @@ -152,7 +152,7 @@ @((await _countryService.GetCountryById(order.BillingAddress.CountryId))?.Name)

var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(order.PaymentMethodSystemName); - var paymentMethodStr = paymentMethod != null ? paymentMethod.FriendlyName : order.PaymentMethodSystemName; + var paymentMethodStr = paymentMethod != null ? paymentMethod.GetFriendlyName(order.CustomerLanguageId) : order.PaymentMethodSystemName; @(string.Format(_translationService.GetResource("PDFInvoice.PaymentMethod", order.CustomerLanguageId), paymentMethodStr))
@await Component.InvokeAsync("Widget", new { widgetZone = "pdf_payment_method_below", additionalData = order.Id }) From 1700a59399840da6ca29fec884eadc6b70760f78 Mon Sep 17 00:00:00 2001 From: support Date: Sun, 18 Oct 2026 08:35:32 +0200 Subject: [PATCH 2/2] Fall back safely when naming the order's payment method Order e-mails and PDFs now get the payment method name through GetPaymentMethodName(order): the name in the order's language, the friendly name when the order has no language or no translation, and the system name when the provider is missing or gives no name. An order without a language no longer throws, a missing translation no longer shows the resource key, and the Vendor order PDF uses the same name. --- .../Extensions/PaymentExtensions.cs | 26 ++++++++++ .../Messages/GetOrderTokensCommandHandler.cs | 5 +- .../BrainTreePaymentProvider.cs | 2 +- .../CashOnDeliveryPaymentProvider.cs | 2 +- .../StripeCheckoutPaymentProvider.cs | 2 +- .../Extensions/PaymentExtensionsTests.cs | 47 ++++++++++++++++++- .../GetOrderTokensCommandHandlerTests.cs | 2 +- .../PdfTemplates/OrderPdfTemplate.cshtml | 3 +- .../PdfTemplates/OrderPdfTemplate.cshtml | 3 +- 9 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/Business/Grand.Business.Core/Extensions/PaymentExtensions.cs b/src/Business/Grand.Business.Core/Extensions/PaymentExtensions.cs index 5fbd259c83..1e407d6492 100644 --- a/src/Business/Grand.Business.Core/Extensions/PaymentExtensions.cs +++ b/src/Business/Grand.Business.Core/Extensions/PaymentExtensions.cs @@ -1,4 +1,5 @@ using Grand.Business.Core.Interfaces.Checkout.Payments; +using Grand.Domain.Orders; using Grand.Domain.Payments; namespace Grand.Business.Core.Extensions; @@ -24,4 +25,29 @@ public static bool IsPaymentMethodActive(this IPaymentProvider paymentMethod, paymentSettings.ActivePaymentProviderSystemNames.Any(activeMethodSystemName => paymentMethod.SystemName.Equals(activeMethodSystemName, StringComparison.OrdinalIgnoreCase)); } + + /// + /// Gets the name of the order's payment method in the order's language, for text that does not follow + /// the current request (e-mails, PDF). Falls back to the friendly name when the order has no language, + /// and to the system name when the provider is missing or gives no name. + /// + /// Payment method, or null when it is no longer installed + /// Order + /// Payment method name + public static string GetPaymentMethodName(this IPaymentProvider paymentMethod, Order order) + { + ArgumentNullException.ThrowIfNull(order); + + if (paymentMethod == null) + return order.PaymentMethodSystemName; + + var name = string.IsNullOrEmpty(order.CustomerLanguageId) + ? paymentMethod.FriendlyName + : paymentMethod.GetFriendlyName(order.CustomerLanguageId); + + if (string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(order.CustomerLanguageId)) + name = paymentMethod.FriendlyName; + + return string.IsNullOrEmpty(name) ? order.PaymentMethodSystemName : name; + } } \ No newline at end of file diff --git a/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs b/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs index a2cb5dcefb..e93a6b99e2 100644 --- a/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs +++ b/src/Business/Grand.Business.Messages/Commands/Handlers/Messages/GetOrderTokensCommandHandler.cs @@ -129,10 +129,7 @@ public async Task Handle(GetOrderTokensCommand request, Cancellatio await _addressAttributeParser.FormatAttributes(language, request.Order.ShippingAddress?.Attributes); var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(request.Order.PaymentMethodSystemName); - liquidOrder.PaymentMethod = - paymentMethod != null - ? paymentMethod.GetFriendlyName(request.Order.CustomerLanguageId) - : request.Order.PaymentMethodSystemName; + liquidOrder.PaymentMethod = paymentMethod.GetPaymentMethodName(request.Order); var dict = new Dictionary(); foreach (var item in request.Order.OrderTaxes) diff --git a/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs b/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs index 75becec8ab..6a57cb995a 100644 --- a/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs +++ b/src/Plugins/Payments.BrainTree/BrainTreePaymentProvider.cs @@ -348,7 +348,7 @@ public async Task SupportVoid() public string FriendlyName => _translationService.GetResource(BrainTreeDefaults.FriendlyName); public string GetFriendlyName(string languageId) => - _translationService.GetResource(BrainTreeDefaults.FriendlyName, languageId); + _translationService.GetResource(BrainTreeDefaults.FriendlyName, languageId, returnEmptyIfNotFound: true); public int Priority => _brainTreePaymentSettings.DisplayOrder; diff --git a/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs b/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs index 35f2aeee98..6027133c69 100644 --- a/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs +++ b/src/Plugins/Payments.CashOnDelivery/CashOnDeliveryPaymentProvider.cs @@ -42,7 +42,7 @@ public CashOnDeliveryPaymentProvider( public string FriendlyName => _translationService.GetResource(CashOnDeliveryPaymentDefaults.FriendlyName); public string GetFriendlyName(string languageId) => - _translationService.GetResource(CashOnDeliveryPaymentDefaults.FriendlyName, languageId); + _translationService.GetResource(CashOnDeliveryPaymentDefaults.FriendlyName, languageId, returnEmptyIfNotFound: true); public int Priority => _cashOnDeliveryPaymentSettings.DisplayOrder; diff --git a/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs b/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs index 7c4b37f678..291178637a 100644 --- a/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs +++ b/src/Plugins/Payments.StripeCheckout/StripeCheckoutPaymentProvider.cs @@ -42,7 +42,7 @@ public StripeCheckoutPaymentProvider( public string FriendlyName => _translationService.GetResource(StripeCheckoutDefaults.FriendlyName); public string GetFriendlyName(string languageId) => - _translationService.GetResource(StripeCheckoutDefaults.FriendlyName, languageId); + _translationService.GetResource(StripeCheckoutDefaults.FriendlyName, languageId, returnEmptyIfNotFound: true); public int Priority => _stripeCheckoutPaymentSettings.DisplayOrder; diff --git a/src/Tests/Grand.Business.Checkout.Tests/Extensions/PaymentExtensionsTests.cs b/src/Tests/Grand.Business.Checkout.Tests/Extensions/PaymentExtensionsTests.cs index a798d5adeb..0570bb140d 100644 --- a/src/Tests/Grand.Business.Checkout.Tests/Extensions/PaymentExtensionsTests.cs +++ b/src/Tests/Grand.Business.Checkout.Tests/Extensions/PaymentExtensionsTests.cs @@ -1,5 +1,6 @@ using Grand.Business.Core.Extensions; using Grand.Business.Core.Interfaces.Checkout.Payments; +using Grand.Domain.Orders; using Grand.Domain.Payments; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -42,4 +43,48 @@ public void IsPaymentMethodActive_NullProvider_ThrowException() var settings = new PaymentSettings(); Assert.ThrowsExactly(() => provider.IsPaymentMethodActive(settings)); } -} \ No newline at end of file + + [TestMethod] + public void GetPaymentMethodName_OrderLanguage_ReturnNameInOrderLanguage() + { + _providerMock.Setup(c => c.FriendlyName).Returns("Request language"); + _providerMock.Setup(c => c.GetFriendlyName("1")).Returns("Order language"); + var order = new Order { CustomerLanguageId = "1", PaymentMethodSystemName = "Payments.Test" }; + Assert.AreEqual("Order language", _providerMock.Object.GetPaymentMethodName(order)); + } + + [TestMethod] + public void GetPaymentMethodName_NoOrderLanguage_ReturnFriendlyName() + { + _providerMock.Setup(c => c.FriendlyName).Returns("Request language"); + var order = new Order { CustomerLanguageId = null, PaymentMethodSystemName = "Payments.Test" }; + Assert.AreEqual("Request language", _providerMock.Object.GetPaymentMethodName(order)); + _providerMock.Verify(c => c.GetFriendlyName(It.IsAny()), Times.Never); + } + + [TestMethod] + public void GetPaymentMethodName_NoTranslation_ReturnFriendlyName() + { + _providerMock.Setup(c => c.FriendlyName).Returns("Request language"); + _providerMock.Setup(c => c.GetFriendlyName("1")).Returns(""); + var order = new Order { CustomerLanguageId = "1", PaymentMethodSystemName = "Payments.Test" }; + Assert.AreEqual("Request language", _providerMock.Object.GetPaymentMethodName(order)); + } + + [TestMethod] + public void GetPaymentMethodName_NoName_ReturnSystemName() + { + _providerMock.Setup(c => c.FriendlyName).Returns(""); + _providerMock.Setup(c => c.GetFriendlyName("1")).Returns(""); + var order = new Order { CustomerLanguageId = "1", PaymentMethodSystemName = "Payments.Test" }; + Assert.AreEqual("Payments.Test", _providerMock.Object.GetPaymentMethodName(order)); + } + + [TestMethod] + public void GetPaymentMethodName_NullProvider_ReturnSystemName() + { + IPaymentProvider provider = null; + var order = new Order { PaymentMethodSystemName = "Payments.Test" }; + Assert.AreEqual("Payments.Test", provider.GetPaymentMethodName(order)); + } +} diff --git a/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs b/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs index 39ae660e9d..6e666dc5b2 100644 --- a/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs +++ b/src/Tests/Grand.Business.Messages.Tests/Commands/GetOrderTokensCommandHandlerTests.cs @@ -1,4 +1,4 @@ -using Grand.Business.Core.Commands.Messages.Tokens; +using Grand.Business.Core.Commands.Messages.Tokens; using Grand.Business.Core.Interfaces.Catalog.Prices; using Grand.Business.Core.Interfaces.Catalog.Products; using Grand.Business.Core.Interfaces.Checkout.GiftVouchers; diff --git a/src/Web/Grand.Web.Vendor/Areas/Vendor/Views/PdfTemplates/OrderPdfTemplate.cshtml b/src/Web/Grand.Web.Vendor/Areas/Vendor/Views/PdfTemplates/OrderPdfTemplate.cshtml index a13dc71806..1b644c3cf7 100644 --- a/src/Web/Grand.Web.Vendor/Areas/Vendor/Views/PdfTemplates/OrderPdfTemplate.cshtml +++ b/src/Web/Grand.Web.Vendor/Areas/Vendor/Views/PdfTemplates/OrderPdfTemplate.cshtml @@ -1,3 +1,4 @@ +@using Grand.Business.Core.Extensions @using Grand.Business.Core.Interfaces.Catalog.Products @using Grand.Business.Core.Interfaces.Checkout.GiftVouchers @using Grand.Business.Core.Interfaces.Checkout.Payments @@ -152,7 +153,7 @@ @((await _countryService.GetCountryById(order.BillingAddress.CountryId))?.Name)

var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(order.PaymentMethodSystemName); - var paymentMethodStr = paymentMethod != null ? paymentMethod.FriendlyName : order.PaymentMethodSystemName; + var paymentMethodStr = paymentMethod.GetPaymentMethodName(order); @(string.Format(_translationService.GetResource("PDFInvoice.PaymentMethod", order.CustomerLanguageId), paymentMethodStr))
@await Component.InvokeAsync("Widget", new { widgetZone = "pdf_payment_method_below", additionalData = order.Id }) diff --git a/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml b/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml index 8c58f982c7..6b42eb2305 100644 --- a/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml +++ b/src/Web/Grand.Web/Views/PdfTemplates/OrderPdfTemplate.cshtml @@ -1,3 +1,4 @@ +@using Grand.Business.Core.Extensions @using Grand.Business.Core.Interfaces.Catalog.Products @using Grand.Business.Core.Interfaces.Checkout.GiftVouchers @using Grand.Business.Core.Interfaces.Checkout.Payments @@ -152,7 +153,7 @@ @((await _countryService.GetCountryById(order.BillingAddress.CountryId))?.Name)

var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(order.PaymentMethodSystemName); - var paymentMethodStr = paymentMethod != null ? paymentMethod.GetFriendlyName(order.CustomerLanguageId) : order.PaymentMethodSystemName; + var paymentMethodStr = paymentMethod.GetPaymentMethodName(order); @(string.Format(_translationService.GetResource("PDFInvoice.PaymentMethod", order.CustomerLanguageId), paymentMethodStr))
@await Component.InvokeAsync("Widget", new { widgetZone = "pdf_payment_method_below", additionalData = order.Id })