Incorporación de la facturación electrónica en Arabia Saudí
La incorporación es obligatoria para todos los contribuyentes sujetos a facturación electrónica en Arabia Saudí. Como resultado del proceso de incorporación, los contribuyentes obtienen Identificadores de Sello Criptográfico (CSID). Los CSID son necesarios para la integración con el portal de facturación electrónica administrado por la autoridad fiscal de Arabia Saudita (ZATCA) y para el posterior envío de facturas electrónicas.
En este artículo se explica cómo incorporar a los contribuyentes y su software de facturación electrónica a las autoridades fiscales de Arabia Saudí.
Requisitos previos
- La entidad jurídica debe estar registrada como contribuyente en Arabia Saudí y debe tener un número de registro de impuesto sobre el valor añadido (IVA) válido.
- La entidad jurídica debe tener acceso al Portal de Tributación de Arabia Saudí (ERAD).
Proceso de incorporación
El proceso de incorporación consta de dos pasos:
- Obtenga un CSID de cumplimiento (CCSID), que ZATCA asigna para realizar verificaciones de cumplimiento de las soluciones de generación de facturas electrónicas (EGS).
- Obtenga un CSID de producción (PCSID), que ZATCA asigna a los EGS compatibles.
Obtener un CCSID
En el Portal de Fiscalidad de Arabia Saudí (ERAD), vaya al Portal de incorporación y administración seleccionando el icono correspondiente.
En la página de aterrizaje principal del portal de incorporación y administración, Seleccione el icono Incorporar nueva unidad de solución/dispositivo y, a continuación, SeleccioneGenerar código OTP. El código OTP solo es válido durante una hora después de generarse. Asegúrese de que se usa dentro de ese marco de tiempo.
Seleccione la cantidad de códigos de contraseña de un solo uso (OTP) que se generarán. El número depende de la cantidad de unidades de generación de facturación electrónica (dispositivos) que se utilizarán.
Guarde los códigos OTP generados para poder usarlos en pasos posteriores.
Prepare un archivo de configuración para la solicitud de firma de certificado. Este archivo de configuración debe tener la forma de un archivo de texto sin formato que contenga los siguientes datos.
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
Guarde el archivo en la misma ubicación que el script de incorporación con el nombre,csr_config.txt .
En el archivo de configuración, actualice el valor emailAddress y los siguientes datos específicos.
Código Description Especificación C El código fiscal del país o región. Un código de dos letras (ISO 3166 Alpha-2) OU El nombre de la unidad organizativa. Para los contribuyentes normales, el valor es texto libre. Para los grupos de IVA, identifique el valor a través del undécimo dígito del identificador de organización que es "1". Compruebe que la entrada sea un número de identificación fiscal (CIF) de 10 dígitos. O El nombre de la organización o del contribuyente. Texto sin formato CN El nombre exclusivo de la solución o unidad. Texto sin formato SN El código de identificación único de la solución. Texto sin formato UID El número de identificación fiscal (NIF) del contribuyente. Quince dígitos. Este número comienza con "3" y termina con "3". título El tipo de documento que emitirá la unidad de solución del contribuyente. Entrada numérica de cuatro dígitos que usa "0" y "1" asignados a "TSCZ": 0 = Falso/No admitido, 1 = Verdadero/Admitido. T = Factura de impuestos (estándar), S = Factura de impuestos simplificada, C = Para uso futuro, Z = Para uso futuro. registeredAddress La dirección de la sucursal o ubicación donde se encuentra principalmente el dispositivo o la unidad de solución. Texto sin formato negocioCategoría La industria o el sector para el que el dispositivo o la solución generará facturas. Texto sin formato Nota
Los valores de CN y certificateTemplateName en el archivo de configuración son diferentes cuando se utiliza el portal de simulación.
En el portal de simulación:
- CN - PREZATCA-Firma-de-Código
- certificateTemplateName - ASN1:PRINTABLESTRING:PREZATCA-Code-Signing
Para cualquier otro caso, utilice los valores indicados anteriormente.
Ejecute el script de incorporación que se proporciona más adelante en este artículo. Especifique la OTP y el archivo de configuración como parámetros de entrada. A continuación, se muestra un ejemplo: El script tiene dos puntos de conexión posibles : simulación y producción.
.\OnboardingScript.ps1 -action getComplianceCSID -endpoint prod -otp 123345 -csrconfig .\csr_config.txt -password 123
Nota
El parámetro de contraseña es opcional y se puede omitir. Si está incluido, el certificado generado tendrá la contraseña especificada.
El CCSID se recibe como un archivo de certificado "CCSID.pfx" y el secreto para el CCSID se guarda como archivo txt "CCSIDSecret.txt". Guarde este archivo de certificado CCSID en el certificado de Microsoft Azure Key Vault y guarde el secreto en Microsoft Azure el secreto de Key Vault. Para obtener más información, consulte Certificados y secretos de cliente.
Configure la configuración de la función relacionada en la característica de facturación electrónica de comprobación de cumplimiento (SA) de ZATCA de Arabia Saudí y haga referencia al certificado CCSID que guardó en Key Vault. El certificado se utilizará para la comunicación con el portal de facturación electrónica de ZATCA.
Comprobación de cumplimiento
Después de obtener el CSID de cumplimiento mediante el script PowerShell, ZATCA requiere que complete ciertas comprobaciones de cumplimiento mediante el envío de facturas de muestra. Este paso es un requisito previo para solicitar un CSID de producción.
Asegúrese de que todos los tipos de facturas de muestra que se configuraron en el archivo de configuración de la solicitud de firma de certificado (CSR) se envíen correctamente a ZATCA. Utilice el proceso estándar para emitir facturas electrónicas. Para obtener más detalles, consulte Emitir facturas electrónicas en Finance y cadena de suministro Management.
Utilice la función "Comprobación de cumplimiento de ZATCA (SA) de Arabia Saudí" en RCS y seguir los pasos de la sección de configuración específica del país/región utilizando el CSID de cumplimiento que obtuvo.
Una vez que las comprobaciones de cumplimiento se hayan completado correctamente, utilice el script PowerShell para obtener el CSID de producción (consulte el script de incorporación).
Nota
En el campo Título , si el tipo de documento del archivo de configuración está establecido en 1000, se deben enviar tres ejemplos de facturas para la verificación de cumplimiento:
- Factura de impuestos estándar
- Nota de débito estándar
- Nota de abono estándar
En el campo Título , si el tipo de documento del archivo de configuración está establecido en 0100, se deben enviar tres ejemplos de facturas para la verificación de cumplimiento:
- Factura de impuestos simplificada
- Nota de débito simplificada
- Nota de crédito simplificada
Si el tipo de documento está establecido en 1100, deben enviarse los seis ejemplos de facturas para la verificación de cumplimiento.
Obtener un PCSID
Para obtener un PCSID, debe configurar correctamente la solución para la generación y el envío de facturas electrónicas, y la solución debe estar en pleno funcionamiento. Para lograr este resultado, debe completar todos los pasos de configuración preliminar necesarios. Para obtener más información, consulte Introducción a la facturación electrónica para Arabia Saudí.
Asegúrese de que todas las facturas electrónicas se envíen correctamente a ZATCA.
Ejecute el script de incorporación que se proporciona más adelante en este artículo. Especifique el CCSID como parámetro de entrada. A continuación, se muestra un ejemplo: El script tiene dos puntos de conexión posibles : simulation & prod
.\OnboardingScript.ps1 -action getProductionCSID -endpoint prod -password 123
Nota
El parámetro de contraseña es opcional y se puede omitir. Si está incluido, el certificado generado tendrá la contraseña especificada.
El PCSID se recibe como un archivo de certificado en formato PFX. Guarde el certificado PCSID y el archivo secreto en el almacén de claves Azure;.
Configure la configuración de la función relacionada en la función de facturación electrónica de envío de Zatca (SA) de Arabia Saudita. Incluya el certificado y el secreto PCSID en los parámetros del almacén de claves en RCS.
Después de completar todos los pasos de configuración, el sistema está listo para su uso en modo de producción.
Para revisar los CSID obtenidos en el lado de ZATCA, utilice el mosaico Revisar identificador de sello criptográfico existente (CSID) en la página de inicio del Portal de incorporación y administración. Se puede acceder a este portal desde el principal Portal de Tributación de Arabia Saudí (ERAD).
Script de incorporación
Nota
Los scripts de ejemplo no son compatibles con ningún programa o servicio de soporte técnico estándar de Microsoft;. Los scripts de ejemplo se proporcionan TAL CUAL, sin garantía de ningún tipo. Microsoft renuncia además a todas las garantías implícitas, incluidas, entre otras, las garantías implícitas de comerciabilidad o idoneidad para un propósito particular. Usted asume todo el riesgo derivado del uso o rendimiento de los scripts y la documentación de ejemplo. En ningún caso Microsoft, sus autores o cualquier otra persona involucrada en la creación, producción o entrega de los guiones serán responsables de ningún daño (incluidos, entre otros, daños por pérdida de ganancias comerciales, interrupción del negocio, pérdida de información comercial u otra pérdida pecuniaria) que surjan del uso o la imposibilidad de usar los guiones o documentación de muestra. incluso si Microsoft ha sido advertido de la posibilidad de tales daños.
Utilice el siguiente script PowerShell de Windows para obtener un CCSID y un 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." } } }
Guarde el archivo de certificado .pfx de salida que se recibe en Key Vault.