| Crates.io | pix-brcode-parser |
| lib.rs | pix-brcode-parser |
| version | 0.1.0 |
| created_at | 2025-07-31 02:02:12.297447+00 |
| updated_at | 2025-07-31 02:02:12.297447+00 |
| description | A Rust library for parsing and validating Brazilian PIX QR codes (BR Code) following EMV QRCPS standard |
| homepage | |
| repository | https://github.com/leandrosmoreira53/pix-brcode-parser |
| max_upload_size | |
| id | 1774306 |
| size | 62,615 |
Uma biblioteca Rust para análise e validação de códigos QR PIX (BR Code) brasileiros seguindo o padrão EMV QRCPS.
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"] }
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);
}
}
}
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);
}
}
}
// 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");
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);
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);
}
}
}
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);
}
_ => {}
}
#[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);
}
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
}
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
}
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>,
}
# Exemplo de análise
cargo run --example parse_pix_qr
# Exemplo de geração
cargo run --example generate_pix_qr
# Testes unitários
cargo test --lib
# Todos os testes
cargo test
# Com saída detalhada
cargo test -- --nocapture
Dual licensed under MIT OR Apache-2.0.
Contribuições são bem-vindas! Por favor:
cargo test para garantir que tudo funcionaEsta 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.