-
Notifications
You must be signed in to change notification settings - Fork 361
Migration guide for v9
Note: starting from stripe-java
version 8, API requests are made with a version header not according to your account API version, but that specified by this library. If you are upgrading from stripe-java
version 7 or below, please see version 8 migration guide here.
stripe-java
version 9 drops supports for jdk 7. Majority of users on jdk 8 and above will not be affected. Additionally, this new major version introduces typed parameters and improves event deserialization. Both are breaking backward-compatibility, but only minor migration effort is expected.
Currently, API calls rely on untyped parameters and unsafe parameters can be passed. Now, each API call has specific typed parameters with builder-style constructors.
The new methods with typed parameters simply overloads the current method replacing the untyped map object with the typed one. The library now supports both usage.
Current:
Map<String, Object> untypedParams = new HashMap<>();
params.put("amount", 100);
params.put("currency", "usd");
params.put("source", "card_123");
Charge charge = Charge.create(untypedParams);
New:
ChargeCreateParams typedParams = ChargeCreateParams.builder()
.setAmount(100L)
.setCurrency("usd")
.setSource("card_123")
.build();
Charge charge = Charge.create(typedParams);
One breaking change arises from overloading method names. Existing integrations passing null
to
the parameters argument will see complier error due to ambiguous types; the compiler does not
know whether null
is a null untyped map, or null typed parameters. You should instead create an
empty parameters with either an empty map, or a built typed parameters without any values set.
To ensure safe migration, consider testing equality between your current untyped Map<String, Object>
parameters and the new typed parameters with toMap()
to get the untyped representation.
Map<String, Object> untypedParams = getUntypedParams();
ApiRequestParams typedParams = getTypedParams();
Map<String, Object> typedParamsAsMap = typedParams.toMap();
assertEquals(untypedParams, typedParamsAsMap);
- When parameters have nested objects, there are builders for each one via
builder()
method. Here,SkuCreateParams.Inventory
is separately built, and used in settingSkuCreateParams
root-level parameters. Note that nested objects are not shared among parameters of different methods. For instance, parameter class to update SKUSkuUpdateParams
separately has its nested object ofSkuUpdateParams.Inventory
which can differ from that in parameters to create SKU.
SkuCreateParams.Inventory inventoryParams = SkuCreateParams.Inventory.builder()
.setQuantity(4L)
.build();
SkuCreateParams createParams = SkuCreateParams.builder()
.setPrice(99L)
.setCurrency("usd")
.setInventory(inventoryParams)
.setProduct("prod_123")
.build();
Sku sku = Sku.create(createParams);
- When parameters require a list or a map, there are similar interfaces to
add
andaddAll
inList<T>
, andput
andputAll
inMap<String, T>
.
PaymentIntentRetrieveParams typedParams = PaymentIntentRetrieveParams.builder()
// support both adding individual element or the whole list
.addExpand("application")
.addExpand("on_behalf_of")
.addAllExpand(Arrays.asList("review", "source", "transfer_data.destination"))
.build();
CustomerUpdateParams customerUpdateParams = CustomerUpdateParams.builder()
// support both putting individual entry or the whole map
.putMetadata("key1", "value1")
.putAllMetadata(ImmutableMap.of("key2", "value2"))
.build();
- When parameters require enums, there are specific enums for each parameter.
WebhookEndpointCreateParams createParams = WebhookEndpointCreateParams
.builder()
.addEnabledEvent(WebhookEndpointCreateParams.EnabledEvent.CHARGE__SUCCEEDED)
.setApiVersion(WebhookEndpointCreateParams.ApiVersion.VERSION_2019_03_14)
.setUrl("https://myEndPoint.com")
.build();
This has been a long-standing ask from the community, so we thank you for your patience!
- Currently, untyped map
Event#previousAttributes
may contain valueObject[]
to represent a list. NowList<Object>
is the deserialized object for list content. This addresses the issue. - Currently,
EventDataObjectDeserializer#getObject
returnsStripeObject
which can benull
when there is API version mismatch betweenstripe-java
pinned versionStripe#API_VERSION
and the event versionEvent#apiVersion
. Now, with jdk8 and above,Optional<StripeObject>
is returned, and the check methoddeserialize
whether deserialization is successful is removed from the public call.
Current:
Event event = getEventFromWebhookOrEndpoint();
EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
if (dataObjectDeserializer.deserialize()) {
StripeObject stripeObject = dataObjectDeserializer.getObject();
doSomething(stripeObject);
}
New:
Event event = getEventFromWebhookOrEndpoint();
EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
if (dataObjectDeserializer.getObject().isPresent()) {
StripeObject stripeObject = dataObjectDeserializer.getObject().get();
doSomething(stripeObject);
} else {
// Handle absent data object with `deserializeUnsafe` or `deserializeUnsafeWith`.
// Please see the usage details in java doc on the class `EventDataObjectDeserializer`.
}
-
ScheduledQueryRun#Error
is renamed toScheduledQueryRun#RunError
to prevent potential ambiguous reference to basicjava.lang.Error