SWIFT MT报文解析需按{1:开头、-\n{4:/5:结尾的边界提取,避免字符串分割错误;MX报文须处理命名空间并校验XSD;日期和金额须硬校验格式与精度。

MT报文解析:别直接用字符串分割,先确认报文边界
SWIFT MT格式是固定结构的纯文本,但实际文件里常混着多条报文、头尾控制字符甚至BIC校验块。直接Split('\n')或ReadAllLines()会切错——比如把一条MT103的{1:F01ABCDBE20AXXX0000000000}头和下一条报文的{2:I103...连在一起。
正确做法是按SWIFT标准报文分隔符识别:每条报文以{1:开头,以-\n{4:或-\n{5:结尾(注意换行符是\n,不是\r\n)。真实文件中还可能有{3:块或空行干扰,必须跳过。
- 用正则
Regex.Matches(content, @"\{1:.*?\}-\n\{[45]:", RegexOptions.Singleline)提取完整报文段(注意Singleline让.匹配换行) - 不要信任
File.ReadAllLines()——它会把-\n{4:拆成两行,导致边界丢失 - 生产环境务必检查报文末尾是否有
{5:校验块,缺失时说明传输截断,整条报文应丢弃
MX报文解析:XML命名空间和XSD校验不能省
MX是基于XML Schema的标准化格式,但银行实际发送的MX报文常带非标准命名空间前缀(如xmlns="urn:swift:xsd:mt103.001.02"或xmlns:p="urn:swift:xsd:mt103.001.02"),用XDocument.Descendants("FIToFICstmrCdtTrf")会查不到节点。
更关键的是,MX报文头部{2:O103...}里的业务类型(如O103)必须和XSD版本严格对应——MT103.001.02和MT103.001.04的XML结构差异在ChrgsInf字段是否可重复,不校验XSD直接反序列化会静默丢数据。
- 加载XML前先用
XNamespace ns = doc.Root.GetDefaultNamespace()获取命名空间,再用ns + "FIToFICstmrCdtTrf"查节点 - 从SWIFT官网下载对应业务类型的XSD(如
mt103.001.02.xsd),用XmlSchemaSet预加载并启用ValidationEventHandler - 避免用
XmlSerializer直接映射——MX里大量使用choice结构(如ChrgsInf和ChrgsInf2互斥),需手写IXmlSerializable实现
MT/MX共用陷阱:日期时间格式和金额精度必须硬校验
SWIFT规范里日期是YYMMDD(如240520),但部分银行发错成YYYYMMDD;金额字段标称Decimal(15,2),实测出现过123456789012345.678(超15位整数+3位小数)。
这些错误不会导致解析失败,但会在后续清算环节被对手行拒收——而且错误发生在下游系统,你根本收不到明确报错。
- 对所有
DTM类字段(如:98A:),强制用DateTime.TryParseExact(value, "yyMMdd", ...),失败则标记报文异常 - 金额字段(如
:19A:)用decimal.TryParse(value, out var amt) && amt.ToString("F2").Length 校验(15整数+2小数+小数点) - 别依赖
Convert.ToDecimal()——它会自动截断超长小数位,掩盖问题
解析后验证:必须比对{1:}和{2:}中的BIC与业务类型
报文头{1:F01ABCDBE20AXXX0000000000}里的BIC(ABCDBE20A)和报文体{2:I103...}里的接收行BIC(:57A:DEUTDEFF)不一致?这是常见配置错误,但多数解析器根本不校验。
更隐蔽的是{2:}中的业务标识码(如I103表示MT103输入,O103表示输出),如果解析器按MT103处理了I202报文,字段映射全错。
- 提取
{1:}块时,用Substring(4, 8)取BIC(位置固定),和报文内:57A:、:56D:等字段逐个比对 - 从
{2:}中提取第4–7位(如I103),查表确认是否为当前支持的业务类型,不支持的立即拒收 - 这个校验必须在解析完成、字段赋值后执行,不能放在XML反序列化之前——因为MX的
{2:O103...}和实际XML根节点可能不匹配
真正麻烦的从来不是解析语法,而是银行之间对SWIFT规范的“灵活实现”:同一条MT103,有的行用:57A:,有的用:57D:,有的甚至把收款人名称塞进:72:备注字段。解析器得能容忍这些,又不能放过致命错误——边界感得靠大量真实报文样本反复调。










