Payments: migrate stripe-php from 17.6.0 to 21.x #194

Closed
opened 2026-08-25 02:10:30 +00:00 by thatguygriff · 1 comment
Owner

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 — parseThinEventparseEventNotification, 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
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 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.
`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.
thatguygriff added the paymentsenhancement labels 2026-08-25 02:10:30 +00:00
Author
Owner

Closed by #195

Closed by #195
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#194