pix-brcode-parser 0.1.0

A Rust library for parsing and validating Brazilian PIX QR codes (BR Code) following EMV QRCPS standard
Documentation

PIX BR Code Parser

Uma biblioteca Rust para análise e validação de códigos QR PIX (BR Code) brasileiros seguindo o padrão EMV QRCPS.

Crates.io Documentation License

Características

  • ✅ Análise de códigos QR PIX estáticos e dinâmicos
  • ✅ Validação de conformidade com EMV QRCPS
  • ✅ Validação de checksum CRC16
  • ✅ API ergonômica com structs tipadas
  • ✅ Suporte opcional ao serde para serialização
  • ✅ Análise zero-allocation para aplicações críticas de performance
  • ✅ Geração de códigos QR PIX
  • ✅ Classificação automática de tipos de chave PIX

Instalação

Adicione ao seu Cargo.toml:

[dependencies]
pix-brcode-parser = "0.1.0"

# Para suporte a serialização
pix-brcode-parser = { version = "0.1.0", features = ["serde"] }

Uso Rápido

Analisando um Código QR PIX

use pix_brcode_parser::{parse_brcode, BRCodeError};

fn main() {
    let qr_string = "00020126580014br.gov.bcb.pix0136123e4567-e12b-12d1-a456-426614174000520400005303986540510.005802BR5913FULANO DE TAL6008BRASILIA62070503***630436D9";
    
    match parse_brcode(qr_string) {
        Ok(brcode) => {
            println!("✅ Código PIX válido!");
            println!("Chave PIX: {}", brcode.merchant_account_info.pix_key);
            println!("Tipo da Chave: {:?}", brcode.pix_key_type());
            println!("Comerciante: {}", brcode.merchant_name);
            println!("Cidade: {}", brcode.merchant_city);
            
            if let Some(amount) = &brcode.transaction_amount {
                println!("Valor: R$ {}", amount);
            } else {
                println!("Valor: A ser definido pelo usuário");
            }
            
            println!("Tipo: {}", if brcode.is_static() { "Estático" } else { "Dinâmico" });
        }
        Err(e) => {
            eprintln!("❌ Erro ao analisar código PIX: {}", e);
        }
    }
}

Gerando um Código QR PIX

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

fn main() {
    let brcode = BRCode {
        payload_format_indicator: "01".to_string(),
        point_of_initiation_method: Some("11".to_string()), // Estático
        merchant_account_info: MerchantAccountInfo {
            gui: "br.gov.bcb.pix".to_string(),
            pix_key: "user@example.com".to_string(),
            description: Some("Pagamento por serviços".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: None,
        crc16: String::new(), // Será calculado automaticamente
    };
    
    match generate_brcode(&brcode) {
        Ok(qr_string) => {
            println!("Código QR gerado: {}", qr_string);
        }
        Err(e) => {
            eprintln!("Erro ao gerar código: {}", e);
        }
    }
}

Exemplos de Códigos PIX

Código PIX Estático com Valor Fixo

// QR Code com valor predefinido de R$ 10,00
let static_qr = "00020126580014br.gov.bcb.pix0136123e4567-e12b-12d1-a456-426614174000520400005303986540510.005802BR5913FULANO DE TAL6008BRASILIA62070503***630436D9";

let brcode = parse_brcode(static_qr).unwrap();
assert_eq!(brcode.transaction_amount, Some("10.00".to_string()));
assert_eq!(brcode.merchant_name, "FULANO DE TAL");
assert_eq!(brcode.merchant_city, "BRASILIA");

Diferentes Tipos de Chave PIX

use pix_brcode_parser::{parse_brcode, PixKeyType, classify_pix_key};

// Chave UUID
let uuid_key = "123e4567-e89b-12d3-a456-426614174000";
assert_eq!(classify_pix_key(uuid_key), PixKeyType::Uuid);

// Chave Email
let email_key = "usuario@exemplo.com";
assert_eq!(classify_pix_key(email_key), PixKeyType::Email);

// Chave Telefone
let phone_key = "+5511999999999";
assert_eq!(classify_pix_key(phone_key), PixKeyType::Phone);

// Chave CPF
let cpf_key = "12345678901";
assert_eq!(classify_pix_key(cpf_key), PixKeyType::Cpf);

// Chave CNPJ
let cnpj_key = "12345678000195";
assert_eq!(classify_pix_key(cnpj_key), PixKeyType::Cnpj);

Tratamento de Erros

use pix_brcode_parser::{parse_brcode, BRCodeError};

let invalid_qr = "codigo_invalido";

match parse_brcode(invalid_qr) {
    Ok(brcode) => println!("Código válido: {:?}", brcode),
    Err(e) => match e {
        BRCodeError::InvalidChecksum => {
            println!("Checksum inválido - código pode estar corrompido");
        }
        BRCodeError::InvalidGui(gui) => {
            println!("GUI inválido: esperado 'br.gov.bcb.pix', encontrado: {}", gui);
        }
        BRCodeError::MissingField(field) => {
            println!("Campo obrigatório ausente: {}", field);
        }
        BRCodeError::InvalidFormat(msg) => {
            println!("Formato inválido: {}", msg);
        }
        _ => {
            println!("Erro: {}", e);
        }
    }
}

Validação de Campos

use pix_brcode_parser::parse_brcode;

// Exemplo com nome do comerciante muito longo (máximo 25 caracteres)
let long_name_qr = "..."; // QR code com nome > 25 chars

match parse_brcode(long_name_qr) {
    Err(BRCodeError::FieldTooLong { tag, max_length, actual_length }) => {
        println!("Campo {} muito longo: máximo {}, atual {}", tag, max_length, actual_length);
    }
    _ => {}
}

Serialização com Serde (Feature Opcional)

#[cfg(feature = "serde")]
{
    use serde_json;
    
    let qr_string = "00020126580014br.gov.bcb.pix0136123e4567-e12b-12d1-a456-426614174000520400005303986540510.005802BR5913FULANO DE TAL6008BRASILIA62070503***630436D9";
    let brcode = parse_brcode(qr_string).unwrap();
    
    // Serializar para JSON
    let json = serde_json::to_string(&brcode).unwrap();
    println!("JSON: {}", json);
    
    // Deserializar de JSON
    let brcode_from_json: BRCode = serde_json::from_str(&json).unwrap();
    assert_eq!(brcode, brcode_from_json);
}

Estrutura dos Dados

BRCode Principal

pub struct BRCode {
    pub payload_format_indicator: String,      // Sempre "01"
    pub point_of_initiation_method: Option<String>, // "11" = estático, "12" = dinâmico
    pub merchant_account_info: MerchantAccountInfo,
    pub merchant_category_code: String,        // Código da categoria do comerciante
    pub transaction_currency: String,          // "986" para BRL
    pub transaction_amount: Option<String>,    // Valor da transação
    pub country_code: String,                  // "BR"
    pub merchant_name: String,                 // Nome do comerciante (máx 25 chars)
    pub merchant_city: String,                 // Cidade (máx 15 chars)
    pub additional_data: Option<AdditionalData>,
    pub crc16: String,                        // Checksum CRC16
}

Informações da Conta PIX

pub struct MerchantAccountInfo {
    pub gui: String,                          // "br.gov.bcb.pix"
    pub pix_key: String,                      // Chave PIX
    pub description: Option<String>,          // Descrição opcional
    pub url: Option<String>,                  // URL para QR dinâmicos
}

Dados Adicionais

pub struct AdditionalData {
    pub bill_number: Option<String>,
    pub mobile_number: Option<String>,
    pub store_label: Option<String>,
    pub loyalty_number: Option<String>,
    pub reference_label: Option<String>,      // Etiqueta de referência
    pub customer_label: Option<String>,
    pub terminal_label: Option<String>,
    pub purpose_of_transaction: Option<String>,
    pub additional_consumer_data_request: Option<String>,
}

Validações Implementadas

  • Checksum CRC16: Validação completa usando CRC-16/CCITT-FALSE
  • GUI PIX: Deve ser "br.gov.bcb.pix"
  • Código da Moeda: Deve ser "986" (Real Brasileiro)
  • Código do País: Deve ser "BR"
  • Indicador de Formato: Deve ser "01"
  • Limites de Campo:
    • Nome do comerciante: máximo 25 caracteres
    • Cidade: máximo 15 caracteres
    • Etiqueta de referência: máximo 25 caracteres
  • Formato da Chave PIX: Validação básica de caracteres

Executando os Exemplos

# Exemplo de análise
cargo run --example parse_pix_qr

# Exemplo de geração
cargo run --example generate_pix_qr

Executando os Testes

# Testes unitários
cargo test --lib

# Todos os testes
cargo test

# Com saída detalhada
cargo test -- --nocapture

Compatibilidade

  • Rust: 1.70+
  • Plataformas: Windows, Linux, macOS
  • Arquiteturas: x86_64, ARM64

Licença

Dual licensed under MIT OR Apache-2.0.

Contribuindo

Contribuições são bem-vindas! Por favor:

  1. Fork o repositório
  2. Crie uma branch para sua feature
  3. Adicione testes para novas funcionalidades
  4. Execute cargo test para garantir que tudo funciona
  5. Envie um Pull Request

Recursos Úteis


Esta biblioteca foi desenvolvida para facilitar a integração com o sistema PIX brasileiro, seguindo rigorosamente os padrões EMV QRCPS e as especificações do Banco Central do Brasil.