stone_deep_tech 1.0.0 copy "stone_deep_tech: ^1.0.0" to clipboard
stone_deep_tech: ^1.0.0 copied to clipboard

PlatformAndroid

Plugin Flutter para integração com Deeplink da Stone para meios de pagamento.

Stone Deep Tech #

Stone

🚨 Aviso #

Este plugin é não oficial e foi desenvolvido de forma independente para facilitar a integração de pagamentos via Deeplink da Stone em dispositivos Android Smart POS.


Plugin Flutter para integração com o sistema de Deeplinks da Stone para meios de pagamento, impressão e reimpressão de comprovantes.

📋 Descrição #

O Stone Deep Tech é um plugin Flutter que permite que desenvolvedores integrem seus aplicativos com o sistema de pagamento da Stone através de deeplinks, sem precisar lidar diretamente com código nativo Android. O plugin oferece uma interface simples e intuitiva para realizar operações de pagamento, cancelamento, impressão customizada e reimpressão de comprovantes.

✨ Funcionalidades #

  • Pagamento: Envio de deeplinks para processamento de pagamentos
  • Cancelamento: Cancelamento de transações através de deeplink
  • Impressão Customizada: Impressão de conteúdo personalizado (texto, linhas, imagens)
  • Reimpressão: Reimpressão de comprovantes de transações anteriores
  • Validação de Licença: Sistema integrado de validação de licença
  • Callbacks Assíncronos: Recebimento de respostas de forma assíncrona
  • Type Safety: Enums para maior segurança de tipos
  • Suporte Completo: DEBIT, CREDIT, VOUCHER, INSTANT_PAYMENT e PIX

📦 Requisitos #

  • Flutter SDK: >=3.0.0
  • Android: SDK mínimo 24 (Android 7.0)
  • Aplicativo Stone instalado no dispositivo

🚀 Instalação #

Adicione o plugin ao seu pubspec.yaml:

dependencies:
  stone_deep_tech:
    path: ../stone_deep_tech # ou use a versão do pub.dev

Execute:

flutter pub get

⚙️ Configuração Android #

1. Configurar o AndroidManifest.xml #

Adicione o intent-filter necessário para receber respostas de deeplink no seu AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:launchMode="singleTop"
    ...>
    <!-- ... outros intent-filters ... -->

    <!-- Intent filter para receber respostas de deeplink da Stone -->
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data
            android:host="pay-response"
            android:scheme="@string/return_scheme" />
    </intent-filter>
</activity>

Importante: O launchMode="singleTop" é necessário para garantir que o app não crie múltiplas instâncias ao receber deeplinks.

2. Configurar o Scheme de Retorno #

Crie ou atualize o arquivo res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="return_scheme">seu_app_scheme</string>
</resources>

Substitua seu_app_scheme pelo scheme único do seu aplicativo (ex: meuapp, stone_deep_tech_example).

3. Configurar as Chaves de Licença #

O plugin requer chaves de licença para funcionar. Configure-as de uma das seguintes formas:

Opção A: Variáveis de Ambiente

export LICENCE_KEY="sua_chave_aqui"
export LICENCE_INTERNAL_KEY="aHR0cHM6Ly9wb3MtcGF5bWVudHMtYXBpLTU3NzQ2NDIzNTQwOC5zb3V0aGFtZXJpY2EtZWFzdDEucnVuLmFwcC9wb3MtcGF5bWVudHMvbGljZW5jZS9jaGVjay9pbnZvaWNl"

Opção B: Arquivo local.properties

Crie ou edite o arquivo android/local.properties na raiz do projeto do plugin:

licenceKey=sua_chave_aqui
licenceInternalKey=aHR0cHM6Ly9wb3MtcGF5bWVudHMtYXBpLTU3NzQ2NDIzNTQwOC5zb3V0aGFtZXJpY2EtZWFzdDEucnVuLmFwcC9wb3MtcGF5bWVudHMvbGljZW5jZS9jaGVjay9pbnZvaWNl

Importante: O arquivo local.properties geralmente está no .gitignore e não deve ser commitado no controle de versão.

4. Validação de Licença #

O plugin valida automaticamente a licença antes de permitir qualquer operação. Se a licença não estiver válida ou não estiver configurada, todas as chamadas de método retornarão um erro com código LICENCE_ERROR.

Como funciona:

  1. Primeiro verifica se existe uma licença válida armazenada localmente (criptografada)
  2. Se não existir ou estiver expirada, faz uma requisição ao servidor de licenciamento
  3. A licença é armazenada localmente de forma criptografada por até 7 dias
  4. Após 7 dias, a validação é feita novamente contra o servidor
  5. Se a validação falhar, todas as operações são bloqueadas

📖 Como Usar #

1. Inicializar o Plugin #

Primeiro, crie um handler para receber os callbacks:

import 'package:stone_deep_tech/stone_deep_tech.dart';

class MyDeepLinkHandler implements IDeepLinkHandler {
  @override
  Future<void> onDeeplinkResponse(String responseUri) async {
    print('Resposta recebida: $responseUri');
    // Processe a resposta aqui
    // Exemplo: extrair código de resultado, ATK, etc.
  }

  @override
  Future<void> onError(String message) async {
    print('Erro: $message');
    // Trate erros aqui
  }

  @override
  Future<void> onDeeplinkSent() async {
    print('Deeplink enviado com sucesso');
  }
}

// Inicialize o plugin
final handler = MyDeepLinkHandler();
StoneDeepTech.I.initDeeplink(handler: handler);

2. Enviar Pagamento #

import 'package:stone_deep_tech/stone_deep_tech.dart';

final params = DeeplinkParams(
  amount: 10000, // R$ 100,00 em centavos
  editableAmount: false, // Não permite editar valor (padrão)
  transactionType: TransactionType.debit, // DEBIT, CREDIT, VOUCHER, INSTANT_PAYMENT, PIX
  returnScheme: 'seu_app_scheme', // Deve corresponder ao strings.xml
  // Parâmetros opcionais:
  installmentCount: 3, // Número de parcelas (2 a 99)
  installmentType: InstallmentType.merchant, // MERCHANT, ISSUER, ou NONE
  orderId: 12345, // ID do pedido
);

final success = await StoneDeepTech.I.deeplink.sendDeeplink(params);
if (success) {
  print('Deeplink de pagamento enviado!');
} else {
  print('Erro ao enviar deeplink');
}

Nota: O campo installmentType só é enviado quando transactionType é credit.

3. Cancelar Transação #

import 'package:stone_deep_tech/stone_deep_tech.dart';

final cancelParams = CancelParams(
  returnScheme: 'seu_app_scheme',
  atk: 'codigo_atk_da_transacao', // Código único da transação gerado pelo autorizador
  amount: 10000, // Valor em centavos (opcional)
  editableAmount: false, // Não permite editar valor (padrão)
);

final success = await StoneDeepTech.I.deeplink.sendCancel(cancelParams);
if (success) {
  print('Deeplink de cancelamento enviado!');
}

4. Impressão Customizada #

import 'package:stone_deep_tech/stone_deep_tech.dart';
import 'dart:convert';

// Criar conteúdo de impressão
final printContent = [
  // Texto customizado
  TextPrintContent(
    content: 'LOJA EXEMPLO',
    align: PrintTextAlign.center,
    size: PrintTextSize.big,
  ),

  // Linha simples
  LinePrintContent(content: '--------------------------------'),

  // Texto alinhado à esquerda
  TextPrintContent(
    content: 'Produto: Item 1',
    align: PrintTextAlign.left,
    size: PrintTextSize.small,
  ),

  // Texto alinhado à direita
  TextPrintContent(
    content: 'R\$ 100,00',
    align: PrintTextAlign.right,
    size: PrintTextSize.medium,
  ),

  // Imagem (Base64)
  ImagePrintContent(
    imagePath: 'iVBORw0KGgoAAAANSUhEUgAA...', // String Base64
  ),
];

final printParams = PrintParams(
  schemeReturn: 'seu_app_scheme',
  printableContent: printContent,
  showFeedbackScreen: true, // Mostrar tela de sucesso/erro
);

final success = await StoneDeepTech.I.deeplink.sendPrint(printParams);
if (success) {
  print('Deeplink de impressão enviado!');
}

5. Reimpressão de Comprovante #

import 'package:stone_deep_tech/stone_deep_tech.dart';

final reprintParams = ReprintParams(
  schemeReturn: 'seu_app_scheme',
  atk: 'codigo_atk_da_transacao', // Código único da transação
  typeCustomer: TypeCustomer.client, // CLIENT ou MERCHANT
  showFeedbackScreen: true, // Mostrar tela de sucesso/erro
);

final success = await StoneDeepTech.I.deeplink.sendReprint(reprintParams);
if (success) {
  print('Deeplink de reimpressão enviado!');
}

6. Processar Resultados de Impressão #

import 'package:stone_deep_tech/stone_deep_tech.dart';

class MyDeepLinkHandler implements IDeepLinkHandler {
  @override
  Future<void> onDeeplinkResponse(String responseUri) async {
    // Verificar se é um resultado de impressão
    final printResult = DeeplinkResponseParser.parsePrintResult(responseUri);

    if (printResult != null) {
      switch (printResult) {
        case PrintResult.success:
          print('Impressão realizada com sucesso!');
          break;
        case PrintResult.printerOutOfPaper:
          print('Impressora sem papel ou com tampa aberta');
          break;
        case PrintResult.printerInitError:
          print('Erro ao inicializar impressora');
          break;
        // ... outros casos
        default:
          print('Erro: ${printResult.description}');
      }
    } else {
      // Processar outros tipos de resposta (pagamento, cancelamento, etc.)
      print('Resposta recebida: $responseUri');
    }
  }

  // ... outros métodos
}

📚 API Completa #

StoneDeepTech #

Classe principal do plugin, singleton.

Métodos

  • static StoneDeepTech get I - Retorna a instância singleton
  • Deeplink initDeeplink({required IDeepLinkHandler handler}) - Inicializa o plugin com um handler

DeeplinkParams #

Parâmetros para envio de pagamento.

Propriedades

Propriedade Tipo Obrigatório Padrão Descrição
amount int? Não - Valor em centavos (ex: 10000 = R$ 100,00)
editableAmount bool Não false Permite editar valor no app de pagamento
transactionType TransactionType? Não - DEBIT, CREDIT, VOUCHER, INSTANT_PAYMENT, PIX
installmentCount int? Não - Número de parcelas (2 a 99)
installmentType InstallmentType? Não NONE MERCHANT, ISSUER, ou NONE
orderId int? Não - ID do pedido para rastreamento
returnScheme String Sim - Scheme do app para receber resposta

Enums

TransactionType:

  • debit - Débito
  • credit - Crédito
  • voucher - Voucher
  • instantPayment - Pagamento instantâneo
  • pix - PIX

InstallmentType:

  • merchant - Parcelado sem juros
  • issuer - Parcelado com juros
  • none - À vista (padrão)

CancelParams #

Parâmetros para cancelamento.

Propriedades

Propriedade Tipo Obrigatório Padrão Descrição
returnScheme String Sim - Scheme do app para receber resposta
atk String Sim - Código único da transação
amount int? Não - Valor em centavos
editableAmount bool Não false Permite editar valor

PrintParams #

Parâmetros para impressão customizada.

Propriedades

Propriedade Tipo Obrigatório Padrão Descrição
schemeReturn String Sim - Scheme do app para receber resposta
printableContent List<PrintContent> Sim - Lista de conteúdo para impressão
showFeedbackScreen bool Não true Mostrar tela de sucesso/erro

Tipos de Conteúdo

TextPrintContent:

  • content (String) - Texto a ser impresso
  • align (PrintTextAlign) - center, right, left
  • size (PrintTextSize) - big, medium, small

LinePrintContent:

  • content (String) - Texto sem customização

ImagePrintContent:

  • imagePath (String) - Imagem em Base64

ReprintParams #

Parâmetros para reimpressão.

Propriedades

Propriedade Tipo Obrigatório Padrão Descrição
schemeReturn String Sim - Scheme do app para receber resposta
atk String Sim - Código único da transação
typeCustomer TypeCustomer Sim - CLIENT ou MERCHANT
showFeedbackScreen bool Não true Mostrar tela de sucesso/erro

Enums

TypeCustomer:

  • client - Comprovante do cliente
  • merchant - Comprovante do lojista

PrintResult #

Resultados possíveis de impressão/reimpressão.

Valores

Resultado Código Descrição
success SUCCESS Impressão realizada com sucesso
printerOutOfPaper PRINTER_OUT_OF_PAPER Impressora sem papel ou com tampa aberta
printerInitError PRINTER_INIT_ERROR Erro ao inicializar impressora
printerLowEnergy PRINTER_LOW_ENERGY Máquina com baixa energia
printerBusy PRINTER_BUSY Impressora ocupada
printerUnsupportedFormat PRINTER_UNSUPPORTED_FORMAT Formato não suportado
printerInvalidData PRINTER_INVALID_DATA Limite máximo do buffer ultrapassado
printerOverheating PRINTER_OVERHEATING Superaquecimento da impressora
printerPaperJam PRINTER_PAPER_JAM Papel preso na caixa de bobina
printerPrintError PRINTER_PRINT_ERROR Erro genérico da impressora

IDeepLinkHandler #

Interface para receber callbacks do plugin.

Métodos

  • Future<void> onDeeplinkResponse(String responseUri) - Chamado quando uma resposta é recebida
  • Future<void> onError(String message) - Chamado quando ocorre um erro
  • Future<void> onDeeplinkSent() - Chamado quando o deeplink é enviado

💡 Exemplos Completos #

Exemplo 1: Pagamento Simples #

import 'package:flutter/material.dart';
import 'package:stone_deep_tech/stone_deep_tech.dart';

class PaymentPage extends StatefulWidget {
  @override
  _PaymentPageState createState() => _PaymentPageState();
}

class _PaymentPageState extends State<PaymentPage> implements IDeepLinkHandler {
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    StoneDeepTech.I.initDeeplink(handler: this);
  }

  Future<void> processPayment() async {
    setState(() => _isLoading = true);

    final params = DeeplinkParams(
      amount: 10000, // R$ 100,00
      editableAmount: false,
      transactionType: TransactionType.debit,
      returnScheme: 'meuapp',
    );

    await StoneDeepTech.I.deeplink.sendDeeplink(params);
  }

  @override
  Future<void> onDeeplinkResponse(String responseUri) async {
    setState(() => _isLoading = false);
    print('Resposta: $responseUri');
    // Processar resposta...
  }

  @override
  Future<void> onError(String message) async {
    setState(() => _isLoading = false);
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Erro: $message')),
    );
  }

  @override
  Future<void> onDeeplinkSent() async {
    print('Deeplink enviado');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Pagamento')),
      body: Center(
        child: ElevatedButton(
          onPressed: _isLoading ? null : processPayment,
          child: _isLoading
            ? CircularProgressIndicator()
            : Text('Pagar R\$ 100,00'),
        ),
      ),
    );
  }
}

Exemplo 2: Impressão com Tratamento de Erros #

import 'package:stone_deep_tech/stone_deep_tech.dart';

class PrintHandler implements IDeepLinkHandler {
  @override
  Future<void> onDeeplinkResponse(String responseUri) async {
    final printResult = DeeplinkResponseParser.parsePrintResult(responseUri);

    if (printResult != null) {
      if (printResult == PrintResult.success) {
        print('✅ Impressão realizada com sucesso!');
      } else {
        print('❌ Erro na impressão: ${printResult.description}');
        // Exibir mensagem de erro ao usuário
      }
    }
  }

  @override
  Future<void> onError(String message) async {
    print('Erro: $message');
    if (message.contains('LICENCE_ERROR')) {
      print('Licença inválida ou não configurada');
    }
  }

  @override
  Future<void> onDeeplinkSent() async {
    print('Enviando impressão...');
  }
}

void printReceipt() {
  final handler = PrintHandler();
  StoneDeepTech.I.initDeeplink(handler: handler);

  final content = [
    TextPrintContent(
      content: 'COMPROVANTE DE VENDA',
      align: PrintTextAlign.center,
      size: PrintTextSize.big,
    ),
    LinePrintContent(content: '--------------------------------'),
    TextPrintContent(
      content: 'Valor: R\$ 100,00',
      align: PrintTextAlign.left,
      size: PrintTextSize.medium,
    ),
  ];

  final params = PrintParams(
    schemeReturn: 'meuapp',
    printableContent: content,
    showFeedbackScreen: true,
  );

  StoneDeepTech.I.deeplink.sendPrint(params);
}

🔍 Tratamento de Erros #

Erros de Licença #

try {
  await StoneDeepTech.I.deeplink.sendDeeplink(params);
} catch (e) {
  if (e.toString().contains('LICENCE_ERROR')) {
    // Licença inválida ou não configurada
    print('Configure as chaves de licença no local.properties');
  }
}

Erros de Validação #

O plugin valida automaticamente:

  • Licença configurada
  • Licença válida no servidor
  • Parâmetros obrigatórios presentes

Erros de Impressão #

Use o enum PrintResult para identificar erros específicos:

final printResult = DeeplinkResponseParser.parsePrintResult(responseUri);
if (printResult == PrintResult.printerOutOfPaper) {
  // Informar usuário sobre falta de papel
}

🐛 Troubleshooting #

Solução:

  1. Verifique se o aplicativo Stone está instalado
  2. Verifique se o returnScheme está configurado corretamente
  3. Verifique os logs do Android para erros

Problema: Resposta não é recebida #

Solução:

  1. Verifique se o intent-filter está configurado no AndroidManifest.xml
  2. Verifique se o launchMode="singleTop" está configurado
  3. Verifique se o returnScheme corresponde ao strings.xml
  4. Verifique se o handler está implementado corretamente

Problema: Erro de licença #

Solução:

  1. Verifique se as chaves estão configuradas em local.properties ou variáveis de ambiente
  2. Verifique se as chaves são válidas
  3. Verifique a conexão com a internet (primeira validação)
  4. Verifique os logs para mensagens de erro específicas

Problema: Parcelamento não funciona #

Solução:

  1. Verifique se transactionType é credit
  2. Verifique se installmentCount está entre 2 e 99
  3. Lembre-se: installmentType só é enviado quando transactionType é credit

📁 Estrutura do Projeto #

lib/
├── src/
│   ├── deeplink/
│   │   └── deeplink.dart              # Classe principal de deeplink
│   ├── interface/
│   │   ├── handler/
│   │   │   └── ideeplink_handler.dart  # Interface de handler
│   │   └── model/
│   │       ├── deeplink_params.dart   # Parâmetros de pagamento
│   │       ├── cancel_params.dart     # Parâmetros de cancelamento
│   │       ├── print_params.dart      # Parâmetros de impressão
│   │       ├── print_result.dart      # Resultados de impressão
│   │       └── reprint_params.dart    # Parâmetros de reimpressão
│   └── licence/
│       ├── constants/
│       │   └── licence_constants.dart  # Constantes de licença
│       └── licence.dart               # Exportação do módulo
└── stone_deep_tech.dart               # Classe principal do plugin

📝 Notas Importantes #

  1. Validação de Licença: Todas as operações são bloqueadas se a licença não for válida
  2. Thread Safety: O plugin é thread-safe e pode ser usado de qualquer thread
  3. Singleton: O plugin usa o padrão singleton, então sempre use StoneDeepTech.I
  4. Callbacks: Os callbacks são assíncronos e podem ser chamados de qualquer thread
  5. Parcelamento: installmentType só é enviado quando transactionType é credit
  6. Impressão: Imagens devem estar em formato Base64
  7. Valores: Todos os valores monetários são em centavos (inteiros)

🔗 Referências #

📄 Licença #

Veja o arquivo LICENSE para mais detalhes.

📞 Suporte #

Para suporte, abra uma issue no repositório do projeto.


Desenvolvido com ❤️ para facilitar a integração com Stone Payment



2
likes
150
points
7
downloads

Publisher

verified publisherjylabtech.com.br

Weekly Downloads

Plugin Flutter para integração com Deeplink da Stone para meios de pagamento.

Homepage

Documentation

API reference

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on stone_deep_tech

Packages that implement stone_deep_tech