Betalingen en facturatie
Abonnementen technisch integreren in uw toepassing
Verbind Bookelio op de server, beheer abonnementen en rechten via de API, stel prorata in en ken gratis maanden toe.
Op deze pagina
- De verantwoordelijkheden begrijpen
- De verbinding en rechten voorbereiden
- HTTP-aanroepen op de server voorbereiden
- De software en plannen aanmaken
- De klant identificeren en zijn abonnement aanmaken
- Functies controleren vóór een actie
- De respijtperiode voor betaling toepassen
- De betaling aanbieden en statussen opvolgen
- Het facturatiemoment instellen
- Gebruikersplaatsen synchroniseren en van plan veranderen
- Een onmiddellijke wijziging met prorata toepassen
- Gratis maanden toekennen via de API
- Opzeggen en opnieuw activeren
- Bookelio via een URL met een facturatie-instantie verbinden
- Organisaties koppelen bij het opstarten
- Plannen toewijzen en externe rechten toepassen
- Expliciete vrijstelling voor legacyorganisaties
- De eigenaar kiest een plan via de klant-API
- De integratie onderzoeken en valideren
De verantwoordelijkheden begrijpen
Uw toepassing authenticeert haar gebruikers en identificeert hun account of organisatie. Bookelio bewaart de commerciële catalogus, de te factureren klanten, de abonnementen en hun betaalperiodes. Uw server vraagt Bookelio om de verkochte functies toe te staan. Een knop in de browser verbergen vervangt deze servercontrole niet.
De verkopende organisatie bezit een of meer softwaretoepassingen. Elke softwaretoepassing heeft haar eigen functies, plannen en abonnementen. De module kan dus meerdere toepassingen en meerdere verkopers bedienen, elk binnen hun eigen omgeving.
De onderstaande voorbeelden zijn fictief. Vervang de domeinen en identificatiegegevens door die van uw installatie. Raadpleeg Softwareabonnementen verkopen voor de werkwijze in de schermen.
De verbinding en rechten voorbereiden
Activeer de module Softwareabonnementen voor de verkopende organisatie. Bereid een facturatieklant in die organisatie voor en een btw-beleid voor betalende aanbiedingen. Configureer haar betaalmethoden en e-maildienst voor betalingen en meldingen.
Maak een API-sleutel van de verkopende organisatie aan met de geschikte rechten. Bewaar die op de server van uw toepassing. De sleutel identificeert de verkoper; hij vervangt de authenticatie van uw gebruikers niet en kan toegang geven tot abonnementen van meerdere klanten van dezelfde verkoper.
| Gebruik | Rechten van de sleutel |
|---|---|
| Software, plannen, abonnementen en toegestane functies lezen | softwareBilling.read |
| De catalogus beheren, opzeggen, aanbiedingen toekennen of gebruikersplaatsen plannen | softwareBilling.manage |
| Functies en externe identiteiten registreren | softwareBilling.manage en customers.create |
| Een abonnement aanmaken | softwareBilling.manage en paymentRequests.create |
Een abonnement wijzigen met een planId, onder meer om het opnieuw te activeren | softwareBilling.manage en paymentRequests.create |
Elke IMMEDIATE-wijziging toepassen, ook zonder toeslag of voor alleen gebruikersplaatsen | softwareBilling.manage en paymentRequests.create |
| Het facturatiemoment in de verkopersinstellingen lezen of wijzigen | settings.read om te lezen; settings.update om te wijzigen |
Om klanten en btw-beleidsregels via hun eigen API's aan te maken of te lezen, hebt u ook de rechten voor die resources nodig. De voorbeelden gaan ervan uit dat die elementen al zijn aangemaakt.
De REST-routes hebben het voorvoegsel /api/v1/admin/software-billing. Het oRPC-transport gebruikt /rpc/v1 en de bewerkingen admin.softwareBilling.*. De specificatie op de API-instantie is te raadplegen via /spec/v1.json. In de Bookelio-monorepo beschrijft het type BookelioApiV1Client dit contract; een externe toepassing kan rechtstreeks REST gebruiken, zonder afhankelijk te zijn van een intern package uit de repository.
HTTP-aanroepen op de server voorbereiden
In de voorbeelden zijn de onderstaande variabelen namen die de externe toepassing zelf kiest. Ze configureren Bookelio zelf niet automatisch.
SOFTWARE_BILLING_API_URL=https://api.billing.example.com
SOFTWARE_BILLING_API_KEY=REPLACE_WITH_SERVER_SIDE_KEY
SOFTWARE_BILLING_APPLICATION_ID=REPLACE_WITH_APPLICATION_ID
Hieronder staat een JavaScript-hulpfunctie die uitsluitend op de server gebruikt mag worden, in een omgeving met fetch. Ze roept de REST-routes aan met een eenvoudige JSON-body. Ontvangen datums zijn ISO 8601-tekenreeksen; de oRPC-client beheert zelf de serialisatie van Date-waarden.
const billingBase = new URL(
'/api/v1/admin/software-billing/',
process.env.SOFTWARE_BILLING_API_URL,
);
async function billingRequest(path, { method = 'GET', body } = {}) {
const response = await fetch(new URL(path, billingBase), {
method,
headers: {
'x-api-key': process.env.SOFTWARE_BILLING_API_KEY,
'content-type': 'application/json',
},
body: body === undefined ? undefined : JSON.stringify(body),
redirect: 'error',
signal: AbortSignal.timeout(10_000),
});
if (!response.ok) {
throw new Error(`Bookelio billing request failed: HTTP ${response.status}`);
}
return response.json();
}
Plaats de sleutel niet in een URL, browsercomponent of publieke variabele. De verbindings-URL is die van de API; betaalpagina's worden gehost door het dashboard van de verkoper, dat een ander domein kan hebben.
De software en plannen aanmaken
Het instellen van de catalogus is een beheerhandeling die u eenmalig uitvoert, niet telkens wanneer een gebruiker zich aanmeldt. Bewaar de id-waarden die Bookelio terugstuurt. De code-waarden zijn leesbare referenties en vervangen deze identificatiegegevens niet in aanroepen.
Om een catalogus te hergebruiken die al in het dashboard is aangemaakt, geeft GET /applications het resultaat { applications: [...] } terug en GET /applications/{applicationId}/plans het resultaat { plans: [...] }, onder het eerder vermelde REST-voorvoegsel. Die laatste lijst bevat ook inactieve plannen: filter op isActive voordat u een aanbieding te koop aanbiedt. Met GET /applications/{applicationId}/subscriptions kan de verkoper abonnementen opvragen, met als antwoord { subscriptions: [...] }.
const application = await billingRequest('applications', {
method: 'POST',
body: {
name: 'Example Workspace',
code: 'example-workspace',
features: [
{ key: 'projects', name: 'Projecten' },
{ key: 'exports', name: 'Exports' },
],
},
});
const enterprise = await billingRequest('plans', {
method: 'POST',
body: {
applicationId: application.id,
name: 'Enterprise',
code: 'enterprise-monthly',
interval: 'MONTHLY',
basePriceCents: 400000,
seatPriceCents: 0,
includedSeats: 0,
trialDays: 14,
gracePeriodDays: 7,
vatPolicyId: 'REPLACE_WITH_SELLER_VAT_POLICY_ID',
featureKeys: ['projects', 'exports'],
},
});
Dit plan kost € 4.000 exclusief btw per maand, ongeacht het aantal gebruikersplaatsen, na een proefperiode van 14 dagen. Daarna biedt het zeven dagen respijt aan het begin van elke betalende periode om tijd voor betaling te geven. seatPriceCents: 0 schakelt de toeslag per gebruikersplaats uit; de API vereist geen veld pricingMode.
| Fictief model | basePriceCents | seatPriceCents | includedSeats | Resultaat exclusief btw |
|---|---|---|---|---|
| Gratis | 0 | 0 | 0 | Geen betaling |
| Vast Enterprise-plan | 400000 | 0 | 0 | € 4.000 per periode, ongeacht het aantal gebruikers |
| Basis en extra gebruikersplaatsen | 1000 | 300 | 2 | € 19 per periode voor 5 gebruikersplaatsen |
| Alle gebruikersplaatsen betalend | 0 | 500 | 0 | € 25 per periode voor 5 gebruikersplaatsen |
De prijzen zijn gehele getallen in eurocenten exclusief btw. interval heeft de waarde MONTHLY of YEARLY: geef bij een jaarlijks aanbod de prijs voor het volledige jaar op, geen maandprijs die nog vermenigvuldigd moet worden. trialDays loopt van 0 tot 365; nul schakelt de proefperiode uit. Een volledig gratis plan maakt geen proefperiode voor een betalend abonnement en geen betaalverzoek aan, ook niet wanneer een duur is ingevuld.
gracePeriodDays is een geheel getal van 0 tot 365, onafhankelijk van de proefperiode. Het is optioneel bij aanmaak: weglaten betekent 0 en behoudt de werking zonder respijtperiode. Bij PATCH /plans/{planId} behoudt weglaten de huidige waarde; 0 versturen schakelt respijt voor toekomstige periodes uit. Bestaande plannen blijven zonder respijtperiode totdat deze waarde wordt gewijzigd.
De sleutels in featureKeys moeten al bestaan in de softwaretoepassing. Een btw-beleid van de verkoper is verplicht zodra een vaste prijs of prijs per gebruikersplaats positief is. Het aantal gebruikersplaatsen van een abonnement is een geheel getal van 1 tot 100.000. Deze technische grens maakt van het vaste tarief geen prijs per gebruikersplaats en is geen commerciële gebruikerslimiet die in het plan is opgenomen.
De klant identificeren en zijn abonnement aanmaken
customerId verwijst naar de te factureren klant in de verkopende organisatie. externalId verwijst naar het account van die klant in uw toepassing, bijvoorbeeld een vaste organisatie-ID. Bewaar deze koppeling op de server. Vermijd een naam of e-mailadres dat kan wijzigen.
De identiteit is uniek per combinatie (applicationId, externalId). In de volgende code moet accountId afkomstig zijn uit uw geverifieerde sessie en uw controles op lidmaatschap, niet uit een vrij te kiezen identificatiegegeven dat de browser verstuurt. Ook het plan en de klant moeten op de server worden geselecteerd en gevalideerd.
const subscription = await billingRequest('subscriptions', {
method: 'POST',
body: {
applicationId: process.env.SOFTWARE_BILLING_APPLICATION_ID,
planId: selectedPlanId,
customerId: billingCustomerId,
externalId: accountId,
seats: memberCount,
},
});
// Bewaar subscription.id voor wijzigingen en opzeggingen.
Een nieuwe poging met dezelfde software, externe referentie, klant en hetzelfde plan vindt het bestaande abonnement terug. Ze herstart de proefperiode niet, factureert niet opnieuw en wijzigt het aantal gebruikersplaatsen niet. Een andere klant of een ander plan voor die referentie veroorzaakt een conflict. Gebruik de wijzigingsbewerking om van plan te veranderen; controleer bij een andere klant uw identiteitskoppeling, want deze bewerking vervangt de facturatieklant niet. Software en plannen aanmaken werkt niet als aanmaken-of-bijwerken; herhaal die bewerkingen niet zoals bij het inschrijven van een klant.
Functies controleren vóór een actie
Gebruik subscriptions.entitlements, niet alleen de opgeslagen status of de naam van het plan. Deze opvraag controleert de huidige periode, de nettobetaling ervoor en de eventuele respijtperiode, en geeft de functiesleutels terug die voor die periode zijn vastgelegd.
async function canUseFeature(verifiedAccountId, featureKey) {
const appId = encodeURIComponent(
process.env.SOFTWARE_BILLING_APPLICATION_ID,
);
const externalId = encodeURIComponent(verifiedAccountId);
try {
const rights = await billingRequest(
`applications/${appId}/entitlements/${externalId}`,
);
return rights.access === true
&& typeof rights.validUntil === 'string'
&& Date.parse(rights.validUntil) > Date.now()
&& Array.isArray(rights.featureKeys)
&& rights.featureKeys.includes(featureKey);
} catch {
// Weiger tijdelijk toegang; stel betalende functies niet open.
return false;
}
}
Fictief voorbeeld van een REST-antwoord:
{
"subscriptionId": "example-subscription",
"status": "PAST_DUE",
"access": true,
"featureKeys": ["projects", "exports"],
"validUntil": "2026-09-29T10:00:00.000Z",
"seats": 5,
"isInGracePeriod": true,
"graceEndsAt": "2026-09-29T10:00:00.000Z"
}
Dit voorbeeld toont de eerste betalende periode na een proefperiode die op 22 september om 10.00 uur UTC eindigde: er wordt nog op betaling gewacht, maar de rechten blijven open tot 29 september om 10.00 uur UTC dankzij de zeven ingestelde dagen. Alleen PAST_DUE volstaat dus niet om een actie te weigeren; gebruik access, de gevraagde sleutel en validUntil, zoals in de hulpfunctie.
Zonder abonnement bevat het antwoord subscriptionId: null, status: null, access: false, featureKeys: [], validUntil: null, seats: 0, isInGracePeriod: false en graceEndsAt: null. Als u een cache toevoegt, scheid die dan per verkoper, softwaretoepassing en externe referentie, beperk de bewaartijd en verleen nooit toegang na validUntil. De module biedt geen uitgaande webhook voor abonnementswijzigingen naar de toepassing: voorzie deze opvragen op de controlepunten van uw server.
De leesbewerkingen entitlements en getByExternalId, en ook syncSeats, behouden hun controles op sleutel, rechten en verkoper, maar blijven toegankelijk zonder de toegang van de verkoper tot de module-interface te controleren. Zo kunnen bestaande abonnementen worden geraadpleegd en in orde gebracht; de overige bewerkingen blijven beschermd door de activering van de module.
De respijtperiode voor betaling toepassen
Bij aanmaak bewaart de periode een momentopname van gracePeriodDays; graceEndsAt wordt berekend uit die waarde en de onveranderlijke datums van de periode. Voor een betalende periode loopt het respijt vanaf periodStart tot de vroegste van twee datums: periodStart + gracePeriodDays × 24 uur of periodEnd. Het eindmoment is niet inbegrepen: op dat tijdstip verleent een nog onbetaalde periode geen toegang meer. Het respijt geldt ook voor de eerste betalende periode en die na de proefperiode, zonder facturatiedatums te wijzigen of een nieuwe proefperiode aan te maken.
Tijdens het respijt blijft de berekende status PAST_DUE, is access true, is isInGracePeriod true en is validUntil gelijk aan graceEndsAt. Een geverifieerde volledige betaling zet de rechten om naar een betaalde periode: isInGracePeriod: false en validUntil: periodEnd. Verlopen respijt met nog onvoldoende betaling geeft access: false, featureKeys: [] en validUntil: null, zonder op de worker te wachten.
graceEndsAt is metadata, geen bewijs van toegang: de datum blijft zichtbaar na betaling of afloop. Ze is null voor een periode zonder respijt, een gratis periode of een proefperiode. Alleen isInGracePeriod geeft aan dat de huidige toegang dit uitstel gebruikt. Voeg geen lokaal respijt toe als de API faalt en verleng geen cache tot die datum zonder access en validUntil te controleren.
Deze velden zijn toegevoegd in compatibele revisie V1-r28. Antwoorden van een oudere V1-instantie kunnen gracePeriodDays, graceEndsAt en isInGracePeriod weglaten: leid uit hun afwezigheid geen respijt af en blijf access en validUntil gebruiken om te beslissen. De verkopende instantie moet worden bijgewerkt om deze functie in te stellen en toe te passen.
De duur en datum liggen voor elke periode vast: een planwijziging, nieuwe poging van de worker of late betaling verschuift ze niet. De worker moet eerst de nieuwe periode aanmaken; vóór die uitvoering verleent een oude verlopen periode geen voorafgaand respijt. Een verwerkingsvertraging kan dus een korte onderbreking veroorzaken, maar kan het begin van de respijtperiode niet uitstellen tot het moment waarop de worker draait.
Een gedeeltelijke betaling verlengt de respijtperiode niet. Een voltooide of lopende terugbetaling verhindert respijt; een mislukte terugbetaling (FAILED) blokkeert het niet op zichzelf. Een effectieve opzegging weigert alle toegang en een geplande opzegging verlengt rechten niet voorbij hun grens. De respijtperiode markeert geen betaling als voltooid, start op zichzelf geen factuur en staat geen nieuwe betaalverzoeken toe zolang de periode onbetaald blijft.
De betaling aanbieden en statussen opvolgen
const appId = encodeURIComponent(process.env.SOFTWARE_BILLING_APPLICATION_ID);
const externalId = encodeURIComponent(accountId);
const { subscription } = await billingRequest(
`applications/${appId}/subscriptions/by-external-id/${externalId}`,
);
const currentCycle = subscription?.cycles.find(
(cycle) => cycle.periodStart === subscription.currentPeriodStart,
);
const paymentUrl = currentCycle?.paymentUrl ?? null;
Deze opvraag geeft maximaal de 20 recentste periodes terug. Toon de paymentUrl van de te betalen periode zoals de verkoper die terugstuurt. Bouw die link niet opnieuw op met het domein van uw toepassing. Is hij null voor een betalende periode, controleer dan de configuratie van BOOKELIO_WEB_URL bij de verkoper. Een gratis plan of proefperiode heeft geen betaalverzoek.
| Status | Gevolg voor de integratie |
|---|---|
TRIALING | Proefperiode loopt; controleer access, de sleutels en validUntil |
ACTIVE | Gratis of betaalde periode; blijf de berekende rechten controleren |
PAST_DUE | Betaling wordt verwacht; tijdelijke toegang is mogelijk tijdens respijt, te controleren via access, isInGracePeriod en validUntil |
CANCELED | Abonnement opgezegd; dit abonnement verleent geen functies |
De worker verwerkt verlengingen elke minuut. Aan het einde van een proefperiode of een betaalde periode maakt hij het volgende betaalverzoek aan. Een onbetaald verzoek blokkeert de aanmaak van volgende verzoeken. Verlopen rechten kunnen al geweigerd worden vóór de volgende uitvoering van de worker: verleen geen extra tijd op basis van een oude status.
De klant betaalt via de betaalmethoden van de verkoper, of de verkoper registreert een externe betaling. Geverifieerde bevestigingen koppelen de betaling aan het verzoek; een volledige betaling start standaard de factuur of hergebruikt de factuur die volgens de verkopersinstelling al bij aanmaak van het verzoek werd uitgereikt. Een geslaagde browseromleiding bewijst niet dat er betaald is: lees de rechten opnieuw op de server. Verlengingen gebruiken betaalverzoeken en geen automatische terugkerende afschrijving. Gedeeltelijke betalingen en terugbetalingen kunnen het recht op toegang voor een volledig betaalde periode doen vervallen.
Het facturatiemoment instellen
Deze instelling geldt voor de verkopende organisatie, niet voor het plan of de aangesloten toepassing. Ze is beschikbaar onder Instellingen → Facturatie → Facturen voor softwareabonnementen en via admin.invoicing.settings.get / .update. De REST-routes zijn GET en PUT /api/v1/admin/invoicing/settings/automation: ze gebruiken niet het voorvoegsel software-billing van de eerdere hulpfunctie.
softwareSubscriptionInvoiceTiming | Werking |
|---|---|
PAYMENT_COMPLETED | Standaard: generatie na geverifieerde volledige betaling |
PAYMENT_REQUEST_CREATED | Generatie bij aanmaak van het betaalverzoek, ook wanneer het nog onbetaald is |
Het veld is optioneel in V1-r28. Weglaten bij een wijziging behoudt de bestaande keuze; zonder verkopersconfiguratie geldt PAYMENT_COMPLETED. De PUT-bewerking vereist ook de booleans bookings, trainings en trainingPaymentReminderInvoices: lees de instellingen met GET en stuur hun huidige waarden samen met de nieuwe softwareSubscriptionInvoiceTiming terug, zodat deze onafhankelijke automatiseringen niet worden gewijzigd. Het activeren van generatie bij aanmaak controleert de e-mail- en opslagdiensten van de verkoper; een ontbrekende voorwaarde verhindert het opslaan.
Bookelio legt de keuze vast in elke nieuwe betalende periode. Ze geldt dus voor nieuwe abonnementen, het einde van proefperiodes, verlengingen en hervattingen die een periode aanmaken, maar niet voor bestaande verzoeken. Een gratis periode of proefperiode zonder betaalverzoek maakt geen factuur aan. Generatie bij aanmaak gebeurt nadat de abonnementstransactie is vastgelegd; de worker probeert fouten opnieuw, en uw toepassing mag het abonnement daarom niet opnieuw aanmaken.
Bij generatie op het aanmaakmoment vallen de uitgifte- en vervaldatum beide samen met de aanmaakdatum van het betaalverzoek: de factuur is bij uitgifte verschuldigd, niet op graceEndsAt. Deze datums verschuiven niet bij nieuwe pogingen. De aanmaak- en betalingstriggers hergebruiken dezelfde factuur: latere betaling maakt geen duplicaat aan en vervangt de bestaande PDF/XML niet. Raadpleeg het gekoppelde verzoek voor de actuele betaalstatus.
Een factuur uitreiken maakt geen betaling aan en verandert access niet. De respijtperiode van het plan en de geverifieerde nettobetaling blijven onafhankelijk van het facturatiemoment. Dezelfde regel geldt wanneer Bookelio zelf via een URL-verbinding klant is van de verkopende instantie.
Gebruikersplaatsen synchroniseren en van plan veranderen
Definieer voor een externe toepassing wat een gebruikersplaats is en bereken het aantal op uw server. Bookelio volgt de gebruikers van uw toepassing niet automatisch en maakt op basis van dat aantal geen aanmeldingsquotum aan.
await billingRequest(
`applications/${appId}/subscriptions/by-external-id/${externalId}/seats`,
{ method: 'PUT', body: { seats: 12 } },
);
await billingRequest(`subscriptions/${encodeURIComponent(subscriptionId)}`, {
method: 'PATCH',
body: { planId: nextPlanId, seats: 12 },
});
Zonder change vullen deze wijzigingen pendingSeats en pendingPlanId voor de volgende verlenging in. Ze herberekenen de prijs of rechten van de huidige periode niet en passen geen proratering toe. Het aantal dat Bookelio bij het begin van de nieuwe periode kent, wordt vastgelegd. Wijzig ook de gebruikersplaatsen van een vast plan als u het aantal gebruikers wilt bijhouden: bij een prijs per gebruikersplaats van nul blijft het bedrag gelijk.
Om de tarieven, functies of respijtperiode van een plan voor toekomstige periodes te wijzigen, gebruikt u PATCH /plans/{planId} met de te wijzigen velden, bijvoorbeeld {"basePriceCents": 450000, "gracePeriodDays": 7}. Bestaande periodes behouden hun voorwaarden. Een softwaretoepassing of plan op isActive: false zetten verhindert nieuwe abonnementen ervoor; bestaande contracten worden daardoor niet opgezegd.
Een onmiddellijke wijziging met prorata toepassen
V1-r29 voegt optionele change toe aan beide bovenstaande bewerkingen. effectiveAt: 'NEXT_PERIOD' behoudt de planning en aanvaardt alleen proration: 'NONE'. Verstuur effectiveAt: 'IMMEDIATE' met een vaste idempotentiesleutel van 1–100 tekens om nu te handelen. De standaardwaarde van proration is NONE: kies de gewenste financiële verwerking expliciet.
await billingRequest(`subscriptions/${encodeURIComponent(subscriptionId)}`, {
method: 'PATCH',
body: {
planId: upgradedPlanId,
seats: 12,
change: {
effectiveAt: 'IMMEDIATE',
proration: 'CHARGE_AND_CREDIT',
idempotencyKey: 'example-account-change-2026-09-08-001',
},
},
});
Voeg voor alleen gebruikersplaatsen hetzelfde change-object toe aan de body { seats: 12 } van PUT .../seats. Leid account, aantal en toegestaan plan altijd op de server af. Bewaar de sleutel voor herhalingen van dezelfde opdracht; een nieuwe sleutel betekent een nieuwe actie. Een sleutel met andere parameters hergebruiken geeft een conflict. Genereer niet voor elke netwerkpoging een nieuwe sleutel.
proration | Gevolg voor de resterende periode |
|---|---|
NONE | Past plan/gebruikersplaatsen toe zonder financiële aanpassing |
CHARGE_ONLY | Factureert alleen verhogingen; geen korting bij verlagingen |
CHARGE_AND_CREDIT | Factureert verhogingen en draagt toegestane gefinancierde verlagingen over als commerciële korting |
De berekening omvat het vaste bedrag en de gebruikersplaatsen, op basis van het exacte aandeel resterende UTC-tijd in de kalenderperiode, afgerond op centen. Ze gaat niet uit van maanden van 30 dagen. Halverwege een periode geeft een fictieve verhoging van € 100 naar € 160 exclusief btw € 30 vóór btw; wijzigingen aan plaatsen beïnvloeden een plan met seatPriceCents: 0 niet.
Het abonnement mag niet opgezegd zijn, de periode moet nog geldig zijn en alle financiële verplichtingen moeten voldaan zijn. Een onbetaald bedrag blokkeert de aanpassing, ook tijdens respijt. De nieuwe facturatiefrequentie moet gelijk blijven; plan overgangen tussen maandelijks en jaarlijks bij de verlenging. Tijdens een proefperiode of aanbieding behoudt de wijziging de gratis einddatum en ontstaat geen verschuldigd bedrag of krediet. Laat change weg of gebruik NEXT_PERIOD zonder prorata om een opgezegd abonnement opnieuw te activeren.
De server voegt een onveranderlijke periode toe waarvan previousCycleId de voorganger aanwijst. currentPeriodStart wordt de wijzigingsdatum, maar het oorspronkelijke einde en de verlengingsankerdatum blijven gelijk. Eerdere facturen en verzoeken blijven intact. Een nog te betalen toeslag maakt een verzoek met vastgelegde factuur- en respijtregels voor deze nieuwe periode; de rechten volgen betaling of dat respijt. Lees entitlements opnieuw na de aanroep: een geslaagde wijziging bewijst geen betaling en schrijft niet automatisch geld van een kaart af.
creditGrantedCents registreert de toegekende korting, creditAppliedCents de verbruikte korting en creditBalanceCents het resterende saldo, in centen exclusief btw voor alleen dit abonnement. Het saldo vermindert toekomstige bedragen vóór btw: het is geen boekhoudkundige creditnota op een eerdere factuur, bankterugbetaling of betaling. Er ontstaat geen negatief verzoek of fictieve betaling. De korting is begrensd tot de gefinancierde waarde; een proefperiode, aanbieding of gratis verhoging levert geen crediteerbare waarde op. Algemene terugbetalingen van een abonnement met aanpassingen worden geweigerd totdat een specifieke reconciliatieprocedure beschikbaar is.
Gratis maanden toekennen via de API
Voeg bij aanmaak bijvoorbeeld offer: { label: 'Welkomstaanbieding', freeMonths: 1 } toe aan de body van POST /subscriptions. Gebruik voor een bestaand abonnement subscriptions.grantOffer:
await billingRequest(
`subscriptions/${encodeURIComponent(subscriptionId)}/offers`,
{
method: 'POST',
body: {
label: 'Eén gratis maand — fictief voorbeeld',
freeMonths: 1,
idempotencyKey: 'example-commercial-offer-001',
},
},
);
De omschrijving telt 1–200 tekens, freeMonths is een geheel getal van 1 tot 36 en de sleutel telt 1–100 tekens. Er mag maar één aanbieding wachten. Dezelfde sleutel en gegevens opnieuw versturen voegt geen maanden toe, ook niet na toepassing; andere gegevens onder die sleutel geven een conflict. De aanmaak van een bestaand abonnement herhalen voegt geen aanbieding toe: gebruik de specifieke bewerking. Een opgezegd abonnement moet eerst opnieuw geactiveerd worden.
Een initiële aanbieding bij een herhaalde aanmaak moet overeenkomen met de reeds geregistreerde aanbieding; een ontbrekende of andere aanbieding op het bestaande abonnement geeft een conflict. Antwoorden tonen maximaal de 20 recentste aanbiedingen, net als de 20 recente periodes: dit is geen volledige export van de historiek.
De aanbieding wacht op de volgende normaal betalende periode, na de proefperiode of reeds uitgereikte periode; zonder proefperiode kan ze bij aanmaak beginnen. Onbetaalde bedragen blijven blokkerend en volledig gratis plannen laten ze wachten. Geen bestaand document of verschuldigd bedrag verandert. Eén maand betekent één UTC-kalendermaand, ook bij een jaarplan, met aanpassing aan het maandeinde; de betalende facturatie hervat aan het einde van de aanbieding met die nieuwe ankerdatum.
De aangeboden periode toont isComplimentary: true en offerId, blijft ACTIVE en maakt geen betaalverzoek of automatische factuur aan. Het is geen nieuwe proefperiode; controleer altijd access en validUntil. offers toont de omschrijving, duur, appliedAt en periodedatums zodra ze verbruikt is. De nieuwe uitvoervelden voor prorata en aanbiedingen zijn optioneel om oudere verkopers te aanvaarden: hun afwezigheid bewijst geen korting of aanbieding. De verkoper moet V1-r29 gebruiken om deze opties toe te passen; controleer zijn revisie voordat u deze acties aanbiedt.
Bij vertraging van de worker begint een aanbieding nooit vóór de toekenningsdatum. Als de volledige gratis periode al verstreken zou zijn vóór verwerking, begint ze bij het hervatten van de worker zodat ze niet volledig in het verleden wordt verbruikt. De datums die Bookelio terugstuurt zijn bepalend.
Opzeggen en opnieuw activeren
await billingRequest(
`subscriptions/${encodeURIComponent(subscriptionId)}/cancel`,
{ method: 'POST', body: { cancelAtPeriodEnd: true } },
);
true plant het einde bij het aflopen van de periode: reeds geldige rechten blijven binnen hun huidige grens bruikbaar, zonder een respijtperiode te verlengen die vóór die datum afloopt. false vraagt om onmiddellijke opzegging en beëindigt ook lopend respijt; het betekent niet dat een geplande opzegging wordt geannuleerd. Uitgegeven betaalverzoeken en de financiële historiek blijven behouden.
Zodra de status CANCELED is, verstuurt u een PATCH /subscriptions/{subscriptionId} met een expliciete planId om opnieuw te activeren. Alleen de gebruikersplaatsen synchroniseren volstaat niet. Een reeds betaalde en nog geldige periode wordt hervat zonder opnieuw gefactureerd te worden; na afloop begint een nieuwe periode. Hervatten geeft geen nieuwe proefperiode en wordt geweigerd als er nog een oud onbetaald verzoek is. POST /subscriptions opnieuw uitvoeren vindt het bestaande abonnement terug en activeert het niet opnieuw.
Het plan wijzigen via subscriptions.update voordat de geplande opzegging ingaat, verwijdert cancelAtPeriodEnd niet. Sinds V1-r33 past expliciete activering via subscriptions.activate, hieronder beschreven, het plan nu toe en verwijdert ze die planning na controle van openstaande bedragen.
Bookelio via een URL met een facturatie-instantie verbinden
Deze configuratie geldt voor Bookelio zelf. Maak op de verkopende instantie een Bookelio-softwaretoepassing aan en bereid uw plannen voor. Bij het opstarten voegt Bookelio ontbrekende sleutels uit zijn catalogus toe, bijvoorbeeld invoicing, trainings of softwareBilling, zonder bestaande definities te overschrijven. Selecteer daarna expliciet de functies in elk plan: een sleutel toevoegen maakt die niet automatisch beschikbaar in aanbiedingen. Zo kan de module voor abonnementsverkoop zelf ook deel uitmaken van een aanbod.
Configureer op de API en de workers van de klantinstantie de drie variabelen die Bookelio herkent:
BOOKELIO_BILLING_URL=https://api.billing.example.com
BOOKELIO_BILLING_API_KEY=REPLACE_WITH_SELLER_ORGANIZATION_KEY
BOOKELIO_BILLING_APPLICATION_ID=REPLACE_WITH_BOOKELIO_APPLICATION_ID
De verbinding verloopt altijd via HTTP /rpc/v1, ook als de URL naar dezelfde instantie verwijst. Het adres moet bereikbaar zijn vanaf de API en de workers. Gebruik een API-URL zonder ingebedde aanmeldgegevens, queryparameters of fragment. Op de API en de workers van de verkopende instantie verwijst BOOKELIO_WEB_URL naar de origin van het publieke dashboard voor betaallinks. De verbindingssleutel heeft softwareBilling.read, softwareBilling.manage en customers.create nodig voor raadpleging, registratie en synchronisatie; voeg paymentRequests.create toe om organisaties op plannen in te schrijven.
Organisaties koppelen bij het opstarten
Na het openen van haar HTTP-server registreert de klant-API de ontbrekende catalogus en accounts voor de lokale niet-legacyorganisaties. Ze gebruikt de organisatie-ID als externalId, de naam en het aantal leden, inclusief de eigenaar, met minstens één gebruikersplaats. Een externe koppeling is uniek voor de toepassing en dit identificatiegegeven. Herhalingen hergebruiken de koppeling; een scan zonder overlap probeert fouten opnieuw en ontdekt elke minuut nieuwe organisaties. Legacyorganisaties worden overgeslagen voor accounts en synchronisatie van gebruikersplaatsen, maar niet voor de registratie van de gedeelde catalogus. Het opstarten wacht niet op een antwoord van de eigen URL voordat de server begint te luisteren.
Als voor deze identiteit al een extern abonnement bestaat, wordt de klant ervan hergebruikt. Anders maken lokale bedrijfsgegevens alleen een facturatieklant aan als het vereiste profiel volledig en geldig is. Er wordt geen land of fiscaal identificatiegegeven verzonnen. Een onvolledig profiel laat een gekoppeld account zonder klant achter; gegevens van een al gekoppelde klant worden niet overschreven. De bewerking applications.provision zelf maakt geen plan, abonnement, betaalverzoek, factuur of betaling aan.
Als er al een abonnement bestaat, roept de scan na deze bewerking subscriptions.syncSeats aan zonder onmiddellijke optie: gebruikersplaatsen worden bij verlenging gepland, zonder prorata of nieuwe betaalverplichting. Een opgezegd abonnement wordt niet opnieuw geactiveerd. Deze aanroep behoudt bestaande automatisering: ze kan een al verwachte factuur voor een bestaand betaalverzoek in de modus PAYMENT_REQUEST_CREATED opnieuw proberen, zonder een nieuw verzoek aan te maken.
De verkoper moet V1-r30 gebruiken en het aanvullende schema hebben uitgerold voordat dit opstartproces bij de klant wordt ingeschakeld. Een oudere instantie kan bestaande leesaanvragen nog beantwoorden, maar biedt de nieuwe registratiebewerking niet aan. De sleutel moet beide registratierechten hebben, ook als een batch uiteindelijk geen nieuwe klant nodig heeft.
De bewerking is ook beschikbaar voor een andere toepassing: applications.provision, of POST /applications/{applicationId}/provision onder het REST-voorvoegsel van de module. Fictief voorbeeld zonder facturatieprofiel, dus zonder klantaanmaak:
const provisioned = await billingRequest(
`applications/${encodeURIComponent(applicationId)}/provision`,
{
method: 'POST',
body: {
features: [{ key: 'reporting', name: 'Rapporten' }],
accounts: [{ externalId: 'example-organisation-001', name: 'Voorbeeldorganisatie', seats: 5 }],
},
},
);
Batches aanvaarden maximaal 200 functies en 100 accounts. Het antwoord identificeert de toepassing, sleutels en voor elke identiteit accountId, customerId en subscriptionId; de laatste twee kunnen null zijn. Een geregistreerde identiteit bewijst dus geen abonnement of toegang. Gebruik altijd entitlements om functies toe te staan. Een identieke aanroep dupliceert geen sleutels of accounts en vervangt geen bestaande functiemetadata.
Plannen toewijzen en externe rechten toepassen
In de superadmin controleert de pagina Facturatie de verbinding. Het abonnementstabblad van een organisatie kan een plan en een klant van de verkopende instantie koppelen. De eigenaar kan na bevestiging ook een plan kiezen via Instellingen → Mijn Bookelio-abonnement. Bookelio gebruikt de ID van de klantorganisatie als externalId en synchroniseert het aantal leden, inclusief de eigenaar, met een minimum van één gebruikersplaats.
De verbinding gebruikt dezelfde berekende rechten, inclusief de respijtperiode op het plan van de verkoper. Er is geen extra respijtinstelling nodig op de klantinstantie, ook niet wanneer die haar eigen URL voor facturatie gebruikt.
Aanbiedingen en aanpassingen bij de verkoper gebruiken ook deze verbinding. De automatische synchronisatie van Bookelio-leden stuurt geen onmiddellijke optie: wijzigingen aan gebruikersplaatsen blijven gepland bij verlenging. Uw eigen abonnementspagina toont aanbiedingen en het kortingssaldo alleen ter inzage; commerciële wijzigingen gebeuren bij de verkoper.
Voor niet-legacyorganisaties bepaalt de Bookelio-leverancier alle functies, ook functies die eerder standaard of zonder tarief waren ingeschakeld. Een sleutel die ontbreekt in zijn rechten is uitgeschakeld. Sinds V1-r32 gebruiken Bookelio-plannen uitsluitend een externe leverancier: oude lokale plannen en abonnementen, standaardwaarden en individuele uitzonderingen verlenen geen toegang meer. De lokale catalogus behoudt definities, sleutelkoppelingen en globale activering, geen commerciële rechten. Historische tabellen worden niet verwijderd; de verkoopmodule blijft haar eigen plannen opslaan, ook op dezelfde instantie via HTTP gelezen.
De generieke leverancier BOOKELIO_FEATURE_PROVIDER_* wordt niet naast Bookelio bevraagd. Een onvolledige Bookelio-configuratie of storing activeert geen terugval. Als de drie variabelen BOOKELIO_BILLING_* ontbreken, kan alleen de generieke leverancier rechten leveren; zonder enige leverancier heeft een niet-legacyorganisatie geen functies. Die generieke leverancier biedt alleen een leescontract: Bookelio verzint geen schrijf-API om er sleutels of organisaties aan te maken. De hier beschreven registratie geldt uitsluitend voor een Bookelio-instantie die via BOOKELIO_BILLING_* is ingesteld.
Expliciete vrijstelling voor legacyorganisaties
V1-r32 voegt Organization.bookelioLegacyAccess toe, standaard false. Alleen een superbeheerder kan een organisatie als legacy markeren, bijvoorbeeld voor Bookelio zelf of een contract voor ontwikkeling op maat. De geauditeerde bewerking superadmin.organizations.setLegacyAccess aanvaardt strikt { organizationId, enabled } en antwoordt met { id, bookelioLegacyAccess }. De REST-route is PUT /api/v1/superadmin/organizations/{organizationId}/legacy-access. Een eigenaar of organisatiesleutel kan ze niet aanroepen; geen generieke variabele of uitzondering per functie verleent deze vrijstelling.
Legacy geeft toegang tot alle globaal actieve functies zonder de leverancier te raadplegen, ook als die ontbreekt, fout geconfigureerd of onbereikbaar is. Het omzeilt noch authenticatie, organisatie-isolatie, bedrijfsrechten van leden en sleutels, noch een globale uitschakeling van een functie. Diagnostiek toont het optionele object providers.legacy: { active: true } en behoudt de V1-bron manual. Oude uitzonderingsroutes blijven beschikbaar voor compatibiliteit, maar hun gegevens verlenen geen rechten meer.
De leesbewerkingen admin.organization.subscription.get/options tonen de optionele boolean bookelioLegacyAccess. Voor legacy antwoorden ze met connected: false, zonder extern leesverzoek, met subscription: null voor get en geen plannen voor options. Dit resultaat betekent een vrijstelling en geen leveranciersstoring. Mijn Bookelio-abonnement legt dat uit zonder plankeuze; configure weigert een plan voor een legacyorganisatie.
De vrijstelling inschakelen annuleert geen bestaand abonnement bij de verkoper, stopt geen toekomstige facturen en verwijdert geen openstaande schuld of documenten. Beheer dat abonnement apart en expliciet bij de verkoper. Legacy uitschakelen herstelt de externe controles; synchronisatie kan hervatten zonder automatisch een abonnement aan te maken.
Laat vóór de uitrol van V1-r32 de aanvullende kolom Organization.bookelioLegacyAccess Boolean @default(false) handmatig genereren, nakijken en toepassen. Bereid externe rechten voor of markeer tijdens de omschakeling expliciet alleen de bedoelde legacyorganisaties. Markeer bestaande klanten niet automatisch en verwijder geen historische tabellen: zonder leverancier krijgt een niet-legacyorganisatie haar eerdere lokale rechten niet meer.
De eigenaar kiest een plan via de klant-API
V1-r31 voegt twee bewerkingen toe op de API van de klantinstantie, niet die van de verkoper. Ze vereisen een menselijke sessie en een owner-lidmaatschap dat nog in de database bestaat voor de actieve organisatie. Een API-sleutel, beheerder zonder eigenaarschap of andere organisatie kan ze niet gebruiken. De controle hangt niet af van de verkoopmodule, zodat verlopen toegang hersteld kan worden. Andere bevoegde rollen behouden de bestaande leesbewerking admin.organization.subscription.get.
| oRPC-bewerking | REST-route | Effect |
|---|---|---|
admin.organization.subscription.options | GET /api/v1/admin/organization/subscription/options | Alleen lezen: connected, actieve plans, serverberekende seats en billingDetailsRequired |
admin.organization.subscription.configure | PUT /api/v1/admin/organization/subscription/plan | Na bevestiging: kiezen met { planId, expectedOrganizationId, activation? }, met het Bookelio-abonnement als antwoord |
expectedOrganizationId vermeldt de organisatie waarvoor de eigenaar net heeft bevestigd. Het is alleen een voorwaarde: als de sessie ondertussen van organisatie is veranderd, weigert de API met CONFLICT vóór enige schrijfactie. Het doel, de externe identiteit en de plaatsen blijven uit de sessie en database afgeleid; extra prijzen, klanten, aantallen, aanbiedingen of prorataparameters worden niet aanvaard.
De opties lezen maakt geen klant of abonnement aan. Bij configuratie hergebruikt de server de klant van het externe abonnement of account. Het verkopersresultaat subscriptions.getByExternalId bevat voortaan een optioneel account voor deze koppeling vóór het abonnement; oude antwoorden zonder dat veld blijven aanvaard. Zonder gekoppelde klant wordt een volledig bedrijfsprofiel aan de bestaande registratie doorgegeven; onvolledige gegevens vereisen het aanvullen van Instellingen → Bedrijfsgegevens vóór bevestiging. Er wordt geen land of fiscaal identificatiegegeven verzonnen en een al gekoppelde klant wordt niet herschreven.
Sinds V1-r33 stuurt het dashboard activation: { idempotencyKey } om het plan onmiddellijk toe te passen. De sleutel blijft gelijk bij nieuwe pogingen voor dezelfde bevestiging. Zonder dit optionele veld behouden oudere aanroepen hun gedrag: eerste aanmaak, een nieuw plan bij verlenging of beschermde hervatting. Een eerste keuze volgt de regels voor gratis gebruik en een proefperiode; een latere keuze begint nooit een nieuwe proefperiode.
De server roept vervolgens admin.softwareBilling.subscriptions.activate bij de verkoper aan (POST /api/v1/admin/software-billing/subscriptions/activate) met de strikte invoer { applicationId, externalId, customerId, planId, seats, idempotencyKey }. Deze atomaire bewerking vereist softwareBilling.manage en paymentRequests.create en bewaart een ontvangstbewijs voor elke geslaagde activering, ook als het plan al toegepast is. De sleutel en vingerafdruk voorkomen dubbele aanrekeningen of het opnieuw toepassen van een oude keuze na een latere wijziging. De verkoper berekent prijzen en financiële verwerking; die worden nooit in de browser gekozen.
Het beleid is CHARGE_ONLY: bij dezelfde facturatiefrequentie wordt alleen een positief verschil naar rato aangerekend voor de resterende tijd tot de oorspronkelijke einddatum. Een gewijzigde frequentie begint nu een nieuwe periode en trekt de resterende waarde exclusief btw af van de dienst waarvan de financiering geverifieerd is; een overschot wordt niet overgedragen of terugbetaald. Een proefperiode of aangeboden periode behoudt haar gratis einddatum, ook bij een andere frequentie. Een verlopen, betaalde periode begint nu opnieuw zonder oude periodes achteraf aan te rekenen. Expliciete activering verwijdert ook een al geplande opzegging.
Een keuze die overeenkomt met de huidige momentopname, zonder geplande wijzigingen, geeft een bestaand betaalverzoek terug zonder extra aanrekening. Openstaande verplichtingen verhinderen een andere configuratie. Het huidige plan opnieuw toepassen kan verouderde functiemomentopnames vernieuwen, bijvoorbeeld die van een oudere gratis periode. Eerdere periodes, betalingen en facturen blijven intact. Lees het abonnement en de rechten opnieuw: de pagina biedt Nu betalen aan voor een verschuldigd verzoek, maar een plan bevestigen schrijft niet automatisch geld van een kaart af en bewijst geen betaling. Betalende functies volgen op geverifieerde betaling of toepasselijke respijt. Aanbiedingen blijven beslissingen van de verkoper.
De serversleutel naar de verkoper behoudt de rechten softwareBilling.read, softwareBilling.manage, customers.create en paymentRequests.create. Hij wordt nooit naar de browser gestuurd. Aanroepen blijven HTTP /rpc/v1, ook voor dezelfde instantie. Laat de aanvullende tabel BookelioSoftwareActivation, relatie en unieke sleutel handmatig genereren, nakijken en toepassen vóór de uitrol van verkoper V1-r33 en daarna de klant die activering vraagt. Een oudere verkoper krijgt geen uitgestelde wijziging als terugval. De bestaande aanvullende periode- en accountschema's en legacykolom blijven vereist; verzin geen historische ontvangstbewijzen en voeg geen extra omgevingsvariabele toe. Zonder verbinding of voor een legacyorganisatie kan via dit traject geen plan gekozen worden.
Vóór activering door de eigenaar leest de server het openbare register /api-versions.json van de verkoper, zonder de API-sleutel mee te sturen. Een V1-vermelding met revisie 33 of hoger is vereist vóór enige accountregistratie of activering. Een oudere verkoper kan nog plannen tonen, maar de activering door de eigenaar wordt geweigerd met een fout SERVICE_UNAVAILABLE die om een update vraagt; dit betekent niet dat het plan of account verdwenen is. Als het register onbereikbaar of ongeldig is, meldt de fout dat de versie niet gecontroleerd kan worden: herstel dat toegangspunt vóór een nieuwe poging. Oudere aanroepen zonder activation blijven ongewijzigd.
De integratie onderzoeken en valideren
| Symptoom | Controle |
|---|---|
| Sleutel geweigerd of toegang verboden | Geldige organisatiesleutel, rechten voor de bewerking en module geactiveerd voor de verkoper |
| Functies ontbreken zonder leverancier | Configureer externe rechten of laat een superbeheerder de legacyvrijstelling nakijken; geen lokaal plan dient als terugval |
| Legacyorganisatie zonder plankeuze | Verwacht gedrag; de vrijstelling annuleert geen abonnement bij de verkoper |
| Bookelio-plankeuze geweigerd | Eigenaarssessie voor de actieve organisatie; geen API-sleutel vervangt deze controle. Na een organisatiewissel herladen vóór bevestiging |
| Gegevens gevraagd vóór inschrijving | Vul de bedrijfsgegevens aan of laat de al gekoppelde klant bij de leverancier controleren; gebruik nooit verzonnen gegevens |
| Software, plan of klant niet gevonden | Identificatiegegevens moeten bij dezelfde verkoper horen; het plan moet bij de softwaretoepassing horen |
| Koppeling bij opstarten ontbreekt | Verkoper met V1-r30, aanvullende migratie toegepast, bereikbare URL en rechten softwareBilling.manage / customers.create; wacht na correctie op de volgende scan |
| Gekoppeld account zonder abonnement of klant | Onvolledig facturatieprofiel of geen toegewezen plan; vervolledig het profiel of selecteer expliciet klant en plan, zonder automatische facturatie te verwachten |
| Conflict bij aanmaak | Externe referentie al in gebruik; lees het abonnement opnieuw en wijzig het in plaats van het opnieuw aan te maken |
| Geen rechten na terugkeer van de betaling | Volledige betaling daadwerkelijk bevestigd, periode nog geldig, functiesleutel inbegrepen |
PAST_DUE terwijl de toegang nog open is | Actief respijt: controleer isInGracePeriod en validUntil, zonder die toegang als betaling te beschouwen |
| Respijt ontbreekt of is al afgelopen | Vastgelegde waarde in de periode, periodebegin, graceEndsAt, opzegging of terugbetaling; het plan wijzigen verandert de historiek niet |
| Nieuw plan of nieuw aantal niet zichtbaar | Controleer zonder onmiddellijke optie pendingPlanId en pendingSeats; lees anders de rechten en het nieuwe te betalen verzoek opnieuw |
| Onmiddellijke wijziging geweigerd | Geen schuld, recht paymentRequests.create en een consistente idempotentiesleutel; subscriptions.update vereist ook een geldige periode en dezelfde frequentie, subscriptions.activate vereist een gemigreerde V1-r33-verkoper |
| Aanbieding blijft wachten | Lopende proefperiode of uitgereikte periode, gratis plan, blokkerend onbetaald bedrag; bekijk de datums in offers |
| Geen betaallink | Gratis periode of proefperiode, of de publieke origin van de verkoper ontbreekt |
| Factuur verwacht bij aanmaak van het verzoek maar ontbreekt | Verkoperskeuze vastgelegd bij aanmaak van de periode, generatie- en verzenddiensten beschikbaar en worker actief; geen terugwerkend effect |
| Geen verlenging | Worker actief, periode afgelopen en geen blokkerend onbetaald verzoek |
Controleer op een testinstallatie die voor deze module is voorbereid een gratis plan, een proefperiode, een onvolledige en daarna volledige betaling, een vast plan met verschillende aantallen gebruikers en een aanbod per gebruikersplaats. Test uitgeschakeld en daarna ingeschakeld respijt, de exacte eindgrens, betaling tijdens en na het respijt, een terugbetaling en een wijziging die alleen toekomstige periodes verandert. Controleer beide factuurtriggers, het ontbreken van duplicaten na betaling en het ontbreken van terugwerkend effect op bestaande verzoeken. Controleer ook dat een account nooit de rechten of betaalverzoeken van een ander account kan raadplegen door een identificatiegegeven in de browser te wijzigen. Sluit af met een geplande wijziging, een opzegging en een hervatting zonder nieuwe proefperiode, en vervolgens met een gesimuleerde verbindingsstoring.
Test voor de V1-r29-opties een onmiddellijke verhoging en daarna verlaging, elke proratamodus, extra plaatsen en herhalingen met dezelfde sleutel. Controleer een korting die op een toekomstig bedrag wordt verbruikt en het ontbreken van krediet na een gratis upgrade. Test één gratis maand op een jaarplan, na een proefperiode en met een onbetaalde factuur, plus de weigering van een tweede wachtende aanbieding. Controleer de nieuwe acties met en zonder hun financiële rechten.
Test voor V1-r30 het opstarten met een externe URL en daarna die van dezelfde instantie, twee opeenvolgende scans, een functie die de verkoper al heeft gedefinieerd en een organisatie die na het opstarten wordt aangemaakt. Controleer volledige en onvolledige profielen, hergebruik van een bestaande klant, geen nieuw abonnement of nieuwe financiële verplichting en weigering van sleutels zonder rechten. Controleer ook geplande gebruikersplaatsen en normale herhalingen van verwachte facturen op bestaande verzoeken. Simuleer een storing: geen lokale waarde of uitzondering mag de rechten van de ingestelde leverancier omzeilen.
Controleer voor V1-r31 dat opties lezen geen klant of abonnement aanmaakt, dat een niet-eigenaar of API-sleutel geen plan kan configureren en dat wisselen van organisatie vóór bevestiging een conflict veroorzaakt. Test hergebruik van een gekoppelde klant, ontbrekende gegevens, een eerste gratis plan of proefperiode, een uitgestelde wijziging en hervatting zonder nieuwe proefperiode. De keuze mag geen door de browser aangeleverde prijzen, klanten, aantallen of commerciële opties aanvaarden.
Controleer voor V1-r32 de weigering zonder leverancier voor een niet-legacyorganisatie, ook met een oud plan of uitzondering. Test legacy met een ontbrekende of onbereikbare leverancier, een inactieve functie en een lid zonder bedrijfsrecht. Controleer dat alleen een superbeheerder de status wijzigt, dat audit wordt vastgelegd en dat voor legacy geen externe account-, plaatsen- of plankeuzeaanroep plaatsvindt. De vrijstelling verwijderen moet externe controles herstellen zonder schuld te wissen of een abonnement aan te maken.
Test voor V1-r33 de onmiddellijke activering van een gratis of betalend plan, het vernieuwen van de huidige functies, de toeslag naar rato, een gewijzigde frequentie en hervatting. Controleer het aangeboden betaalverzoek na bevestiging en herladen, de weigering van een andere configuratie bij openstaande schuld, nieuwe pogingen zonder dubbels en oudere aanroepen zonder activation die wijzigingen blijven plannen. Een oudere verkoper moet activering weigeren zonder stilzwijgend een wijziging bij verlenging toe te passen.
Betaalperiodes, toegangsrechten en facturen worden door Bookelio beheerd. De aangesloten toepassing gebruikt de API om ze te raadplegen en te beheren; ze wijzigt periodes, betaalstatussen of de facturatiedatabase niet rechtstreeks.