Partilhar via


Gerar códigos QR e imprimi-los em recibos para a Arábia Saudita

Nota

A funcionalidade descrita neste artigo destina-se a suportar os requisitos da Fase 1 da implementação da Faturação Eletrónica no Reino da Arábia Saudita. Para obter informações sobre os recursos legados que estão destinados a suportar os requisitos da Fase 2 da implementação de faturação eletrónica no Reino da Arábia Saudita, consulte Gerar e submeter faturas eletrónicas simplificadas para a Arábia Saudita.

Este artigo fornece uma descrição geral da funcionalidade para imprimir códigos QR que estão disponíveis para a Arábia Saudita no Microsoft Dynamics 365 Commerce.

Numa loja associada a uma entidade legal que tenha o seu endereço principal na Arábia Saudita, os utilizadores podem imprimir um código QR no recibo de uma transação de venda a dinheiro ou de encomenda de cliente. O código QR contém as seguintes informações.

Sequência Campo Origem de dados
1 Nome da empresa O nome da entidade legal
2 Número de registo IVA da empresa O número de identificação fiscal da entidade legal
3 Data e hora da transação A data e a hora da transação da loja de revenda
4 Montante total do recebo (incluindo o imposto sobre o valor acrescentado [IVA]) O montante total da transação da loja de revenda
5 Montante total do IVA incluído no recibo O montante de imposto total da transação da loja de revenda

Nota

Quando as transações de encomendas de clientes são criadas, o montante total do recibo é calculado ao adicionar os valores totais de todas as linhas de transações que utilizam o modo de entrega de transporte.

O código QR é gerado ao aplicar a transformação base64 às informações de transação codificadas no formato TLV (Tag-Length-Value). A Zakat, Autoridade Tributária e Aduaneira (ZATCA), fornece ferramentas que podem ser usadas para validar o código QR. Para obter mais informações sobre os requisitos de faturação eletrónica e capacidades de validação de código QR, consulte o Portal de faturação eletrónica da ZATCA.

Configurar códigos QR

Para gerar códigos QR e imprimi-los em recibos para a Arábia Saudita, tem de concluir as tarefas a seguir.

  1. Configurar campos personalizados para que possam ser utilizados em formatos de recibo para recibos de venda.
  2. Configurar formatos de recibo.
  3. Especifique dimensões de código QR em parâmetros do Commerce.
  4. Ativar extensões do Commerce Runtime (CRT).

Configurar campos personalizados para que possam ser utilizados em formatos de recibo para recibos de venda

Pode configurar o texto de idioma e os campos personalizados utilizados nos formatos de recibo do ponto de venda (POS). Na página de Texto do idioma, adicione os seguintes registos para as etiquetas dos campos personalizados para esquemas de recibo. Observe que os valores ID de idioma, ID de texto e Texto mostrados na tabela são apenas exemplos. Pode alterá-los para atender às suas necessidades. No entanto, os valores de ID de texto que usa devem ser exclusivos e devem ser iguais ou superiores a 900001.

ID do idioma ID de texto Texto
pt-PT 900001 Código QR (SA)

Nota

A empresa predefinida do utilizador que cria a configuração de recibo deve ser a mesma entidade legal onde a configuração de texto de idioma é criada. Como alternativa, os mesmos textos de idioma devem ser criados na empresa predefinida do utilizador e na entidade legal da loja para a qual a configuração foi criada.

Na página Campos personalizados, adicione os seguintes registos para os campos personalizados para esquemas de recibo. Observe que os valores de ID de texto de legenda devem corresponder aos valores de ID de texto especificados na página de Texto de idioma .

Nome Tipo ID de texto de legenda
INVOICEQRCODE_SA Recebimento 900001

Configurar formatos de recibo

Para cada formato de recibo necessário, altere o valor do campo Comportamento de impressão para Imprimir sempre.

No estruturador de formatos de recibo, adicione o seguinte campo personalizado à secção Rodapé do recibo. Note que o nome do campo corresponde aos textos de idioma definidos na secção anterior.

  • Código QR (SA) — Este campo imprime o código QR no recibo.

Para obter mais informações sobre como trabalhar com formatos de recibo, consulte Configurar e conceber formatos de recibo.

Especifique dimensões de código QR em parâmetros do Commerce

No separador Parâmetros de configuração da página Parâmetros do Commerce, adicione os seguintes parâmetros de configuração:

  • QrCodeWidth — A largura da imagem do código QR, em pixels. Especifique um valor apropriado para o parâmetro.
  • QrCodeHeight — A altura da imagem do código QR, em pixels. Especifique um valor apropriado para o parâmetro.

Nota

É obrigatório especificar os valores destes parâmetros de configuração para imprimir códigos QR em recibos. O suporte para valores predefinidos dos parâmetros pode ser adicionado em atualizações futuras.

Ativar extensões do CRT

Aviso

Esta funcionalidade de localização não pode ser usada com o novo modelo independente de empacotamento e extensão e o Kit de desenvolvimento de software (SDK) do Commerce. Tem de usar a versão anterior do Retail SDK numa máquina virtual (VM) de programador no Microsoft Dynamics Lifecycle Services (LCS). Para obter informações sobre a caraterísticas de localização para a Arábia Saudita que estão disponíveis no SDK do Commerce, consulte Gerar e submeter faturas eletrónicas simplificadas para a Arábia Saudita

Ambiente de desenvolvimento

Siga estes passos para configurar um ambiente de programação para que possa testar e expandir a funcionalidade de localização.

  1. Encontre o ficheiro de configuração da extensão para CRT:

    • Servidor de Revenda: o ficheiro é chamado de commerceruntime.ext.config e pode ser encontrado na pasta bin\ext na localização do site do Servidor de Revenda dos Serviços de Informação Internet (IIS).
    • CRT Local no POS Moderno: o ficheiro é chamado de CommerceRuntime.MPOSOffline.Ext.config e pode ser encontrado na localização do mediador do cliente do CRT local.
  2. Registe a alteração de CRT no ficheiro de configuração da extensão, conforme mostrado no exemplo a seguir.

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

Ambiente de produção

Siga estes passos para criar pacotes implementáveis que contenham componentes do Commerce e para aplicar esses pacotes num ambiente de produção.

  1. Nos ficheiros de configuração do pacote commerceruntime.ext.config e CommerceRuntime.MPOSOffline.Ext.config na pasta RetailSdk\Assets, adicione as seguintes linhas à secção de composição.

    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ReceiptsSaudiArabia" />
    <add source="assembly" value="Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting" />
    
  2. Abra o Pedido de Comandos MSBuild para o utilitário Visual Studio e execute msbuild na pasta Retail SDK para criar pacotes implementáveis.

  3. Aplique os pacotes através de LCS ou manualmente. Para obter mais informações, consulte a secção Criar pacotes implementáveis.

Quando utiliza uma impressora OPOS (Object Linking and Embedding for Retail POS), poderá ter de implementar personalizações adicionais para suportar requisitos específicos da impressora para a imagem de código QR. Por exemplo, poderá ter de converter a imagem do código QR do formato PNG para o formato BMP. Esta secção mostra um exemplo deste tipo de personalização.

Nota

Este exemplo de personalização foi testado utilizando a impressora OPOS EPSON TM-T88V. Poderá ter de ser modificada para suportar diferentes marcas ou modelos de impressoras.

Siga estes passos para criar uma nova extensão e adicioná-la ao seu ambiente.

  1. Instale o Retail SDK. Para obter mais informações, consulte o Kit de desenvolvimento de software de revenda (SDK).

  2. No Retail SDK, use o código a seguir, com base na sua versão do Commerce para criar um projeto C#, sob a solução CommerceRuntimeSamples.sln em 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>
    

    Também tem de alterar o valor do elemento HintPath para referenciar a biblioteca Microsoft.Dynamics.Commerce.Runtime.ElectronicReporting.dll sob a localização do site do Servidor de Revenda IIS.

  3. Use o código a seguir, com base na sua versão do Commerce, para criar uma classe de extensão.

    /**
     * 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. Nos ficheiros de configuração commerceruntime.ext.config e CommerceRuntime.MPOSOffline.Ext.config na pasta RetailSdk\Assets, adicione as seguintes linhas à secção de composição.

    <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. No ficheiro de configuração pacote Customization.definições de personalização do pacote, na pasta BuildTools, adicione as seguintes linhas para incluir as extensões de CRT nos pacotes implementáveis.

    <ISV_CommerceRuntime_CustomizableFile Include="$(SdkReferencesPath)\Contoso.Commerce.Runtime.QrCodeExtension.dll" />
    
  6. Inicie o Pedido de Comandos MSBuild para o utilitário Visual Studio e execute msbuild na pasta Retail SDK para criar pacotes implementáveis.

  7. Aplique os pacotes através de LCS ou manualmente. Para obter mais informações, consulte a secção Criar pacotes implementáveis.