Kwaliteitseisen voor de app-review
Stripe beoordeelt elke app die bij de marketplace wordt ingediend aan de hand van een uitgebreide set kwaliteitseisen. Als je deze eisen kent voordat je begint met bouwen, bespaar je tijd en heb je minder reviewrondes nodig.
Overzicht
De review van een Stripe App beoordeelt je app op zes hoofdgebieden:
- Transparante prijzen, duidelijke communicatie over kosten
- Werking van de app, betrouwbaarheid en volledigheid
- Ontwikkelaarsnormen, codekwaliteit en API-gebruik
- UX-kwaliteit, eisen aan interface en gebruikerservaring
- Beveiliging, gegevensbescherming en veilige werkwijzen
- Juridische naleving, privacy en wet- en regelgeving
Transparante prijzen
Je app moet alle kosten duidelijk aan gebruikers communiceren:
- Prijsvermelding: alle prijzen moeten vooraf in de marketplace-vermelding staan
- Geen verborgen kosten: gebruikers mogen na installatie niet voor onverwachte kosten komen te staan
- Proefvoorwaarden: bied je een proefperiode aan, vermeld dan duidelijk hoe lang die duurt en wat er daarna gebeurt
- Upgradeflows: upsell- of upgradeprompts moeten discreet en duidelijk optioneel zijn
- Valuta: toon prijzen waar mogelijk in de lokale valuta van de gebruiker
Caution
Apps die hun prijzen verhullen of gebruikers zonder duidelijke toestemming kosten in rekening brengen, worden direct afgewezen.
Datum- en tijdnotatie
Alle datums en tijden die je app toont, moeten de conventies van het Stripe Dashboard volgen:
- Gebruik waar mogelijk de locale van de gebruiker voor de datumnotatie
- Toon tijden in de lokale tijdzone van de gebruiker
- Gebruik relatieve tijdsaanduidingen voor recente gebeurtenissen (bijvoorbeeld “2 uur geleden”)
- Gebruik absolute tijdsaanduidingen met volledige datum en tijd voor oudere gebeurtenissen
- Volg ISO 8601 voor alle datumvelden richting de API
// Good: Use Stripe's date formatting utilitiesimport { formatDate, formatRelativeTime } from '@stripe/ui-extension-sdk/utils';
const formattedDate = formatDate(timestamp); // Locale-awareconst relativeTime = formatRelativeTime(timestamp); // "2 hours ago"App-instellingen
Heeft je app configuratie nodig:
- Bied een aparte instellingenweergave die vanuit de viewport van de app bereikbaar is
- Vul waar mogelijk verstandige standaardwaarden vooraf in
- Valideer alle invoer van gebruikers met duidelijke foutmeldingen
- Laat gebruikers instellingen aanpassen zonder de app opnieuw te installeren
- Bewaar instellingen tussen sessies met de Secret Store API van Stripe
Ondersteuning voor de sandbox
Je app moet correct werken in de sandbox (testmodus) van Stripe:
- Compatibiliteit met de testmodus: alle functies moeten werken in de testmodus
- Testgegevens: gebruik realistische testgegevens die de werking van de app laten zien
- Geen live gegevens in de sandbox: toon nooit productiegegevens in de testmodus
- Nette afhandeling: is een functie niet beschikbaar in de sandbox, toon dan een duidelijke uitleg waarom
- Zet
sandbox_install_compatible: truein je manifest
{ "sandbox_install_compatible": true}Werking van de app
Betrouwbaarheid
- De app mag bij normaal gebruik niet crashen of vastlopen
- Alle aangeprezen functies moeten werken zoals beschreven
- Netwerkfouten moeten netjes worden afgehandeld, met een optie om het opnieuw te proberen
- De app moet responsief blijven tijdens achtergrondprocessen
Volledigheid
- Geen placeholderinhoud, functies met “binnenkort beschikbaar” of kapotte links
- Alle UI-elementen moeten werken, dus geen dode knoppen of inactieve besturingselementen
- Helpteksten en documentatielinks moeten naar geldige pagina’s leiden
- Bij het verwijderen van de app moeten alle app-gegevens en webhooks netjes worden opgeruimd
Prestaties
- De UI moet binnen 3 seconden renderen op een gewone verbinding
- Synchronisatie op de achtergrond mag de UI niet blokkeren
- Grote datasets moeten paginering of lazy loading gebruiken
- Beperk het aantal API-aanroepen om rate limiting te voorkomen
Ontwikkelaarsnormen
API-gebruik
- Gebruik de nieuwste stabiele versie van de Stripe API
- Volg de best practices van de Stripe API voor paginering, foutafhandeling en idempotentie
- Overschrijd de rate limits niet en gebruik exponentiële backoff bij nieuwe pogingen
- Gebruik webhooks voor event-gestuurde updates in plaats van polling
Codekwaliteit
- Geen consolefouten of waarschuwingen in productiebuilds
- Verwijder alle debuglogging voordat je indient
- Handel alle randgevallen af (lege statussen, ontbrekende gegevens, netwerkfouten)
- Volg de patronen van de componentbibliotheek van Stripe voor een consistente UI
Versiebeheer
- Gebruik semantische versienummers (MAJOR.MINOR.PATCH)
- Documenteer breaking changes bij versie-updates
- Houd waar mogelijk achterwaartse compatibiliteit aan
UX-kwaliteit
Advertenties
- Geen advertenties: je app mag geen enkele vorm van reclame tonen
- Geen cross-promotie: promoot geen andere producten of diensten binnen de UI van de app
- Merkinhoud: toon alleen je eigen merkidentiteit, niet die van derden (behalve integratiepartners zoals Brevo)
Taal en inhoud
- Consistente taal: gebruik dezelfde terminologie in de hele app
- Professionele toon: sluit aan bij de professionele, beknopte communicatiestijl van het Stripe Dashboard
- Geen jargon: vermijd technisch jargon dat merchants misschien niet begrijpen
- Spellingcontrole: zorg dat alle tekst vrij is van spel- en grammaticafouten
- Alleen Engels: alle tekst die gebruikers te zien krijgen, moet in het Engels zijn voor marketplace-apps
Bevestigingsdialogen
Vraag gebruikers om bevestiging bij ingrijpende of onomkeerbare acties:
// Good: Confirm before destructive actionsconst handleDisconnect = async () => { const confirmed = await showConfirmation({ title: 'Disconnect Brevo Integration', message: 'This will stop syncing customer data to Brevo. You can reconnect at any time.', confirmLabel: 'Disconnect', cancelLabel: 'Cancel', destructive: true, });
if (confirmed) { await disconnectIntegration(); }};Acties waarvoor bevestiging nodig is:
- Integraties loskoppelen
- Gesynchroniseerde gegevens verwijderen
- Instellingen wijzigen die de gegevensstroom beïnvloeden
- De configuratie terugzetten naar de standaardwaarden
Laadstatussen
Toon altijd een laadindicator bij asynchrone bewerkingen:
// Good: Show loading state during data fetchconst CustomerSyncStatus = () => { const { data, isLoading, error } = useSyncStatus();
if (isLoading) { return <Spinner label="Loading sync status..." />; }
if (error) { return <Banner type="critical" title="Failed to load sync status"> {error.message} </Banner>; }
return <SyncStatusDisplay data={data} />;};Vereisten:
- Toon spinners of skeletonschermen terwijl gegevens laden
- Schakel knoppen uit tijdens het versturen van een formulier
- Toon voortgangsindicatoren bij langlopende bewerkingen
- Laat nooit een leeg scherm zien tijdens het laden
Foutmeldingen
Geef duidelijke foutmeldingen waar gebruikers iets mee kunnen:
// Bad: Generic error"Something went wrong"
// Good: Specific and actionable"Unable to sync customer data to Brevo. Please verify your Brevo API keyin Settings and try again."Richtlijnen voor foutmeldingen:
- Leg in gewone taal uit wat er gebeurd is
- Stel een concrete actie voor waarmee de gebruiker het probleem oplost
- Bied een manier om de mislukte bewerking opnieuw te proberen
- Log gedetailleerde foutinformatie voor debugging (die de gebruiker niet te zien krijgt)
- Vermeld foutcodes voor de support waar dat zinvol is
Beveiliging
Secret Store API
Gebruik de Secret Store API van Stripe voor het opslaan van alle gevoelige gegevens:
import { createHttpClient, STRIPE_API_KEY } from '@stripe/ui-extension-sdk/http_client';
// Good: Store secrets using the Secret Store APIconst storeBrevoApiKey = async (apiKey: string) => { const stripe = createHttpClient(STRIPE_API_KEY); await stripe.apps.secrets.create({ name: 'brevo_api_key', payload: apiKey, scope: { type: 'account' }, });};
// Good: Retrieve secrets from the Secret Storeconst getBrevoApiKey = async () => { const stripe = createHttpClient(STRIPE_API_KEY); const secret = await stripe.apps.secrets.find({ name: 'brevo_api_key', scope: { type: 'account' }, }); return secret.payload;};Sla gevoelige gegevens nooit op in:
- Local storage of session storage
- Cookies
- URL-parameters
- Hardcoded waarden in je broncode
- Configuratiebestanden in platte tekst
Cryptografie
- Geen eigen cryptografie: bouw geen eigen versleutelingsalgoritmen
- Gebruik de ingebouwde beveiligingsbouwstenen van Stripe (Secret Store, signing secrets)
- Gebruik HTTPS voor alle externe API-aanroepen
- Valideer alle webhook-handtekeningen voordat je ze verwerkt
Omgaan met gegevens
- Vraag alleen de permissies aan die je app echt nodig heeft
- Sla geen Stripe-gegevens op die niet nodig zijn voor de werking van je app
- Voer een bewaarbeleid voor gegevens dat aansluit bij je privacybeleid
- Bied gebruikers een manier om verwijdering van hun gegevens aan te vragen
Juridische naleving
Privacybeleid
Je app moet een openbaar toegankelijk privacybeleid hebben dat het volgende behandelt:
- Welke gegevens je app uit Stripe haalt
- Hoe die gegevens worden opgeslagen, verwerkt en gedeeld
- Het bewaar- en verwijderbeleid voor gegevens
- De rechten van gebruikers met betrekking tot hun gegevens
- Contactgegevens voor privacyvragen
- Naleving van de geldende regelgeving (AVG, CCPA, enzovoort)
Servicevoorwaarden
- Bied duidelijke servicevoorwaarden voor je app
- Neem geen voorwaarden op die botsen met de servicevoorwaarden van Stripe
- Vermeld eventuele gebruiksbeperkingen duidelijk
Naleving van regelgeving
- Voldoe aan alle geldende regelgeving voor gegevensbescherming
- Sluit passende verwerkersovereenkomsten
- Ondersteun verzoeken om gegevensoverdraagbaarheid en verwijdering
- Houd auditlogs bij van toegang tot en verwerking van gegevens
Doorlooptijd van de review
| Fase | Duur |
|---|---|
| Eerste indiening | 5-10 werkdagen |
| Review van een herziening | 3-7 werkdagen |
| Definitieve goedkeuring | 1-2 werkdagen |
| Publicatie | Direct na goedkeuring |
Tip
Verwerk alle feedback uit de review in één herziening, zo voorkom je meerdere reviewrondes. Het team van Stripe geeft bij elk gevonden punt concrete, bruikbare feedback.
Veelvoorkomende redenen voor afwijzing
- Ontbrekende foutafhandeling, de app crasht bij netwerkfouten of onverwachte gegevens
- Te weinig laadstatussen, lege schermen terwijl gegevens laden
- Onduidelijke prijzen, de prijzen staan niet volledig in de vermelding
- Te veel permissies, permissies aanvragen die de app niet nodig heeft
- Sandbox werkt niet, de app functioneert niet in de testmodus
- Beveiligingsproblemen, secrets buiten de Secret Store API opslaan
- Ontbrekend privacybeleid, geen bereikbare URL naar het privacybeleid
- Onvolledige functionaliteit, functies met “binnenkort beschikbaar” of placeholderinhoud