Udostępnij za pośrednictwem


Generowanie kodów QR i drukowanie ich na paragonach dla Arabii Saudyjskiej

Banknot

Funkcjonalność opisana w tym artykule ma na celu obsługę wymagań fazy 1 wdrożenia fakturowania elektronicznego w Królestwie Arabii Saudyjskiej. Aby uzyskać informacje na temat funkcji, które mają na celu obsługę wymagań fazy 2 implementacji fakturowania elektronicznego w Królestwie Arabii Saudyjskiej, zobacz Generowanie i przesyłanie uproszczonych faktur elektronicznych dla Arabii Saudyjskiej.

Ten artykuł zawiera omówienie funkcji drukowania kodów QR, która jest dostępna dla Arabii Saudyjskiej w Microsoft Dynamics 365 Commerce.

W sklepie połączonym z firmą, której główny adres znajduje się w Arabii Saudyjskiej, użytkownicy mogą wydrukować kod QR na paragonie dla transakcji sprzedaży typu „kasa i przeniesienie” lub zamówienia odbiorcy. Kod QR zawiera następujące informacje.

Kolejność Pole Źródło danych
1 przypada na wpłatę z zysku na rzecz budżetu państwa Nazwa firmy Nazwa firmy
2 Numer rejestracji VAT firmy Numer identyfikacji podatkowej firmy
3 Data i godzina transakcji Data i godzina transakcji sklepu sieci sprzedaży
4 Łączna kwota przychodu (w tym podatek od towarów i usług [VAT]) Łączna kwota transakcji sklepu sieci sprzedaży
5 Łączna kwota podatku VAT uwzględniona w paragonie Łączna kwota podatku od transakcji w sklepie sieci sprzedaży

Banknot

Podczas tworzenia transakcji zamówienia odbiorcy łączna kwota przyjęcia jest obliczana przez dodanie łącznych kwot ze wszystkich wierszy transakcji, w których jest używana metoda dostawy na wynos.

Kod QR jest generowany przez zastosowanie transformacji base64 do informacji o transakcji zakodowanych w formacie Tag-Length-Value (TLV). Zakat, Urząd Podatkowy i Celny (ZATCA) zapewnia narzędzia, których można użyć do walidacji kodu QR. Aby uzyskać więcej informacji na temat wymagań dotyczących fakturowania elektronicznego i możliwości sprawdzania poprawności kodów QR, zobacz Portal fakturowania elektronicznego firmy ZATCA.

Konfigurowanie kodów QR

Aby wygenerować kody QR i wydrukować je na paragonach dla Arabii Saudyjskiej, należy wykonać następujące zadania.

  1. Skonfiguruj pola niestandardowe tak, aby mogły być używane w formatach paragonów dla paragonów sprzedaży.
  2. Konfigurowanie formatów paragonów.
  3. Określ wymiary kodu QR w parametrach rozwiązania Commerce.
  4. Włącz rozszerzenia środowiska uruchomieniowego Commerce Runtime(CRT).

Konfigurowanie pól niestandardowych, aby można było ich używać w formatach paragonów dla paragonów sprzedaży

Można skonfigurować język, tekst i pola niestandardowe używane w formatach paragonów w punkcie sprzedaży (POS). Na stronie Tekst w języku dodaj wymienione poniżej rekordy dla etykiet pól niestandardowych używanych w układach paragonów. Pamiętaj, że wartości Identyfikatora języka, Identyfikatora tekstu i Tekst przedstawione w poniższej tabeli są tylko przykładami. Można je zmienić, aby spełniały wymagania użytkownika. Jednak używane wartości identyfikatora tekstu muszą być unikatowe i muszą być równe lub wyższe niż 900001.

Identyfikator języka Identyfikator tekstu Tekst
pl 900001 Kod QR (SA)

Banknot

Domyślna firma użytkownika, który tworzy konfigurację paragonu, powinna być tą samą osobowością prawną, w której jest tworzone ustawienie tekstu w języku. Alternatywnie, można również utworzyć ten sam tekst językowy w domyślnej firmie użytkownika i dla tego samego bytu prawnego, dla którego utworzono konfigurację.

Na stronie Pola niestandardowe dodaj następujące rekordy dla pól niestandardowych używanych w układach paragonów. Pamiętaj, że wartości Identyfikatora tekstu podpisu muszą być zgodne z wartościami Identyfikatora tekstu określonymi na stronie Tekst w danym języku.

Nazwa Typ Identyfikator tekstu podpisu
INVOICEQRCODE_SA Pokwitowanie 900001

Konfiguracja formatów paragonów

Dla każdego wymaganego formatu paragonu zmień wartość pola Zachowanie drukowania na Zawsze drukuj.

W projektancie formatu paragonu dodaj następujące pole niestandardowe do sekcji Stopka paragonu. Pamiętaj, że nazwy pól muszą odpowiadać tekstom w języku zdefiniowanym w poprzedniej sekcji.

  • Kod QR (SA) – w tym polu drukowany jest kod QR na paragonie.

Aby uzyskać więcej informacji na temat pracy z formatami paragonów, zobacz Konfigurowanie i projektowanie formatów paragonów.

Określanie wymiarów kodu QR w parametrach rozwiązania Commerce

Na karcie Parametry konfiguracji na stronie Parametry rozwiązania Commerce dodaj następujące parametry konfiguracji:

  • QrCodeWidth — szerokość obrazu kodu QR w pikselach. Określ odpowiednią wartość parametru.
  • QrCodeHeight — wysokość obrazu kodu QR w pikselach. Określ odpowiednią wartość parametru.

Banknot

Podanie wartości tych parametrów konfiguracyjnych jest obowiązkowe w celu drukowania kodów QR w paragonach. Obsługa domyślnych wartości parametrów może zostać dodana w przyszłych aktualizacjach.

Włączanie rozszerzeń CRT

Ostrzeżenie

Tej funkcji lokalizacji nie można używać z nowym, niezależnym modelem pakowania i rozszerzania oraz zestawem SDK (Commerce Software Development Kit). Musisz użyć poprzedniej wersji zestawu Retail SDK na maszynie wirtualnej dewelopera w usłudze Microsoft Dynamics Lifecycle Services (LCS). Aby uzyskać informacje o funkcjach lokalizacji dla Arabii Saudyjskiej, które są dostępne w zestawie SDK do Commerce, zobacz Generowanie i przesyłanie uproszczonych faktur elektronicznych dla Arabii Saudyjskiej

Środowisko projektowe

Wykonaj poniższe kroki, aby skonfigurować środowisko projektowe, aby móc testować i rozszerzać funkcje lokalizacji.

  1. Znajdź plik konfiguracji rozszerzenia dla kolekcji CRT:

    • Retail Server: Plik nosi nazwę commerceruntime.ext.config i można go znaleźć w folderze bin\ext w lokalizacji witryny Internet Information Services (IIS) Retail Server.
    • Lokalnie CRT w Modern POS: Plik nosi nazwę CommerceRuntime.MPOSOffline.Ext.config i można go znaleźć w lokalizacji lokalnego CRT brokera klienta.
  2. Zarejestruj CRT zmianę w pliku konfiguracji rozszerzenia, jak pokazano w poniższym przykładzie.

    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    

Środowisko produkcyjne

Wykonaj następujące kroki, aby utworzyć możliwe do wdrożenia pakiety, które zawierają składniki Commerce i aby stosować te pakiety w środowisku produkcyjnym.

  1. W plikach konfiguracji pakietu commerceruntime.ext.config i CommerceRuntime.MPOSOffline.Ext.config w folderze RetailSdk\Assets dodaj następujące wiersze do sekcji kompozycji .

    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    
  2. Otwórz wiersz polecenia programu MSBuild dla Visual Studio narzędzia i uruchom program msbuild w folderze Retail SDK, aby utworzyć pakiety wdrażalne.

  3. Zastosuj pakiety za pośrednictwem usługi LCS lub ręcznie. Aby uzyskać więcej informacji, zobacz Tworzenie wdrażalnych pakietów.

W przypadku korzystania z drukarki OPOS (Object Linking and Embedding for Retail POS) może być konieczne wdrożenie dodatkowych dostosowań w celu spełnienia specyficznych dla drukarki wymagań dotyczących obrazu kodu QR. Na przykład może być konieczne przekonwertowanie obrazu kodu QR z formatu PNG na format BMP. W tej sekcji przedstawiono przykład tego typu dostosowań.

Banknot

Ten przykład personalizacji został przetestowany przy użyciu drukarki EPSON TM-T88V OPOS. Może być konieczne zmodyfikowanie go w celu obsługi różnych marek lub modeli drukarek.

Wykonaj poniższe kroki, aby utworzyć nowe rozszerzenie i dodać je do środowiska.

  1. Zainstaluj zestaw SDK do Retail SDK. Aby uzyskać więcej informacji, zobacz Zestaw SDK (Retail Software Development Kit).

  2. W zestawie SDK do Retail użyj poniższego kodu, na podstawie wersji Commerce, aby utworzyć projekt w języku C# w ramach rozwiązania CommerceRuntimeSamples.sln w zestawie RetailSdk\SampleExtensions\CommerceRuntime.

    <Project Sdk="Microsoft.NET.Sdk">
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.props" />
        <Import Project="..\..\..\BuildTools\Common.props" />
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.settings" />
    
        <PropertyGroup>
            <TargetFramework>netstandard2.0</TargetFramework>
            <AssemblyName>$(AssemblyNamePrefix).Commerce.Runtime.QrCodeExtension</AssemblyName>
            <RootNamespace>Contoso.Commerce.Runtime.QrCodeExtension</RootNamespace>
            <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
        </PropertyGroup>
    
        <Import Project="..\..\..\BuildTools\Microsoft.Dynamics.RetailSdk.Build.targets" />
    
        <ItemGroup>
            <PackageReference Include="Microsoft.Dynamics.Commerce.Runtime.Framework" Version="$(FrameworkRepoPackagesVersion)" />
            <PackageReference Include="Microsoft.Dynamics.Commerce.Runtime.Services.Messages" Version="$(ChannelRepoPackagesVersion)" />
            <PackageReference Include="System.Drawing.Common" Version="4.7.0" />
        </ItemGroup>
    
        <ItemGroup>
            <Reference Include="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting">
                <HintPath>..\..\..\..\..\nuget packages\microsoft.dynamics.commerce.runtime.electronicreporting.9.35.21321.4\lib\netstandard2.0\Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting.dll</HintPath>
            </Reference>
        </ItemGroup>
    
        <ItemGroup>
            <Folder Include="Properties\" />
        </ItemGroup>
    </Project>
    

    Należy również zmienić wartość elementu HintPath , aby odwoływał się do pliku Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting.DLL w lokalizacji witryny usługi IIS Retail Server.

  3. Użyj poniższego kodu, opartego na wersji rozwiązania Commerce, aby utworzyć klasę rozszerzenia.

    /**
     * SAMPLE CODE NOTICE
     * 
     * THIS SAMPLE CODE IS MADE AVAILABLE AS IS. MICROSOFT MAKES NO WARRANTIES, WHETHER EXPRESS OR IMPLIED,
     * OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OR CONDITIONS OF MERCHANTABILITY.
     * THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS SAMPLE CODE REMAINS WITH THE USER.
     * NO TECHNICAL SUPPORT IS PROVIDED. YOU MAY NOT DISTRIBUTE THIS CODE UNLESS YOU HAVE A LICENSE AGREEMENT WITH MICROSOFT THAT ALLOWS YOU TO DO SO.
     */
    
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    
    namespace Contoso
    {
        namespace Commerce.Runtime.QrCodeExtension
        {
            using System;
            using System.Collections.Generic;
            using System.Threading.Tasks;
            using Microsoft.Dynamics.Commerce.Runtime;
            using Microsoft.Dynamics.Commerce.Runtime.Messages;
            using Microsoft.Dynamics.Commerce.Runtime.Services.Messages;
    
            /// <summary>
            /// The extension for QR code printing.
            /// </summary>
            internal class QrCodeServiceExtension : IRequestHandlerAsync
            {
                /// <summary>
                /// Printer horizontal resolution for image.
                /// </summary>
                private const float PrinterXDpi = 60f;
    
                /// <summary>
                /// Printer vertical resolution for image.
                /// </summary>
                private const float PrinterYDpi = 90f;
    
                /// <summary>
                /// Printer pixel format for image.
                /// </summary>
                private const PixelFormat PrinterPixelFormat = PixelFormat.Format8bppIndexed;
    
                /// <summary>
                /// Gets the collection of supported request types by this service.
                /// </summary>
                public IEnumerable<Type> SupportedRequestTypes
                {
                    get => new[] {typeof(EncodeQrCodeServiceRequest)};
                }
    
                /// <summary>
                /// Processes the request.
                /// </summary>
                /// <param name="request">The request.</param>
                /// <returns>The response.</returns>
                public async Task<Response> Execute(Request request)
                {
                    ThrowIf.Null(request, nameof(request));
    
                    switch (request)
                    {
                        case EncodeQrCodeServiceRequest encodeQrCodeServiceRequest:
                        {
                            EncodeQrCodeServiceResponse nextResponse = await this.ExecuteNextAsync<EncodeQrCodeServiceResponse>(encodeQrCodeServiceRequest).ConfigureAwait(false);
    
                            if (nextResponse != null)
                            {
                                var qrCodeBmp = string.IsNullOrWhiteSpace(nextResponse.QRcode) ? nextResponse.QRcode : ConvertToGenericCompatibilityImage(nextResponse.QRcode);
                                return new EncodeQrCodeServiceResponse(qrCodeBmp);
                            }
    
                            return nextResponse;
                        }
                    }
    
                    return new NotHandledResponse();
                }
    
                /// <summary>
                /// Converts QR code image from any format to compatible with printer.
                /// </summary>
                /// <param name="base64data">Base64 image.</param>
                /// <returns>Image that Compatible with printer.</returns>
                private static string ConvertToGenericCompatibilityImage(string base64data)
                {
                    string convertedQrCode = base64data;
                    byte[] imageBytes = Convert.FromBase64String(convertedQrCode);
                    using (MemoryStream msOriginal = new MemoryStream(imageBytes))
                    using (MemoryStream msConverted = new MemoryStream())
                    {
                        var bitmapOriginal = new Bitmap(msOriginal);
                        if (!IsFormatCompatible(bitmapOriginal) || !AreResolutionAndPixelFormatCompatible(bitmapOriginal))
                        {
                            var bitmapConverted = bitmapOriginal;
    
                            if (!AreResolutionAndPixelFormatCompatible(bitmapOriginal))
                            {
                                var rectangle = new Rectangle(0, 0, bitmapOriginal.Width, bitmapOriginal.Height);
                                bitmapConverted = bitmapOriginal.Clone(rectangle, PrinterPixelFormat);
                                bitmapConverted.SetResolution(PrinterXDpi, PrinterYDpi);
                            }
    
                            bitmapConverted.Save(msConverted, ImageFormat.Bmp);
                        }
    
                        convertedQrCode = Convert.ToBase64String(msConverted.ToArray());
                    }
    
                    return convertedQrCode;
                }
    
                /// <summary>
                /// Verifies if the resolution and pixel format of bitmap are compatible with printer requirements.
                /// </summary>
                /// <param name="source">Bitmap.</param>
                /// <returns>True if compatible; otherwise false.</returns>
                private static bool AreResolutionAndPixelFormatCompatible(Bitmap source)
                {
                    return source.VerticalResolution == PrinterYDpi &&
                           source.HorizontalResolution == PrinterXDpi &&
                           source.PixelFormat == PrinterPixelFormat;
                }
    
                /// <summary>
                /// Verifies if the format of bitmap is compatible with printer requirements.
                /// </summary>
                /// <param name="source">Bitmap.</param>
                /// <returns>True if compatible; otherwise false.</returns>
                private static bool IsFormatCompatible(Bitmap source)
                {
                    return source.RawFormat.Equals(ImageFormat.Bmp);
                }
            }
        }
    }
    
  4. W plikach konfiguracyjnych commerceruntime.ext.config i CommerceRuntime.MPOSOffline.Ext.config w folderze RetailSdk\Assets dodaj następujące wiersze do sekcji kompozycji .

    <add source="assembly" value="Contoso.Commerce.Runtime.QrCodeExtension" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    
  5. W pliku konfiguracji dostosowywania pakietu Customization.settings w folderze BuildTools dodaj następujące wiersze, aby uwzględnić CRT rozszerzenia w pakietach, które można wdrożyć.

    <ISV_CommerceRuntime_CustomizableFile Include="$(SdkReferencesPath)\Contoso.Commerce.Runtime.QrCodeExtension.dll" />
    
  6. Uruchom wiersz polecenia MSBuild dla Visual Studio i uruchom msbuild w folderze Retail SDK, aby utworzyć pakiety, które można wdrożyć.

  7. Zastosuj pakiety za pośrednictwem usługi LCS lub ręcznie. Aby uzyskać więcej informacji, zobacz Tworzenie wdrażalnych pakietów.