Skip to content

Commit 2fd8a04

Browse files
authored
Merge pull request #128 from bunq/feature/sdk_csharp-psd2-examples
Fix NotificationFilter, Serialization issues and implement PSD2
2 parents 6bbec06 + 1071afe commit 2fd8a04

File tree

231 files changed

+8308
-8765
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

231 files changed

+8308
-8765
lines changed

BunqSdk.Tests/BunqSdk.Tests.csproj

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>netcoreapp1.1</TargetFramework>
43
<RootNamespace>Bunq.Sdk.Tests</RootNamespace>
54
<LangVersion>default</LangVersion>
65
<AssemblyName>BunqSdk.Tests.xunit.runner.json</AssemblyName>
6+
<TargetFramework>netcoreapp2.2</TargetFramework>
77
</PropertyGroup>
88
<ItemGroup>
99
<ProjectReference Include="..\BunqSdk\BunqSdk.csproj" />
1010
</ItemGroup>
1111
<ItemGroup>
1212
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
13-
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-*" />
14-
<PackageReference Include="xunit" Version="2.2.0-*" />
1513
<DotNetCliToolReference Include="dotnet-xunit" Version="2.2.0-*" />
14+
<PackageReference Include="MSTest.TestAdapter" Version="1.4.0" />
15+
<PackageReference Include="MSTest.TestFramework" Version="2.0.0-beta4" />
16+
<PackageReference Include="xunit" Version="2.4.1" />
17+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
18+
<PackageReference Include="xunit.runners" Version="2.0.0" />
1619
</ItemGroup>
1720
<ItemGroup>
1821
<Content Include="xunit.runner.json">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using Bunq.Sdk.Context;
5+
using Bunq.Sdk.Json;
6+
using Bunq.Sdk.Model.Generated.Endpoint;
7+
using Bunq.Sdk.Security;
8+
using Bunq.Sdk.Tests.Util;
9+
using Xunit;
10+
using Assert = Xunit.Assert;
11+
12+
namespace Bunq.Sdk.Tests.Context
13+
{
14+
[TestCaseOrderer("Bunq.Sdk.Tests.Util.TestPriorityOrderer", "Psd2ApiContextTest")]
15+
public class Psd2ApiContextTest: IClassFixture<Psd2ApiContextTest>
16+
{
17+
/// <summary>
18+
/// File constants.
19+
/// </summary>
20+
private const string FILE_TEST_CONFIGURATION = "../../../Resources/bunq-psd2-test.conf";
21+
private const string FILE_TEST_OAUTH = "../../../Resources/bunq-oauth-test.conf";
22+
23+
private const string FILE_TEST_CREDENTIALS = "../../../Resources/credentials.pfx";
24+
private const string FILE_TEST_CERTIFICATE_CHAIN = "../../../Resources/chain.cert";
25+
26+
/// <summary>
27+
/// Test constants.
28+
/// </summary>
29+
private const string TEST_DEVICE_DESCRIPTION = "PSD2TestDevice";
30+
private const string TEST_PASSPHRASE_CREDENTIALS = "secret";
31+
32+
[Fact, TestPriority(1)]
33+
public void TestCreatePsd2Context()
34+
{
35+
ApiContext apiContext = null;
36+
if (File.Exists(FILE_TEST_CONFIGURATION))
37+
{
38+
apiContext = ApiContext.Restore(FILE_TEST_CONFIGURATION);
39+
Assert.NotNull(apiContext);
40+
41+
BunqContext.LoadApiContext(apiContext);
42+
return;
43+
}
44+
45+
apiContext = CreateApiContext();
46+
BunqContext.LoadApiContext(apiContext);
47+
48+
Assert.True(File.Exists(FILE_TEST_CONFIGURATION));
49+
}
50+
51+
[Fact, TestPriority(0)]
52+
public void TestCreateOauthClient()
53+
{
54+
if (File.Exists(FILE_TEST_OAUTH))
55+
{
56+
return;
57+
}
58+
59+
int clientId = OauthClient.Create().Value;
60+
OauthClient oauthClient = OauthClient.Get(clientId).Value;
61+
Assert.NotNull(oauthClient);
62+
63+
File.WriteAllText(
64+
FILE_TEST_OAUTH,
65+
BunqJsonConvert.SerializeObject(oauthClient)
66+
);
67+
Assert.True(File.Exists(FILE_TEST_OAUTH));
68+
}
69+
70+
private ApiContext CreateApiContext()
71+
{
72+
ApiContext apiContext = ApiContext.CreateForPsd2(
73+
ApiEnvironmentType.SANDBOX,
74+
SecurityUtils.GetCertificateFromFile(FILE_TEST_CREDENTIALS, TEST_PASSPHRASE_CREDENTIALS),
75+
SecurityUtils.GetCertificateCollectionFromAllPath(
76+
new[] { FILE_TEST_CERTIFICATE_CHAIN }
77+
),
78+
TEST_DEVICE_DESCRIPTION,
79+
new List<string>()
80+
);
81+
apiContext.Save(FILE_TEST_CONFIGURATION);
82+
83+
return apiContext;
84+
}
85+
}
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
using System.Collections.Generic;
2+
using Bunq.Sdk.Context;
3+
using Bunq.Sdk.Model.Core;
4+
using Bunq.Sdk.Model.Generated.Endpoint;
5+
using Bunq.Sdk.Model.Generated.Object;
6+
using Xunit;
7+
8+
namespace Bunq.Sdk.Tests.Model.Core
9+
{
10+
/// <summary>
11+
/// Tests:
12+
/// NotificationFilterUrlMonetaryAccountInternal
13+
/// NotificationFilterUrlUserInternal
14+
/// NotificationFilterPushUserInternal
15+
/// </summary>
16+
public class NotificationFilterTest: BunqSdkTestBase, IClassFixture<NotificationFilterTest>
17+
{
18+
/// <summary>
19+
/// Filter constants.
20+
/// </summary>
21+
private const string FILTER_CATEGORY_MUTATION = "MUTATION";
22+
private const string FILTER_CALLBACK_URL = "https://test.com/callback";
23+
24+
/// <summary>
25+
/// Test NotificationFilterUrlMonetaryAccount creation.
26+
/// </summary>
27+
[Fact]
28+
public void TestNotificationFilterUrlMonetaryAccount()
29+
{
30+
SetUpApiContext();
31+
32+
NotificationFilterUrl notificationFilter = GetNotificationFilterUrl();
33+
List<NotificationFilterUrl> allCreatedNotificationFilter = NotificationFilterUrlMonetaryAccountInternal.CreateWithListResponse(
34+
GetPrimaryMonetaryAccount().Id.Value,
35+
new List<NotificationFilterUrl>() {notificationFilter}
36+
).Value;
37+
38+
Assert.True(allCreatedNotificationFilter.Count == 1);
39+
}
40+
41+
/// <summary>
42+
/// Test NotificationFilterUrlUser creation.
43+
/// </summary>
44+
[Fact]
45+
public void TestNotificationFilterUrlUser()
46+
{
47+
SetUpApiContext();
48+
49+
NotificationFilterUrl notificationFilter = GetNotificationFilterUrl();
50+
List<NotificationFilterUrl> allCreatedNotificationFilter = NotificationFilterUrlUserInternal.CreateWithListResponse(
51+
new List<NotificationFilterUrl>() {notificationFilter}
52+
).Value;
53+
54+
Assert.True(allCreatedNotificationFilter.Count == 1);
55+
}
56+
/// <summary>
57+
/// Test NotificationFilterPushUser creation.
58+
/// </summary>
59+
[Fact]
60+
public void TestNotificationFilterPushUser()
61+
{
62+
SetUpApiContext();
63+
64+
NotificationFilterPush notificationFilter = GetNotificationFilterPush();
65+
List<NotificationFilterPush> allCreatedNotificationFilter = NotificationFilterPushUserInternal.CreateWithListResponse(
66+
new List<NotificationFilterPush>() {notificationFilter}
67+
).Value;
68+
69+
Assert.True(allCreatedNotificationFilter.Count == 1);
70+
}
71+
72+
/// <summary>
73+
/// Test clear all filters.
74+
/// </summary>
75+
[Fact]
76+
public void TestNotificationFilterClear()
77+
{
78+
SetUpApiContext();
79+
80+
List<NotificationFilterPush> allCreatedNotificationFilterPushUser =
81+
NotificationFilterPushUserInternal.CreateWithListResponse().Value;
82+
List<NotificationFilterUrl> allCreatedNotificationFilterUrlUser =
83+
NotificationFilterUrlUserInternal.CreateWithListResponse().Value;
84+
List<NotificationFilterUrl> allCreatedNotificationFilterUrlMonetaryAccount =
85+
NotificationFilterUrlMonetaryAccountInternal.CreateWithListResponse().Value;
86+
87+
Assert.Empty(allCreatedNotificationFilterPushUser);
88+
Assert.Empty(allCreatedNotificationFilterUrlUser);
89+
Assert.Empty(allCreatedNotificationFilterUrlMonetaryAccount);
90+
91+
Assert.StrictEqual(0, NotificationFilterPushUserInternal.List().Value.Count);
92+
Assert.StrictEqual(0, NotificationFilterUrlUserInternal.List().Value.Count);
93+
Assert.StrictEqual(0, NotificationFilterUrlMonetaryAccountInternal.List().Value.Count);
94+
}
95+
96+
private NotificationFilterUrl GetNotificationFilterUrl()
97+
{
98+
return new NotificationFilterUrl(FILTER_CATEGORY_MUTATION, FILTER_CALLBACK_URL);
99+
}
100+
101+
private NotificationFilterPush GetNotificationFilterPush()
102+
{
103+
return new NotificationFilterPush(FILTER_CATEGORY_MUTATION);
104+
}
105+
106+
private MonetaryAccountBank GetPrimaryMonetaryAccount()
107+
{
108+
return BunqContext.UserContext.PrimaryMonetaryAccountBank;
109+
}
110+
}
111+
}

BunqSdk.Tests/Model/Generated/Endpoint/CardDebitTest.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ public void TestOrderNewMaestroCard()
5353
var cardDebit = CardDebit.Create(
5454
GenerateRandomSecondLine(),
5555
GetAnAllowedName(),
56-
GetAlias(),
5756
CardTypeMaestro,
57+
GetAlias(),
5858
allCardPinAssignments
5959
).Value;
6060

BunqSdk.Tests/Resources/chain.cert

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIID1zCCAr+gAwIBAgIBATANBgkqhkiG9w0BAQsFADB1MQswCQYDVQQGEwJOTDEW
3+
MBQGA1UECBMNTm9vcmQtSG9sbGFuZDESMBAGA1UEBxMJQW1zdGVyZGFtMRIwEAYD
4+
VQQKEwlidW5xIGIudi4xDzANBgNVBAsTBkRldk9wczEVMBMGA1UEAxMMUFNEMiBU
5+
ZXN0IENBMB4XDTE5MDIxODEzNDkwMFoXDTI5MDIxODEzNDkwMFowdTELMAkGA1UE
6+
BhMCTkwxFjAUBgNVBAgTDU5vb3JkLUhvbGxhbmQxEjAQBgNVBAcTCUFtc3RlcmRh
7+
bTESMBAGA1UEChMJYnVucSBiLnYuMQ8wDQYDVQQLEwZEZXZPcHMxFTATBgNVBAMT
8+
DFBTRDIgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOv
9+
zPl+uegBpnFhXsjuKs0ws00e+232wR9tvDqYBjGdOlYorw8CyrT+mr0HKO9lx7vg
10+
xhJ3f+oonkZvBb+IehDmEsBbZ+vRtdjEWw3RTWVBT69jPcRQGE2e5qUuTJYVCONY
11+
JsOQP8CoCHXa6+oUSmUyMZX/zNJhTvbLV9e/qpIWwWVrKzK0EEB5c71gITNgzOXG
12+
+lIKJmOnvvJyWPCx02hIgQI3nVphDj8ydMEKuwTgBrFV5Lqkar3L6ngF7LgzjXPC
13+
Nbf3JL/2Ccp0hYPb2MLVEpYba8/38eN6izjorJiwu+uGehOpj/RNcfv27iGyvXRY
14+
FC2PfRP8ZP5CpoijJR8CAwEAAaNyMHAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
15+
FgQU38gzLVi6UQYiNLXKIhwoklPnSYMwCwYDVR0PBAQDAgEGMBEGCWCGSAGG+EIB
16+
AQQEAwIABzAeBglghkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3
17+
DQEBCwUAA4IBAQBt6HBrnSvEbUX514ab3Zepdct0QWVLzzEKFC8y9ARLWttyaRJ5
18+
AhzCa4t8LJnyoYuEPHOKDIsqLzmJlwqBnsXPuMdWEd3vnFRgj1oL3vVqoJwrfqDp
19+
S3jHshWopqMKtmzAO9Q3BWpk/lrqJTP1y/6057LtMGhwA6m0fDmvA+VuTrh9mgzw
20+
FgWwmahVa08h1Cm5+vc1Phi8wVXi3R1NzmVUQFYOixSwifs8P0MstBfCFlBFQ47C
21+
EvGEYvOBLlEiiaoMUT6aoYj+L8zHWXakSQFAzIzQFJn668q2ds6zx67P7wKFZ887
22+
VJSv7sTqspxON1s1oFlkRXu5JihaVJcHmFAY
23+
-----END CERTIFICATE-----
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace Bunq.Sdk.Tests.Util
4+
{
5+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
6+
public class TestPriorityAttribute: Attribute
7+
{
8+
public int Priority { get; private set; }
9+
10+
public TestPriorityAttribute(int priority)
11+
{
12+
Priority = priority;
13+
}
14+
}
15+
}
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Xunit.Abstractions;
5+
using Xunit.Sdk;
6+
7+
namespace Bunq.Sdk.Tests.Util
8+
{
9+
public class TestPriorityOrderer: ITestCaseOrderer
10+
{
11+
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> allTestCase) where TTestCase : ITestCase
12+
{
13+
SortedDictionary<int, List<TTestCase>> sortedMethods = new SortedDictionary<int, List<TTestCase>>();
14+
15+
foreach (TTestCase testCase in allTestCase)
16+
{
17+
string orderAttributeName = typeof(TestPriorityAttribute).AssemblyQualifiedName;
18+
IEnumerable<IAttributeInfo> allAttributeInfo = testCase.TestMethod.Method.GetCustomAttributes(orderAttributeName);
19+
20+
int testPriority = 0;
21+
foreach (IAttributeInfo attributeInfo in allAttributeInfo)
22+
{
23+
testPriority = attributeInfo.GetNamedArgument<int>("Priority");
24+
}
25+
26+
GetOrCreate(sortedMethods, testPriority).Add(testCase);
27+
}
28+
29+
foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority]))
30+
{
31+
list.Sort((method1, method2) =>
32+
{
33+
return StringComparer.OrdinalIgnoreCase.Compare(
34+
method1.TestMethod.Method.Name,
35+
method2.TestMethod.Method.Name
36+
);
37+
});
38+
39+
foreach (TTestCase testCase in list)
40+
yield return testCase;
41+
}
42+
}
43+
44+
static TValue GetOrCreate<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key) where TValue : new()
45+
{
46+
TValue result;
47+
48+
if (dictionary.TryGetValue(key, out result))
49+
return result;
50+
51+
result = new TValue();
52+
dictionary[key] = result;
53+
54+
return result;
55+
}
56+
}
57+
}

BunqSdk/BunqSdk.csproj

-7
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,4 @@
2525
<PackageReference Include="Newtonsoft.Json" Version="10.0.3-*" />
2626
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
2727
</ItemGroup>
28-
<ItemGroup>
29-
<Content Include="../CHANGELOG.md" />
30-
<Content Include="../CONTRIBUTING.md" />
31-
<Content Include="../LICENSE.md" />
32-
<Content Include="../README.md" />
33-
<Content Include="../.gitignore" />
34-
</ItemGroup>
3528
</Project>

BunqSdk/Context/ApiEnvironmentType.cs

+12
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,17 @@ public ApiEnvironmentType(string typeString)
3838
TypeString = typeString;
3939
BaseUri = NAME_TO_BASE_URI_MAP[typeString];
4040
}
41+
42+
public override bool Equals(object obj)
43+
{
44+
if (obj is ApiEnvironmentType)
45+
{
46+
return (obj as ApiEnvironmentType).TypeString.Equals(TypeString);
47+
}
48+
else
49+
{
50+
return base.Equals(obj);
51+
}
52+
}
4153
}
4254
}

BunqSdk/Json/AnchorObjectConverter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
2323
{
2424
ContractResolver = new BunqContractResolver(new List<Type> {typeof(IAnchorObjectInterface)}),
2525
DateFormatString = FORMAT_DATE,
26-
FloatParseHandling = FloatParseHandling.Decimal,
26+
FloatParseHandling = FloatParseHandling.Double,
2727
Formatting = Formatting.Indented,
2828
NullValueHandling = NullValueHandling.Ignore,
2929
}

BunqSdk/Json/NonIntegerNumberConverter.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
2020
}
2121
else
2222
{
23-
writer.WriteValue(((decimal) value).ToString(FORMAT_DECIMAL));
23+
writer.WriteValue(((double) value).ToString(FORMAT_DECIMAL));
2424
}
2525
}
2626

@@ -31,7 +31,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
3131

3232
if (jToken.Type == JTokenType.String)
3333
{
34-
return jToken.ToObject<decimal>();
34+
return jToken.ToObject<double>();
3535
}
3636

3737
return null;

0 commit comments

Comments
 (0)