stripe/stripe-php is pinned at ^17.0 and locked to 17.6.0. The current release is 21.2.1 — four majors behind. It is the plugin's only production dependency, it sits in the payments path, and it ships inside the release zip, so this is the one dependency where being behind carries real risk rather than tooling inconvenience.
Deliberately kept out of #192 and #193, which are lockfile and dev-tooling work.
Blast radius is small
The whole Stripe surface is four symbols, all confined to src/Payment/StripeGateway.php:
Symbol
Use
Stripe\StripeClient
StripeGateway.php:104 — constructed with the secret key
paymentIntents->create
StripeGateway.php:74
Stripe\Webhook::constructEvent
StripeGateway.php:99 — signature verification
Stripe\Event
StripeGateway.php:82,98 — return type of verifyWebhook()
Everything else that mentions Stripe (PaymentService, PaymentEndpoint, PaymentRepository, BillingMethodResolver, StudioSettings) goes through the gateway rather than the SDK. Existing coverage: tests/Unit/Payment/StripeGatewayTest.php plus four sibling test files.
The actual risk is the pinned API version, not the PHP code
Each major re-pins the Stripe API version the SDK talks to:
⚠️ V2 null preservation in JSON bodies; has a migration guide
21.0.0
2026-06-24.dahlia
⚠️ErrorObject properties correctly typed null|string; otherwise functionally a patch
Most of the flagged breakage is in the V2 Events API, which this plugin does not use — webhooks go through Stripe\Webhook::constructEvent, the V1 path. So the library-side migration looks light. What needs real attention is the jump in pinned API version from whatever 17.6.0 carries to 2026-06-24.dahlia: that changes what the Stripe API itself does, independently of this code.
The 21.0.0 ErrorObject retyping is worth noting separately — properties becoming null|string may surface new PHPStan errors wherever error objects are inspected.
Suggested approach
Read the Stripe API changelog for dahlia and confirm nothing in payment_intents.create or webhook event shape changes for our usage.
Bump to ^21.0, run composer lint — expect the ErrorObject typing change to be the main source of new findings.
Verify verifyWebhook() against a real signed payload; signature verification is the part unit tests stub rather than exercise.
Exercise a live payment against Stripe test mode before shipping — the unit tests mock the client, so no test here proves an API-version change is safe.
Done when
composer.json requires ^21.0 and the lock carries 21.2.1.
composer lint, composer cs and composer test pass.
A test-mode payment and a test-mode webhook both round-trip successfully.
`stripe/stripe-php` is pinned at `^17.0` and locked to 17.6.0. The current release is 21.2.1 — four majors behind. It is the plugin's **only production dependency**, it sits in the payments path, and it ships inside the release zip, so this is the one dependency where being behind carries real risk rather than tooling inconvenience.
Deliberately kept out of #192 and #193, which are lockfile and dev-tooling work.
## Blast radius is small
The whole Stripe surface is four symbols, all confined to `src/Payment/StripeGateway.php`:
| Symbol | Use |
|---|---|
| `Stripe\StripeClient` | `StripeGateway.php:104` — constructed with the secret key |
| `paymentIntents->create` | `StripeGateway.php:74` |
| `Stripe\Webhook::constructEvent` | `StripeGateway.php:99` — signature verification |
| `Stripe\Event` | `StripeGateway.php:82,98` — return type of `verifyWebhook()` |
Everything else that mentions Stripe (`PaymentService`, `PaymentEndpoint`, `PaymentRepository`, `BillingMethodResolver`, `StudioSettings`) goes through the gateway rather than the SDK. Existing coverage: `tests/Unit/Payment/StripeGatewayTest.php` plus four sibling test files.
## The actual risk is the pinned API version, not the PHP code
Each major re-pins the Stripe API version the SDK talks to:
| Version | Pinned API version | Notes |
|---|---|---|
| 18.0.0 | `2025-09-30.clover` | ⚠️ V2 Events overhaul — `parseThinEvent` → `parseEventNotification`, `ThinEvent` removed |
| 19.0.0 | `2025-11-17.clover` | V2 array serialization changes to indexed format |
| 20.0.0 | `2026-03-25.dahlia` | ⚠️ V2 null preservation in JSON bodies; has a [migration guide](https://github.com/stripe/stripe-php/wiki/Migration-guide-for-v20) |
| 21.0.0 | `2026-06-24.dahlia` | ⚠️ `ErrorObject` properties correctly typed `null\|string`; otherwise functionally a patch |
Most of the flagged breakage is in the **V2 Events API**, which this plugin does not use — webhooks go through `Stripe\Webhook::constructEvent`, the V1 path. So the library-side migration looks light. What needs real attention is the jump in pinned API version from whatever 17.6.0 carries to `2026-06-24.dahlia`: that changes what the Stripe API itself does, independently of this code.
The 21.0.0 `ErrorObject` retyping is worth noting separately — properties becoming `null|string` may surface new PHPStan errors wherever error objects are inspected.
## Suggested approach
1. Read the [Stripe API changelog for dahlia](https://docs.stripe.com/changelog/dahlia) and confirm nothing in `payment_intents.create` or webhook event shape changes for our usage.
2. Bump to `^21.0`, run `composer lint` — expect the `ErrorObject` typing change to be the main source of new findings.
3. Verify `verifyWebhook()` against a real signed payload; signature verification is the part unit tests stub rather than exercise.
4. Exercise a live payment against Stripe test mode before shipping — the unit tests mock the client, so no test here proves an API-version change is safe.
## Done when
- `composer.json` requires `^21.0` and the lock carries 21.2.1.
- `composer lint`, `composer cs` and `composer test` pass.
- A test-mode payment and a test-mode webhook both round-trip successfully.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
stripe/stripe-phpis pinned at^17.0and locked to 17.6.0. The current release is 21.2.1 — four majors behind. It is the plugin's only production dependency, it sits in the payments path, and it ships inside the release zip, so this is the one dependency where being behind carries real risk rather than tooling inconvenience.Deliberately kept out of #192 and #193, which are lockfile and dev-tooling work.
Blast radius is small
The whole Stripe surface is four symbols, all confined to
src/Payment/StripeGateway.php:Stripe\StripeClientStripeGateway.php:104— constructed with the secret keypaymentIntents->createStripeGateway.php:74Stripe\Webhook::constructEventStripeGateway.php:99— signature verificationStripe\EventStripeGateway.php:82,98— return type ofverifyWebhook()Everything else that mentions Stripe (
PaymentService,PaymentEndpoint,PaymentRepository,BillingMethodResolver,StudioSettings) goes through the gateway rather than the SDK. Existing coverage:tests/Unit/Payment/StripeGatewayTest.phpplus four sibling test files.The actual risk is the pinned API version, not the PHP code
Each major re-pins the Stripe API version the SDK talks to:
2025-09-30.cloverparseThinEvent→parseEventNotification,ThinEventremoved2025-11-17.clover2026-03-25.dahlia2026-06-24.dahliaErrorObjectproperties correctly typednull|string; otherwise functionally a patchMost of the flagged breakage is in the V2 Events API, which this plugin does not use — webhooks go through
Stripe\Webhook::constructEvent, the V1 path. So the library-side migration looks light. What needs real attention is the jump in pinned API version from whatever 17.6.0 carries to2026-06-24.dahlia: that changes what the Stripe API itself does, independently of this code.The 21.0.0
ErrorObjectretyping is worth noting separately — properties becomingnull|stringmay surface new PHPStan errors wherever error objects are inspected.Suggested approach
payment_intents.createor webhook event shape changes for our usage.^21.0, runcomposer lint— expect theErrorObjecttyping change to be the main source of new findings.verifyWebhook()against a real signed payload; signature verification is the part unit tests stub rather than exercise.Done when
composer.jsonrequires^21.0and the lock carries 21.2.1.composer lint,composer csandcomposer testpass.Closed by #195