'month'` alone and be * adopted as if it charged our figure per unit per month — which is adoption * moving money, the one thing nothing here may do. * * Not a list of everything Stripe can put on a Price: it is the list of * fields known to change what one CHARGES. A fifth would have to be added * here, at the boundary, before the shape below is handed on. * * @return array}> */ public function activePricesFor(string $productId): array; /** * Write metadata onto a Price that already exists. * * Metadata is one of the few fields a Stripe Price lets you change — the * same property activatePrice() rests on, and the reason the metadata format * is NOT part of a Price's identity. An adopted orphan is brought up to * today's metadata rather than replaced, which is exactly what was done by * hand after 2026-07-29 and keeps Stripe's own dashboard readable. */ public function updatePriceMetadata(string $priceId, array $metadata): void; /** Stop a Price being offered. The Price itself stays, as Stripe requires. */ public function archivePrice(string $priceId): void; /** * Offer an archived Price again. * * The other half of archivePrice(), and it was missing. A rate that moves and * then moves back finds the Price for the figure it has come back to already * in our register: the sync brings that row back rather than minting a second * Price for one amount, which is right — but the Price was archived AT STRIPE, * and only this makes it sellable again. Without it the catalogue pointed at * an inactive Price and the failure was a customer meeting a refused checkout. */ public function activatePrice(string $priceId): void; /** * Move a subscription onto another Price. * * The ITEM is what carries a price, not the subscription, so the swap needs * both ids. `$prorationBehaviour` is one of the constants above and is * always passed explicitly: Stripe's own default settles a proration * silently, and a default deciding what a customer is charged is exactly * the kind of thing that must be written down at the call site. */ public function updateSubscriptionPrice( string $subscriptionId, string $itemId, string $priceId, string $prorationBehaviour, ): void; /** * The id of the item a subscription bills its PACKAGE through, or null if it * has none. * * For contracts opened before the item id was stored: Stripe knows it, we * did not ask, and asking once is cheaper than being unable to move them. * The first item is the package, because that is the one the checkout * created; modules are added afterwards and carry their own ids, which are * stored on the bookings themselves. */ public function subscriptionItemId(string $subscriptionId): ?string; /** * Put a module on the subscription as an item of its own, and return the * item's id. * * `$prorationBehaviour` is passed explicitly for the same reason as above. * A module booked in the middle of a term is charged PRORATE_IMMEDIATELY: * Stripe works out the days that are left, raises an invoice for exactly * that and takes the money there and then — which is the invoice the * customer is owed a document for. */ public function addSubscriptionItem( string $subscriptionId, string $priceId, int $quantity, string $prorationBehaviour, ?string $idempotencyKey = null, ): string; /** * Change how many of a module the subscription bills for. * * A pack is sold by the unit, so a second one is a quantity of two on one * item rather than a second item at the same price — two items on one price * is a thing Stripe allows and nothing could later tell apart. */ public function updateSubscriptionItemQuantity( string $itemId, int $quantity, string $prorationBehaviour, ): void; /** * Take a module off the subscription. * * Removed with PRORATE_NONE by everything that calls it: a cancelled module * is kept until the end of the term the customer has already paid for and * earns no credit, so nothing is to be settled — only the next cycle is * smaller. */ public function removeSubscriptionItem(string $itemId, string $prorationBehaviour): void; /** * Tell Stripe to stop charging for a contract that is over. * * The one call this platform could not make. Nothing here cancelled a Stripe * subscription at all: a customer's cancellation wrote a date on the * instance, a withdrawal marked the contract cancelled and sent the money * back, and in both cases Stripe went on taking the next month, and the next, * for a service that had ended — and every one of those payments arrived as * `invoice.paid` and drew a number out of the gapless Austrian series. * * `$when` is one of the CANCEL_* constants and is always passed explicitly, * for the same reason `$prorationBehaviour` is above: the two are different * promises to the customer, and which one a caller means has to be legible at * the call site rather than inherited from a default written down here. * * `$idempotencyKey` because a retry after a timeout cannot tell whether the * first attempt landed. Cancelling twice is harmless at Stripe, but the same * key makes the retry provably a no-op instead of merely a likely one. */ public function cancelSubscription( string $subscriptionId, string $when, ?string $idempotencyKey = null, ): void; /** * Send money back, against the payment that took it. * * The only outgoing money movement this platform makes, and it exists * because a consumer who withdraws within fourteen days is owed one — see * App\Actions\WithdrawContract. `$amountCents` is the whole of what was * taken: the owner has decided a withdrawing consumer gets everything back, * not the amount less the days the cloud ran. It stays an explicit figure * rather than "refund the payment" because a Storno states an amount and the * money has to be the amount the Storno states. * * `$paymentReference` is a PaymentIntent (`pi_…`) or a Charge (`ch_…`) — * whichever Stripe reported for the payment. Both are accepted rather than * one normalised: which of the two an account produces depends on the API * version it is pinned to, and a refund that silently does nothing because * the wrong field was read is the worst possible failure here. * * `$idempotencyKey` is not optional in practice. A refund is the one call * whose retry after a timeout would send the customer's money twice. * * @return string the refund's id */ public function refund( string $paymentReference, ?int $amountCents = null, ?string $idempotencyKey = null, ): string; /** * The payment behind a Stripe invoice, or null if it has none. * * A subscription checkout charges through an invoice, so the invoice id is * usually all we have written down — and a refund cannot be issued against * an invoice. This is the one hop between the two. */ public function invoicePaymentReference(string $invoiceId): ?string; /** * Every line on a Stripe invoice, for the document we owe it. * * The webhook payload carries the lines already; this is for the invoice * that has more of them than Stripe puts in an event. A document missing a * line that was charged is worse than one nobody sent, so the complete list * is worth an extra call. * * @return array> */ public function invoiceLines(string $invoiceId): array; }