-
Notifications
You must be signed in to change notification settings - Fork 898
Migration guide for v20
This version uses API version 2026-03-25.dahlia. If the format of this API version looks new to you, see our new API release process.
Please review our API changelog for 2026-03-25.dahlia to understand all the breaking changes to the Stripe API, the reasons behind them and potential alternatives.
The PHP SDK specific changelog for v20 has the corresponding changes in the SDKs as well as SDK specific breaking changes.
PHP versions 5.6, 7.0, and 7.1 are no longer supported. The SDK now requires PHP >= 7.2.0 and throws a RuntimeException at load time on older versions.
Action required: Upgrade to PHP 7.2 or later before updating to the latest SDK version. For more information, see our language version support policy.
Note that this is the last major release that supports PHP 7.2 and 7.3. If you're still on those versions, please make plans to update to at least 7.4 (and ideally 8.1 or higher) before September 2026.
Previously, passing a V2 event notification payload to Webhook::constructEvent (or a V1 event payload to StripeClient::parseEventNotification) would silently succeed and return a malformed object. Both methods now throw UnexpectedValueException with a message directing you to the correct method.
Before (silently broken):
// V2 payload accidentally passed to V1 method — returned garbage, no error
$event = \Stripe\Webhook::constructEvent($v2Payload, $sigHeader, $secret);After (loud error with guidance):
// Now throws UnexpectedValueException:
// "You passed an event notification to Webhook::constructEvent, which expects
// a webhook payload. Use StripeClient::parseEventNotification instead."And the reverse:
// V1 payload to V2 method now throws:
// "You passed a webhook payload to StripeClient::parseEventNotification, which
// expects an event notification. Use Webhook::constructEvent instead."The fix — use the right method for each event version:
// V1 events (object: "event")
$event = \Stripe\Webhook::constructEvent($payload, $sigHeader, $secret);
// V2 event notifications (object: "v2.core.event")
$event = $client->parseEventNotification($payload, $sigHeader, $secret);The public method signature of \Stripe\Util\Util::objectsToIds() changed from one parameter to two. The new $serializeNull parameter is required and controls whether null values in associative arrays are preserved (for V2 JSON bodies) or stripped (for V1 form-encoded bodies).
Before:
$result = \Stripe\Util\Util::objectsToIds($params);After:
// Preserve existing behavior (strip nulls, as V1 always did):
$result = \Stripe\Util\Util::objectsToIds($params, false);
// Or preserve nulls for V2 JSON encoding:
$result = \Stripe\Util\Util::objectsToIds($params, true);For V2 API requests, null values in params are now preserved and serialized as JSON null instead of being stripped from the request. This enables clearing metadata entries and emptyable fields on V2 resources, and may change behavior of existing code that passed a null parameter value if that V2 API interprets a null value as "clear this field."
V1 behavior is unchanged — null values continue to be converted to empty strings for form-encoded V1 request bodies.
Before (V2 — null silently dropped):
$client->v2->core->accounts->update($accountId, [
'contact_phone' => null, // Sent: {} -- WRONG
]);After (V2 — null sent as JSON null):
$client->v2->core->accounts->update($accountId, [
'contact_phone' => null, // Sends: {"contact_phone": null} -- CORRECT
]);