Intégration de la passerelle de paiement
La passerelle traite les opérations financières. Kevmi les connecte aux commandes, paramètres de boutique et notifications. Ce guide décrit le contrat d'intégration et les vérifications de disponibilité.
Sur cette page
Vérification de la disponibilité#
Kevmi utilise l'API v3 de la passerelle pour créer et récupérer des opérations, lire les statuts et rapprocher les résultats. L'intégration prend en charge le transport chiffré des cartes et codes bancaires, les paiements QR Alipay et SBP, un catalogue de crypto-monnaies/réseaux et des événements financiers entrants.
gateway.configured dans GET /api/config indique si les paramètres de connexion requis sont présents. Cet endpoint ne sonde pas la passerelle ; gateway.connected=false ici signifie que la connectivité n'a pas été vérifiée. Pour une facture spécifique, lisez invoice.availability dans GET /api/checkout/{token} : il vérifie la méthode, le montant, les conditions et l'approbation du commerçant. Le champ de compatibilité invoice.gatewayConnected reflète availability.available et n'est ni un contrôle de santé ni une garantie d'approbation de paiement.
Un nouveau paiement et une intention de carte nécessitent l'approbation de la dernière demande de revue du site du marchand. L'approbation seule ne connecte pas la passerelle de paiement. Si la revue change après l'envoi, l'opération existante reste disponible pour la lecture des statuts, le rapprochement et un code bancaire demandé.
Contrat de paiement client#
Les données sensibles sont chiffrées dans le navigateur avec RSA-OAEP-256 et A256GCM. La clé privée reste sur la passerelle. Kevmi valide que l'intention appartient à cette facture et à cet objectif, relaie l'enveloppe, et ne stocke pas de numéros de carte en clair, CVV, nom d'acheteur, e-mail, codes bancaires ni l'enveloppe elle-même.
Installez l'extension de transport chiffré sur l'hôte de la passerelle avant d'activer les cartes. Elle vérifie la signature d'intention, l'expiration, le rejouage, la commande et les montants. Il n'y a pas de repli en clair. Ceci décrit le mécanisme de protection, pas la certification PCI.
| Route Kevmi | Objectif |
|---|---|
| GET /api/checkout/{token} | Facture, devis, disponibilité de la méthode et paiement existant |
| POST /api/checkout/{token}/card-intent | Intention unique et clé publique pour le paiement ou le code |
| POST /api/checkout/{token}/pay | Démarrer une opération ; la carte utilise un chiffrement : {intent,jwe} |
| POST /api/checkout/{token}/code | Code unique chiffré pour le défi bancaire en cours |
| GET /api/checkout/{token}/status | Lire l’opération d’origine sans frais supplémentaires |
| POST /api/checkout/{token}/reconcile | Rapprocher explicitement l’opération d’origine |
| GET /api/checkout/{token}/crypto-services | Pièces, réseaux et limites actuels pour une facture USDT |
Hébergement et connectivité de la passerelle#
Kevmi prend en charge l’hébergement du site sur Cloudflare Workers avec D1, et l’auto-hébergement sur Node.js avec SQLite. SQLite nécessite un volume persistant et des sauvegardes. La passerelle de paiement s’exécute comme un service distinct avec son propre stockage durable.
Une passerelle externe nécessite une origine HTTPS accessible par le serveur. Dans le pack auto-hébergé, le serveur se connecte à un service de passerelle fixe sur le réseau privé du conteneur ; l’API du service de passerelle n’est pas exposée à Internet. Le site public et les rappels utilisent HTTPS. Le navigateur chiffre également les données de carte et les codes bancaires avant qu’ils n’atteignent Kevmi.
localhost fait référence au serveur ou conteneur actuel ; il n’expose pas l’ordinateur du propriétaire de la passerelle. Les clés de connexion et les secrets n’appartiennent qu’à la configuration du serveur.
Pour un domaine personnalisé, définissez une origine HTTPS publique dans NEXT_PUBLIC_SITE_URL avant la compilation. La documentation, les liens canoniques et les ressources d’indexation utilisent cette valeur. Elle n’accepte qu’un schéma et un hôte avec un port facultatif, sans chemin, requête, fragment ni identifiants. Faites-la correspondre à APP_ORIGIN dans la configuration du serveur.
Calcul et conditions prises en charge#
Les factures du nouvel espace de travail utilisent un prix de base en USD et Any propose les quatre méthodes. SBP convertit en RUB au taux de référence gelé de la Banque de Russie ; la crypto utilise la règle de facturation explicite 1:1 USD/USDT. La tarification native héritée reste disponible pour les anciennes factures et les demandes API sans pricingMode=universal. Voir la section multi-boutiques et tarification USD ci-dessous.
Pour un nouveau paiement en direct par carte ou Alipay, la passerelle actuelle ne prend en charge que feeCustomerPercent=0 et vatCustomerPercent=100 : le marchand couvre la totalité des frais de traitement et la TVA est ajoutée intégralement pour le client. D'autres parts peuvent être enregistrées et calculées sur une facture, mais l'exécution est bloquée avec unsupported_allocation. Le serveur ne modifie jamais silencieusement les conditions enregistrées. Les paiements crypto SBP et USDT prennent en charge toutes les parts de frais de traitement et n'ont pas de TVA.
L’envoi d’un total_cents arbitraire ne modifie pas le calcul de taxe du fournisseur. Un montant réel différent du total enregistré entre en révision et ne peut pas confirmer l’exécution. Les champs business_balance de la passerelle sont conservés comme preuve de règlement, et non traités comme un solde marchand Kevmi.
Connexion d’une passerelle en direct#
La connexion de la passerelle inclut la configuration du serveur, les vérifications des canaux sélectionnés et le traitement des événements financiers vérifiés. L’état de préparation de la configuration est vérifié séparément de la connectivité du fournisseur. Un paiement réussi est accepté après vérification du statut et du montant de l’opération. Les instructions de déploiement se trouvent dans ops/gateway-integration.md.
- 1
Déployez le serveur Kevmi et la passerelle comme services distincts. Configurez un stockage durable, des sauvegardes et les processus en arrière-plan requis.
- 2
Pour une connexion externe, définissez une origine HTTPS dans GATEWAY_BASE_URL. Le pack auto-hébergé utilise son service interne configuré. Les deux nécessitent une GATEWAY_API_KEY réservée au serveur et un GATEWAY_WEBHOOK_SECRET distinct ; les secrets n’atteignent jamais le navigateur.
- 3
Définissez BACKEND_WEBHOOK_URL sur /api/gateway/webhook chez Kevmi et un BACKEND_WEBHOOK_SECRET correspondant.
- 4
Activez le transport chiffré des cartes et conservez sa clé privée exclusivement sur l’hôte de la passerelle. Vérifiez la disponibilité de la clé publique et les paramètres de signature d’intention correspondants.
- 5
Vérifiez l’état de préparation des canaux, les restrictions et l’approbation du site marchand avant le lancement.
Plusieurs boutiques et un prix de base USD unique#
Choisissez Toutes les boutiques pour les analyses et opérations agrégées, ou sélectionnez une boutique pour ses propres enregistrements. Chaque boutique possède un storeId, un nom, une TVA par défaut, des factures, des clés API, des points de terminaison webhook, un historique d'événements et une application de site Web distincts. Les notifications et les tickets de support appartiennent au compte. Un compte peut créer jusqu'à 100 boutiques. Les enregistrements existants restent dans sa première boutique.
Les factures du nouvel espace de travail utilisent pricingMode="universal" et un prix de base en USD. Any inclut carte, alipay, sbp et crypto ; un commerçant peut sélectionner un sous-ensemble. Les cartes et Alipay facturent en USD. SBP facture en RUB en utilisant le taux de référence USD/RUB de la Banque de Russie. La crypto facture en USDT selon la règle de facturation explicite 1 USD = 1 USDT. Il s'agit d'une règle de conversion de facturation, pas d'une cotation USDT de marché. La passerelle fournit le taux de la pièce sélectionnée, le montant exact du transfert et les instructions avant le transfert.
Le taux de référence et les deux montants sont gelés à la création. Les factures impliquant une conversion RUB expirent dans les 24 heures. Si le taux de référence ne peut pas être obtenu, la création échoue avec FX_UNAVAILABLE ; aucun taux de secours inventé ou obsolète n'est utilisé. Le montant en monnaie mineure du propriétaire et les cotations utilisent la monnaie comptable USD. quotes[method].settlement contient la cotation de frais native. Le paiement public expose la monnaie de frais sélectionnée dans currency, le prix d'origine dans baseAmountMinor/baseCurrency, et le taux de référence dans fx. Une fois qu'un paiement a été envoyé, sa méthode ne peut pas être modifiée ; une facture a une seule opération de passerelle.
Créez une clé API dans la boutique prévue et envoyez Authorization: Bearer <key> depuis votre serveur. Sa liaison de boutique est immuable ; X-Kevmi-Store ne peut pas lui accorder l'accès à une autre boutique. Les sessions de navigateur sélectionnent X-Kevmi-Store: <storeId> ; si omis, la première boutique est sélectionnée. La valeur all n'est acceptée que par GET /api/account/dashboard et GET /api/payment-links. Les mutations nécessitent une boutique sélectionnée, Origin et X-CSRF-Token. Les identifiants de compte et les identifiants de boutique sont des identifiants différents.
Pour la compatibilité, les demandes API sans pricingMode="universal" conservent la tarification native et les restrictions de monnaie d'origine. Les factures existantes ne sont jamais recalculées. Les reçus confirmés dans les analyses reflètent les paiements vérifiés moins les dépenses de facture enregistrées ; ils ne constituent pas un solde retirable. Les monnaies de facture héritées restent séparées et les paiements sont organisés avec le support. Exécutez une commande uniquement après avoir vérifié payment.fulfillmentReady=true et payment.status="succeeded" via l'API serveur, l'historique d'événements ou un webhook signé.
Assistant, support et administration de projet#
Activer l'autorisation d'accès à mes données dans le chat lorsque vous avez besoin d'aide pour des opérations privées. Une requête web avec includeAccount=true nécessite une session valide, Origin et X-CSRF-Token ; X-Kevmi-Store sélectionne un magasin possédé ou tous les magasins possédés. Sans autorisation, l'assistant utilise la documentation publique. Dans Telegram, un bouton séparé permet l'accès après identification de l'expéditeur.
L'outil read_account lit les magasins possédés, les factures avec statut de reçu vérifié, les événements, les applications et les demandes de support avec réponses de spécialistes. Il renvoie 30 enregistrements et nextPage ; les enregistrements plus anciens sont disponibles via pagination. Les lectures par réponse sont limitées, donc un échantillon incomplet doit être divulgué. Les clés API, les secrets de webhook, les détails de carte et les sessions ne sont pas fournis à l'outil. Il ne peut pas facturer, payer, rembourser ou modifier les paramètres.
Créer une demande de support dans l'espace de travail ou Telegram place une alerte d'administrateur séparée dans une file durable. Elle pointe vers /admin/tickets?ticket=<id> ; les pannes temporaires de Telegram sont réessayées. La récupération reprend également les anciennes demandes ouvertes sans alerte. Les administrateurs répondent sur la page de demande ; la réponse est enregistrée dans l'espace de travail de l'utilisateur et envoyée via Telegram lorsque les notifications de support sont activées.
Le bot utilise des boutons en ligne pour le menu principal, les magasins, les notifications, le support, la sécurité et la langue. La navigation modifie le message actuel ; un ancien menu indisponible est remplacé. Les notifications de paiement et de sécurité ne sont pas traitées comme une navigation jetable. Se déconnecter via le menu nécessite une confirmation. La commande explicite /logout met fin à chaque session de compte.
Le panneau /admin/project est restreint aux identifiants Telegram de la liste blanche MODERATOR_TELEGRAM_IDS côté serveur. Il inclut les utilisateurs, les magasins, les opérations, la révocation de clés, la désactivation de webhooks, la mise en pause de factures, les contrôles d'acceptation et un journal d'audit. Les mutations nécessitent CSRF et une raison. Le panneau ne peut pas restreindre un administrateur ni déclarer manuellement un paiement réussi. Restreindre un propriétaire met fin aux sessions et bloque l'accès aux clés API ; restreindre un magasin arrête les nouvelles opérations. L'historique est conservé.
L'offre publique est disponible à /public-offer et la politique de confidentialité à /privacy-policy dans chaque langue activée. Recherchez les pièces par nom ou ticker. Un sélecteur de réseau apparaît uniquement lorsque plusieurs réseaux actifs sont disponibles. Un seul réseau est sélectionné automatiquement et reste nommé dans la confirmation. La disponibilité du passerelle en direct détermine les paires sélectionnables ; le catalogue de référence n'active pas un service.
Utilisez update.sh pour les versions routinières de l'application web : construisez le candidat, vérifiez l'historique de migration, sauvegardez SQLite en ligne, démarrez un deuxième conteneur, vérifiez-le, et basculez Caddy en douceur. La passerelle, PostgreSQL et la messagerie ne sont pas redémarrés. Les anciens fichiers statiques restent disponibles pour les onglets ouverts. Une nouvelle migration nécessite une autorisation revue explicite ; un changement de schéma incompatible n'est pas un déploiement transparent.