Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions PAYNLSDK/API/Merchant/Clearing/Request.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using PAYNLSDK.API;
using PAYNLSDK.Exceptions;
using PAYNLSDK.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;

namespace PayNLSdk.API.Merchant.Clearing
{
Expand All @@ -22,12 +21,12 @@
/// <summary>
/// The merchant to clear
/// </summary>
public string? MerchantId { get; set; }

Check warning on line 24 in PAYNLSDK/API/Merchant/Clearing/Request.cs

View workflow job for this annotation

GitHub Actions / build-and-publish

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

/// <summary>
/// The content category Id.
/// </summary>
public string? ContentCategoryId { get; set; }

Check warning on line 29 in PAYNLSDK/API/Merchant/Clearing/Request.cs

View workflow job for this annotation

GitHub Actions / build-and-publish

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

/// <inheritdoc />
public override NameValueCollection GetParameters()
Expand All @@ -42,11 +41,21 @@
return nvc;
}

public Response Response { get { return (Response)response; } }

/// <inheritdoc />
/// <exception cref="NotImplementedException"></exception>
protected override void PrepareAndSetResponse()
{
throw new NotImplementedException();
if (ParameterValidator.IsEmpty(rawResponse))
{
throw new PayNlException("rawResponse is empty!");
}
response = Response.FromRawResponse(RawResponse);
if (!Response.Request.Result)
{
throw new PayNlException(Response.Request.Code + " " + Response.Request.Message);
}
}
}
}
10 changes: 8 additions & 2 deletions PAYNLSDK/API/Merchant/Info/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ protected override void PrepareAndSetResponse()
throw new PayNlException("rawResponse is empty!");
}
response = JsonConvert.DeserializeObject<API.Merchant.Get.Response>(RawResponse);
if (!response.Request.Result)
var merchantResponse = response as API.Merchant.Get.Response;

// Check if request was successful (result can be "1" for success or other values for failure)
if (merchantResponse?.request != null && merchantResponse.request.result != "1")
{
// toss
throw new PayNlException(response.Request.Message);
var errorMessage = !string.IsNullOrEmpty(merchantResponse.request.errorMessage)
? merchantResponse.request.errorMessage
: "Request failed";
throw new PayNlException(errorMessage);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion PAYNLSDK/API/Merchant/Info/Response.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public class Merchant
public Address postalAddress { get; set; }
public Address visitAddress { get; set; }
public Tradename[] tradeNames { get; set; }
public Contact[] contactData { get; set; }
public string state { get; set; }

public class Address
{
Expand Down Expand Up @@ -159,4 +161,4 @@ public class Contact
}

}
}
}
6 changes: 1 addition & 5 deletions PAYNLSDK/API/Statistics/GetManagement/GetStatsMultiLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ public class TopLevelStatsData
{
public string Id { get; set; }
public string Label { get; set; }
public GetStatsResultBase.StatsData[] Data { get; set; }
public GetStatsResultBase.StatsLine[] Data { get; set; }
}




}
4 changes: 2 additions & 2 deletions PAYNLSDK/API/Transaction/Start/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public override NameValueCollection GetParameters()
{
nvc.Add("transaction[currency]", TransactionData.Currency);
}
if (!ParameterValidator.IsNonEmptyInt(TransactionData.CostsVat))
if (ParameterValidator.IsNonEmptyInt(TransactionData.CostsVat))
{
nvc.Add("transaction[costsVat]", TransactionData.CostsVat.ToString());
}
Expand All @@ -152,7 +152,7 @@ public override NameValueCollection GetParameters()
nvc.Add("transaction[description]", TransactionData.Description);
}

if (!ParameterValidator.IsNonEmptyInt(TransactionData.EnduserId))
if (ParameterValidator.IsNonEmptyInt(TransactionData.EnduserId))
{
nvc.Add("transaction[enduserId]", TransactionData.EnduserId.ToString());
}
Expand Down
5 changes: 1 addition & 4 deletions PAYNLSDK/Enums/enums.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace PAYNLSDK.Enums
{
Expand Down Expand Up @@ -82,7 +79,7 @@ public enum Gender
/// <summary>
/// A male gender
/// </summary>
[EnumMember(Value="m")]
[EnumMember(Value = "m")]
Male,
/// <summary>
/// A female gender
Expand Down
2 changes: 1 addition & 1 deletion PAYNLSDK/PayNLSdk.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>RoodFluweel.PAYNLSDK</PackageId>
<Version>1.7.6</Version>
<Version>1.7.7</Version>
<Authors>paynl, dampee, Sebsoft</Authors>
<Company>dampee, paynl</Company>
<PackageLicenseUrl></PackageLicenseUrl>
Expand Down
3 changes: 2 additions & 1 deletion PAYNLSDK/Statistics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ public GetStatsMultiLevel GetMultiLevelStats(Request request, string groupByFiel
request.GroupByFieldNames.Add(groupByFieldName2);

var response = _webClient.PerformRequest(request);
return Newtonsoft.Json.JsonConvert.DeserializeObject<GetStatsMultiLevel>(response);
var jsonConverters = new List<JsonConverter> { new DecimalConverter() };
return Newtonsoft.Json.JsonConvert.DeserializeObject<GetStatsMultiLevel>(response, jsonConverters.ToArray());
}
}

Expand Down
136 changes: 136 additions & 0 deletions PayNLSdk.Tests/AllianceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
using NSubstitute;
using PAYNLSDK;
using PAYNLSDK.API;
using PAYNLSDK.Net;
using Shouldly;
using Xunit;

namespace PayNLSdk.Tests;

public class AllianceTests
{

[Fact]
public void GetMerchant_ShouldDeserializeFullResult()
{
// Arrange
var rawResponse = """
{
"request": {
"result": true,
"errorId": null,
"errorMessage": null
},
"merchantId": "M-4",
"merchantName": "Alliance Merchant",
"services": []
}
""";
var client = CreateClient(rawResponse);
var alliance = new Alliance(client);
var request = new PAYNLSDK.API.Alliance.GetMerchant.Request { MerchantId = "M-4" };

// Act
var result = alliance.GetMerchant(request);

// Assert
result.merchantId.ShouldBe("M-4");
result.merchantName.ShouldBe("Alliance Merchant");
result.services.ShouldBeEmpty();
}

[Fact]
public void AddMerchant_ShouldReturnDeserializedResult()
{
// Arrange
var rawResponse = """
{
"success": true,
"merchantId": "M-5",
"merchantToken": "token",
"accounts": [
{
"accountId": "A-1",
"email": "mail@example.com"
}
]
}
""";
var client = CreateClient(rawResponse);
var alliance = new Alliance(client);

// Act
var result = alliance.AddMerchant(new PAYNLSDK.API.Alliance.AddMerchant.Request());

// Assert
result.Success.ShouldBeTrue();
result.MerchantId.ShouldBe("M-5");
result.Accounts.ShouldHaveSingleItem();
result.Accounts[0].AccountId.ShouldBe("A-1");
}

[Fact]
public void AddService_ShouldReturnServiceIdentifier()
{
// Arrange
var rawResponse = """
{
"request": {
"result": true,
"errorId": null,
"errorMessage": null
},
"serviceId": "SL-1000-2000"
}
""";
var client = CreateClient(rawResponse);
var alliance = new Alliance(client);

// Act
var result = alliance.AddService(new PAYNLSDK.API.Alliance.AddService.Request());

// Assert
result.ServiceId.ShouldBe("SL-1000-2000");
}

[Fact]
public void AddInvoice_ShouldReturnReferenceId()
{
// Arrange
var rawResponse = """
{
"request": {
"result": true,
"errorId": null,
"errorMessage": null
},
"referenceId": "INV-1"
}
""";
var client = CreateClient(rawResponse);
var alliance = new Alliance(client);

// Act
var result = alliance.AddInvoice(new PAYNLSDK.API.Alliance.AddInvoice.Request(
merchantId: "M-4",
serviceId: "SL-1000-2000",
invoiceId: "INV-1",
description: "Alliance invoice",
amountInCents: 1234));

// Assert
result.ReferenceId.ShouldBe("INV-1");
result.ToString().ShouldContain("INV-1");
}

private static IClient CreateClient(string rawResponse)
{
var client = Substitute.For<IClient>();
client.PerformRequest(Arg.Any<RequestBase>()).Returns(callInfo =>
{
callInfo.Arg<RequestBase>().RawResponse = rawResponse;
return rawResponse;
});
return client;
}
}
124 changes: 124 additions & 0 deletions PayNLSdk.Tests/BanktransferTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using NSubstitute;
using PAYNLSDK;
using PAYNLSDK.API;
using PAYNLSDK.Net;
using Shouldly;
using System;
using Xunit;
using BanktransferAddRequest = PAYNLSDK.API.Banktransfer.Add.Request;

namespace PayNLSdk.Tests;

public class BanktransferTests
{
[Fact]
public void Add_WithRequest_ShouldReturnResponseFromRequest()
{
// Arrange
var client = Substitute.For<IClient>();
var request = new BanktransferAddRequest(12.34m, "Alice", "NL01PAYN0123456789", "PAYNNL2A")
{
Description = "Invoice 42"
};
const string rawResponse = """
{
"refundId": "RF-123",
"request": {
"result": true,
"errorId": null,
"errorMessage": null
}
}
""";
client.PerformRequest(Arg.Do<RequestBase>(performedRequest =>
{
performedRequest.ShouldBeSameAs(request);
performedRequest.RawResponse = rawResponse;
}));
var sut = new Banktransfer(client);

// Act
var response = sut.Add(request);

// Assert
client.Received(1).PerformRequest(request);
response.ShouldNotBeNull();
response.RefundId.ShouldBe("RF-123");
}

[Fact]
public void Add_WithPrimitiveParameters_ShouldCreateRequestAndPopulateValues()
{
// Arrange
var client = Substitute.For<IClient>();
BanktransferAddRequest? capturedRequest = null;
const string rawResponse = """
{
"refundId": "RF-456",
"request": {
"result": true,
"errorId": null,
"errorMessage": null
}
}
""";
client.PerformRequest(Arg.Do<RequestBase>(performedRequest =>
{
capturedRequest = performedRequest.ShouldBeOfType<BanktransferAddRequest>();
performedRequest.RawResponse = rawResponse;
}));
var sut = new Banktransfer(client);

// Act
var response = sut.Add(2599, "Bob", "NL02BANK0123456789", "BANKNL2A");

// Assert
client.Received(1).PerformRequest(Arg.Any<BanktransferAddRequest>());
capturedRequest.ShouldNotBeNull();
capturedRequest!.AmountInCents.ShouldBe(259900);
capturedRequest.BankAccountHolder.ShouldBe("Bob");
capturedRequest.BankAccountNumber.ShouldBe("NL02BANK0123456789");
capturedRequest.BankAccountBic.ShouldBe("BANKNL2A");
response.ShouldNotBeNull();
response.RefundId.ShouldBe("RF-456");
}

[Fact]
public void Request_GetParameters_ShouldIncludeOptionalFields()
{
// Arrange
var processDate = new DateTime(2024, 05, 19);
var request = new BanktransferAddRequest(12.34m, "Carol", "NL03TEST0123456789", "TESTNL2A")
{
Description = "Invoice 99",
PromotorId = 42,
Tool = "affiliate",
Info = "campaign",
Object = "OBJ-7",
Extra1 = "custom-1",
Extra2 = "custom-2",
Extra3 = "custom-3",
Currency = "USD",
ProcessDate = processDate
};

// Act
var parameters = request.GetParameters();

// Assert
parameters["amount"].ShouldBe("1234");
parameters["bankAccountHolder"].ShouldBe("Carol");
parameters["bankAccountNumber"].ShouldBe("NL03TEST0123456789");
parameters["bankAccountBic"].ShouldBe("TESTNL2A");
parameters["description"].ShouldBe("Invoice 99");
parameters["promotorId"].ShouldBe("42");
parameters["tool"].ShouldBe("affiliate");
parameters["info"].ShouldBe("campaign");
parameters["object"].ShouldBe("OBJ-7");
parameters["extra1"].ShouldBe("custom-1");
parameters["extra2"].ShouldBe("custom-2");
parameters["extra3"].ShouldBe("custom-3");
parameters["currency"].ShouldBe("USD");
parameters["processDate"].ShouldBe(processDate.ToString("yyyy-MM-dd"));
}
}
Loading
Loading