You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用巴西政府SOAP接口返回null,响应内容映射失败求助

问题分析与解决方案

一、核心问题定位

从你提供的信息来看,问题本质是wsimport生成的Stub无法正确解析服务端返回的retMDFe节点,同时请求参数传递存在错误:

  • WSDL定义的返回类型MdfeRecepcaoResult未包含retMDFe字段映射,但服务端实际返回了该节点,导致自动映射失败
  • 你传递了完整的SOAP Envelope作为mdfeDadosMsg的值,而wsimport生成的Stub会自动构建SOAP信封,最终造成请求体嵌套两层Envelope,干扰服务端解析

二、具体修正步骤

1. 修正请求参数传递

删除参数中的SOAP Envelope和mdfeDadosMsg标签,只传递内部的业务XML内容:

ObjectFactory of = new ObjectFactory();
// 仅传入业务XML,不要包含SOAP信封结构
String businessXml = "你的MDFe业务XML内容(符合巴西财政规范的格式)";
JAXBElement<String> jaxb = of.createMdfeDadosMsg(businessXml);

MDFeRecepcaoSinc recepcao = new MDFeRecepcaoSinc();
MDFeRecepcaoSincSoap12 soap = recepcao.getMDFeRecepcaoSincSoap12();
MdfeRecepcaoResult result = soap.mdfeRecepcao(jaxb.getValue());

2. 解决retMDFe映射失败问题

因为WSDL定义与服务端实际返回不匹配,有两种可行方案:

方案A:拦截响应手动解析retMDFe

通过自定义SOAPHandler拦截响应,直接提取retMDFe节点内容:

public class ResponseHandler implements SOAPHandler<SOAPMessageContext> {
    @Override
    public boolean handleMessage(SOAPMessageContext context) {
        Boolean isOutbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (!isOutbound) { // 处理入站响应
            try {
                SOAPMessage msg = context.getMessage();
                SOAPBody body = msg.getSOAPBody();
                // 定位retMDFe节点(注意对应命名空间)
                Node retMDFeNode = body.getElementsByTagNameNS("http://www.portalfiscal.inf.br/mdfe/wsdl/MDFeRecepcaoSinc", "retMDFe").item(0);
                if (retMDFeNode != null) {
                    // 提取节点内容,比如转为字符串
                    String retMDFeContent = retMDFeNode.getTextContent();
                    System.out.println("retMDFe内容:" + retMDFeContent);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) { return true; }
    @Override
    public void close(MessageContext context) {}
    @Override
    public Set<QName> getHeaders() { return Collections.emptySet(); }
}

给Stub添加Handler:

MDFeRecepcaoSinc recepcao = new MDFeRecepcaoSinc();
MDFeRecepcaoSincSoap12 soap = recepcao.getMDFeRecepcaoSincSoap12();
BindingProvider bp = (BindingProvider) soap;
List<Handler> handlers = bp.getBinding().getHandlerChain();
handlers.add(new ResponseHandler());
bp.getBinding().setHandlerChain(handlers);

方案B:修改WSDL重新生成Stub

手动修改下载的WSDL文件,补充retMDFe的类型定义,再重新生成Stub:

  1. 找到MdfeRecepcaoResult的complexType定义,添加retMDFe元素:
<xs:complexType name="MdfeRecepcaoResult">
    <xs:sequence>
        <xs:element name="retMDFe" type="xs:string"/>
    </xs:sequence>
</xs:complexType>
  1. 重新执行wsimport命令:
wsimport -extension -keep -verbose 修改后的MDFeRecepcaoSinc.wsdl

3. 关于MDFeRecepcaoSincSoap12接口的实现类

该接口的实现类是JAX-WS运行时动态生成的代理类,没有对应的物理Java文件。MDFeRecepcaoSinc服务类的getMDFeRecepcaoSincSoap12()方法会通过JDK动态代理机制,在运行时创建符合接口规范的代理实例,底层由JAX-WS RI(比如Sun的实现)提供支持。

三、额外注意事项

  • 针对SOAP 1.2非标准绑定的警告,可尝试启用RespectBindingFeature严格遵循WSDL绑定:
MDFeRecepcaoSincSoap12 soap = recepcao.getMDFeRecepcaoSincSoap12(new RespectBindingFeature(true));
  • 利用HttpTransportPipe.dump对比SoapUI和Stub的请求体差异,确保请求XML的命名空间、签名等细节完全符合服务端要求。

内容的提问来源于stack exchange,提问作者DevSoloDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 00:30:55