Nota: Este artigo é uma tradução automática do post original em japonês. Se notar algum erro de tradução, por favor nos informe.
Aqui está uma explicação técnica do sistema de autocaixa totalmente sem dinheiro que construímos em apenas dois dias para a abertura da LOPPO Art Supply Shibuya Store (um ponto de venda autônomo).
Introdução: O projeto da loja autônoma LOPPO Art Supply
LOPPO Art Supply é uma marca de materiais artísticos para animação cel que começou como um hobby de Takahashi e tem sido comercializada principalmente através de vendas online. No início deste ano, decidimos alugar um pequeno espaço como local de eventos para a LOPPO Art Supply. Tínhamos planejado usar um canto como depósito, mas surgiu a ideia: "Se vamos armazenar estoque aqui de qualquer forma, por que não transformá-lo em um ponto de venda?"
Já existiam pedidos para uma loja física há algum tempo, mas garantir os recursos humanos necessários para a operação da loja era um desafio. Foi quando surgiu o conceito de uma "loja de materiais artísticos autônoma". Pense em uma banca de verduras self-service, mas para materiais de animação cel — um lugar dos sonhos (ou insano!) onde se pode comprar 24 horas por dia, 365 dias por ano.
Loja de materiais artísticos autônoma (imagem conceitual)
1. Desafios das soluções de autocaixa existentes
Para criar uma loja autônoma que não exija funcionários no local, é essencial um sistema de autocaixa totalmente automatizado. Para este projeto, decidimos aceitar apenas pagamentos sem dinheiro como medida de prevenção contra roubo.
Inicialmente consideramos soluções de autocaixa comerciais, mas encontramos dois problemas principais:
- Altos custos fixos mensais além dos custos iniciais de configuração
- Longos ciclos entre a liquidação e o depósito
Para garantir a sustentabilidade, é importante manter os custos fixos ao mínimo enquanto se mantém um fluxo de caixa saudável. Foi então que voltamos nossa atenção para o sistema de pagamento Square, que já havíamos utilizado em vendas em eventos.
O Square suporta uma ampla variedade de métodos de pagamento, não cobra taxas mensais (apenas comissões por transação) e oferece depósitos rápidos — já no próximo dia útil. Além disso, a Square API permite a criação de aplicações personalizadas. Como já possuíamos um Square Terminal, determinamos que seu aproveitamento também manteria os custos iniciais baixos.
No entanto, havia uma grande restrição no desenvolvimento. Já estávamos sobrecarregados com a fabricação de produtos para a abertura da loja e só pudemos dedicar apenas 2 dias ao desenvolvimento do sistema de autocaixa.
2. Design do sistema: Um autocaixa seguro e fácil de usar
Arquitetura geral
O sistema é composto pelos seguintes componentes principais:
- Servidor de aplicação Linux: Frontend React e backend Express
- Sistema na loja: Terminal cliente em modo quiosque Windows 11 Pro, periféricos e Square Terminal
- Serviços Square: Square API, dados mestres de produtos
- Monitoramento e operações: Câmeras de segurança, fonte de alimentação ininterrupta (UPS), redundância de rede
Da perspectiva do cliente, apenas o monitor sensível ao toque, o leitor de código de barras e o Square Terminal são visíveis. O cliente funciona em modo quiosque do Windows 11 Pro, enquanto a lógica principal da aplicação reside em uma máquina Linux localizada fora da loja.
Segurança e rede
A rede opera em um ambiente VPN usando Tailscale, que protege a comunicação entre o terminal cliente e o servidor Linux. Além disso, todos os dispositivos estão conectados a uma fonte de alimentação ininterrupta para proteção contra raios e quedas de energia, e a rede é configurada com redundância para garantir uma operação estável.
A adoção do Tailscale também facilita a manutenção remota. Nenhum dado local é armazenado em nenhum terminal — todos os dados são obtidos dos sistemas do Square.
Configuração de hardware
- Monitor sensível ao toque
- Leitor de código de barras USB
- Square Terminal (processamento de pagamentos e impressão de recibos)
- Câmera de segurança (para monitoramento em tempo real)
Implementação do frontend
Tela de seleção do método de pagamento
O frontend é construído com React e consiste nas seguintes telas principais:
- Tela de escaneamento de produtos
- Tela de seleção do método de pagamento
- Tela de processamento do pagamento
- Tela de pagamento concluído
Embora utilizando tradução automática, também implementamos suporte multilíngue, cobrindo 6 idiomas: japonês, inglês, francês, espanhol, chinês tradicional e chinês simplificado. Isso permite que visitantes internacionais usem o sistema com confiança.
// Exemplo de configuração de idiomas
const translations = {
ja: {
title: 'セルフレジシステム',
scanTitle: '商品スキャン',
// ...omitido
},
en: {
title: 'Self-Checkout System',
scanTitle: 'Product Scan',
// ...omitido
},
// Outros idiomas...
};
Também projetamos o sistema para priorizar a entrada do leitor de código de barras, visando uma interface que os usuários possam operar sem confusão.
3. Pontos-chave da integração com Square API
Processamento de pagamentos com Terminal API
Entre as APIs do Square, a Terminal API é particularmente importante. Ela nos permite enviar solicitações de processamento de pagamento ao Square Terminal.
// Criar checkout do Terminal
app.post("/api/create-terminal-checkout", async (req, res) => {
try {
const { order, amountMoney, paymentType = "CARD_PRESENT" } = req.body;
const ALLOWED = new Set([
"CARD_PRESENT",
"FELICA_TRANSPORTATION_GROUP",
"FELICA_ID",
"FELICA_QUICPAY",
"QR_CODE"
]);
if (!ALLOWED.has(paymentType)) {
return res.status(400).json({ error: "Método de pagamento não suportado especificado" });
}
// Criar o pedido primeiro
const orderId = await createOrder(order);
// Criar Square Terminal Checkout
const checkoutResponse = await squareClient.terminal.checkouts.create({
idempotencyKey: randomUUID(),
checkout: {
amountMoney: {
// O valor deve ser BigInt
amount: BigInt(amountMoney.amount),
currency: amountMoney.currency,
},
deviceOptions: {
deviceId: SQUARE_DEVICE_ID,
skip_receipt_screen: true,
show_itemized_cart: false,
},
referenceId: orderId,
orderId,
note: "Pagamento no autocaixa LOPPO",
paymentType: paymentType
},
});
res.json(checkoutResponse);
} catch (error) {
handleError("Erro na criação do Terminal Checkout", error, res);
}
});
Métodos de pagamento diversificados
Como o Square Terminal suporta uma ampla gama de métodos de pagamento, os clientes podem pagar com seu método preferido:
- Cartões de crédito/débito
- Cartões IC de transporte (Suica/PASMO, etc.)
- iD
- QUICPay
- Pagamentos por código QR (PayPay, etc.)
Observe que cartões UnionPay não são suportados.
Polling do status do pagamento
Como o processamento do pagamento ocorre no Square Terminal, precisamos verificar o status por polling para detectar a conclusão ou o cancelamento.
// Verificar o status do pagamento por polling
const checkPaymentStatus = async () => {
try {
const statusResponse = await fetch(`/api/get-checkout-status?checkoutId=${data.checkout.id}`);
const statusData = await statusResponse.json();
if (statusData.status === 'COMPLETED') {
setPaymentStatus(t.paymentCompleted);
// Processamento de conclusão
setTimeout(() => {
setStatus('complete');
setCart([]);
}, 2000);
} else if (statusData.status === 'CANCELED' || statusData.status === 'CANCEL_REQUESTED') {
setPaymentStatus(t.paymentCanceled);
setTimeout(() => {
setStatus('ready');
}, 3000);
} else {
// Se ainda não concluído, verificar novamente
setPaymentStatus(t.processing);
setTimeout(checkPaymentStatus, 2000);
}
} catch (error) {
console.error(t.statusCheckFailed, error);
setPaymentStatus(t.statusCheckFailed);
setTimeout(() => {
setStatus('ready');
}, 3000);
}
};
Gestão de dados mestres de produtos
Todas as informações de produtos são registradas pelo painel do Square e obtidas via API. Isso simplifica as tarefas operacionais como adicionar produtos ou alterar preços.
app.get("/api/catalog-items", async (_req, res) => {
try {
const TYPES = "ITEM,ITEM_VARIATION,CATEGORY,IMAGE"; // Listar todos os tipos necessários
//------------------------------------------------------------------
// 1. Carregar tudo
//------------------------------------------------------------------
const objects = [];
for await (const obj of await squareClient.catalog.list({ types: TYPES }))
objects.push(obj);
//------------------------------------------------------------------
// 2. Criar mapas para CATEGORY / IMAGE / VARIATION primeiro
//------------------------------------------------------------------
const imageMap = {};
const categoryMap = {};
const variationMap = {};
// ...omitido (lógica de criação de mapas)
//------------------------------------------------------------------
// 3. Expandir ITEMs e incorporar informações usando os mapas criados acima
//------------------------------------------------------------------
const filtered = objects
.filter((o) => o.type === "ITEM")
.map((item) => {
// ...omitido (lógica de transformação de dados)
})
// -- Aplicar filtros de requisitos aqui --
.filter(
(item) =>
!item.isArchived &&
item.categoryNames.includes("六方画材")
);
res.json(filtered);
} catch (error) {
handleError("Erro ao obter itens do catálogo", error, res);
}
});
4. Desenvolvimento rápido com LLMs
A característica marcante deste projeto é que foi concluído em apenas 2 dias. Isso foi possível graças ao uso de LLMs (Modelos de Linguagem de Grande Escala).
Distribuição do tempo de desenvolvimento
- Desenvolvimento do sistema base: ~2 horas
- Refinamento e ajustes de UI: ~4 horas
- Testes e implantação: tempo restante
Como usamos o Claude 3.7 Sonnet
Utilizamos principalmente o Claude 3.7 Sonnet durante o desenvolvimento para otimizar a implementação. Ele lidou não apenas com a lógica da aplicação, mas também com o design da UI sem esforço, e até preparou documentação de configuração — um assistente verdadeiramente completo. As sugestões do LLM foram especialmente valiosas para o código de suporte multilíngue e a integração com Square API.
Também tentamos combinar ChatGPT 4o e ChatGPT o3, mas quando se tratava de compreensão de aplicações web, eles não se comparavam ao 3.7 Sonnet.
Exemplos práticos do uso de LLMs
Esta é uma advertência comum ao usar LLMs no desenvolvimento, mas é difícil usar o código gerado como está — é essencial compreendê-lo e fazer as modificações necessárias. Por exemplo, as seguintes correções foram necessárias para a integração com Square Terminal API:
- Adição de métodos de pagamento: O código gerado pelo LLM suportava apenas pagamentos com cartão de crédito, então precisamos adicionar uma tela de seleção de método de pagamento
- Tratamento de erros: O tratamento de eventos de cancelamento de pagamento do Terminal estava incorreto, então o corrigimos com base na documentação da API
- Segurança: Parte da comunicação entre aplicações utilizava protocolos inseguros, então construímos uma VPN privada para proteger a rota de comunicação
O LLM forneceu a estrutura básica do código, mas os ajustes para produção tiveram que ser feitos manualmente.
5. Internacionalização e usabilidade
Implementação multilíngue
Para atender visitantes internacionais, o sistema suporta 6 idiomas: japonês, inglês, francês, espanhol, chinês tradicional e chinês simplificado. As configurações de idioma são gerenciadas dentro dos componentes React, e todos os textos na tela são obtidos de objetos de tradução.
// Gerenciamento de estado da seleção de idioma
const [language, setLanguage] = useState('ja'); // Definir idioma padrão como japonês
// Obter configurações de idioma
const t = translations[language];
// Exemplo de uso
<h1 className="text-4xl font-bold">{t.title}</h1>
<p className="text-lg text-gray-700 mb-6">
{t.scanDescription}
</p>
Considerações de usabilidade
Visamos uma experiência de usuário semelhante às máquinas de autocaixa em supermercados e lojas de conveniência, incorporando as seguintes escolhas de design:
- Prioridade para escaneamento de código de barras: A entrada do teclado é aceita em qualquer lugar da página, sempre priorizando a entrada do leitor de código de barras
- Botões grandes: Tamanhos de botões otimizados para fácil operação por toque
- Feedback claro: Mensagens fáceis de entender mostrando os resultados das operações
Através dessas escolhas de design, acreditamos ter alcançado uma interface que os usuários podem operar sem confusão.
6. Considerações operacionais
Monitoramento em tempo real e resposta a incidentes
Câmeras de rede estão instaladas na loja, permitindo verificar o estado da loja em tempo real. Se ocorrer um problema, os clientes podem ligar para o número de telefone afixado na vitrine para obter assistência.
Quando uma anomalia operacional é detectada, temos um sistema para chegar ao local dentro de 30 minutos a 2 horas. Além disso, como alternativa caso o terminal de pagamento não esteja funcionando, podemos fornecer um link de pagamento posteriormente para completar a transação.
Para uma operação estável, também temos backup de energia por UPS, redundância de rede e reinicializações periódicas durante os períodos de inatividade.
Houve um incidente em que o cabo de alimentação do cliente se soltou porque não estava totalmente inserido, mas desde então o sistema tem funcionado de forma muito estável.
7. Resultados e impacto
Expansão das oportunidades de vendas
A abertura da loja autônoma nos permitiu garantir valiosas oportunidades de vendas 24/7 perto de uma estação de trem central. A maior conquista foi atender à demanda por uma loja física enquanto superávamos as restrições de recursos humanos.
Tendências dos métodos de pagamento
Todos os métodos de pagamento implementados estão sendo usados de forma bastante equilibrada, mas os mais populares em ordem são:
- Cartões IC de transporte
- Pagamentos por código QR (PayPay, etc.)
- Cartões de crédito (pagamentos por aproximação)
8. Planos futuros e expansão
Expansão para vendas online
A atual loja online LOPPO Art Supply é construída no BASE, mas planejamos migrá-la para um sistema baseado em Square API. Isso não apenas reduzirá as comissões por transação, mas também melhorará o fluxo de compra de produtos e unificará a gestão de estoque e vendas entre a loja física e as vendas online.
Além disso, gostaríamos de oferecer a opção de comprar online e retirar na loja.
Conclusão: Se você sabe fazer tinta, pode construir um sistema de caixa
LOPPO tem reproduzido artesanalmente diversos materiais artísticos para animação cel, e desta vez construímos artesanalmente um sistema de caixa.
Aplicações de software às vezes podem ser construídas de forma relativamente fácil aproveitando APIs existentes e a assistência de LLMs, como demonstrado aqui. Dito isso, nunca imaginamos que um sistema de caixa pudesse ser construído tão facilmente, e foi uma experiência extremamente educativa.
Princípios-chave
- Aproveitamento de serviços existentes: Maximizar o uso de plataformas existentes como Square API
- Utilização de ferramentas de suporte como LLMs: Adoção proativa de ferramentas que impulsionam a eficiência do desenvolvimento
- Foco no escopo mínimo necessário: Manter a implementação simples concentrando-se nas funcionalidades essenciais
Esperamos que este artigo sirva como referência útil para qualquer pessoa interessada em construir um sistema de autocaixa ou considerando o uso da Square API.
O código-fonte completo do sistema que construímos está disponível no GitHub.
