📚 Módulo 12: Mobile - Integração com Câmera (Leitor QRCode Pix) e Compilação EAS Cloud Build

Neste módulo final de encerramento da TecLoja 03, daremos o toque profissional e nativo definitivo ao nosso aplicativo móvel.

Implementaremos o fluxo de checkout e faturamento móvel integrando a Câmera do Dispositivo para leitura e decodificação de códigos QR de pagamento Pix. Por fim, utilizaremos os serviços em nuvem do Expo (EAS Build) para compilar o binário nativo final (.apk / .aab) de forma automática, eliminando a dependência de termos o Android Studio local instalado.


🗺️ 1. Fluxo de Checkout Pix Nativo e Leitura de Câmera

Abaixo, descrevemos a interação sequencial entre a câmera física do aparelho, a decodificação da string Pix e o encerramento do pedido no NestJS:

sequenceDiagram
    participant U as Usuário (App)
    participant C as Expo Camera Component
    participant P as Pix Decoder (Scanner)
    participant N as API NestJS (Backend)

    U->>C: Clica em "Pagar com QRCode"
    C->>U: Exibe tela de captura de câmera
    U->>C: Aponta a câmera para o QR Code do Pix
    C->>P: Captura frames de vídeo em tempo real
    P-->>C: QR Code detectado e decodificado
    C->>N: Enviar confirmação de pagamento (/api/pedidos/faturar)
    N-->>U: Exibe "Pedido Realizado com Sucesso!"

📸 2. Leitor de QRCode Pix com expo-camera

Para capturar códigos QR em tempo real, utilizaremos o módulo de câmera oficial do ecossistema Expo.

Instalação

npx expo install expo-camera

Configuração de Permissões Nativa

Ao contrário do Android puro, o Expo gerencia as permissões no arquivo de configuração do app app.json. Abra app.json e adicione o plugin de câmera:

{
  "expo": {
    "name": "TecLoja 03 Mobile",
    "slug": "tecloja-03-mobile",
    "plugins": [
      [
        "expo-camera",
        {
          "cameraPermission": "Permitir acesso à câmera para ler códigos QR de pagamento do Pix."
        }
      ]
    ]
  }
}

Implementação da Tela de Pagamento (app/pagamento.tsx)

Crie o arquivo de tela de pagamento móvel utilizando os novos recursos:

import React, { useState, useEffect } from 'react';
import { StyleSheet, Text, View, Button, TouchableOpacity } from 'react-native';
import { Camera, CameraView } from 'expo-camera';
import { router } from 'expo-router';

export default function PagamentoScreen() {
  const [temPermissao, setTemPermissao] = useState<boolean | null>(null);
  const [escanado, setEscanado] = useState(false);

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setTemPermissao(status === 'granted');
    })();
  }, []);

  const handleBarCodeScanned = ({ type, data }: { type: string, data: string }) => {
    setEscanado(true);
    // Simulação didática de validação de código Pix da TecLoja
    if (data.startsWith('000201')) {
      alert(`Pagamento Pix processado com sucesso!\nDados: ${data.substring(0, 30)}...`);
      router.replace('/(tabs)');
    } else {
      alert('Código QR inválido. Certifique-se de apontar para um Pix válido.');
      setEscanado(false);
    }
  };

  if (temPermissao === null) {
    return <View style={styles.container}><Text style={styles.texto}>Solicitando permissão de câmera...</Text></View>;
  }
  if (temPermissao === false) {
    return <View style={styles.container}><Text style={styles.texto}>Acesso à câmera foi negado.</Text></View>;
  }

  return (
    <View style={styles.container}>
      <Text style={styles.instrucoes}>Aponte a câmera para o QR Code de pagamento</Text>
      
      <CameraView
        onBarcodeScanned={escanado ? undefined : handleBarCodeScanned}
        barcodeScannerSettings={{
          barcodeTypes: ['qr'],
        }}
        style={StyleSheet.absoluteFillObject}
      />

      {escanado && (
        <TouchableOpacity style={styles.botaoReiniciar} onPress={() => setEscanado(false)}>
          <Text style={styles.botaoTexto}>Escanear Novamente</Text>
        </TouchableOpacity>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    backgroundColor: '#000',
  },
  texto: {
    color: '#fff',
    textAlign: 'center',
    fontSize: 18,
  },
  instrucoes: {
    color: '#fff',
    textAlign: 'center',
    fontSize: 16,
    position: 'absolute',
    top: 40,
    width: '100%',
    zIndex: 10,
    backgroundColor: 'rgba(15, 23, 42, 0.8)',
    paddingVertical: 12,
  },
  botaoReiniciar: {
    position: 'absolute',
    bottom: 40,
    alignSelf: 'center',
    backgroundColor: '#38bdf8',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
    zIndex: 10,
  },
  botaoTexto: {
    color: '#0f172a',
    fontWeight: 'bold',
  }
});

🏗️ 3. Compilação Automatizada na Nuvem via EAS Build

Uma das maiores dores no desenvolvimento móvel tradicional é a necessidade de possuir um computador macOS potente para compilar binários iOS ou configurar o pesado ambiente do Android Studio localmente. O EAS (Expo Application Services) resolve isso realizando as compilações em servidores dedicados na nuvem do Expo.

Passo a Passo para Gerar a Build na Nuvem:

  1. Instalar a CLI Global do EAS: No console global da sua máquina, instale a ferramenta de nuvem:
    npm install -g eas-cli
    
  2. Autenticar ou Criar Conta no Expo: Crie uma conta gratuita em expo.dev e autentique-se no console local:
    eas login
    
  3. Configurar o Projeto para Builds: Inicialize as configurações do EAS no projeto móvel. O comando lerá as propriedades locais e criará um arquivo eas.json:
    eas build:configure
    
  4. Ajustar o eas.json para Gerar APK de Testes: Por padrão, compilações Android de release geram o formato .aab (Android App Bundle, aceito apenas pela Play Store). Para testes locais, altere o perfil preview no arquivo eas.json para produzir um arquivo .apk instalável:
    {
      "cli": {
        "version": ">= 9.0.0"
      },
      "build": {
        "development": {
          "developmentClient": true,
          "distribution": "internal"
        },
        "preview": {
          "distribution": "internal",
          "android": {
            "buildType": "apk"
          }
        },
        "production": {}
      }
    }
    
  5. Disparar a Build na Nuvem: Execute o comando abaixo para iniciar o empacotamento em fila na nuvem:
    eas build --platform android --profile preview
    
  6. A CLI compactará o código JS e o enviará para os servidores do Expo. O console exibirá um link de rastreamento onde você poderá acompanhar o andamento em tempo real.
  7. Ao final da build, um QR Code será exibido diretamente no seu terminal. Basta escaneá-lo com seu celular para baixar e instalar o APK compilado nativo de sua TecLoja 03 instantaneamente!

✅ Pré-Requisitos deste Módulo

Antes de compilar a versão final móvel, confirme se:


🤔 Por que fizemos assim?


🔍 Checkpoint

  1. Validação de Câmera: Inicie a tela de pagamento e confirme se o pop-up nativo solicitando acesso à câmera é disparado. Aponte para um gerador de Pix online e confirme se a decodificação ocorre em tempo real.
  2. Build Concluído: Acesse seu dashboard no site expo.dev e valide se a build do projeto consta como concluída (status “Success”) e possui o APK disponível para download.

⚠️ Erros Comuns

Erro Causa Solução
Camera permission denied O usuário negou o acesso ou os metadados do plugin de câmera não foram inseridos no app.json. Insira o bloco de plugins da câmera no app.json e limpe os dados do aplicativo no menu de configurações do Android.
O leitor de código escaneia o Pix mas não dispara nenhuma ação A string do Pix gerada não inicia com o cabeçalho padrão EMV ou a função de callback está com o estado de travamento de scan travado em true. Garanta que o código do scanner verifique corretamente a assinatura 000201 e resete a variável reativa escanado em caso de erro.
Fila de build no EAS muito demorada Contas gratuitas do Expo compartilham uma fila de espera comunitária que pode demorar em horários de pico. Planeje a build final com antecedência ou utilize o comando de build local npx expo run:android caso possua o Android Studio completo e potente instalado na máquina local.

Voltar para o Sumário