stone_deep_tech 1.1.0 copy "stone_deep_tech: ^1.1.0" to clipboard
stone_deep_tech: ^1.1.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.

A implementação nativa Android é distribuída como um binário privado embarcado no plugin. Nenhum passo adicional de build é necessário para consumidores.

✨ 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 #

As chaves de licença agora são enviadas pelo código Dart ao inicializar o plugin:

StoneDeepTech.I.initDeeplink(
  handler: handler,
  licenceKey: const String.fromEnvironment('STONE_DEEP_TECH_LICENCE_KEY'),
  licenceInternalKey: const String.fromEnvironment('STONE_DEEP_TECH_LICENCE_INTERNAL_KEY'),
);

Sugerimos definir as chaves com --dart-define (ou outro mecanismo seguro) ao executar seu app:

flutter run \
  --dart-define STONE_DEEP_TECH_LICENCE_KEY="sua_chave_aqui" \
  --dart-define STONE_DEEP_TECH_LICENCE_INTERNAL_KEY="aHR0cHM6Ly9wb3MtcGF5bWVudHMtYXBpLTU3NzQ2NDIzNTQwOC5zb3V0aGFtZXJpY2EtZWFzdDEucnVuLmFwcC9wb3MtcGF5bWVudHMvbGljZW5jZS9jaGVjay9pbnZvaWNl"

Alternativamente, armazene as chaves em um serviço seguro (ex.: vault, remote config) e só então invoque initDeeplink.

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,
  licenceKey: 'SUA_CHAVE',
  licenceInternalKey: 'SUA_CHAVE_INTERNA',
);

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, required String licenceKey, required String licenceInternalKey}) - Inicializa o plugin com um handler e configura as chaves de licença

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,
      licenceKey: 'SUA_CHAVE',
      licenceInternalKey: 'SUA_CHAVE_INTERNA',
    );
  }

  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,
    licenceKey: 'SUA_CHAVE',
    licenceInternalKey: 'SUA_CHAVE_INTERNA',
  );

  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 antes de chamar initDeeplink (ex.: via --dart-define).');
  }
}

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 sendo fornecidas ao chamar StoneDeepTech.I.initDeeplink
  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
12
downloads

Documentation

API reference

Publisher

verified publisherjylabtech.com.br

Weekly Downloads

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

Homepage

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on stone_deep_tech

Packages that implement stone_deep_tech