Skip to content

Commit dc4d5f1

Browse files
committed
Use an interface for PaymentIntentSourceAction
1 parent e9da922 commit dc4d5f1

File tree

8 files changed

+215
-15
lines changed

8 files changed

+215
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Stripe
2+
{
3+
public interface IPaymentIntentSourceActionValue
4+
{
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
namespace Stripe
22
{
3+
using System.Runtime.Serialization;
34
using Newtonsoft.Json;
5+
using Newtonsoft.Json.Converters;
46
using Stripe.Infrastructure;
57

8+
[JsonConverter(typeof(StringEnumConverter))]
69
public enum PaymentIntentSourceActionType
710
{
811
Unknown,
12+
13+
[EnumMember(Value = "authorize_with_url")]
914
AuthorizeWithUrl,
10-
None,
1115
}
1216

1317
[JsonConverter(typeof(PaymentIntentSourceActionConverter))]
1418
public class PaymentIntentSourceAction : StripeEntity
1519
{
1620
public PaymentIntentSourceActionType Type { get; set; }
1721

18-
public PaymentIntentSourceActionAuthorizeWithUrl AuthorizeWithUrl { get; set; }
22+
public IPaymentIntentSourceActionValue Value { get; set; }
1923
}
2024
}

src/Stripe.net/Entities/PaymentIntents/PaymentIntentSourceActionAuthorizeWithUrl.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ namespace Stripe
22
{
33
using Newtonsoft.Json;
44

5-
public class PaymentIntentSourceActionAuthorizeWithUrl : StripeEntity
5+
public class PaymentIntentSourceActionAuthorizeWithUrl : StripeEntity, IPaymentIntentSourceActionValue
66
{
77
[JsonProperty("url")]
88
public string Url { get; set; }
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
namespace Stripe.Infrastructure
22
{
33
using System;
4+
using System.Collections.Generic;
45
using Newtonsoft.Json;
56
using Newtonsoft.Json.Linq;
67

78
internal class PaymentIntentSourceActionConverter : JsonConverter
89
{
910
public override bool CanWrite => false;
1011

12+
protected Dictionary<PaymentIntentSourceActionType, Func<string, IPaymentIntentSourceActionValue>> TypesToMapperFuncs
13+
=> new Dictionary<PaymentIntentSourceActionType, Func<string, IPaymentIntentSourceActionValue>>()
14+
{
15+
{ PaymentIntentSourceActionType.AuthorizeWithUrl, Mapper<PaymentIntentSourceActionAuthorizeWithUrl>.MapFromJson },
16+
};
17+
1118
public override bool CanConvert(Type objectType)
1219
{
13-
throw new NotImplementedException();
20+
return objectType == typeof(PaymentIntentSourceAction);
1421
}
1522

1623
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
@@ -22,27 +29,52 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
2229

2330
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
2431
{
25-
var sourceAction = new PaymentIntentSourceAction();
26-
2732
if (reader.TokenType == JsonToken.Null)
2833
{
29-
sourceAction.Type = PaymentIntentSourceActionType.None;
30-
return sourceAction;
34+
return null;
3135
}
3236

3337
var incoming = JObject.Load(reader);
38+
var sourceAction = new PaymentIntentSourceAction();
39+
40+
// Parse type
41+
var typeString = incoming.SelectToken("type")?.ToString();
42+
PaymentIntentSourceActionType type;
43+
if (!TryParseEnum<PaymentIntentSourceActionType>(typeString, out type))
44+
{
45+
type = PaymentIntentSourceActionType.Unknown;
46+
}
47+
48+
sourceAction.Type = type;
3449

35-
if (incoming.SelectToken("type")?.ToString() == "authorize_with_url")
50+
// Parse value according to type
51+
if (this.TypesToMapperFuncs.ContainsKey(type))
3652
{
37-
sourceAction.Type = PaymentIntentSourceActionType.AuthorizeWithUrl;
38-
sourceAction.AuthorizeWithUrl = Mapper<PaymentIntentSourceActionAuthorizeWithUrl>.MapFromJson(incoming.SelectToken("value")?.ToString());
53+
var mapperFunc = this.TypesToMapperFuncs[type];
54+
var valueString = incoming.SelectToken("value")?.ToString();
55+
sourceAction.Value = mapperFunc(valueString);
3956
}
4057
else
4158
{
42-
sourceAction.Type = PaymentIntentSourceActionType.Unknown;
59+
sourceAction.Value = null;
4360
}
4461

4562
return sourceAction;
4663
}
64+
65+
protected static bool TryParseEnum<T>(string str, out T value)
66+
{
67+
try
68+
{
69+
value = JsonConvert.DeserializeObject<T>($"\"{str}\"");
70+
}
71+
catch (JsonSerializationException)
72+
{
73+
value = default(T);
74+
return false;
75+
}
76+
77+
return true;
78+
}
4779
}
4880
}

src/StripeTests/Entities/PaymentIntents/PaymentIntentTest.cs

+34-3
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,23 @@ public void DeserializeWithExpansions()
5050
}
5151

5252
[Fact]
53-
public void DeserializeNextSourceAction()
53+
public void DeserializeNextSourceActionNull()
5454
{
55-
var json = GetResourceAsString("api_fixtures.payment_intent_with_next_source_action.json");
55+
var json = GetResourceAsString("api_fixtures.payment_intent.action_null.json");
56+
var intent = Mapper<PaymentIntent>.MapFromJson(json);
57+
58+
Assert.NotNull(intent);
59+
Assert.IsType<PaymentIntent>(intent);
60+
Assert.NotNull(intent.Id);
61+
Assert.Equal("payment_intent", intent.Object);
62+
63+
Assert.Null(intent.NextSourceAction);
64+
}
65+
66+
[Fact]
67+
public void DeserializeNextSourceActionAuthorizeWithUrl()
68+
{
69+
var json = GetResourceAsString("api_fixtures.payment_intent.action_authorize_with_url.json");
5670
var intent = Mapper<PaymentIntent>.MapFromJson(json);
5771

5872
Assert.NotNull(intent);
@@ -61,7 +75,24 @@ public void DeserializeNextSourceAction()
6175
Assert.Equal("payment_intent", intent.Object);
6276

6377
Assert.Equal(PaymentIntentSourceActionType.AuthorizeWithUrl, intent.NextSourceAction.Type);
64-
Assert.Equal("https://stripe.com", intent.NextSourceAction.AuthorizeWithUrl.Url);
78+
var authorizeWithUrl = intent.NextSourceAction.Value as PaymentIntentSourceActionAuthorizeWithUrl;
79+
Assert.NotNull(authorizeWithUrl);
80+
Assert.Equal("https://stripe.com", authorizeWithUrl.Url);
81+
}
82+
83+
[Fact]
84+
public void DeserializeNextSourceActionUnknown()
85+
{
86+
var json = GetResourceAsString("api_fixtures.payment_intent.action_unknown.json");
87+
var intent = Mapper<PaymentIntent>.MapFromJson(json);
88+
89+
Assert.NotNull(intent);
90+
Assert.IsType<PaymentIntent>(intent);
91+
Assert.NotNull(intent.Id);
92+
Assert.Equal("payment_intent", intent.Object);
93+
94+
Assert.Equal(PaymentIntentSourceActionType.Unknown, intent.NextSourceAction.Type);
95+
Assert.Null(intent.NextSourceAction.Value);
6596
}
6697
}
6798
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
{
2+
"id": "pi_123",
3+
"object": "payment_intent",
4+
"allowed_source_types": [
5+
"card"
6+
],
7+
"amount": 1099,
8+
"amount_capturable": 1000,
9+
"amount_received": 0,
10+
"application": null,
11+
"application_fee": null,
12+
"canceled_at": null,
13+
"capture_method": "automatic",
14+
"charges": {
15+
"object": "list",
16+
"data": [
17+
{
18+
"id": "ch_123",
19+
"object": "charge"
20+
}
21+
],
22+
"has_more": false,
23+
"total_count": 1,
24+
"url": "/v1/charges?payment_intent=pi_123"
25+
},
26+
"client_secret": null,
27+
"confirmation_method": "publishable",
28+
"created": 123456789,
29+
"currency": "usd",
30+
"customer": null,
31+
"description": "PaymentIntent Description",
32+
"livemode": false,
33+
"metadata": {
34+
"order_id": "123456789"
35+
},
36+
"next_source_action": null,
37+
"on_behalf_of": null,
38+
"receipt_email": "test@stripe.com",
39+
"return_url": null,
40+
"shipping": {
41+
"address": {
42+
"city": "city",
43+
"country": "USA",
44+
"line1": "123 Main St",
45+
"line2": "Apt B",
46+
"postal_code": "90210",
47+
"state": "NC"
48+
},
49+
"carrier": "Carrier",
50+
"name": "Namey Namerson",
51+
"phone": null,
52+
"tracking_number": "12345"
53+
},
54+
"source": "src_123",
55+
"statement_descriptor": "PaymentIntent Statement Descriptor",
56+
"status": "succeeded",
57+
"transfer_data": {
58+
"amount": 1234
59+
},
60+
"transfer_group": null
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"id": "pi_123",
3+
"object": "payment_intent",
4+
"allowed_source_types": [
5+
"card"
6+
],
7+
"amount": 1099,
8+
"amount_capturable": 1000,
9+
"amount_received": 0,
10+
"application": null,
11+
"application_fee": null,
12+
"canceled_at": null,
13+
"capture_method": "automatic",
14+
"charges": {
15+
"object": "list",
16+
"data": [
17+
{
18+
"id": "ch_123",
19+
"object": "charge"
20+
}
21+
],
22+
"has_more": false,
23+
"total_count": 1,
24+
"url": "/v1/charges?payment_intent=pi_123"
25+
},
26+
"client_secret": null,
27+
"confirmation_method": "publishable",
28+
"created": 123456789,
29+
"currency": "usd",
30+
"customer": null,
31+
"description": "PaymentIntent Description",
32+
"livemode": false,
33+
"metadata": {
34+
"order_id": "123456789"
35+
},
36+
"next_source_action": {
37+
"type": "foo",
38+
"value": {
39+
"bar": [1, 2, 3]
40+
}
41+
},
42+
"on_behalf_of": null,
43+
"receipt_email": "test@stripe.com",
44+
"return_url": null,
45+
"shipping": {
46+
"address": {
47+
"city": "city",
48+
"country": "USA",
49+
"line1": "123 Main St",
50+
"line2": "Apt B",
51+
"postal_code": "90210",
52+
"state": "NC"
53+
},
54+
"carrier": "Carrier",
55+
"name": "Namey Namerson",
56+
"phone": null,
57+
"tracking_number": "12345"
58+
},
59+
"source": "src_123",
60+
"statement_descriptor": "PaymentIntent Statement Descriptor",
61+
"status": "succeeded",
62+
"transfer_data": {
63+
"amount": 1234
64+
},
65+
"transfer_group": null
66+
}

0 commit comments

Comments
 (0)