Przejdź do głównej zawartości
getnextpdf.com

Enterprise edycja

Billing — szczegółowa referencja

Ta strona jest szczegółową referencją powierzchni rozliczeń NextPDF Enterprise. Powierzchnia ma dwie warstwy. Model rozliczeń w NextPDF\Enterprise\Billing definiuje poziomy planów, limity, polityki przekroczenia limitu oraz zdeduplikowane alerty zużycia. Substrat egzekwowania w NextPDF\Enterprise\Billing\Substrate umieszcza ten model na aktywnej ścieżce żądań — odporny na awarie (fail-closed) i bezpieczny współbieżnie. Punktami wejścia są PlanRegistry, QuotaManager, OverageCalculator, BillingAlertService oraz QuotaEnforcementGuard. Przewodnik na poziomie przepływu pracy znajduje się na stronie możliwości Billing.

Ta możliwość jest dostarczana w NextPDF Enterprise (nextpdf/enterprise) i aktywuje się wraz z kopertą licencyjną na poziomie Enterprise. Wdrożenie bez tego uprawnienia nie ładuje klas tej możliwości. Porównaj edycje i uzyskaj licencję.

Billing to podstawowa możliwość Enterprise bez osobnej flagi dla poszczególnych funkcji; jest dostępna po zainstalowaniu pakietu Enterprise obok pakietu Core. NextPDF Core (Apache-2.0) oraz NextPDF Pro nie mają modelu planów, limitów ani przekroczeń; ta powierzchnia nie ma odpowiednika na niższym poziomie. Uwzględnione elementy planu, limity oraz warunki komercyjne są regulowane umową licencyjną, a nie egzekwowaniem w czasie wykonywania; niniejsza referencja nie jest opinią prawną ani umowną.

Wszystkie symbole znajdują się w NextPDF\Enterprise\Billing. Wiersze oznaczone jako substrate znajdują się w NextPDF\Enterprise\Billing\Substrate. TenantContext to uwierzytelniony typ najemcy z NextPDF\Enterprise\SaaS.

SymbolParametryDomyślne zachowanieZwracaZgłasza lub kończy się błędemUwagi
SaaSPlan (enum)Poziomy planów oparte na łańcuchach: standard, advanced, high_controlNie zgłaszalabel() zwraca nazwę wyświetlaną
PlanDefinition::__constructSaaSPlan $plan, float $includedCuQuota, list<CapabilityCode> $capabilities, non-empty-string $priceTier, bool $intelligencePackIncluded, bool $privacyPackIncludedNiezmienny obiekt wartości planu; przechowuje dane wejściowe w podanej postaciNowa instancjaNie zgłaszafinal readonly; promowane właściwości publiczne
PlanDefinition::includesCapabilityCapabilityCode $capabilityŚcisłe sprawdzenie przynależności przez tożsamośćboolNie zgłasza
PlanRegistry::__constructlist<PlanDefinition> $definitionsIndeksuje definicje według poziomu; ostatnia definicja dla danego poziomu wygrywaNowy rejestrNie zgłaszaDo testów oraz zestawów planów white-label
PlanRegistry::getSaaSPlan $planKanoniczne wyszukiwanie planuPlanDefinitionInvalidArgumentException, gdy plan nie jest zarejestrowany
PlanRegistry::hasSaaSPlan $planSonda rejestracjiboolNie zgłasza
PlanRegistry::defaultRegistry (static)Domyślne ustawienia produkcyjne: Standard 1,000 CU; Advanced 5,000 CU plus Intelligence Pack; High Control 20,000 CU plus Intelligence i Privacy PackPlanRegistryNie zgłaszaUżywaj, chyba że warunki umowne wymagają niestandardowych definicji
OveragePolicy (enum)hard_stop, soft_stop, budget_alertNie zgłaszahttpStatusCode() odwzorowuje 402 / 429 / 200; isBlocking() jest prawdą tylko dla twardego i miękkiego zatrzymania
QuotaManager::__constructPlanRegistry $planRegistry, OveragePolicy $overagePolicyWiąże rejestr z jedną politykąNowa instancjaNie zgłasza
QuotaManager::checkQuotaTenantContext $tenant, SaaSPlan $plan, float $currentCuZwraca po cichu przy limicie lub poniżej, albo przy polityce nieblokującejvoidQuotaExceededException przy ścisłym przekroczeniu w ramach polityki blokującej; InvalidArgumentException z rejestru przy niezarejestrowanym planieresetsAt = pierwszy dzień następnego miesiąca, północ UTC
QuotaManager::remainingQuotaSaaSPlan $plan, float $currentCuCzysty odczyt; nigdy nie blokujefloatInvalidArgumentException z rejestruUjemny przy przekroczeniu
QuotaManager::usagePercentageSaaSPlan $plan, float $currentCuCzysty odczyt; nigdy nie blokujefloatInvalidArgumentException z rejestru0.0, gdy uwzględniony limit jest niedodatni; powyżej 1.0 przy przekroczeniu
OverageCalculator::calculatePlanDefinition $plan, float $currentCuOblicza niezmienny obraz przekroczeniaOverageResultNie zgłaszafinal readonly, bezstanowy
OverageResultincludedCu, usedCu, overageCu, usageRatio, isOverageNiezmienny wynik obliczeńNie zgłaszaoverageCu = max(0, used - included); isOverage wymaga ścisłego przekroczenia
BillingAlertType (enum)quota_warning_80, quota_warning_100, budget_exceeded, monthly_cap_reachedNie zgłaszathreshold() 0.8 / 1.0 / 1.0 / 1.0; severity() warning / critical / critical / critical
BillingAlertService::__constructAlertStateRepositoryInterface $alertStateWiąże magazyn deduplikacjiNowa instancjaNie zgłasza
BillingAlertService::evaluateTenantContext $tenant, SaaSPlan $plan, PlanDefinition $planDef, float $currentCuUruchamia jeszcze nieuruchomione alerty w rosnącej kolejności progów i rejestruje jelist<BillingAlertType>InvalidArgumentException przy niezgodności planu i definicjiKlucz deduplikacji: najemca, typ, okres UTC YYYY-MM
BillingAlertService::clearAlertsTenantContext $tenantCzyści stan uruchomienia najemcy dla bieżącego okresu UTCvoidBłędy zdefiniowane przez repozytorium są propagowanePonownie uzbraja alerty w tym samym okresie
AlertStateRepositoryInterfacehasAlertFired(), markAlertFired(), clearForPeriod()Trwały kontrakt utrwalania deduplikacji alertówZależnie od metodyZależne od implementacjiOperator odpowiada za trwałość między replikami
InMemoryAlertStateRepositoryStan uruchomienia oparty na tablicyZgodnie z interfejsemNie zgłaszaWyłącznie cykle życia pojedynczego żądania i testy
QuotaExceededExceptionReadonly currentCu, limitCu, resetsAt, tenantId, isSaaSOdmowa limitu świadoma trybu wdrożeniaJest wyjątkiem (throwable)httpStatusCode() 402 SaaS / 403 on-prem; specCode() SPEC-BILLING-003 / SPEC-LIC-001; toErrorEnvelope() zwraca ustrukturyzowane ciało błędu
DeploymentMode (enum)saas, self_hosted_oss, local_developmentNie zgłaszaSubstrate. enforcesQuota() jest prawdą tylko dla Saas; rezygnacja jest zawsze jawna
QuotaEnforcementGuard::__constructDeploymentMode, PlanResolverInterface, QuotaManager, UsageCounterStoreInterfaceSkłada aktywną bramę limituNowa instancjaNie zgłaszaSubstrate. final readonly
QuotaEnforcementGuard::enforce?TenantContext $tenant, non-empty-string $featureKey, float $amount = 1.0Odporna na awarie brama limitu z atomową rezerwacjąQuotaDecision (wyłącznie dozwolone wyniki)Zobacz taksonomię odmów poniżejSubstrate. Zamontuj po uwierzytelnieniu najemcy, przed rozliczanym handlerem
PlanResolverInterface::resolveTenantContext $tenantRozwiązuje najemcę do jego planu oraz polityk poszczególnych funkcjiResolvedPlanNoPlanForTenantExceptionSubstrate. Awaryjne przejście do planu domyślnego dla nieznanych najemców jest defektem
RegistryPlanResolverarray<non-empty-string, ResolvedPlan> $plansByTenantResolver oparty na mapieResolvedPlanNoPlanForTenantException dla niezmapowanych najemcówSubstrate. Odporny na awarie z założenia
ResolvedPlan::policyFornon-empty-string $featureKeyWyszukiwanie polityki na rozwiązanym planie?QuotaPolicyNie zgłaszaSubstrate. null oznacza nieznaną funkcję; brama ją odrzuca
QuotaPolicynon-empty-string $featureKey, float $limit, OveragePolicy $overagePolicyLimit poszczególnej funkcji i polityka naruszeniaNie zgłaszaSubstrate. UNLIMITED = -1.0; limit 0.0 oznacza zerowy przydział, a nie brak limitu; isUnlimited(), isBlocking()
QuotaDecisionStatyczne bypassed(), unlimited(), consumed()Obiekt wartości dozwolonego wynikuQuotaDecisionNie zgłaszaSubstrate. isAllowed() jest zawsze prawdą; każda odmowa zamiast tego zgłasza wyjątek
UsageCounterObraz wiersza: najemca, funkcja, granice okresu, used, limit, updatedAtNiezmienny wiersz zużyciaNie zgłaszaSubstrate. remaining() może być ujemny; wouldExceed() jest ścisły
UsageCounterStoreInterface::getNajemca, funkcja, granice okresu, float $limitOdczytuje wiersz zużycia, tworząc go z used = 0, gdy nie istniejeUsageCounterUsageStoreUnavailableExceptionSubstrate. Nigdy nie zwraca wartości falsy przy awarii zaplecza
UsageCounterStoreInterface::tryConsumeNajemca, funkcja, granice okresu, float $amount, float $limitAtomowa rezerwacja compare-and-set w granicach limitu?UsageCounter (null, gdy rezerwacja naruszyłaby limit)UsageStoreUnavailableExceptionSubstrate. Musi być pojedynczą operacją atomową względem magazynu zaplecza
InMemoryUsageCounterStoreReferencyjna implementacja kontraktu magazynu działająca w procesieZgodnie z interfejsemZgodnie z interfejsemSubstrate. Tylko pojedynczy proces; dokumentuje niezmiennik atomowości
QuotaEnforcementException (abstract)Typ bazowy każdej odmowy substratuJest rodziną wyjątków (throwable)Substrate. Każdy podtyp deklaruje httpStatusCode()
public function checkQuota(TenantContext $tenant, SaaSPlan $plan, float $currentCu): void
public function evaluate(
TenantContext $tenant,
SaaSPlan $plan,
PlanDefinition $planDef,
float $currentCu,
): array
public function enforce(?TenantContext $tenant, string $featureKey, float $amount = 1.0): QuotaDecision
public function tryConsume(
string $tenantId,
string $featureKey,
DateTimeImmutable $periodStart,
DateTimeImmutable $periodEnd,
float $amount,
float $limit,
): ?UsageCounter;

Taksonomia odmów QuotaEnforcementGuard::enforce

WyjątekStatus HTTPZgłaszany, gdy
MissingTenantContextException401Tryb SaaS bez uwierzytelnionego kontekstu najemcy
NoPlanForTenantException402Resolver nie znajduje planu przypisanego do najemcy
UnknownFeatureException402Rozwiązany plan nie definiuje polityki dla klucza funkcji
UsageStoreUnavailableException503Magazynu zużycia nie można odczytać ani atomowo zaktualizować; zgłaszany także dla niedodatniej wartości $amount
QuotaExceededException402 (SaaS) / 403 (on-prem)Limit polityki blokującej został przekroczony lub współbieżna rezerwacja zużyła ostatni zapas
  • Domyślny rejestr dostarcza trzy poziomy (Standard / Advanced / High Control) z rosnącymi limitami CU oraz zestawami możliwości. Żądanie niezarejestrowanego planu kończy się jawnym InvalidArgumentException.
  • QuotaManager::checkQuota() zgłasza wyłącznie wtedy, gdy spełnione są oba warunki: polityka jest blokująca, a bieżące zużycie jest ściśle powyżej uwzględnionego limitu. Polityka alertu budżetowego nigdy nie zgłasza; przekroczenie jest sygnalizowane przez alerty.
  • remainingQuota() oraz usagePercentage() to czyste odczyty i nigdy nie blokują. Pozostały limit staje się ujemny przy przekroczeniu; procent zużycia przekracza 1.0 przy przekroczeniu.
  • Alerty są oceniane w rosnącej kolejności progów: ostrzeżenie 80%, ostrzeżenie 100% (critical), a następnie przekroczenie budżetu (critical). Przekroczenie budżetu jest bramkowane ścisłym przekroczeniem; zużycie dokładnie na poziomie 100% uruchamia ostrzeżenie 100%, a nie przekroczenie budżetu.
  • Każdy typ alertu uruchamia się co najwyżej raz na najemcę na okres rozliczeniowy. Stan uruchomienia jest rejestrowany przez AlertStateRepositoryInterface, więc deduplikacja jest tak trwała, jak wybrana implementacja.
  • Klucz deduplikacji osadza okres UTC YYYY-MM. Nowy miesiąc kalendarzowy automatycznie ponownie uzbraja więc każdy typ alertu; przejście do nowego okresu nie wymaga wywołania czyszczenia. clearAlerts() czyści bieżący okres, co ponownie uzbraja alerty w trakcie okresu, na przykład po podniesieniu planu.
  • Zabezpieczenie niezgodności planu w evaluate() odrzuca wywołanie, w którym dostarczony plan i definicja planu się różnią, chroniąc przed definicją z innego poziomu niż plan najemcy.
  • Cała arytmetyka okresów jest zakotwiczona w UTC. Momentem resetu przekroczenia limitu jest pierwszy dzień następnego miesiąca kalendarzowego o północy UTC; odpowiedź miękkiego zatrzymania powinna ogłaszać go jako horyzont ponawiania.
  • QuotaEnforcementGuard jest odporna na awarie (fail-closed) w trybie SaaS. Brak najemcy, brak planu, nieznana funkcja, awaria magazynu oraz naruszenie limitu — wszystko to prowadzi do odmowy; nic nie przechodzi do niejawnego zezwolenia. Wdrożenia inne niż SaaS rezygnują wyłącznie przez skonstruowanie bramy z DeploymentMode innym niż SaaS.
  • Polityki blokujące rezerwują zużycie przez UsageCounterStoreInterface::tryConsume, atomowy compare-and-set. Współbieżne żądania nie mogą wspólnie przekroczyć limitu zużycia; przegrany wyścigu otrzymuje QuotaExceededException, mimo że wstępne sprawdzenie przeszło.
  • W ramach polityki alertu budżetowego brama rejestruje zużycie w miarę możliwości (best-effort) i nigdy nie odmawia; rezerwacja powyżej miękkiego pułapu nadal rejestruje wiersz na poziomie limitu.
  • QuotaExceededException jest świadomy trybu wdrożenia: odmowy SaaS odwzorowują się na HTTP 402 z kodem specyfikacji SPEC-BILLING-003 i są oznaczone jako ponawialne; odmowy on-prem odwzorowują się na HTTP 403 z SPEC-LIC-001.
  • Biblioteka sama nie emituje odpowiedzi HTTP. Zadeklarowane kody statusu są kontraktem dla warstwy brzegowej, która odwzorowuje zgłoszoną odmowę na odpowiedź i nie może wywoływać rozliczanego handlera.
  • Niedodatni uwzględniony limit. usagePercentage(), evaluate() oraz OverageCalculator::calculate() zwracają współczynnik zużycia 0.0 zamiast dzielić przez zero. Alerty progowe nie uruchamiają się wtedy z samego współczynnika.
  • Alert budżetowy plus duże przekroczenie. Zarówno menedżer, jak i brama zwracają dozwolone wyniki. Nie traktuj braku wyjątku jako dowodu na mieszczenie się w limicie; sprawdź OverageResult lub strumień alertów.
  • Dokładnie na poziomie limitu. checkQuota() przy currentCu == includedCuQuota przechodzi. BudgetExceeded wymaga ścisłego przekroczenia. UsageCounter::wouldExceed() również jest ścisły.
  • MonthlyCapReached. Enum deklaruje ten czwarty typ alertu, ale BillingAlertService::evaluate() nigdy go nie emituje; jego lista kandydatów obejmuje tylko trzy alerty progowe. Jest zarezerwowany dla emiterów śledzących limity poza tym modułem.
  • Zduplikowane definicje poziomów. PlanRegistry indeksuje według wartości poziomu; ostatnia definicja dla danego poziomu po cichu zastępuje wcześniejsze. Konstruuj rejestry z listy pozbawionej duplikatów.
  • Zerowy przydział a brak limitu. Limit QuotaPolicy równy 0.0 oznacza, że każde zużycie w okresie jest przekroczeniem. Tylko ujemny wartownik UNLIMITED wyłącza pomiar; isUnlimited() nigdy nie blokuje.
  • Niedodatnia wielkość rezerwacji. enforce() odmawia niedodatniej wartości $amount w trybie odporności na awarie (fail-closed) z UsageStoreUnavailableException (503). To defekt wywołującego, a nie awaria magazynu.
  • Awaria magazynu. Każda awaria odczytu lub rezerwacji ujawnia się jako UsageStoreUnavailableException i skutkuje odmową. Brama nigdy nie zezwala na niezmierzoną pracę, gdy licznik jest niedostępny.
  • Implementacje w pamięci. InMemoryAlertStateRepository oraz InMemoryUsageCounterStore są poprawne wyłącznie w obrębie jednego procesu PHP. Wdrożenia z wieloma replikami muszą dostarczyć implementacje oparte na magazynie danych z rzeczywistą atomowością; magazyn typu odczyt-następnie-zapis jest defektem, który dopuszcza przekroczenie limitu pod obciążeniem.
  • Tryb FIPS. Billing nie wykonuje żadnych własnych operacji kryptograficznych i nie ma zachowania specyficznego dla FIPS. Konsumowana przez niego tożsamość najemcy musi pochodzić z uwierzytelnionego kontekstu, którego stanowisko FIPS jest udokumentowane przy powierzchni SaaS.
TwierdzenieStandardKlauzula
Kod statusu 402 jest zarezerwowany do przyszłego użytku; sam w sobie nie niesie żadnej normatywnej semantyki żądania.RFC 9110§15.5.3
429 wskazuje, że klient wysłał zbyt wiele żądań w danym czasie („ograniczanie liczby żądań”).RFC 6585§4
Retry-After wskazuje, jak długo agent użytkownika powinien czekać przed wykonaniem kolejnego żądania.RFC 9110§10.2.3

Wszystkie klauzule są sparafrazowane; NextPDF nie odtwarza tekstu normatywnego. NextPDF nie formułuje żadnego twierdzenia o zgodności z protokołem HTTP ani o certyfikacji dla tej powierzchni. Odwzorowanie 402 / 429 / 200 zadeklarowane przez OveragePolicy::httpStatusCode() oraz kody odmów bramy 401 / 402 / 503 to konwencja produktowa zgodna z powyższymi klauzulami: RFC 9110 rezerwuje 402, więc jego użycie tutaj do odmowy płatności jest powszechną konwencją branżową, a nie semantyką zdefiniowaną przez IETF. Horyzont ponawiania miękkiego zatrzymania (resetsAt) to wartość, którą warstwa brzegowa powinna udostępnić jako wskazówkę Retry-After. Emitowanie rzeczywistych odpowiedzi HTTP, nagłówków oraz zachowania buforowania jest odpowiedzialnością aplikacji hostującej.

  • Złóż model z PlanRegistry::defaultRegistry(), jednej OveragePolicy oraz QuotaManager; dodaj BillingAlertService z trwałą implementacją AlertStateRepositoryInterface na potrzeby alertów.
  • Zamontuj QuotaEnforcementGuard w potoku żądań po uwierzytelnieniu najemcy i przed rozliczanym handlerem. Przechwytuj QuotaEnforcementException oraz QuotaExceededException z modułu rozliczeń na warstwie brzegowej i odwzoruj httpStatusCode() na odpowiedź.
  • Definicje planów w tym module są jedynym źródłem prawdy dla rozliczeń; nie utrzymuj równoległej definicji rozliczeń w innym miejscu wdrożenia.
  • Implementacje w pamięci sprawiają, że całą powierzchnię można testować jednostkowo bez operacji wejścia/wyjścia. Zalecane testy brzegowe: zużycie dokładnie na poziomie limitu, jedną jednostkę powyżej, progi współczynnika przy 0.8 i 1.0, zabezpieczenie niezgodności planu, wyścig CAS (dwie rezerwacje o ostatnią jednostkę zapasu) oraz odmowa przy awarii magazynu.
  • Klasy modelu głównego niosą @since 2.2.0; substrat niesie @since 2.3.0. Bieżąca linia pakietu to 3.1.0.
  • Operator odpowiada za implementacje repozytorium stanu alertów oraz magazynu zużycia, ich trwałość między replikami, a także za wszelkie ponowne uzbrajanie alertów w trakcie okresu przez clearAlerts().

Ta strona dokumentuje wyłącznie zewnętrznie obserwowalne zachowanie oraz wspieraną publiczną powierzchnię API. Wewnętrzne ścieżki przestrzeni nazw, klasy pomocnicze, tabele mechanizmów, nazwy plików runbooków oraz prefiksy zgłoszeń są poza zakresem.