Problema al enviar XML a SUNAT 29 Abril 2026 - SOLUCION

Desde el 29/04/2026 varios colegas has presentado problemas al enviar sus XML a SUNAT obteniendo el error “The remote server returned an unexpected response (400) bad request” o “El servidor remoto devolvió una respuesta inesperada: (400) Bad Request”

Luego de varias pruebas y  con el apoyo de colegas se llegó a la conclusión que el error esta ocasionado por la trama SOAP enviada a SUNAT la cual en algunos casos no se enviaban correctamente o completo, y SUNAT desde esa fecha está siendo más estricto y exigiendo que se envié correctamente, esta es un ejemplo de la trama correcta y aceptada por SUNAT:

<?xml version="1.0" encoding="utf-16"?>
<s:Envelope
	xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:ser="http://service.sunat.gob.pe"
	xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
	<s:Header>
		<Action s:mustUnderstand="1"
			xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:sendBill
		</Action>
		<wsse:Security>
			<wsse:UsernameToken wsu:Id="SecurityToken-b1f5b626-a6dd-4b6f-8a3b-d9eb38e20ea6"
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
				<wsse:Username>MODDATOS</wsse:Username>
				<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MODDATOS</wsse:Password>
				<wsse:Nonce></wsse:Nonce>
				<wsu:Created>2026-05-04T02:36:48Z</wsu:Created>
			</wsse:UsernameToken>
		</wsse:Security>
	</s:Header>
	<s:Body
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:xsd="http://www.w3.org/2001/XMLSchema">
		<ser:sendBill>
			<fileName>10123456789-01-FAC1-00004138.zip</fileName>
			<contentFile>base64file</contentFile>
		</ser:sendBill>
	</s:Body>
</s:Envelope>
  

 Donde lo importante es que esta seccion tenga todo estos valores

<?xml version="1.0" encoding="utf-16"?>
<s:Envelope
	xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:ser="http://service.sunat.gob.pe"
	xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
	<s:Header>
		<Action s:mustUnderstand="1"
			xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:sendBill
		</Action>
		<wsse:Security>
			<wsse:UsernameToken wsu:Id="SecurityToken-b1f5b626-a6dd-4b6f-8a3b-d9eb38e20ea6"
				xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
				<wsse:Username>MODDATOS</wsse:Username>
				<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">MODDATOS</wsse:Password>
				<wsse:Nonce></wsse:Nonce>
				<wsu:Created>2026-05-04T02:36:48Z</wsu:Created>
			</wsse:UsernameToken>
		</wsse:Security>
	</s:Header>
    ...
  

Ahora esto para quien usa C# en net framework con la clase PasswordDigestBehavior y PasswordDigestMessageInspector debe revisar el codigo public object BeforeSendRequest(ref Message request, IClientChannel channel) y colocar lo siguiente

public object BeforeSendRequest(ref Message request, IClientChannel channel)
{           
    UsernameToken token = new UsernameToken(Username, Password, PasswordOption.SendPlainText);
    XmlElement securityToken = token.GetXml(new XmlDocument());

    // Limpias el Nonce si no quieres que aparezca
    var nodo = securityToken.GetElementsByTagName("wsse:Nonce").Item(0);
    nodo?.RemoveAll();

    // Header WSSE
    var securityHeader = MessageHeader.CreateHeader(
        "Security",
        "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
        securityToken,
        false);

    request.Headers.Add(securityHeader);

    // Forzar namespaces en el Envelope
    request = new CustomMessage(request);
    return null;
}
  
Adicional a ello necesitara la clase CustomMessage
public class CustomMessage : Message
{
    private readonly Message _inner;

    public CustomMessage(Message inner)
    {
        _inner = inner;
    }

    public override MessageHeaders Headers => _inner.Headers;
    public override MessageProperties Properties => _inner.Properties;
    public override MessageVersion Version => _inner.Version;

    protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
    {
        // Obtiene el namespace correcto según la versión SOAP
        string envelopeNs = _inner.Version.Envelope == EnvelopeVersion.Soap11
            ? "http://schemas.xmlsoap.org/soap/envelope/"
            : "http://www.w3.org/2003/05/soap-envelope";

        writer.WriteStartElement("s", "Envelope", envelopeNs);

        // Declaraciones de namespaces adicionales
        writer.WriteXmlnsAttribute("s", envelopeNs);
        writer.WriteXmlnsAttribute("ser", "http://service.sunat.gob.pe");
        writer.WriteXmlnsAttribute("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
    }

    protected override void OnWriteStartBody(XmlDictionaryWriter writer)
    {
        _inner.WriteStartBody(writer);
    }

    protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
    {
        _inner.WriteBodyContents(writer);
    }
}
  
Por ultimo el metodo del envio seria algo asi
wsSunat.billServiceClient wsSunat = new wsSunat.billServiceClient();

ServicePointManager.UseNagleAlgorithm = true;
ServicePointManager.Expect100Continue = false;
ServicePointManager.CheckCertificateRevocationList = true;

var behavior = new PasswordDigestBehavior(usuario, clave);
wsSunat.Endpoint.Behaviors.Add(behavior);
    wsSunat.Open();
    byte[] returnbyte = wsSunat.sendBill(nombreArchivo, bytearray,null);
    wsSunat.Close();
  

OJO si no usas C# lo importante es que la trama SOAP tenga los valores mencionados arriba

Comentarios

Entradas populares