Compartilhar via


Integração da Faturação eletrónica na Arábia Saudita

A integração é obrigatória para todos os contribuintes sujeitos a faturação eletrónica na Arábia Saudita. Como resultado do processo de integração, os contribuintes obtêm Identificadores de Selo Criptográfico (CSIDs). Os CSIDs são necessários para a integração com o portal faturação eletrónica que é gerenciado pela autoridade tributária da Arábia Saudita (ZATCA) e para o envio posterior de faturas eletrônicas.

Isto artigo explica como integrar os contribuintes e o seu software faturação eletrónica com as autoridades fiscais da Arábia Saudita.

Pré-requisitos

  • A entidade jurídica deve estar registada como contribuinte na Arábia Saudita e deve ter um número de registo válido para o imposto sobre o valor acrescentado (IVA).
  • A pessoa coletiva deve ter acesso ao Portal de Tributação da Arábia Saudita (ERAD).

Processo de integração

O processo de integração consiste em duas etapas:

  1. Obter um CSID de conformidade (CCSID), que a ZATCA atribui para realizar verificações de conformidade de soluções de geração de faturas eletrônicas (EGSs).
  2. Obtenha um CSID de produção (PCSID), que a ZATCA atribui a EGSs compatíveis.

Fluxo de trabalho de integração.

Obter um CCSID

  1. No Portal de Tributação da Arábia Saudita (ERAD), vá para o Portal de integração e gerenciamento selecionando o bloco relevante.

  2. Na página de destino principal do Portal de Gestão e Integração, selecione o mosaico Integrar nova unidade de solução/dispositivo e, em seguida, selecione Gerar código OTP. O código OTP só é válido durante uma hora após ser gerado. Certifique-se de que é utilizado dentro desse período de tempo.

  3. Selecione o número de códigos de senha de uso único (OTP) para gerar. O número depende do número de unidades de geração (dispositivos) de faturação eletrónica que serão utilizadas.

  4. Salve os códigos OTP gerados para que você possa usá-los em etapas posteriores.

  5. Prepare um ficheiro de configuração para a solicitação de assinatura de certificado. Esse ficheiro de configuração deve estar na forma de um ficheiro de texto sem formatação que contenha os seguintes dados.

    oid_section = OIDs
    [OIDs]
    certificateTemplateName = 1.3.6.1.4.1.311.20.2
    [req]
    default_bits = 2048
    emailAddress = MyEmail@email.com
    req_extensions = v3_req
    x509_extensions = v3_ca
    prompt = no
    default_md = sha 256
    req_extensions = req_ext
    distinguished_name = dn
    [dn]
    C=SA
    OU=Riyad Branch
    O=Contoso
    CN=EA123456789
    [v3_req]
    basicConstraints = CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment
    [req_ext]
    certificateTemplateName = ASN1:PRINTABLESTRING:ZATCA-Code-Signing
    subjectAltName = dirName:alt_names
    [alt_names]
    SN=1-TST|2-TST|3-ed22f1d8-e6a2-1118-9b58-d9a8f11e445f
    UID=310122393500003
    title=1100
    registeredAddress= MyAddress
    businessCategory=Industry
    
  6. Salve o ficheiro no mesmo local do script de integração com o nome,csr_config.txt .

  7. No ficheiro de configuração, atualize o valor emailAddress e os seguintes dados específicos.

    Código Descrição Especificação
    C O código do país/região. Um código de duas letras (ISO 3166 Alpha-2)
    UO O nome da unidade organizacional. Para os contribuintes normais, o valor é de texto livre. Para grupos de IVA, identifique o valor através do décimo primeiro dígito do identificador da organização que é "1". Valide se a entrada é um Número de Identificação Fiscal (NIF) de 10 dígitos.
    O O nome da organização ou contribuinte. Texto livre
    NC O nome exclusivo da solução ou unidade. Texto livre
    SN O código de identificação único da solução. Texto livre
    UID O número de contribuinte para efeitos de IVA. Quinze dígitos. Isto número começa com "3" e termina com "3".
    título O tipo de documento que a unidade de solução do contribuinte emitirá. Entrada numérica de quatro dígitos que usa "0" e "1" mapeados para "TSCZ": 0 = False/Não suportado, 1 = True/Supported. T = Fatura fiscal (padrão), S = Fatura fiscal simplificada, C = Para uso futuro, Z = Para uso futuro.
    Endereço registado O endereço da filial ou local onde o dispositivo ou unidade de solução está principalmente situado. Texto livre
    negócioCategoria A indústria ou setor para o qual o dispositivo ou solução irá gerar faturas. Texto livre

    Nota

    Os valores para CN e certificateTemplateName no ficheiro de configuração são diferentes quando você usa o portal de simulação.

    No portal de simulação:

    • CN - PREZATCA-Assinatura de Código
    • certificateTemplateName - ASN1:PRINTABLESTRING:PREZATCA-Code-Signing

    Para qualquer outro caso, utilize os valores conforme as instruções acima.

  8. Execute o script de integração fornecido posteriormente neste artigo. Especifique a OTP e o ficheiro de configuração como parâmetros de entrada. Aqui está um exemplo: Script tem dois possíveis endpoints simulação e prod.

    .\OnboardingScript.ps1 -action getComplianceCSID -endpoint prod -otp 123345 -csrconfig .\csr_config.txt -password 123

    Nota

    O parâmetro password é opcional e pode ser omitido. Se estiver incluído, o certificado gerado terá a senha especificada.

  9. O CCSID é recebido como um ficheiro de certificado "CCSID.pfx", e o segredo para CCSID é salvo como ficheiro txt "CCSIDSecret.txt". Salve isto ficheiro de certificado CCSID no certificado do cofre de Microsoft Azure chaves e salve o segredo no Microsoft Azure segredo do cofre de chaves. Para obter mais informações, consulte Certificados e segredos de cliente.

  10. Configure a configuração do recurso relacionado no recurso de verificação de conformidade (SA) ZATCA da Arábia Saudita faturação eletrónica e faça referência ao certificado CCSID que você salvou no cofre de chaves. O certificado será utilizado para comunicação com o portal ZATCA faturação eletrónica.

Verificação da conformidade

Depois de obter o CSID de conformidade usando o script PowerShell, o ZATCA exige que você conclua determinadas verificações de conformidade enviando faturas de exemplo. Isto passo é um pré-requisito para solicitar um CSID de produção.

Certifique-se de que todos os tipos de faturas de exemplo que foram configuradas no ficheiro de configuração CSR (Solicitação de Assinatura de Certificado) sejam enviados com êxito ao ZATCA. Utilize o processo padrão de emissão de faturas eletrónicas. Para obter mais detalhes, consulte Emitir faturas eletrônicas no Finance and cadeia de fornecimento Management.

Utilize a funcionalidade "Saudi Arabian ZATCA compliance check (SA)" no RCS e siga os passos da secção Configuração específica do país/região utilizando o CSID de conformidade que obteve.

Depois que as verificações de conformidade forem concluídas com êxito, use o script PowerShell para obter o CSID de produção (consulte o script de integração).

Nota

No campo Título , se o tipo de documento do ficheiro de configuração estiver definido como 1000, três faturas de exemplo deverão ser enviadas para a verificação de conformidade:

  • Fatura fiscal padrão
  • Nota de débito padrão
  • Nota de crédito padrão

No campo Título , se o tipo de documento do ficheiro de configuração estiver definido como 0100, três faturas de exemplo deverão ser enviadas para a verificação de conformidade:

  • Fatura fiscal simplificada
  • Nota de débito simplificada
  • Nota de Crédito Simplificada

Se o tipo de documento estiver definido como 1100, todas as seis faturas de amostra deverão ser enviadas para a verificação de conformidade.

Obter um PCSID

Para obter um PCSID, você deve configurar corretamente a solução para geração e envio de fatura eletrônica, e a solução deve estar em pleno funcionamento. Para obter esse resultado, você deve concluir todas as etapas de configuração preliminares necessárias. Para obter mais informações, consulte Introdução ao faturação eletrónica para a Arábia Saudita.

  1. Certifique-se de que todas as faturas eletrónicas são submetidas com sucesso à ZATCA.

  2. Execute o script de integração fornecido posteriormente neste artigo. Especifique o CCSID como um parâmetro de entrada. Aqui está um exemplo: Script tem dois possíveis endpoints simulation & prod

    .\OnboardingScript.ps1 -action getProductionCSID -endpoint prod -password 123

    Nota

    O parâmetro password é opcional e pode ser omitido. Se estiver incluído, o certificado gerado terá a senha especificada.

  3. O PCSID é recebido como um ficheiro de certificado no formato PFX. Salve isto certificado PCSID e ficheiro secreto no cofre de chaves Azure.

  4. Configure a configuração do recurso relacionado no recurso faturação eletrónica Zatca (SA) da Arábia Saudita. Inclua o certificado PCSID e o segredo nos parâmetros do cofre de chaves no RCS.

Depois de concluir todas as etapas de configuração, o sistema estará pronto para ser utilizado no modo de produção.

Para revisar os CSIDs obtidos no lado ZATCA, use o bloco Revisar Identificador de Selo Criptográfico (CSID) existente na página de destino do Portal de Integração e Gerenciamento. Isto portal pode ser acessado a partir do principal Portal de Tributação da Arábia Saudita (ERAD).

Script de integração

Nota

Os scripts de exemplo não são suportados em nenhum programa ou serviço de suporte padrão Microsoft. Os scripts de exemplo são fornecidos no estado em que se encontram sem qualquer tipo de garantia. Microsoft renuncia ainda a todas as garantias implícitas, incluindo, sem limitação, quaisquer garantias implícitas de comercialização ou de adequação a uma finalidade específica. Todo o risco decorrente do uso ou desempenho dos scripts de exemplo e da documentação permanece com você. Em nenhum caso a Microsoft, seus autores ou qualquer outra pessoa envolvida na criação, produção ou entrega dos scripts serão responsáveis por quaisquer danos (incluindo, sem limitação, danos por perda de lucros comerciais, interrupção de negócios, perda de informações comerciais ou outras perdas pecuniárias) decorrentes do uso ou incapacidade de usar os scripts de amostra ou documentação, mesmo que Microsoft tenha sido avisado da possibilidade de tais danos.

  1. Use o seguinte script PowerShell do Windows para obter um CCSID e um PCSID.

    #Saudi Arabian electronic invoice onboarding script
     #Version 1.1
     param($action, $endpoint, $otp, $csrconfig, $password)
     $env:path = $env:path + ";C:\Program Files\Git\usr\bin"
    
     $simulationEndpoint = 'https://gw-fatoora.zatca.gov.sa/e-invoicing/simulation'
     $prodEndpoint = 'https://gw-fatoora.zatca.gov.sa/e-invoicing/core'
    
     if ($endpoint -eq "simulation")
     {
     	$serviceEndpoint = $simulationEndpoint
     } elseif ($endpoint -eq "prod") {
     	$serviceEndpoint = $prodEndpoint
     } else {
     	Write-Host "`nMissing parameter (with values simulation/prod): endpoint"
     	Break
     }
    
     if ($action -eq "getComplianceCSID")
     {
     	if (-not (Test-Path -Path $csrconfig))
     	{
     		throw "CSR configuration file does not exist, please make sure to provide a valid file path for the '-csrconfig' parameter."
     	}
    
     	if ($otp -eq $null)
     	{
     		throw "OTP code is not provided, please carry correct parameters."
     	}
    
     	#Generate private key
     	openssl ecparam -name secp256k1 -genkey -noout -out privatekey.pem
     	Write-Host "Private key generated."
    
     	#Generate public key
     	openssl ec -in privatekey.pem -pubout -conv_form compressed -out publickey.pem
     	Write-Host "Public key generated."
    
     	#Generate CSR(Certificate signing request)
     	openssl base64 -d -in publickey.pem -out publickey.bin
     	openssl req -new -sha256 -key privatekey.pem -extensions v3_req -config $csrconfig -out .\taxpayer.csr 
     	openssl base64 -in taxpayer.csr -out taxpayerCSRbase64Encoded.txt
     	$CSRbase64Encoded = Get-Content -path taxpayerCSRbase64Encoded.txt -Raw
     	$CSRbase64Encoded = $CSRbase64Encoded -replace "`n",""
     	$CSRbase64Encoded = $CSRbase64Encoded -replace "`r",""
    
     	#Init request for CCSID
     	$postParams = @{"csr"=$CSRbase64Encoded} | ConvertTo-Json
     	$postHeader = @{
     		   "Accept"="application/json"
     		   "OTP"=$otp
     		   "Content-Type"="application/json"
     		   "Accept-Version"="V2"}
     	echo $CSRbase64Encoded
     	try
     	{
     		$response = Invoke-WebRequest -Uri $serviceEndpoint'/compliance' -Method POST -Body $postParams -Headers $postHeader 
     	}
     	catch
     	{
     		$respStream = $_.Exception.Response.GetResponseStream()
     		$reader = New-Object System.IO.StreamReader($respStream)
     		$respBody = $reader.ReadToEnd()
     		$reader.Close()
    
     		Write-Host "`nZatca service communication error:"
     		Write-Host $_.Exception.Message
     		Write-Host "Detailed error message: " $respBody
     		Write-Host "The process of obtaining a Compliance CSID (CCSID) is interrupted."
     	}
    
     	if ($response -ne $null)
     	{
     		$response = $response | ConvertFrom-Json
     		$requestId = $response.requestID
     		Write-Host "Request ID:"
     		Write-Host $requestId
     		$requestId | Out-File -FilePath .\requestId.txt -Encoding utf8 -NoNewline
    
     		$CCSIDbase64 = $response.binarySecurityToken
     		Write-Host "`nCompliance CSID received from Zatca:"
     		Write-Host $CCSIDbase64
     		$CCSID = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($CCSIDbase64))
     		$CCSIDCertString = "-----BEGIN CERTIFICATE-----`n" + $CCSID + "`n" + "-----END CERTIFICATE-----"
    
     		$CCSIDSecret = $response.secret
     		Write-Host "`nCompliance CSID secret received from Zatca:"
     		Write-Host $CCSIDSecret
    
     		$CCSIDStringFileName = "CCSIDString.txt"
     		$CCSIDSecretFileName = "CCSIDSecret.txt"
     		$CCSIDCertFileName = "CCSID.pem"
     		$CCSIDFolderPath = Get-Location
     		$CCSIDCertFilePath = Join-Path $CCSIDFolderPath $CCSIDCertFileName
     		$CCSIDStringFilePath = Join-Path $CCSIDFolderPath $CCSIDStringFileName
     		$CCSIDSecretFilePath = Join-Path $CCSIDFolderPath $CCSIDSecretFileName
    
     		$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
     		[System.IO.File]::WriteAllLines($CCSIDCertFilePath, $CCSIDCertString, $Utf8NoBomEncoding)
     		[System.IO.File]::WriteAllLines($CCSIDStringFilePath, $CCSIDbase64, $Utf8NoBomEncoding)
     		[System.IO.File]::WriteAllLines($CCSIDSecretFilePath, $CCSIDSecret, $Utf8NoBomEncoding)
    
     		openssl pkcs12 -inkey privatekey.pem -in CCSID.pem -export -passout pass:$password -out CCSID.pfx
     		Write-Host "`nCertificate is saved to CCSID.pfx file and secret is saved to CCSIDSecret.txt file."
     		Write-Host "The process of obtaining a Compliance CSID (CCSID) is complete, please process the compliance check and do not delete or move any created files before getting PCSID."
     	}
    
     }
    
    
     if ($action -eq "getProductionCSID")
     {
     	if (-not (Test-Path -Path requestId.txt))
     	{
     		throw "'requestId.txt' file is missing, please make sure you're running the script in the same location where the results of getting the CCSID are stored."
     	}
     	if (-not (Test-Path -Path CCSIDString.txt))
     	{
     		throw "'CCSIDString.txt' file is missing, please make sure you're running the script in the same location where the results of getting the CCSID are stored."
     	}
     	if (-not (Test-Path -Path CCSIDSecret.txt))
     	{
     		throw "'CCSIDSecret.txt' file is missing, please make sure you're running the script in the same location where the results of getting the CCSID are stored."
     	}
    
     	$requestId = Get-Content -path requestId.txt -Raw
     	$requestId = $requestId -replace "`n",""
     	$requestId = $requestId -replace "`r",""
     	Write-Host "Request ID is:" $requestId
     	$CCSID = Get-Content -path CCSIDString.txt -Raw
     	$CCSID = $CCSID -replace "`n",""
     	$CCSID = $CCSID -replace "`r",""
     	Write-Host "`nCompliance CSID read locally:"
     	Write-Host $CCSID
     	$CCSIDSecretString = Get-Content -path CCSIDSecret.txt -Raw
     	$CCSIDSecretString = $CCSIDSecretString -replace "`n",""
     	$CCSIDSecretString = $CCSIDSecretString -replace "`r",""
     	Write-Host "`nCompliance CSID secret read locally:"
     	Write-Host $CCSIDSecretString
     	$AuthTokenString = $CCSID + ":" + $CCSIDSecretString
     	$BasicAuthToken = "Basic " + [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($AuthTokenString))
    
     	#Init request for Production CSID (PCSID)
     	$postParams = @{"compliance_request_id"=$requestId} | ConvertTo-Json
     	$postHeader = @{
     		   "Accept"="application/json"
     		   "Authorization"=$BasicAuthToken
     		   "Content-Type"="application/json"
     		   "Accept-Version"="V2"}
    
     	try
     	{
     		$response = Invoke-WebRequest -Uri $serviceEndpoint'/production/csids' -Method POST -Body $postParams -Headers $postHeader
     	}
     	catch
     	{
     		$respStream = $_.Exception.Response.GetResponseStream()
     		$reader = New-Object System.IO.StreamReader($respStream)
     		$respBody = $reader.ReadToEnd()
     		$reader.Close() 
    
     		Write-Host "`nZatca service communication error:"
     		Write-Host $_.Exception.Message
     		Write-Host "Detailed error message: " $respBody 
     		Write-Host "Please make sure the compliance check process has been done before obtaining a Production CSID (PCSID)."
     		Write-Host "The process of obtaining a Production CSID (PCSID) is interrupted."
     	}
    
     	if ($response -ne $null)
     	{
     		$response = $response | ConvertFrom-Json
     		$PCSIDbase64 = $response.binarySecurityToken
     		Write-Host "`nProduction CSID received from Zatca:"
     		Write-Host $PCSIDbase64
    
     		$PCSID = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($PCSIDbase64))
     		$PCSIDCertString = "-----BEGIN CERTIFICATE-----`n" + $PCSID + "`n" + "-----END CERTIFICATE-----"
    
     		$PCSIDSecret = $response.secret
     		Write-Host "`nProduction CSID secret received from Zatca:"
     		Write-Host $PCSIDSecret
    
     		$PCSIDCertFileName = "PCSID.pem"
     		$PCSIDSecretFileName = "PCSIDSecret.txt"
     		$PCSIDFolderPath = Get-Location
     		$PCSIDCertFilePath = Join-Path $PCSIDFolderPath $PCSIDCertFileName
     		$PCSIDSecretFilePath = Join-Path $PCSIDFolderPath $PCSIDSecretFileName
    
     		$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
     		[System.IO.File]::WriteAllLines($PCSIDCertFilePath, $PCSIDCertString, $Utf8NoBomEncoding)
     		[System.IO.File]::WriteAllLines($PCSIDSecretFilePath, $PCSIDSecret, $Utf8NoBomEncoding)
    
     		# Sandbox API will get error: openssl : No certificate matches private key
     		openssl pkcs12 -inkey privatekey.pem -in PCSID.pem -export -passout pass:$password -out PCSID.pfx
    
     		if (Test-Path -Path PCSID.pfx)
     		{
     			Write-Host "`nCertificate is saved to PCSID.pfx file and secret is saved to PCSIDSecret.txt file."
     			Write-Host "The process of obtaining a Production CSID (PCSID) is complete."
     		}
     		else
     		{
     			Write-Host "`nThe process of obtaining a Production CSID (PCSID) is interrupted."
     		}
     	}
     }
    
  2. Salve o ficheiro de certificado .pfx de saída recebido no cofre de chaves.

Recursos adicionais