mx-message 3.1.1

A fast, type-safe Rust implementation of MXMessage for parsing MX messages.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
<div align="center">
  <img src="https://avatars.githubusercontent.com/u/207296579?s=200&v=4" alt="Plasmatic Logo" width="120" height="120">

# MXMessage

**A Rust library for parsing, validating, and serializing ISO 20022 (MX) financial messages.**

*Full CBPR+ compliance with comprehensive validation and test data generation.*

  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
  [![Rust](https://img.shields.io/badge/rust-1.70+-orange.svg)](https://www.rust-lang.org)
  [![Crates.io](https://img.shields.io/crates/v/mx-message.svg)](https://crates.io/crates/mx-message)
  [![Swift CBPR+](https://img.shields.io/badge/Swift-CBPR%2B%20SR2025-green.svg)](https://www.swift.com)

  <p>
    <a href="https://github.com/GoPlasmatic">๐Ÿข Organization</a> โ€ข
    <a href="https://docs.rs/mx-message">๐Ÿ“– Documentation</a> โ€ข
    <a href="https://github.com/GoPlasmatic/MXMessage/issues">๐Ÿ› Issues</a>  
  </p>
</div>

-----

MXMessage is a comprehensive Rust library for handling ISO 20022 (MX) financial messages. It provides type-safe parsing, validation, and serialization for CBPR+ compliant messages, with powerful test data generation capabilities for all supported message types.

## ๐Ÿš€ Key Features

  - **CBPR+ SR2025 Compliant:** Full support for Central Bank Payment Regulation Plus SR2025 schemas.
  - **Simplified v3 API:** Two main functions (`to_json` and `to_xml`) handle all message types with automatic envelope generation.
  - **Type-Safe:** Strongly typed Rust structures generated from official XSD schemas.
  - **Comprehensive Validation:** Field-level, pattern, and business rule validation with detailed error codes.
  - **Complete MX XML Generation:** Automatic ISO 20022 compliant XML with proper AppHdr envelope.
  - **Multiple Formats:** Native support for both JSON and XML serialization.
  - **Test Data Generation:** Automatic generation of valid test messages using configurable scenarios.
  - **Extensive Coverage:** Support for pacs, pain, and camt message families.
  - **Zero-Copy Parsing:** Efficient processing with minimal allocations.
  - **Dataflow Integration:** Plugin support for dataflow-rs engine enabling async processing pipelines.
  - **Enhanced XML Support:** Advanced XML serialization with configurable formatting and namespace handling.

## ๐Ÿ—๏ธ How It Works: Schema-Driven Architecture

### Generated Types from XSD

All message types are automatically generated from official ISO 20022 XSD schemas.

```rust
use mx_message::document::Document;
use mx_message::pacs_008_001_08::*;

// Create a strongly-typed payment message
let payment = FIToFICustomerCreditTransferV08 {
    grp_hdr: GroupHeader93 {
        msg_id: "MSGID123456".to_string(),
        cre_dt_tm: "2024-01-15T10:30:00Z".to_string(),
        nb_of_txs: "1".to_string(),
        // ... other fields
    },
    cdt_trf_tx_inf: vec![/* transactions */],
    splmtry_data: None,
};

// Automatic validation
match Document::FIToFICustomerCreditTransferV08(Box::new(payment)).validate() {
    Ok(_) => println!("โœ“ Valid CBPR+ compliant message"),
    Err(e) => println!("โœ— Validation error: {} (code: {})", e.message, e.code),
}
```

### Message Families

```rust
// Payment messages
use mx_message::document::Document;
use mx_message::pacs_008_001_08::*;  // Customer Credit Transfer
use mx_message::pacs_009_001_08::*;  // Financial Institution Credit Transfer

// Cash management messages  
use mx_message::camt_053_001_08::*;  // Bank to Customer Statement
use mx_message::camt_056_001_08::*;  // Payment Cancellation Request

// Payment initiation messages
use mx_message::pain_001_001_09::*;  // Customer Credit Transfer Initiation
use mx_message::pain_008_001_08::*;  // Customer Direct Debit Initiation
```

## ๐ŸŽฏ Serialization Support

MXMessage provides seamless serialization between JSON and XML formats with enhanced XML capabilities.

```rust
use mx_message::document::Document;
use mx_message::xml::{XmlConfig, to_mx_xml};
use serde_json;

// Parse from JSON
let doc: Document = serde_json::from_str(json_str)?;

// Serialize to pretty JSON
let json_output = serde_json::to_string_pretty(&doc)?;

// Enhanced XML serialization with configuration
let xml_config = XmlConfig {
    include_declaration: true,
    pretty_print: true,
    indent: "  ".to_string(),
    include_schema_location: true,
};

// Generate complete MX XML with envelope
let xml_output = to_mx_xml(&doc, header, "pacs.008.001.08", Some(xml_config))?;
```

**Example JSON Output:**

```json
{
  "FIToFICstmrCdtTrf": {
    "GrpHdr": {
      "MsgId": "MSGID123456",
      "CreDtTm": "2024-01-15T10:30:00Z",
      "NbOfTxs": "1",
      "TtlIntrBkSttlmAmt": {
        "@Ccy": "EUR",
        "$value": 1000.00
      }
    },
    "CdtTrfTxInf": [{
      "PmtId": {
        "EndToEndId": "E2E123456",
        "UETR": "12345678-1234-5678-1234-567812345678"
      },
      "IntrBkSttlmAmt": {
        "@Ccy": "EUR", 
        "$value": 1000.00
      }
    }]
  }
}
```

## ๐Ÿ”ง Installation

Add `mx-message` to your `Cargo.toml`:

```toml
[dependencies]
mx-message = "3.1"
serde_json = "1.0"  # For JSON support
quick-xml = { version = "0.38", features = ["serialize"] }  # For XML support

# Optional: For dataflow pipeline integration
dataflow-rs = "2.0"  # For async processing pipelines
datalogic-rs = "4.0"  # For validation logic
```

## ๐Ÿ“– Usage

### Basic Message Creation (v3 API)

```rust
use mx_message::{to_json, to_xml};
use mx_message::document::Document;
use mx_message::pacs_008_001_08::*;

// Create a payment message
let payment = FIToFICustomerCreditTransferV08 {
    grp_hdr: GroupHeader93 {
        msg_id: "MSGID123456".to_string(),
        cre_dt_tm: "2024-01-15T10:30:00Z".to_string(),
        nb_of_txs: "1".to_string(),
        // ... other fields
    },
    cdt_trf_tx_inf: vec![/* transactions */],
    splmtry_data: None,
};

let document = Document::FIToFICustomerCreditTransferV08(Box::new(payment));

// Validate against CBPR+ SR2025 rules
match document.validate() {
    Ok(_) => println!("โœ“ Message is valid"),
    Err(e) => eprintln!("โœ— Validation failed: {}", e.message),
}

// Convert to JSON (simplified v3 API)
let json = to_json(&document)?;
println!("{}", json);

// Convert to XML with automatic envelope (simplified v3 API)
let xml = to_xml(&document)?;
println!("{}", xml);
```

### Test Data Generation

```rust
use mx_message::sample::generate_sample;

// Generate test data from scenario files
let sample = generate_sample("pacs008", Some("cbpr_cross_border_payment"))?;
println!("Generated sample: {}", serde_json::to_string_pretty(&sample)?);

// Scenarios support fake data generation
// See test_scenarios/ directory for examples
```

### Complete MX XML Generation (v3 Simplified API)

Generate ISO 20022 compliant XML with proper envelope and Business Application Header using the simplified v3 API:

```rust
use mx_message::{to_json, to_xml};
use mx_message::document::Document;

// Create or load your message
let document = Document::FIToFICustomerCreditTransferV08(/* ... */);

// Convert to JSON - simple one-liner
let json = to_json(&document)?;
println!("{}", json);

// Convert to XML with automatic envelope generation
let xml = to_xml(&document)?;
println!("{}", xml);
```

The v3 API automatically:
- Generates the correct Business Application Header based on message type
- Creates a properly formatted MX envelope with AppHdr
- Sets appropriate namespaces and CBPR+ compliance indicators
- Handles all message types uniformly

**Note:** The simplified API uses sensible defaults. For advanced customization of headers and envelopes, the lower-level APIs are still available:

```rust
use mx_message::mx_envelope::create_mx_envelope;
use mx_message::header::head_001_001_02::BusinessApplicationHeaderV02;

// Create custom header for advanced use cases
let custom_header = BusinessApplicationHeaderV02 {
    fr: Party44Choice {
        fiid: Some(FinancialInstitutionIdentification18 {
            bicfi: Some("BANKUS33XXX".to_string()),
            ..Default::default()
        }),
        ..Default::default()
    },
    to: Party44Choice {
        fiid: Some(FinancialInstitutionIdentification18 {
            bicfi: Some("BANKGB22XXX".to_string()),
            ..Default::default()
        }),
        ..Default::default()
    },
    biz_msg_idr: "MSG-2024-001".to_string(),
    msg_def_idr: "pacs.008.001.08".to_string(),
    biz_svc: Some("swift.cbprplus.02".to_string()),
    cre_dt: "2024-01-15T10:30:00Z".to_string(),
    ..Default::default()
};

// Create envelope with custom header
let envelope = create_mx_envelope(custom_header, document)?;
let xml = quick_xml::se::to_string(&envelope)?;
```

### Validation Error Handling

```rust
use mx_message::document::Document;

match document.validate() {
    Ok(_) => println!("โœ“ Valid"),
    Err(e) => {
        match e.code {
            1001 => println!("Field too short: {}", e.message),
            1002 => println!("Field too long: {}", e.message),
            1005 => println!("Invalid pattern: {}", e.message),
            _ => println!("Validation error: {}", e.message),
        }
    }
}
```

### Dataflow Integration (New in v3.1)

MXMessage now provides seamless integration with dataflow-rs for building async processing pipelines with a clean, refactored plugin architecture:

```rust
use mx_message::plugin::register_mx_functions;
use dataflow_rs::Engine;

// Register MX message functions with dataflow engine
let functions = register_mx_functions();
let mut engine = Engine::new();

for (name, handler) in functions {
    engine.register_function(name, handler);
}

// Create a pipeline workflow
let workflow = r#"
{
  "name": "mx-processing-pipeline",
  "tasks": [
    {
      "id": "generate",
      "function": "generate_mx",
      "params": {
        "message_type": "pacs.008",
        "scenario": "cbpr_business_payment"
      }
    },
    {
      "id": "validate",
      "function": "validate_mx",
      "inputs": ["generate.output"]
    },
    {
      "id": "publish",
      "function": "publish_mx",
      "params": {
        "format": "xml"
      },
      "inputs": ["validate.output"]
    }
  ]
}
"#;

// Execute the pipeline asynchronously
let result = engine.execute(workflow).await?;
```

Available dataflow functions:
- `parse_mx`: Parse MX messages from JSON/XML
- `validate_mx`: Validate against schema and business rules
- `generate_mx`: Generate sample data from scenarios
- `publish_mx`: Serialize to JSON/XML formats

The plugin architecture has been refactored for better maintainability:
- **Common utilities module** (`plugin::common`) provides shared functionality
- **Centralized format detection** and message type mapping
- **Reduced code duplication** across plugin modules
- **Type-safe error handling** with improved error types

### Error Collection (Comprehensive Validation)

MXMessage supports collecting all validation errors instead of stopping at the first error:

```rust
use mx_message::validation::Validate;
use mx_message::parse_result::{ParserConfig, ErrorCollector};
use mx_message::pacs_008_001_08::FIToFICustomerCreditTransferV08;

// Create a message with multiple validation issues
let payment = FIToFICustomerCreditTransferV08 {
    grp_hdr: GroupHeader93 {
        msg_id: "ID",  // Too short (min 5 chars)
        cre_dt_tm: "invalid-date",  // Wrong format
        nb_of_txs: "ABC",  // Should be numeric
        // ... other fields
    },
    // ... other fields
};

// Collect all validation errors
let config = ParserConfig::default();
let mut collector = ErrorCollector::new();
payment.validate("", &config, &mut collector);

// Process all errors at once
if collector.has_errors() {
    println!("Found {} validation errors:", collector.errors().len());
    for error in collector.errors() {
        println!("  - {}: {} (code: {})", 
            error.path.as_ref().unwrap_or(&"root".to_string()),
            error.message, 
            error.code
        );
    }
} else {
    println!("โœ“ Message is valid");
}
```

## ๐Ÿงช Testing Strategy

MXMessage uses comprehensive testing with 168 real-world scenarios migrated from MT messages, covering cross-border payments, securities, cash management, and more.

### Key Testing Features

- **Scenario-Based Testing**: 168 scenarios across 16 message types
- **Round-Trip Validation**: JSON โ†’ Generate โ†’ Validate โ†’ JSON testing
- **MT to MX Migration**: 99.4% coverage of MT message scenarios
- **Sample Generation**: Automatic test data using `datafake` library
- **100% Success Rate**: All 1,680 tests pass (10 samples per scenario)

### Quick Start

```bash
# Run all test scenarios
cargo test round_trip_scenarios

# Test specific message type
TEST_MESSAGE_TYPE=pacs.008 cargo test round_trip_scenarios

# Debug a specific scenario
TEST_MESSAGE_TYPE=pacs.008 TEST_SCENARIO=cbpr_cross_border_payment TEST_DEBUG=1 cargo test round_trip_scenarios -- --nocapture
```

For detailed test scenarios and MT to MX mapping, see the [Test Scenarios Documentation](test_scenarios/README.md).

## ๐Ÿ›๏ธ CBPR+ SR2025 Compliance

This library implements CBPR+ SR2025 (Central Bank Payment Regulation Plus Standards Release 2025) compliant schemas, providing:

- **Enhanced Validation**: Stricter rules for regulatory compliance
- **UETR Support**: Unique End-to-end Transaction Reference tracking
- **Central Bank Integration**: Support for central bank payment systems
- **Cross-Border Payments**: Full support for international transactions
- **Regulatory Reporting**: Compliance with reporting requirements
- **BizSvc SR2025**: Updated Business Service identifier `swift.cbprplus.02` for SR2025 compliance

## ๐Ÿ“Š Supported Message Types

### Payment Messages (pacs)
- **pacs.002.001.10**: Payment Status Report
- **pacs.003.001.08**: Direct Debit
- **pacs.004.001.09**: Payment Return
- **pacs.008.001.08**: Customer Credit Transfer
- **pacs.009.001.08**: Financial Institution Credit Transfer
- **pacs.010.001.03**: Financial Institution Direct Debit (New in v3.1)

### Payment Initiation (pain)
- **pain.001.001.09**: Customer Credit Transfer Initiation
- **pain.008.001.08**: Customer Direct Debit Initiation

### Cash Management (camt)
- **camt.025.001.05**: Receipt
- **camt.027.001.07**: Claim Non Receipt
- **camt.028.001.09**: Additional Payment Information
- **camt.029.001.09**: Resolution of Investigation
- **camt.052.001.08**: Bank to Customer Account Report
- **camt.053.001.08**: Bank to Customer Statement
- **camt.054.001.08**: Bank to Customer Debit/Credit Notification
- **camt.056.001.08**: Payment Cancellation Request
- **camt.057.001.06**: Notification to Receive
- **camt.060.001.05**: Account Reporting Request
- **camt.107.001.01**: Cheque Presentment Notification (New in v3.1)
- **camt.108.001.01**: Cheque Stop Request (New in v3.1)
- **camt.109.001.01**: Cheque Cancellation or Stop Request Status (New in v3.1)

## ๐Ÿค Contributing

Contributions are welcome! If you'd like to help, please feel free to fork the repository, make your changes, and submit a pull request. We ask that you:

- Ensure all new message types follow CBPR+ compliance standards
- Add comprehensive tests for new functionality
- Update documentation for any new features
- Follow existing code style and validation patterns

## ๐Ÿข About Plasmatic

MXMessage is developed by [Plasmatic](https://github.com/GoPlasmatic), an organization focused on building open-source tools for financial infrastructure. We believe in transparency, security, and performance.

Check out our other projects:

  - [SwiftMTMessage]https://github.com/GoPlasmatic/SwiftMTMessage: A SWIFT MT message parsing library.
  - [Reframe]https://github.com/GoPlasmatic/Reframe: A SWIFT MT to ISO 20022 (and back) transformation engine.

## ๐Ÿ“„ License

This library is licensed under the Apache License, Version 2.0. See the [LICENSE](LICENSE) file for details.

-----

<div align="center">
<p>Built with โค๏ธ by the <a href="https://github.com/GoPlasmatic">Plasmatic</a> team</p>
</div>