stripe / stripe-dotnet

Stripe.net is a sync/async .NET 4.6.1+ client, and a portable class library for stripe.com.
Apache License 2.0
1.37k stars 572 forks source link

Failure to parse response from /v1/forwarding/requests #3028

Open dgregory-resnexus opened 3 hours ago

dgregory-resnexus commented 3 hours ago

Describe the bug

When making a request to the /v1/forwarding/requests endpoint using v45.11 or v47.0 of the SDK, the response fails to be parsed.

It appears to me that it is the value of "created" (1731082862469) that is failing to parse. In a different successful request to a different endpoint, the value of "created" was 1731082744. The one that is failing appears to be a longdata type and the one that is working appears to be an intdata type.

To Reproduce

Make any request to the endpoint using the SDK. I used the suggested sample from the API docs

Expected behavior

Parse the response correctly

Code snippets

{ "id": "fwdreqm_ymtq5DT1Y!LQxwPJEesM6wfg0Rf68V9QxssGDwpSzBw*EhcKFWFjY3RfMVB2blRrUFE2d2VhS3JKTw", "object": "forwarding.request", "created": 1731082862469, "livemode": false, "payment_method": "pm_1QIutzPQ6weaKrJOWhTfGN3x", "replacements": [ "card_number", "card_expiry", "cardholder_name" ], "request_context": { "destination_duration": 89, "destination_ip_address": "35.190.113.80" }, "request_details": { "body": "{\"card\":{\"exp_month\":\"02\", \"exp_year\":\"2025\", \"name\":\"REDACTED3\", \"number\":\"555555******4444\"}, \"metadata\":{\"REDACTED1\":\"1954\", \"REDACTED2\":\"4\"}}", "headers": [ { "name": "Authorization", "value": "Bearer *******************************************************************************************" }, { "name": "Content-Type", "value": "application/json" } ], "http_method": "POST" }, "response_details": { "body": "{\"id\":\"token_1\"}", "headers": [ { "name": "Content-Length", "value": "16" }, { "name": "Etag", "value": "W/\"10-eOqXY39ivjugjwCuZPjsCZw1UEE\"" }, { "name": "Via", "value": "1.1 google" }, { "name": "X-Powered-By", "value": "Express" }, { "name": "X-Robots-Tag", "value": "noindex, nofollow" }, { "name": "Content-Type", "value": "application/json; charset=utf-8" }, { "name": "Server", "value": "envoy" }, { "name": "Alt-Svc", "value": "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000" }, { "name": "Date", "value": "Fri, 08 Nov 2024 16:21:02 GMT" }, { "name": "X-Cloud-Trace-Context", "value": "aa86744918565aa04aba1d2909d56221;o=1" } ], "status": 200 }, "url": "https://forwarding-api-demo.stripedemos.com/tokens"}

OS

Windows 11

.NET version

.NET 4.7.2

Library version

stripe-dotnet-v45.11

API version

2024-09-05

Additional context

System.ArgumentOutOfRangeException Value to add was out of range

Partial Stack Trace at System.DateTime.Add(Double value, Int32 scale) in System\DateTime.cs:line 860 at Stripe.Infrastructure.UnixDateTimeConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in //src/Stripe.net/Infrastructure/JsonConverters/UnixDateTimeConverter.cs:line 87 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Populate(JsonReader reader, Object target) at Stripe.Infrastructure.StripeEntityConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer) in //src/Stripe.net/Infrastructure/JsonConverters/StripeEntityConverter.cs:line 74

dgregory-resnexus commented 3 hours ago

FYI the code snippet I provided is the redacted response I retrieved from my Stripe dashboard

dgregory-resnexus commented 3 hours ago

https://github.com/stripe/stripe-dotnet/blob/master/src/Stripe.net/Infrastructure/JsonConverters/UnixDateTimeConverter.cs

Line 87. Most responses (the working ones) are actually being returned in seconds (int data type), but the forwarding API is responding in milliseconds (long data type), which is why adding seconds to UnixEpoch is failing (it's adding milliseconds instead of actual seconds).

dgregory-resnexus commented 15 minutes ago

Possible solution 1:

if (seconds > (long)int.MaxValue)
{
    return UnixEpoch.AddMilliseconds(seconds);
}
else if (seconds >= 0)
{
    return UnixEpoch.AddSeconds(seconds);
}
else
{
    throw new JsonSerializationException(string.Format("Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970 to {0}.", objectType));
}

Possible solution 2 (avoids SDK fix): Fix the response from the API to return seconds instead of milliseconds