Configurer votre compte de paiement
Fonctionnalité en cours de déploiement. L'interface décrite ici est celle de la prochaine livraison : elle peut encore évoluer, et n'est pas forcément activée sur votre tenant.
À quoi ça sert
Le manifeste BillingAccount décrit votre compte de paiement : sous quel nom vos clients
vous voient, sur quels comptes Stripe ou PayPal l'argent arrive, ce qui figure sur vos
factures, et quelle application a le droit d'appeler l'API de paiement. Il n'en existe
qu'un par tenant, nommé default.
Prérequis
- Une session sur le tenant (
sng tenant use acme) et le droit d'appliquer des manifestes (policyreadwriteouadmin). - Un compte Stripe et/ou un compte PayPal Business à votre nom.
- L'annuaire du tenant initialisé (
sng iam init), pour déclarer l'application qui appellera l'API. Voir Identités machine.
1. Ranger vos clés Stripe et PayPal dans des secrets
Vos clés ne vont jamais dans le manifeste. Rangez-les dans des secrets de votre tenant, comme pour vos autres secrets (voir Créer et lire un secret), avec ces noms de clés :
| Fournisseur | Clés du secret | Où les trouver |
|---|---|---|
| Stripe | secretKey, publishableKey | tableau de bord Stripe, Développeurs → Clés API |
| PayPal | clientId, clientSecret | tableau de bord développeur PayPal, Apps & Credentials |
# Stripe : collez les clés quand le terminal les demande (rien ne reste dans l'historique)
read -rs STRIPE_SECRET_KEY && read -rs STRIPE_PUBLISHABLE_KEY
sng secret set stripe-keys \
--data secretKey="$STRIPE_SECRET_KEY" \
--data publishableKey="$STRIPE_PUBLISHABLE_KEY"
# PayPal
read -rs PAYPAL_CLIENT_ID && read -rs PAYPAL_CLIENT_SECRET
sng secret set paypal-keys \
--data clientId="$PAYPAL_CLIENT_ID" \
--data clientSecret="$PAYPAL_CLIENT_SECRET"
Commencez avec vos clés de test Stripe (sk_test_…) et le sandbox PayPal, et
mode: test dans le manifeste ; passez en live une fois le parcours validé.
2. Déclarer l'application qui appellera l'API
L'API de paiement accepte un jeton d'application de votre organisation. Déclarez une
application machine (flux client_credentials) :
apiVersion: iam.stackngo.io/v1alpha1
kind: IAMApplication
metadata:
name: shop-backend
spec:
displayName: Boutique (serveur)
grantTypes: [client_credentials]
token:
expireInHours: 1
Ses identifiants (clientId, clientSecret) sont mis à disposition de vos App sous le nom
shop-backend-oidc ; voir Authentification de vos applications.
3. Écrire le BillingAccount
apiVersion: billing.stackngo.io/v1alpha1
kind: BillingAccount
metadata:
name: default # un seul compte par tenant, toujours « default »
spec:
displayName: Acme
slug: acme # https://pay.dev.stackngo.fr/acme/…
defaultCurrency: EUR
locale: fr-FR
identity:
applications:
- name: shop-backend # une IAMApplication de votre espace
kind: service # jeton client_credentials
scopes: [carts, charges, subscriptions, refunds, invoices:read]
providers:
- type: stripe
mode: test # test ou live
default: true
secretRef: { name: stripe-keys }
webhook: { autoRegister: true }
- type: paypal
mode: test
secretRef: { name: paypal-keys }
webhook: { autoRegister: true }
billingModes: [one_time, subscription, usage]
invoicing:
legalName: Acme SAS
legalForm: SAS
siren: "123456789"
siret: "12345678900012"
vatNumber: FR32123456789
rcs: RCS Paris B 123 456 789
shareCapital: "10 000 €"
address:
line1: 10 rue de la Paix
postalCode: "75002"
city: Paris
country: FR
companySize: pme # pme, eti ou ge
numberPrefix: ACME # ACME-2026-000001
numberingReset: yearly # yearly ou never
paymentTermsDays: 30
legalMentions: "TVA acquittée sur les débits."
latePenaltyText: "Pénalités de retard : 3 fois le taux d'intérêt légal."
recoveryFeeText: "Indemnité forfaitaire pour frais de recouvrement : 40 €."
facturxProfile: EN16931 # EN16931 ou BASIC
exemptionReasons: # motif imprimé sur la facture, par catégorie de TVA
E: "Exonération de TVA, article 261-4-4° du CGI"
branding:
logoURL: https://www.acme.example/logo.svg
primaryColor: "#1F4FD8"
accentColor: "#F2A900"
fontFamily: Inter
carts:
defaultTTL: 24h
maxTTL: 168h
maxLines: 100
allowedReturnURLs:
- https://shop.acme.example/
dunning:
retryDelays: [24h, 72h, 168h] # relances après un échec de paiement
finalAction: unpaid # unpaid ou cancel
sng apply billing/shop-backend.yml billing/account.yml
Les champs
| Champ | Rôle | Remarques |
|---|---|---|
displayName | nom affiché sur la page de paiement, le portail et les factures | |
slug | votre adresse de page de paiement : pay.dev.stackngo.fr/<slug> | 2 à 63 caractères, a-z, 0-9, - ; unique sur la plateforme |
defaultCurrency, locale | devise et langue par défaut | EUR, fr-FR |
identity.applications[] | applications autorisées à appeler l'API | name : une IAMApplication du tenant ; kind: service ; scopes (ci-dessous) |
providers[] | vos comptes Stripe et PayPal | type (stripe, paypal), mode (test, live), default, secretRef.name |
providers[].webhook.autoRegister | la plateforme déclare elle-même, avec vos clés, l'adresse de notification chez Stripe ou PayPal | recommandé : true |
billingModes | modes autorisés parmi one_time, subscription, usage | un panier d'un autre mode est refusé (403) |
invoicing | l'émetteur de vos factures : raison sociale, forme, SIREN, SIRET, TVA, RCS, capital, adresse, taille d'entreprise, numérotation, délai de paiement, mentions, pénalités et frais de recouvrement, profil Factur-X, motifs d'exonération de TVA | figé dans chaque facture au moment de son émission |
branding | logo, couleurs (#RRGGBB), police | page de paiement et portail |
carts.defaultTTL, carts.maxTTL | durée de vie d'un panier non payé | 24 h par défaut ; un panier ne peut pas demander plus que maxTTL |
carts.maxLines | nombre maximal de lignes par panier | |
carts.allowedReturnURLs | adresses de retour acceptées (success_url, cancel_url, return_url) | |
dunning.retryDelays | délais des nouvelles tentatives après un échec de paiement | [24h, 72h, 168h] par exemple |
dunning.finalAction | ce qui arrive après la dernière relance | unpaid (l'abonnement reste, impayé) ou cancel (il est résilié) |
Scopes d'une application :
| Scope | Permet |
|---|---|
carts | créer, lire et supprimer des paniers |
charges | enregistrer un client, lui envoyer un lien d'enregistrement de moyen de paiement, le débiter |
subscriptions | lire, modifier et résilier des abonnements |
refunds | rembourser |
invoices:read | lire clients, paiements, factures, rapports ; créer un lien de portail client |
4. Obtenir un jeton et vérifier le compte
TOKEN=$(curl -s -X POST https://auth.dev.stackngo.fr/oauth/token \
-d grant_type=client_credentials -d client_id="$CLIENT_ID" -d client_secret="$CLIENT_SECRET" \
| jq -r .access_token)
curl -s https://billing-api.dev.stackngo.fr/v1/account -H "Authorization: Bearer $TOKEN"
Ce jeton s'utilise tel quel avec l'API de paiement (pas besoin de session de tenant).
Ce que vous obtenez
{
"slug": "acme",
"display_name": "Acme",
"default_currency": "EUR",
"billing_modes": ["one_time", "subscription", "usage"],
"providers": [
{ "type": "stripe", "mode": "test", "default": true, "loaded": true },
{ "type": "paypal", "mode": "test", "default": false, "loaded": true }
],
"carts": { "default_ttl_seconds": 86400, "max_ttl_seconds": 604800, "max_lines": 100 },
"invoicing": { "legal_name": "Acme SAS", "number_prefix": "ACME", "facturx_profile": "EN16931" },
"ready": true
}
(extrait) ready: true : le compte est prêt à encaisser. loaded: true : les clés du
fournisseur ont été lues et vérifiées auprès de Stripe ou PayPal.
Ce que vous pouvez en attendre
- Le compte est prêt quelques instants après
sng applysi les clés sont valides. - Vos clés sont vérifiées auprès du fournisseur avant d'être utilisées : une clé révoquée ou fausse empêche le compte d'être prêt, sans casser les paiements déjà faits.
- Changer vos clés : mettez à jour le secret (
sng secret set stripe-keys …) ; la nouvelle clé est prise en compte dans les minutes qui suivent, sans réappliquer le manifeste. - Modifier
invoicingne change jamais une facture déjà émise. - Supprimer le
BillingAccountdésactive l'encaissement ; vos factures restent conservées et consultables 10 ans.
Si ça ne marche pas
| Ce que vous voyez | Cause | Correction |
|---|---|---|
sng apply refuse un second BillingAccount | un seul compte par tenant | gardez metadata.name: default et modifiez-le |
ready: false, loaded: false sur un fournisseur | secret absent, clé manquante (secretKey…), clé refusée par le fournisseur, ou clé de test avec mode: live | vérifiez le secret avec sng secret describe stripe-keys (les clés attendues doivent y figurer) et le mode |
403 sur tous les appels | l'application du jeton n'est pas déclarée dans identity.applications, ou le compte n'est pas prêt | ajoutez-la et réappliquez ; attendez ready: true |
403 sur une seule route | scope manquant (par exemple refunds) | ajoutez le scope à l'application |
sng apply refuse le slug | déjà utilisé, ou caractères non permis | choisissez-en un autre |
Voir aussi Dépannage des paiements.