Freigeben über


Onboarding für elektronische Rechnungsstellung in Saudi-Arabien

Das Onboarding ist für alle Steuerzahler obligatorisch, die in Saudi-Arabien der Elektronische Fakturierung unterliegen. Als Ergebnis des Onboarding-Prozesses erhalten Steuerzahler Cryptographic Stamp Identifiers (CSIDs). CSIDs werden für die Integration mit dem von der saudi-arabischen Steuerbehörde (ZATCA) verwalteten Portal Lieferkette und für die weitere Übermittlung elektronischer Rechnungen benötigt.

In diesem Artikel wird erläutert, wie Steuerzahler und ihre Elektronische Fakturierung-Software bei den saudi-arabischen Steuerbehörden registriert werden.

Erforderliche Komponenten

  • Die juristische Person muss in Saudi-Arabien als Steuerzahler registriert sein und über eine gültige Umsatzsteuer-Identifikationsnummer verfügen.
  • Die juristische Person muss Zugriff auf das Saudi Arabian Taxation Portal (ERAD) haben.

Onboarding-Prozess

Der Onboardingprozess besteht aus zwei Schritten:

  1. Erhalten Sie eine Compliance CSID (CCSID), die von ZATCA zugewiesen wird, um Konformitätsprüfungen von Lösungen zur elektronischen Rechnungserstellung (EGSs) durchzuführen.
  2. Erhalten Sie eine Produktions-CSID (PCSID), die ZATCA konformen EGSs zuweist.

Onboarding-Workflow.

Abrufen einer CCSID

  1. Gehen Sie im Saudi Arabian Taxation Portal (ERAD) zum Onboarding- und Management-Portal, indem Sie die entsprechende Kachel auswählen.

  2. Klicken Sie auf der Haupt-Zielseite des Onboarding- und Verwaltungsportals auf die Kachel Neue Lösungseinheit/neues Gerät an Bord holen und anschließend auf Auswählen OTP-Code generieren. Der OTP-Code ist nach seiner Generierung nur eine Stunde lang gültig. Stellen Sie sicher, dass es innerhalb dieser Zeit verwendet wird Rahmen.

  3. Auswählen die Anzahl der zu generierenden Einmalkennwortcodes (OTP). Die Anzahl hängt von der Anzahl der zu verwendenden E-Rechnungsgenerierungseinheiten (Geräte) ab.

  4. Speichern Sie die generierten OTP-Codes, damit Sie sie in späteren Schritten verwenden können.

  5. Bereiten Sie eine Konfigurationsdatei für die Zertifikatsignieranforderung vor. Diese Konfigurationsdatei sollte die Form einer einfachen Textdatei haben, die die folgenden Daten enthält.

    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. Speichern Sie die Datei am selben Speicherort wie das Onboarding-Skript unter dem Namen csr_config.txt.

  7. Aktualisieren Sie in der Konfigurationsdatei den Wert emailAddress und die folgenden spezifischen Daten.

    Code Description Spezifikation
    k Der Länder-/Regionscode. Ein zweistelliger Code (ISO 3166 Alpha-2)
    Organisationseinheit Der Name der Organisationseinheit. Für normale Steuerzahler ist der Wert ein Freitext. Bei Umsatzsteuergruppen ist der Wert durch die elfte Ziffer der Organisationskennung „1“ zu ermitteln. Überprüfen Sie, ob es sich bei der Eingabe um eine 10-stellige Steueridentifikationsnummer (TIN) handelt.
    O Der Name der Organisation oder des Steuerzahlers. Freitext
    CN Der eindeutige Name der Lösung oder Einheit. Freitext
    SN Der eindeutige Identifikationscode für die Lösung. Freitext
    UID Die Umsatzsteuer-Identifikationsnummer des Steuerzahlers. Fünfzehn Ziffern. Diese Nummer beginnt mit „3“ und endet mit „3“.
    Titel Der Dokumenttyp, den die Lösungseinheit des Steuerzahlers ausstellen wird. Vierstellige numerische Eingabe, bei der „0“ und „1“ verwendet und „TSCZ“ zugeordnet werden: 0 = Falsch/Nicht unterstützt, 1 = Wahr/Unterstützt. T = Steuerrechnung (Standard), S = Vereinfachte Steuerrechnung, C = Zur zukünftigen Verwendung, Z = Zur zukünftigen Verwendung.
    Registrierte Adresse Die Adresse der Niederlassung oder des Standortes, an dem sich das Gerät bzw. die Lösungseinheit vorrangig befindet. Freitext
    Geschäftskategorie Die Branche oder der Sektor, für den das Gerät oder die Lösung Rechnungen erstellen wird. Freitext

    Notiz

    Die Werte für CN und certificateTemplateName in der Konfigurationsdatei sind unterschiedlich, wenn Sie das Simulationsportal verwenden.

    Im Simulationsportal:

    • CN - PREZATCA-Code-Signing
    • Zertifikatsvorlagenname - ASN1:PRINTABLESTRING:PREZATCA-Code-Signing

    Verwenden Sie in allen anderen Fällen die oben angegebenen Werte.

  8. Führen Sie das Onboarding-Skript aus, das später in diesem Artikel bereitgestellt wird. Geben Sie OTP und Konfigurationsdatei als Eingabeparameter an. Hier ist ein Beispiel: Das Skript hat zwei mögliche Endpunkte: Simulation und Prod.

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

    Notiz

    Der Parameter Passwort ist optional und kann weggelassen werden. Wenn es enthalten ist, enthält das generierte Zertifikat das angegebene Kennwort.

  9. Die CCSID wird als Zertifikatsdatei „CCSID.pfx“ empfangen und das Geheimnis für die CCSID wird als TXT-Datei „CCSIDSecret.txt“ gespeichert. Speichern Sie diese CCSID-Zertifikatsdatei im Microsoft Azure Schlüsseltresor-Zertifikat und speichern Sie das Geheimnis im Microsoft Azure Schlüsseltresor-Geheimnis. Weitere Informationen finden Sie unter Kundenzertifikate und -geheimnisse.

  10. Konfigurieren Sie die zugehörigen Funktionseinstellungen in der Funktion Saudi-Arabien: ZATCA-Konformitätsprüfung (SA) Elektronische Fakturierung und verweisen Sie auf das CCSID-Zertifikat, das Sie im Schlüsseltresor gespeichert haben. Das Zertifikat wird für die Kommunikation mit dem ZATCA-Portal Elektronische Fakturierung verwendet.

Konformitätsprüfung

Nachdem Sie die Compliance-CSID mithilfe des Skripts PowerShell erhalten haben, müssen Sie bei ZATCA bestimmte Compliance-Prüfungen durch die Übermittlung von Beispielrechnungen durchführen. Dieses Schritt ist eine Voraussetzung, um eine Produktions-CSID anzufordern.

Stellen Sie sicher, dass alle Arten von Beispielrechnungen, die in der Konfigurationsdatei „Certificate Signing Request“ (CSR) konfiguriert wurden, erfolgreich an ZATCA übermittelt werden. Nutzen Sie den Standardprozess zur Ausstellung elektronischer Rechnungen. Weitere Einzelheiten finden Sie unter Elektronische Rechnungen im Finanzwesen und im Auswählen Management ausstellen.

Nutzen Sie die Funktion, „Saudi-arabischer ZATCA-Compliance-Check (SA)“ in RCS und folgen die Länder-/regionsspezifischer Konfigurationsbereich Schritte mithilfe der erhaltenen Compliance-CSID.

Nachdem die Konformitätsprüfungen erfolgreich abgeschlossen sind, verwenden Sie das Skript PowerShell, um die Produktions-CSID zu erhalten (siehe Onboarding-Skript).

Notiz

Im Titel Feld, wenn der Dokumenttyp in der Konfigurationsdatei eingestellt ist 1000 sind für die Konformitätsprüfung drei Musterrechnungen einzureichen:

  • Standard-Steuerrechnung
  • Standard-Lastschrift
  • Standardgutschrift

Im Titel Feld, wenn der Dokumenttyp in der Konfigurationsdatei eingestellt ist 0100 sind für die Konformitätsprüfung drei Musterrechnungen einzureichen:

  • Vereinfachte Steuerrechnung
  • Vereinfachte Lastschrift
  • Vereinfachte Gutschrift

Wenn der Dokumenttyp auf 1100 eingestellt ist, müssen alle sechs Musterrechnungen zur Konformitätsprüfung eingereicht werden.

Erhalten Sie eine PCSID

Um eine PCSID zu erhalten, müssen Sie die Lösung für die elektronische Rechnungserstellung und -übermittlung korrekt konfigurieren und die Lösung muss voll funktionsfähig sein. Um dieses Ergebnis zu erreichen, müssen Sie alle erforderlichen vorbereitenden Konfigurationsschritte durchführen. Weitere Informationen finden Sie unter Erste Schritte mit Elektronische Fakturierung für Saudi-Arabien.

  1. Stellen Sie sicher, dass alle elektronischen Rechnungen erfolgreich an ZATCA übermittelt werden.

  2. Führen Sie das Onboarding-Skript aus, das später in diesem Artikel bereitgestellt wird. Geben Sie die CCSID als Eingabeparameter an. Hier ist ein Beispiel: Das Skript hat zwei mögliche Endpunkte Simulation & Prod

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

    Notiz

    Der Parameter Passwort ist optional und kann weggelassen werden. Wenn es enthalten ist, enthält das generierte Zertifikat das angegebene Kennwort.

  3. Die PCSID wird als Zertifikatsdatei im PFX-Format empfangen. Speichern Sie dieses PCSID-Zertifikat und die geheime Datei im Schlüsseltresor Azure.

  4. Konfigurieren Sie die zugehörigen Funktionseinstellungen in der Funktion Saudi-Arabische Zatca-Einreichung (SA) Elektronische Fakturierung. Fügen Sie das PCSID-Zertifikat und das Geheimnis in die Schlüsseltresorparameter in RCS ein.

Nachdem Sie alle Konfigurationsschritte abgeschlossen haben, ist das System für den Einsatz im Produktionsmodus bereit.

Um die erhaltenen CSIDs auf der ZATCA-Seite zu überprüfen, verwenden Sie die Kachel vorhandenen Cryptographic Stamp Identifier (CSID) überprüfen auf der Zielseite des Onboarding- und Verwaltungsportals. Auf dieses Portal kann über das Hauptportal Saudi Arabian Taxation Portal (ERAD) zugegriffen werden.

Onboarding-Skript

Notiz

Die Beispielskripts werden von keinem Standard-Supportprogramm oder -Dienst von Microsoft unterstützt. Die Beispielskripte werden „WIE BESEHEN“ und ohne jegliche Gewährleistung bereitgestellt. Microsoft lehnt außerdem alle stillschweigenden Gewährleistungen ab, einschließlich und ohne Einschränkung jegliche stillschweigende Gewährleistung der Marktgängigkeit oder Eignung für einen bestimmten Zweck. Das gesamte Risiko, das aus der Verwendung oder Ausführung der Beispielskripte und der Dokumentation entsteht, verbleibt bei Ihnen. Microsoft, seine Autoren oder andere Personen, die an der Erstellung, Produktion oder Bereitstellung der Skripte beteiligt sind, haften unter keinen Umständen für Schäden jeglicher Art (einschließlich, aber nicht beschränkt auf Schäden durch entgangenen Geschäftsgewinn, Geschäftsunterbrechung, Verlust von Geschäftsinformationen oder andere finanzielle Verluste), die aus der Verwendung der Beispielskripte oder der Dokumentation oder der Unmöglichkeit der Verwendung entstehen, selbst wenn Microsoft auf die Möglichkeit derartiger Schäden hingewiesen wurde.

  1. Verwenden Sie das folgende Windows-Skript PowerShell, um eine CCSID und eine PCSID zu erhalten.

    #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. Speichern Sie die empfangene Ausgabe-Zertifikatdatei im PFX-Format im Schlüsseltresor.

Zusätzliche Ressourcen