Note: Cet article est une traduction automatique de l'article original en japonais. Si vous remarquez des erreurs de traduction, veuillez nous en informer.
Voici une explication technique du système de caisse automatique entièrement sans espèces que nous avons construit en seulement deux jours pour l'ouverture du LOPPO Art Supply Shibuya Store (un point de vente sans personnel).
Introduction : Le projet de magasin sans personnel LOPPO Art Supply
LOPPO Art Supply est une marque de fournitures artistiques pour l'animation cel qui a commencé comme un passe-temps de Takahashi et a principalement été commercialisée par la vente en ligne. En début d'année, nous avons décidé de louer un petit local comme espace événementiel pour LOPPO Art Supply. Nous avions prévu d'utiliser un coin comme entrepôt, mais l'idée a émergé : « Si nous stockons déjà des marchandises ici, pourquoi ne pas en faire un point de vente ? »
Des demandes pour un magasin physique existaient depuis un certain temps, mais il était difficile de garantir les ressources humaines nécessaires à l'exploitation d'un magasin. C'est alors que nous avons eu l'idée d'un « magasin de fournitures artistiques sans personnel ». Imaginez un stand de légumes en libre-service, mais pour des fournitures d'animation cel — un endroit de rêve (ou de folie !) où l'on peut acheter 24 heures sur 24, 365 jours par an.
Magasin de fournitures artistiques sans personnel (image conceptuelle)
1. Défis des solutions de caisse automatique existantes
Pour créer un magasin sans personnel ne nécessitant pas de personnel sur place, un système de caisse entièrement automatique est essentiel. Pour ce projet, nous avons décidé de n'accepter que les paiements sans espèces comme mesure de prévention contre le vol.
Nous avons d'abord envisagé des solutions de caisse automatique commerciales, mais avons rencontré deux problèmes majeurs :
- Des coûts fixes mensuels élevés en plus des frais d'installation initiaux
- Des cycles longs entre le règlement et le dépôt
Pour assurer la pérennité, il est important de maintenir les coûts fixes au minimum tout en préservant un flux de trésorerie sain. C'est alors que nous nous sommes tournés vers le système de paiement Square, que nous avions déjà utilisé lors de ventes événementielles.
Square prend en charge une large gamme de moyens de paiement, ne facture aucun frais mensuel (uniquement des commissions par transaction) et offre des dépôts rapides — dès le jour ouvrable suivant. De plus, la Square API permet la création d'applications personnalisées. Comme nous possédions déjà un Square Terminal, nous avons déterminé que son utilisation permettrait également de maintenir les coûts initiaux bas.
Cependant, il y avait une contrainte majeure pour le développement. Nous étions déjà débordés par la fabrication des produits pour l'ouverture du magasin et ne pouvions consacrer que seulement 2 jours au développement du système de caisse automatique.
2. Conception du système : Une caisse automatique sécurisée et conviviale
Architecture globale
Le système est composé des principaux composants suivants :
- Serveur d'applications Linux : Frontend React et backend Express
- Système en magasin : Terminal client en mode kiosque Windows 11 Pro, périphériques et Square Terminal
- Services Square : Square API, données de référence des produits
- Surveillance et exploitation : Caméras de surveillance, alimentation sans interruption (ASI), redondance réseau
Du point de vue du client, seuls l'écran tactile, le lecteur de codes-barres et le Square Terminal sont visibles. Le client fonctionne en mode kiosque Windows 11 Pro, tandis que la logique applicative principale réside sur une machine Linux située en dehors du magasin.
Sécurité et réseau
Le réseau fonctionne dans un environnement VPN utilisant Tailscale, qui protège la communication entre le terminal client et le serveur Linux. De plus, tous les appareils sont connectés à une alimentation sans interruption pour la protection contre la foudre et les coupures de courant, et le réseau est configuré avec une redondance pour assurer un fonctionnement stable.
L'adoption de Tailscale facilite également la maintenance à distance. Aucune donnée locale n'est stockée sur aucun terminal — toutes les données sont récupérées depuis les systèmes de Square.
Configuration matérielle
- Écran tactile
- Lecteur de codes-barres USB
- Square Terminal (traitement des paiements et impression des reçus)
- Caméra de surveillance (pour la surveillance en temps réel)
Implémentation du frontend
Écran de sélection du moyen de paiement
Le frontend est construit avec React et comprend les écrans principaux suivants :
- Écran de scan des produits
- Écran de sélection du moyen de paiement
- Écran de traitement du paiement
- Écran de paiement terminé
Bien qu'utilisant la traduction automatique, nous avons également implémenté le support multilingue, couvrant 6 langues : japonais, anglais, français, espagnol, chinois traditionnel et chinois simplifié. Cela permet aux visiteurs internationaux d'utiliser le système en toute confiance.
// Exemple de configuration des langues
const translations = {
ja: {
title: 'セルフレジシステム',
scanTitle: '商品スキャン',
// ...omis
},
en: {
title: 'Self-Checkout System',
scanTitle: 'Product Scan',
// ...omis
},
// Autres langues...
};
Nous avons également conçu le système pour prioriser l'entrée du lecteur de codes-barres, visant une interface que les utilisateurs peuvent utiliser sans confusion.
3. Points clés de l'intégration Square API
Traitement des paiements avec Terminal API
Parmi les APIs Square, la Terminal API est particulièrement importante. Elle nous permet d'envoyer des demandes de traitement de paiement au Square Terminal.
// Créer un checkout 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: "Moyen de paiement non pris en charge spécifié" });
}
// Créer la commande en premier
const orderId = await createOrder(order);
// Créer le Square Terminal Checkout
const checkoutResponse = await squareClient.terminal.checkouts.create({
idempotencyKey: randomUUID(),
checkout: {
amountMoney: {
// Le montant doit être en 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: "Paiement à la caisse automatique LOPPO",
paymentType: paymentType
},
});
res.json(checkoutResponse);
} catch (error) {
handleError("Erreur de création du Terminal Checkout", error, res);
}
});
Moyens de paiement diversifiés
Comme le Square Terminal prend en charge une large gamme de moyens de paiement, les clients peuvent payer avec leur méthode préférée :
- Cartes de crédit/débit
- Cartes IC de transport (Suica/PASMO, etc.)
- iD
- QUICPay
- Paiements par code QR (PayPay, etc.)
Veuillez noter que les cartes UnionPay ne sont pas prises en charge.
Interrogation de l'état du paiement par polling
Comme le traitement du paiement a lieu sur le Square Terminal, nous devons interroger l'état par polling pour détecter l'achèvement ou l'annulation.
// Vérifier l'état du paiement par 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);
// Traitement de finalisation
setTimeout(() => {
setStatus('complete');
setCart([]);
}, 2000);
} else if (statusData.status === 'CANCELED' || statusData.status === 'CANCEL_REQUESTED') {
setPaymentStatus(t.paymentCanceled);
setTimeout(() => {
setStatus('ready');
}, 3000);
} else {
// Si pas encore terminé, vérifier à nouveau
setPaymentStatus(t.processing);
setTimeout(checkPaymentStatus, 2000);
}
} catch (error) {
console.error(t.statusCheckFailed, error);
setPaymentStatus(t.statusCheckFailed);
setTimeout(() => {
setStatus('ready');
}, 3000);
}
};
Gestion des données de référence des produits
Toutes les informations produits sont enregistrées via le tableau de bord Square et récupérées via l'API. Cela simplifie les tâches opérationnelles telles que l'ajout de produits ou la modification des prix.
app.get("/api/catalog-items", async (_req, res) => {
try {
const TYPES = "ITEM,ITEM_VARIATION,CATEGORY,IMAGE"; // Lister tous les types nécessaires
//------------------------------------------------------------------
// 1. Tout charger
//------------------------------------------------------------------
const objects = [];
for await (const obj of await squareClient.catalog.list({ types: TYPES }))
objects.push(obj);
//------------------------------------------------------------------
// 2. Créer d'abord les maps pour CATEGORY / IMAGE / VARIATION
//------------------------------------------------------------------
const imageMap = {};
const categoryMap = {};
const variationMap = {};
// ...omis (logique de création des maps)
//------------------------------------------------------------------
// 3. Développer les ITEMs et intégrer les informations avec les maps créées ci-dessus
//------------------------------------------------------------------
const filtered = objects
.filter((o) => o.type === "ITEM")
.map((item) => {
// ...omis (logique de transformation des données)
})
// -- Appliquer les filtres de conditions ici --
.filter(
(item) =>
!item.isArchived &&
item.categoryNames.includes("六方画材")
);
res.json(filtered);
} catch (error) {
handleError("Erreur de récupération des articles du catalogue", error, res);
}
});
4. Développement rapide avec les LLMs
La caractéristique remarquable de ce projet est qu'il a été achevé en seulement 2 jours. Cela a été rendu possible grâce à l'utilisation des LLMs (Grands Modèles de Langage).
Répartition du temps de développement
- Développement du système de base : ~2 heures
- Perfectionnement et ajustements de l'UI : ~4 heures
- Tests et déploiement : temps restant
Comment nous avons utilisé Claude 3.7 Sonnet
Nous avons principalement utilisé Claude 3.7 Sonnet pendant le développement pour rationaliser l'implémentation. Il a géré non seulement la logique applicative mais aussi la conception de l'UI sans effort, et a même préparé la documentation de configuration — un assistant véritablement complet. Les suggestions du LLM ont été particulièrement précieuses pour le code de support multilingue et l'intégration avec Square API.
Nous avons également essayé de combiner ChatGPT 4o et ChatGPT o3, mais en termes de compréhension des applications web, ils n'étaient pas à la hauteur de 3.7 Sonnet.
Exemples pratiques d'utilisation des LLMs
C'est une mise en garde courante lors de l'utilisation des LLMs pour le développement, mais il est difficile d'utiliser le code généré tel quel — il est essentiel de le comprendre et d'apporter les modifications nécessaires. Par exemple, les corrections suivantes ont été nécessaires pour l'intégration avec Square Terminal API :
- Ajout de moyens de paiement : Le code généré par le LLM ne supportait que les paiements par carte de crédit, nous avons donc dû ajouter un écran de sélection du moyen de paiement
- Gestion des erreurs : La gestion des événements d'annulation de paiement du Terminal était incorrecte, nous l'avons donc corrigée en nous basant sur la documentation de l'API
- Sécurité : Certaines communications inter-applications utilisaient des protocoles non sécurisés, nous avons donc construit un VPN privé pour sécuriser le chemin de communication
Le LLM a fourni la structure de base du code, mais les ajustements pour la mise en production ont dû être effectués manuellement.
5. Internationalisation et ergonomie
Implémentation multilingue
Pour accueillir les visiteurs internationaux, le système supporte 6 langues : japonais, anglais, français, espagnol, chinois traditionnel et chinois simplifié. Les paramètres de langue sont gérés au sein des composants React, et tous les textes affichés sont récupérés à partir d'objets de traduction.
// Gestion de l'état de sélection de la langue
const [language, setLanguage] = useState('ja'); // Définir la langue par défaut sur le japonais
// Obtenir les paramètres de langue
const t = translations[language];
// Exemple d'utilisation
<h1 className="text-4xl font-bold">{t.title}</h1>
<p className="text-lg text-gray-700 mb-6">
{t.scanDescription}
</p>
Considérations d'ergonomie
Nous avons visé une expérience utilisateur similaire aux caisses automatiques des supermarchés et des commerces de proximité, en intégrant les choix de conception suivants :
- Priorité au scan de codes-barres : Les saisies clavier sont acceptées partout sur la page, en priorisant toujours les entrées du lecteur de codes-barres
- Grands boutons : Des tailles de boutons optimisées pour une utilisation tactile facile
- Retour d'information clair : Des messages faciles à comprendre montrant les résultats des opérations
Grâce à ces choix de conception, nous pensons avoir réalisé une interface que les utilisateurs peuvent utiliser sans confusion.
6. Considérations opérationnelles
Surveillance en temps réel et réponse aux incidents
Des caméras réseau sont installées dans le magasin, nous permettant de vérifier l'état du magasin en temps réel. En cas de problème, les clients peuvent appeler le numéro de téléphone affiché en devanture pour obtenir de l'aide.
Lorsqu'une anomalie opérationnelle est détectée, nous avons un système permettant d'arriver sur place dans un délai de 30 minutes à 2 heures. De plus, en cas de défaillance du terminal de paiement, nous pouvons fournir un lien de paiement a posteriori pour finaliser la transaction.
Pour un fonctionnement stable, nous avons également mis en place une alimentation de secours par ASI, une redondance réseau et des redémarrages périodiques pendant les périodes d'inactivité.
Il y a eu un incident où le câble d'alimentation du client s'est détaché car il n'était pas complètement inséré, mais depuis lors, le système fonctionne de manière très stable.
7. Résultats et impact
Expansion des opportunités de vente
L'ouverture du magasin sans personnel nous a permis de sécuriser de précieuses opportunités de vente 24h/24 et 7j/7 à proximité d'une gare centrale. Le plus grand accomplissement a été de répondre à la demande d'un magasin physique tout en surmontant les contraintes de ressources humaines.
Tendances des moyens de paiement
Tous les moyens de paiement implémentés sont utilisés de manière assez équilibrée, mais les plus populaires dans l'ordre sont :
- Cartes IC de transport
- Paiements par code QR (PayPay, etc.)
- Cartes de crédit (paiement sans contact)
8. Plans futurs et expansion
Extension aux ventes en ligne
La boutique en ligne LOPPO Art Supply actuelle est construite sur BASE, mais nous prévoyons de la migrer vers un système basé sur Square API. Cela permettra non seulement de réduire les commissions de transaction, mais aussi d'améliorer le parcours d'achat des produits et d'unifier la gestion des stocks et des ventes entre le magasin physique et les ventes en ligne.
De plus, nous souhaitons offrir l'option d'acheter en ligne et de retirer en magasin.
Conclusion : Si vous pouvez fabriquer de la peinture, vous pouvez construire un système de caisse
LOPPO a fabriqué artisanalement la reproduction de divers matériaux artistiques pour l'animation cel, et cette fois nous avons fabriqué artisanalement un système de caisse.
Les applications logicielles peuvent parfois être construites relativement facilement en exploitant les APIs existantes et l'assistance des LLMs, comme démontré ici. Cela dit, nous n'aurions jamais imaginé qu'un système de caisse puisse être construit aussi facilement, et ce fut une expérience extrêmement instructive.
Principes clés
- Exploitation des services existants : Maximiser l'utilisation des plateformes existantes comme Square API
- Utilisation d'outils d'aide comme les LLMs : Adoption proactive d'outils qui améliorent l'efficacité du développement
- Concentration sur le périmètre minimal nécessaire : Garder l'implémentation simple en se concentrant sur les fonctionnalités essentielles
Nous espérons que cet article servira de référence utile pour toute personne intéressée par la construction d'un système de caisse automatique ou envisageant l'utilisation de Square API.
Le code source complet du système que nous avons construit est disponible sur GitHub.
