Aller au contenu principal

Configurer votre compte de paiement

Bêta

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 (policy readwrite ou admin).
  • 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 :

FournisseurClés du secretOù les trouver
StripesecretKey, publishableKeytableau de bord Stripe, Développeurs → Clés API
PayPalclientId, clientSecrettableau 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) :

billing/shop-backend.yml
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​

billing/account.yml
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​

ChampRôleRemarques
displayNamenom affiché sur la page de paiement, le portail et les factures
slugvotre adresse de page de paiement : pay.dev.stackngo.fr/<slug>2 à 63 caractères, a-z, 0-9, - ; unique sur la plateforme
defaultCurrency, localedevise et langue par défautEUR, fr-FR
identity.applications[]applications autorisées à appeler l'APIname : une IAMApplication du tenant ; kind: service ; scopes (ci-dessous)
providers[]vos comptes Stripe et PayPaltype (stripe, paypal), mode (test, live), default, secretRef.name
providers[].webhook.autoRegisterla plateforme déclare elle-même, avec vos clés, l'adresse de notification chez Stripe ou PayPalrecommandé : true
billingModesmodes autorisés parmi one_time, subscription, usageun panier d'un autre mode est refusé (403)
invoicingl'é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 TVAfigé dans chaque facture au moment de son émission
brandinglogo, couleurs (#RRGGBB), policepage de paiement et portail
carts.defaultTTL, carts.maxTTLdurée de vie d'un panier non payé24 h par défaut ; un panier ne peut pas demander plus que maxTTL
carts.maxLinesnombre maximal de lignes par panier
carts.allowedReturnURLsadresses de retour acceptées (success_url, cancel_url, return_url)
dunning.retryDelaysdélais des nouvelles tentatives après un échec de paiement[24h, 72h, 168h] par exemple
dunning.finalActionce qui arrive après la dernière relanceunpaid (l'abonnement reste, impayé) ou cancel (il est résilié)

Scopes d'une application :

ScopePermet
cartscréer, lire et supprimer des paniers
chargesenregistrer un client, lui envoyer un lien d'enregistrement de moyen de paiement, le débiter
subscriptionslire, modifier et résilier des abonnements
refundsrembourser
invoices:readlire 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 apply si 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 invoicing ne change jamais une facture déjà émise.
  • Supprimer le BillingAccount désactive l'encaissement ; vos factures restent conservées et consultables 10 ans.

Si ça ne marche pas​

Ce que vous voyezCauseCorrection
sng apply refuse un second BillingAccountun seul compte par tenantgardez metadata.name: default et modifiez-le
ready: false, loaded: false sur un fournisseursecret absent, clé manquante (secretKey…), clé refusée par le fournisseur, ou clé de test avec mode: livevérifiez le secret avec sng secret describe stripe-keys (les clés attendues doivent y figurer) et le mode
403 sur tous les appelsl'application du jeton n'est pas déclarée dans identity.applications, ou le compte n'est pas prêtajoutez-la et réappliquez ; attendez ready: true
403 sur une seule routescope manquant (par exemple refunds)ajoutez le scope à l'application
sng apply refuse le slugdéjà utilisé, ou caractères non permischoisissez-en un autre

Voir aussi Dépannage des paiements.

Voir aussi​