pix-brcode-parser 0.1.0

A Rust library for parsing and validating Brazilian PIX QR codes (BR Code) following EMV QRCPS standard
Documentation
//! Example: Generate PIX QR codes programmatically

use pix_brcode_parser::{
    BRCode, MerchantAccountInfo, AdditionalData, 
    generate_brcode, parse_brcode
};

fn main() {
    println!("=== PIX QR Code Generator Example ===\n");
    
    // Example 1: Generate a static PIX QR code with amount
    let static_brcode = BRCode {
        payload_format_indicator: "01".to_string(),
        point_of_initiation_method: Some("11".to_string()), // Static
        merchant_account_info: MerchantAccountInfo {
            gui: "br.gov.bcb.pix".to_string(),
            pix_key: "user@example.com".to_string(),
            description: Some("Payment for services".to_string()),
            url: None,
        },
        merchant_category_code: "0000".to_string(),
        transaction_currency: "986".to_string(), // BRL
        transaction_amount: Some("25.50".to_string()),
        country_code: "BR".to_string(),
        merchant_name: "ACME CORP".to_string(),
        merchant_city: "SAO PAULO".to_string(),
        additional_data: Some(AdditionalData {
            bill_number: None,
            mobile_number: None,
            store_label: None,
            loyalty_number: None,
            reference_label: Some("INV001".to_string()),
            customer_label: None,
            terminal_label: None,
            purpose_of_transaction: None,
            additional_consumer_data_request: None,
        }),
        crc16: String::new(), // Will be calculated automatically
    };
    
    match generate_brcode(&static_brcode) {
        Ok(qr_string) => {
            println!("✅ Generated Static PIX QR Code:");
            println!("📋 Details:");
            println!("  Merchant: {}", static_brcode.merchant_name);
            println!("  PIX Key: {}", static_brcode.merchant_account_info.pix_key);
            println!("  Amount: R$ {}", static_brcode.transaction_amount.as_ref().unwrap());
            println!("  Reference: {}", static_brcode.additional_data.as_ref().unwrap().reference_label.as_ref().unwrap());
            println!();
            println!("🔗 QR Code String:");
            println!("{}", qr_string);
            println!();
            
            // Verify by parsing it back
            match parse_brcode(&qr_string) {
                Ok(parsed) => {
                    println!("✅ Verification: Generated QR code is valid!");
                    println!("  Parsed PIX Key: {}", parsed.merchant_account_info.pix_key);
                    println!("  Parsed Amount: {:?}", parsed.transaction_amount);
                }
                Err(e) => {
                    println!("❌ Verification failed: {}", e);
                }
            }
        }
        Err(e) => {
            println!("❌ Failed to generate QR code: {}", e);
        }
    }
    
    println!("\n{}", "=".repeat(60));
    
    // Example 2: Generate a dynamic PIX QR code (no amount)
    let dynamic_brcode = BRCode {
        payload_format_indicator: "01".to_string(),
        point_of_initiation_method: Some("12".to_string()), // Dynamic
        merchant_account_info: MerchantAccountInfo {
            gui: "br.gov.bcb.pix".to_string(),
            pix_key: "12345678901".to_string(), // CPF
            description: None,
            url: Some("api.merchant.com/pix/charge/abc123".to_string()),
        },
        merchant_category_code: "5812".to_string(), // Restaurant
        transaction_currency: "986".to_string(),
        transaction_amount: None, // User will define amount
        country_code: "BR".to_string(),
        merchant_name: "RESTAURANT XYZ".to_string(),
        merchant_city: "RIO DE JANEIRO".to_string(),
        additional_data: None,
        crc16: String::new(),
    };
    
    match generate_brcode(&dynamic_brcode) {
        Ok(qr_string) => {
            println!("\n✅ Generated Dynamic PIX QR Code:");
            println!("📋 Details:");
            println!("  Merchant: {}", dynamic_brcode.merchant_name);
            println!("  PIX Key: {} (CPF)", dynamic_brcode.merchant_account_info.pix_key);
            println!("  Category: {} (Restaurant)", dynamic_brcode.merchant_category_code);
            println!("  Amount: User defined");
            println!("  URL: {}", dynamic_brcode.merchant_account_info.url.as_ref().unwrap());
            println!();
            println!("🔗 QR Code String:");
            println!("{}", qr_string);
            println!();
            
            // Verify parsing
            match parse_brcode(&qr_string) {
                Ok(parsed) => {
                    println!("✅ Verification: Generated QR code is valid!");
                    println!("  Type: {}", if parsed.is_dynamic() { "Dynamic" } else { "Static" });
                    println!("  Has Amount: {}", parsed.has_amount());
                    println!("  Key Type: {:?}", parsed.pix_key_type());
                }
                Err(e) => {
                    println!("❌ Verification failed: {}", e);
                }
            }
        }
        Err(e) => {
            println!("❌ Failed to generate dynamic QR code: {}", e);
        }
    }
    
    println!("\n{}", "=".repeat(60));
    
    // Example 3: Generate QR codes with different PIX key types
    let key_examples = vec![
        ("UUID", "123e4567-e89b-12d3-a456-426614174000"),
        ("Email", "merchant@company.com"),
        ("Phone", "+5511999999999"),
        ("CPF", "12345678901"),
        ("CNPJ", "12345678000195"),
        ("Random", "randomkey123abc"),
    ];
    
    println!("\n🔑 PIX Key Type Examples:\n");
    
    for (key_type, pix_key) in key_examples {
        let example_brcode = BRCode {
            payload_format_indicator: "01".to_string(),
            point_of_initiation_method: Some("11".to_string()),
            merchant_account_info: MerchantAccountInfo {
                gui: "br.gov.bcb.pix".to_string(),
                pix_key: pix_key.to_string(),
                description: None,
                url: None,
            },
            merchant_category_code: "0000".to_string(),
            transaction_currency: "986".to_string(),
            transaction_amount: None,
            country_code: "BR".to_string(),
            merchant_name: "TEST MERCHANT".to_string(),
            merchant_city: "SAO PAULO".to_string(),
            additional_data: None,
            crc16: String::new(),
        };
        
        match generate_brcode(&example_brcode) {
            Ok(qr_string) => {
                // Parse to get key type
                if let Ok(parsed) = parse_brcode(&qr_string) {
                    println!("{} Key: {} -> {:?}", key_type, pix_key, parsed.pix_key_type());
                }
            }
            Err(e) => {
                println!("{} Key: {} -> Error: {}", key_type, pix_key, e);
            }
        }
    }
    
    println!("\n💡 Integration Tips:");
    println!("  1. Always validate generated QR codes by parsing them back");
    println!("  2. Use appropriate merchant category codes for your business");
    println!("  3. For dynamic QR codes, implement the URL endpoint properly");
    println!("  4. Keep merchant names under 25 characters and cities under 15");
    println!("  5. Use reference labels in additional data for transaction tracking");
}